Merge "Lazily loading the widget providers to avoid loading app-resources on userUnlock"

This commit is contained in:
TreeHugger Robot
2021-01-26 20:19:53 +00:00
committed by Android (Google) Code Review

View File

@@ -89,10 +89,12 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.AttributeSet;
import android.util.IntArray;
import android.util.LongSparseArray;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.util.TypedValue;
@@ -105,6 +107,7 @@ import android.view.View;
import android.widget.RemoteViews;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.SuspendedAppActivity;
import com.android.internal.app.UnlaunchableAppActivity;
import com.android.internal.appwidget.IAppWidgetHost;
@@ -161,8 +164,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
private static final int UNKNOWN_UID = -1;
private static final int LOADED_PROFILE_ID = -1;
private static final int UNKNOWN_USER_ID = -10;
// Bump if the stored widgets need to be upgraded.
@@ -220,7 +221,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
private final ArraySet<Pair<Integer, String>> mPackagesWithBindWidgetPermission =
new ArraySet<>();
private final SparseIntArray mLoadedUserIds = new SparseIntArray();
private final SparseBooleanArray mLoadedUserIds = new SparseBooleanArray();
private final Object mWidgetPackagesLock = new Object();
private final SparseArray<ArraySet<String>> mWidgetPackages = new SparseArray<>();
@@ -525,7 +526,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
boolean suspended;
try {
suspended = mPackageManager.isPackageSuspendedForUser(
provider.info.provider.getPackageName(), provider.getUserId());
provider.id.componentName.getPackageName(), provider.getUserId());
} catch (IllegalArgumentException ex) {
// Package not found.
suspended = false;
@@ -563,7 +564,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
Provider provider = mProviders.get(i);
int providerUserId = provider.getUserId();
if (providerUserId != profileId
|| !packages.contains(provider.info.provider.getPackageName())) {
|| !packages.contains(provider.id.componentName.getPackageName())) {
continue;
}
if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
@@ -624,7 +625,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (widgetCount == 0) {
return;
}
final String providerPackage = provider.info.provider.getPackageName();
final String providerPackage = provider.id.componentName.getPackageName();
final int providerUserId = provider.getUserId();
Bitmap iconBitmap = createMaskedWidgetBitmap(providerPackage, providerUserId);
if (iconBitmap == null) {
@@ -725,35 +726,17 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId);
// Careful lad, we may have already loaded the state for some
// group members, so check before loading and read only the
// state for the new member(s).
int newMemberCount = 0;
final int profileIdCount = profileIds.length;
for (int i = 0; i < profileIdCount; i++) {
final int profileId = profileIds[i];
if (mLoadedUserIds.indexOfKey(profileId) >= 0) {
profileIds[i] = LOADED_PROFILE_ID;
} else {
newMemberCount++;
IntArray newIds = new IntArray(1);
for (int profileId : profileIds) {
if (!mLoadedUserIds.get(profileId)) {
mLoadedUserIds.put(profileId, true);
newIds.add(profileId);
}
}
if (newMemberCount <= 0) {
if (newIds.size() <= 0) {
return;
}
int newMemberIndex = 0;
final int[] newProfileIds = new int[newMemberCount];
for (int i = 0; i < profileIdCount; i++) {
final int profileId = profileIds[i];
if (profileId != LOADED_PROFILE_ID) {
mLoadedUserIds.put(profileId, profileId);
newProfileIds[newMemberIndex] = profileId;
newMemberIndex++;
}
}
final int[] newProfileIds = newIds.toArray();
clearProvidersAndHostsTagsLocked();
loadGroupWidgetProvidersLocked(newProfileIds);
@@ -772,7 +755,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (args.length > 0 && "--proto".equals(args[0])) {
dumpProto(fd);
} else {
dumpInternal(pw);
dumpInternalLocked(pw);
}
}
}
@@ -816,11 +799,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
proto.end(token);
}
private void dumpInternal(PrintWriter pw) {
private void dumpInternalLocked(PrintWriter pw) {
int N = mProviders.size();
pw.println("Providers:");
for (int i = 0; i < N; i++) {
dumpProvider(mProviders.get(i), i, pw);
dumpProviderLocked(mProviders.get(i), i, pw);
}
N = mWidgets.size();
@@ -850,7 +833,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
public ParceledListSlice<PendingHostUpdate> startListening(IAppWidgetHost callbacks,
String callingPackage, int hostId, int[] appWidgetIds) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "startListening() " + userId);
}
@@ -879,7 +861,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
LongSparseArray<PendingHostUpdate> updatesMap = new LongSparseArray<>();
for (int i = 0; i < N; i++) {
updatesMap.clear();
host.getPendingUpdatesForId(appWidgetIds[i], updatesMap);
host.getPendingUpdatesForIdLocked(mContext, appWidgetIds[i], updatesMap);
// We key the updates based on request id, so that the values are sorted in the
// order they were received.
int m = updatesMap.size();
@@ -1090,7 +1072,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setComponent(provider.info.configure);
intent.setComponent(provider.getInfoLocked(mContext).configure);
intent.setFlags(secureFlags);
// All right, create the sender.
@@ -1434,7 +1416,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
Binder.getCallingUid(), callingPackage);
if (widget != null && widget.provider != null && !widget.provider.zombie) {
return cloneIfLocalBinder(widget.provider.info);
return cloneIfLocalBinder(widget.provider.getInfoLocked(mContext));
}
return null;
@@ -1644,14 +1626,14 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
String keyToUse = metadataKey == null
? AppWidgetManager.META_DATA_APPWIDGET_PROVIDER : metadataKey;
AppWidgetProviderInfo info =
parseAppWidgetProviderInfo(providerId, provider.info.providerInfo, keyToUse);
AppWidgetProviderInfo info = parseAppWidgetProviderInfo(mContext, providerId,
provider.getPartialInfoLocked().providerInfo, keyToUse);
if (info == null) {
throw new IllegalArgumentException("Unable to parse " + keyToUse
+ " meta-data to a valid AppWidget provider");
}
provider.info = info;
provider.setInfoLocked(info);
provider.infoTag = metadataKey;
// Update all widgets for this provider
@@ -1701,7 +1683,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (provider == null || provider.zombie) {
return false;
}
info = provider.info;
info = provider.getInfoLocked(mContext);
if ((info.widgetCategory & AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN) == 0) {
return false;
}
@@ -1739,7 +1721,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
final int providerCount = mProviders.size();
for (int i = 0; i < providerCount; i++) {
Provider provider = mProviders.get(i);
AppWidgetProviderInfo info = provider.info;
AppWidgetProviderInfo info = provider.getInfoLocked(mContext);
// Ignore an invalid provider, one not matching the filter,
// or one that isn't in the given package, if any.
@@ -1907,7 +1889,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
try {
mContext.bindServiceAsUser(intent, conn,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
widget.provider.info.getProfile());
widget.provider.id.getProfile());
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -2102,7 +2084,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
SomeArgs args = SomeArgs.obtain();
args.arg1 = widget.host;
args.arg2 = widget.host.callbacks;
args.arg3 = widget.provider.info;
args.arg3 = widget.provider.getInfoLocked(mContext);
args.arg4 = requestId;
args.argi1 = widget.appWidgetId;
@@ -2312,31 +2294,34 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
ri.activityInfo.name);
ProviderId providerId = new ProviderId(ri.activityInfo.applicationInfo.uid, componentName);
Provider provider = parseProviderInfoXml(providerId, ri, null);
if (provider != null) {
// we might have an inactive entry for this provider already due to
// a preceding restore operation. if so, fix it up in place; otherwise
// just add this new one.
Provider existing = lookupProviderLocked(providerId);
// we might have an inactive entry for this provider already due to
// a preceding restore operation. if so, fix it up in place; otherwise
// just add this new one.
Provider existing = lookupProviderLocked(providerId);
// If the provider was not found it may be because it was restored and
// we did not know its UID so let us find if there is such one.
if (existing == null) {
ProviderId restoredProviderId = new ProviderId(UNKNOWN_UID, componentName);
existing = lookupProviderLocked(restoredProviderId);
}
// If the provider was not found it may be because it was restored and
// we did not know its UID so let us find if there is such one.
if (existing == null) {
ProviderId restoredProviderId = new ProviderId(UNKNOWN_UID, componentName);
existing = lookupProviderLocked(restoredProviderId);
}
AppWidgetProviderInfo info = createPartialProviderInfo(providerId, ri, existing);
if (info != null) {
if (existing != null) {
if (existing.zombie && !mSafeMode) {
// it's a placeholder that was set up during an app restore
existing.id = providerId;
existing.zombie = false;
existing.info = provider.info; // the real one filled out from the ResolveInfo
existing.setPartialInfoLocked(info);
if (DEBUG) {
Slog.i(TAG, "Provider placeholder now reified: " + existing);
}
}
} else {
Provider provider = new Provider();
provider.id = providerId;
provider.setPartialInfoLocked(info);
mProviders.add(provider);
}
return true;
@@ -2375,60 +2360,61 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
private void sendEnableIntentLocked(Provider p) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED);
intent.setComponent(p.info.provider);
sendBroadcastAsUser(intent, p.info.getProfile());
intent.setComponent(p.id.componentName);
sendBroadcastAsUser(intent, p.id.getProfile());
}
private void sendUpdateIntentLocked(Provider provider, int[] appWidgetIds) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
intent.setComponent(provider.info.provider);
sendBroadcastAsUser(intent, provider.info.getProfile());
intent.setComponent(provider.id.componentName);
sendBroadcastAsUser(intent, provider.id.getProfile());
}
private void sendDeletedIntentLocked(Widget widget) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED);
intent.setComponent(widget.provider.info.provider);
intent.setComponent(widget.provider.id.componentName);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId);
sendBroadcastAsUser(intent, widget.provider.info.getProfile());
sendBroadcastAsUser(intent, widget.provider.id.getProfile());
}
private void sendDisabledIntentLocked(Provider provider) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED);
intent.setComponent(provider.info.provider);
sendBroadcastAsUser(intent, provider.info.getProfile());
intent.setComponent(provider.id.componentName);
sendBroadcastAsUser(intent, provider.id.getProfile());
}
public void sendOptionsChangedIntentLocked(Widget widget) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED);
intent.setComponent(widget.provider.info.provider);
intent.setComponent(widget.provider.id.componentName);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, widget.options);
sendBroadcastAsUser(intent, widget.provider.info.getProfile());
sendBroadcastAsUser(intent, widget.provider.id.getProfile());
}
private void registerForBroadcastsLocked(Provider provider, int[] appWidgetIds) {
if (provider.info.updatePeriodMillis > 0) {
AppWidgetProviderInfo info = provider.getInfoLocked(mContext);
if (info.updatePeriodMillis > 0) {
// if this is the first instance, set the alarm. otherwise,
// rely on the fact that we've already set it and that
// PendingIntent.getBroadcast will update the extras.
boolean alreadyRegistered = provider.broadcast != null;
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
intent.setComponent(provider.info.provider);
intent.setComponent(info.provider);
final long token = Binder.clearCallingIdentity();
try {
// Broadcast alarms sent by system are immutable
provider.broadcast = PendingIntent.getBroadcastAsUser(mContext, 1, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE,
provider.info.getProfile());
info.getProfile());
} finally {
Binder.restoreCallingIdentity(token);
}
if (!alreadyRegistered) {
// Set the alarm outside of our locks; we've latched the first-time
// invariant and established the PendingIntent safely.
final long period = Math.max(provider.info.updatePeriodMillis, MIN_UPDATE_PERIOD);
final long period = Math.max(info.updatePeriodMillis, MIN_UPDATE_PERIOD);
final PendingIntent broadcast = provider.broadcast;
mSaveStateHandler.post(() ->
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
@@ -2447,8 +2433,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
return appWidgetIds;
}
private static void dumpProvider(Provider provider, int index, PrintWriter pw) {
AppWidgetProviderInfo info = provider.info;
private static void dumpProviderLocked(Provider provider, int index, PrintWriter pw) {
AppWidgetProviderInfo info = provider.getPartialInfoLocked();
pw.print(" ["); pw.print(index); pw.print("] provider ");
pw.println(provider.id);
pw.print(" min=("); pw.print(info.minWidth);
@@ -2467,7 +2453,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
pw.print(Integer.toHexString(info.initialLayout));
pw.print(" initialKeyguardLayout=#");
pw.print(Integer.toHexString(info.initialKeyguardLayout));
pw.print(" zombie="); pw.println(provider.zombie);
pw.print(" zombie="); pw.println(provider.zombie);
}
private static void dumpHost(Host host, int index, PrintWriter pw) {
@@ -2502,8 +2488,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
private static void serializeProvider(TypedXmlSerializer out, Provider p) throws IOException {
out.startTag(null, "p");
out.attribute(null, "pkg", p.info.provider.getPackageName());
out.attribute(null, "cl", p.info.provider.getClassName());
out.attribute(null, "pkg", p.id.componentName.getPackageName());
out.attribute(null, "cl", p.id.componentName.getClassName());
out.attributeIntHex(null, "tag", p.tag);
if (!TextUtils.isEmpty(p.infoTag)) {
out.attribute(null, "info_tag", p.infoTag);
@@ -2604,30 +2590,32 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
@SuppressWarnings("deprecation")
private Provider parseProviderInfoXml(ProviderId providerId, ResolveInfo ri,
Provider oldProvider) {
AppWidgetProviderInfo info = null;
if (oldProvider != null && !TextUtils.isEmpty(oldProvider.infoTag)) {
info = parseAppWidgetProviderInfo(providerId, ri.activityInfo, oldProvider.infoTag);
}
if (info == null) {
info = parseAppWidgetProviderInfo(providerId, ri.activityInfo,
AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
}
if (info == null) {
private AppWidgetProviderInfo createPartialProviderInfo(ProviderId providerId, ResolveInfo ri,
Provider provider) {
boolean hasXmlDefinition = false;
Bundle metaData = ri.activityInfo.metaData;
if (metaData == null) {
return null;
}
Provider provider = new Provider();
provider.id = providerId;
provider.info = info;
return provider;
if (provider != null && !TextUtils.isEmpty(provider.infoTag)) {
hasXmlDefinition = metaData.getInt(provider.infoTag) != 0;
}
hasXmlDefinition |= metaData.getInt(AppWidgetManager.META_DATA_APPWIDGET_PROVIDER) != 0;
if (hasXmlDefinition) {
AppWidgetProviderInfo info = new AppWidgetProviderInfo();
info.provider = providerId.componentName;
info.providerInfo = ri.activityInfo;
return info;
}
return null;
}
private AppWidgetProviderInfo parseAppWidgetProviderInfo(
private static AppWidgetProviderInfo parseAppWidgetProviderInfo(Context context,
ProviderId providerId, ActivityInfo activityInfo, String metadataKey) {
try (XmlResourceParser parser =
activityInfo.loadXmlMetaData(mContext.getPackageManager(), metadataKey)) {
final PackageManager pm = context.getPackageManager();
try (XmlResourceParser parser = activityInfo.loadXmlMetaData(pm, metadataKey)) {
if (parser == null) {
Slog.w(TAG, "No " + metadataKey + " meta-data for AppWidget provider '"
+ providerId + '\'');
@@ -2657,7 +2645,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
final Resources resources;
final long identity = Binder.clearCallingIdentity();
try {
final PackageManager pm = mContext.getPackageManager();
final int userId = UserHandle.getUserId(providerId.uid);
final ApplicationInfo app = pm.getApplicationInfoAsUser(activityInfo.packageName,
0, userId);
@@ -2696,7 +2683,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
info.configure = new ComponentName(providerId.componentName.getPackageName(),
className);
}
info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString();
info.label = activityInfo.loadLabel(pm).toString();
info.icon = activityInfo.getIconResource();
info.previewImage = sa.getResourceId(
com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
@@ -2821,7 +2808,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (provider.widgets.size() > 0) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"appwidget init " + provider.info.provider.getPackageName());
"appwidget init " + provider.id.componentName.getPackageName());
sendEnableIntentLocked(provider);
int[] appWidgetIds = getWidgetIds(provider.widgets);
sendUpdateIntentLocked(provider, appWidgetIds);
@@ -2949,7 +2936,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (packages == null) {
mWidgetPackages.put(userId, packages = new ArraySet<String>());
}
packages.add(widget.provider.info.provider.getPackageName());
packages.add(widget.provider.id.componentName.getPackageName());
}
// If we are adding a widget it might be for a provider that
@@ -2976,7 +2963,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (widget.provider == null) return;
final int userId = widget.provider.getUserId();
final String packageName = widget.provider.info.provider.getPackageName();
final String packageName = widget.provider.id.componentName.getPackageName();
synchronized (mWidgetPackagesLock) {
ArraySet<String> packages = mWidgetPackages.get(userId);
if (packages == null) {
@@ -2989,7 +2976,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
Widget w = mWidgets.get(i);
if (w.provider == null) continue;
if (w.provider.getUserId() == userId
&& packageName.equals(w.provider.info.provider.getPackageName())) {
&& packageName.equals(w.provider.id.componentName.getPackageName())) {
return;
}
}
@@ -3185,10 +3172,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (provider == null && mSafeMode) {
// if we're in safe mode, make a temporary one
AppWidgetProviderInfo info = new AppWidgetProviderInfo();
info.provider = providerId.componentName;
info.providerInfo = providerInfo;
provider = new Provider();
provider.info = new AppWidgetProviderInfo();
provider.info.provider = providerId.componentName;
provider.info.providerInfo = providerInfo;
provider.setPartialInfoLocked(info);
provider.zombie = true;
provider.id = providerId;
mProviders.add(provider);
@@ -3197,15 +3186,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
final int providerTag = parser.getAttributeIntHex(null, "tag",
legacyProviderIndex);
provider.tag = providerTag;
provider.infoTag = parser.getAttributeValue(null, "info_tag");
if (!TextUtils.isEmpty(provider.infoTag) && !mSafeMode) {
AppWidgetProviderInfo info = parseAppWidgetProviderInfo(
providerId, providerInfo, provider.infoTag);
if (info != null) {
provider.info = info;
}
}
} else if ("h".equals(tag)) {
legacyHostIndex++;
Host host = new Host();
@@ -3426,11 +3407,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
providersUpdated = true;
}
} else {
Provider parsed = parseProviderInfoXml(providerId, ri, provider);
if (parsed != null) {
AppWidgetProviderInfo info =
createPartialProviderInfo(providerId, ri, provider);
if (info != null) {
keep.add(providerId);
// Use the new AppWidgetProviderInfo.
provider.info = parsed.info;
provider.setPartialInfoLocked(info);
// If it's enabled
final int M = provider.widgets.size();
if (M > 0) {
@@ -3460,7 +3442,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
N = mProviders.size();
for (int i = N - 1; i >= 0; i--) {
Provider provider = mProviders.get(i);
if (packageName.equals(provider.info.provider.getPackageName())
if (packageName.equals(provider.id.componentName.getPackageName())
&& provider.getUserId() == userId
&& !keep.contains(provider.id)) {
if (removedProviders != null) {
@@ -3479,7 +3461,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
final int N = mProviders.size();
for (int i = 0; i < N; ++i) {
Provider provider = mProviders.get(i);
if (pkgName.equals(provider.info.provider.getPackageName())
if (pkgName.equals(provider.id.componentName.getPackageName())
&& provider.getUserId() == userId
&& provider.widgets.size() > 0) {
deleteWidgetsLocked(provider, parentUserId);
@@ -3493,7 +3475,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
final int N = mProviders.size();
for (int i = N - 1; i >= 0; i--) {
Provider provider = mProviders.get(i);
if (pkgName.equals(provider.info.provider.getPackageName())
if (pkgName.equals(provider.id.componentName.getPackageName())
&& provider.getUserId() == userId) {
deleteProviderLocked(provider);
removed = true;
@@ -3972,17 +3954,21 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
private static final class Provider {
ProviderId id;
AppWidgetProviderInfo info;
ArrayList<Widget> widgets = new ArrayList<>();
PendingIntent broadcast;
String infoTag;
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
boolean maskedByLockedProfile;
boolean maskedByQuietProfile;
boolean maskedBySuspendedPackage;
boolean mInfoParsed = false;
int tag = TAG_UNDEFINED; // for use while saving state (the index)
public int getUserId() {
@@ -4007,6 +3993,51 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
return false;
}
@GuardedBy("mLock")
public AppWidgetProviderInfo getInfoLocked(Context context) {
if (!mInfoParsed) {
// parse
if (!zombie) {
AppWidgetProviderInfo newInfo = null;
if (!TextUtils.isEmpty(infoTag)) {
newInfo = parseAppWidgetProviderInfo(
context, id, info.providerInfo, infoTag);
}
if (newInfo == null) {
newInfo = parseAppWidgetProviderInfo(context, id, info.providerInfo,
AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
}
if (newInfo != null) {
info = newInfo;
}
}
mInfoParsed = true;
}
return info;
}
/**
* Returns the last updated AppWidgetProviderInfo for this provider. This info may not
* be completely parsed and only contain placeHolder information like
* {@link AppWidgetProviderInfo#providerInfo}
*/
@GuardedBy("mLock")
public AppWidgetProviderInfo getPartialInfoLocked() {
return info;
}
@GuardedBy("mLock")
public void setPartialInfoLocked(AppWidgetProviderInfo info) {
this.info = info;
mInfoParsed = false;
}
@GuardedBy("mLock")
public void setInfoLocked(AppWidgetProviderInfo info) {
this.info = info;
mInfoParsed = true;
}
@Override
public String toString() {
return "Provider{" + id + (zombie ? " Z" : "") + '}';
@@ -4051,6 +4082,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
this.componentName = componentName;
}
public UserHandle getProfile() {
return UserHandle.getUserHandleForUid(uid);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
@@ -4116,8 +4151,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
final int N = widgets.size();
for (int i = 0; i < N; i++) {
Provider provider = widgets.get(i).provider;
if (provider != null && provider.getUserId() == userId && provider.info != null
&& pkg.equals(provider.info.provider.getPackageName())) {
if (provider != null && provider.getUserId() == userId
&& pkg.equals(provider.id.componentName.getPackageName())) {
return true;
}
}
@@ -4127,7 +4162,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
/**
* Adds all pending updates in {@param outUpdates} keys by the update time.
*/
public void getPendingUpdatesForId(int appWidgetId,
public void getPendingUpdatesForIdLocked(Context context, int appWidgetId,
LongSparseArray<PendingHostUpdate> outUpdates) {
long updateSequenceNo = lastWidgetUpdateSequenceNo;
int N = widgets.size();
@@ -4144,7 +4179,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
switch (id) {
case ID_PROVIDER_CHANGED:
update = PendingHostUpdate.providerChanged(
appWidgetId, widget.provider.info);
appWidgetId, widget.provider.getInfoLocked(context));
break;
case ID_VIEWS_UPDATE:
update = PendingHostUpdate.updateAppWidget(appWidgetId,
@@ -4493,10 +4528,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
Provider p = findProviderLocked(componentName, userId);
if (p == null) {
AppWidgetProviderInfo info = new AppWidgetProviderInfo();
info.provider = componentName;
p = new Provider();
p.id = new ProviderId(UNKNOWN_UID, componentName);
p.info = new AppWidgetProviderInfo();
p.info.provider = componentName;
p.setPartialInfoLocked(info);
p.zombie = true;
mProviders.add(p);
}
@@ -4561,7 +4598,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
addWidgetLocked(id);
}
if (id.provider != null && id.provider.info != null) {
if (id.provider != null
&& id.provider.getPartialInfoLocked() != null) {
stashProviderRestoreUpdateLocked(id.provider,
restoredId, id.appWidgetId);
} else {
@@ -4787,7 +4825,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS, oldIds);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, newIds);
if (provider != null) {
intent.setComponent(provider.info.provider);
intent.setComponent(provider.id.componentName);
sendBroadcastAsUser(intent, userHandle);
}
if (host != null) {