Methods Summary |
---|
private boolean | addProviderLocked(android.content.pm.ResolveInfo ri)
if ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
return false;
}
if (!ri.activityInfo.isEnabled()) {
return false;
}
ComponentName componentName = new ComponentName(ri.activityInfo.packageName,
ri.activityInfo.name);
ProviderId providerId = new ProviderId(ri.activityInfo.applicationInfo.uid, componentName);
Provider provider = parseProviderInfoXml(providerId, ri);
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);
// 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 (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
if (DEBUG) {
Slog.i(TAG, "Provider placeholder now reified: " + existing);
}
}
} else {
mProviders.add(provider);
}
return true;
}
return false;
|
public int | allocateAppWidgetId(java.lang.String callingPackage, int hostId)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "allocateAppWidgetId() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
if (mNextAppWidgetIds.indexOfKey(userId) < 0) {
mNextAppWidgetIds.put(userId, AppWidgetManager.INVALID_APPWIDGET_ID + 1);
}
final int appWidgetId = incrementAndGetAppWidgetIdLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access hosts it owns.
HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
Host host = lookupOrAddHostLocked(id);
Widget widget = new Widget();
widget.appWidgetId = appWidgetId;
widget.host = host;
host.widgets.add(widget);
mWidgets.add(widget);
saveGroupStateAsync(userId);
if (DEBUG) {
Slog.i(TAG, "Allocated widget id " + appWidgetId
+ " for host " + host.id);
}
return appWidgetId;
}
|
public boolean | bindAppWidgetId(java.lang.String callingPackage, int appWidgetId, int providerProfileId, android.content.ComponentName providerComponent, android.os.Bundle options)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "bindAppWidgetId() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
// Check that if a cross-profile binding is attempted, it is allowed.
if (!mSecurityPolicy.isEnabledGroupProfile(providerProfileId)) {
return false;
}
// If the provider is not under the calling user, make sure this
// provider is white listed for access from the parent.
if (!mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed(
providerComponent.getPackageName(), providerProfileId)) {
return false;
}
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// A special permission or white listing is required to bind widgets.
if (!mSecurityPolicy.hasCallerBindPermissionOrBindWhiteListedLocked(
callingPackage)) {
return false;
}
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget == null) {
Slog.e(TAG, "Bad widget id " + appWidgetId);
return false;
}
if (widget.provider != null) {
Slog.e(TAG, "Widget id " + appWidgetId
+ " already bound to: " + widget.provider.id);
return false;
}
final int providerUid = getUidForPackage(providerComponent.getPackageName(),
providerProfileId);
if (providerUid < 0) {
Slog.e(TAG, "Package " + providerComponent.getPackageName() + " not installed "
+ " for profile " + providerProfileId);
return false;
}
// NOTE: The lookup is enforcing security across users by making
// sure the provider is in the already vetted user profile.
ProviderId providerId = new ProviderId(providerUid, providerComponent);
Provider provider = lookupProviderLocked(providerId);
if (provider == null) {
Slog.e(TAG, "No widget provider " + providerComponent + " for profile "
+ providerProfileId);
return false;
}
if (provider.zombie) {
Slog.e(TAG, "Can't bind to a 3rd party provider in"
+ " safe mode " + provider);
return false;
}
widget.provider = provider;
widget.options = (options != null) ? cloneIfLocalBinder(options) : new Bundle();
// We need to provide a default value for the widget category if it is not specified
if (!widget.options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) {
widget.options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
}
provider.widgets.add(widget);
final int widgetCount = provider.widgets.size();
if (widgetCount == 1) {
// Tell the provider that it's ready.
sendEnableIntentLocked(provider);
}
// Send an update now -- We need this update now, and just for this appWidgetId.
// It's less critical when the next one happens, so when we schedule the next one,
// we add updatePeriodMillis to its start time. That time will have some slop,
// but that's okay.
sendUpdateIntentLocked(provider, new int[] {appWidgetId});
// Schedule the future updates.
registerForBroadcastsLocked(provider, getWidgetIds(provider.widgets));
saveGroupStateAsync(userId);
if (DEBUG) {
Slog.i(TAG, "Bound widget " + appWidgetId + " to provider " + provider.id);
}
}
return true;
|
private void | bindLoadedWidgets(java.util.List loadedWidgets)
final int loadedWidgetCount = loadedWidgets.size();
for (int i = loadedWidgetCount - 1; i >= 0; i--) {
LoadedWidgetState loadedWidget = loadedWidgets.remove(i);
Widget widget = loadedWidget.widget;
widget.provider = findProviderByTag(loadedWidget.providerTag);
if (widget.provider == null) {
// This provider is gone. We just let the host figure out
// that this happened when it fails to load it.
continue;
}
widget.host = findHostByTag(loadedWidget.hostTag);
if (widget.host == null) {
// This host is gone.
continue;
}
widget.provider.widgets.add(widget);
widget.host.widgets.add(widget);
mWidgets.add(widget);
}
|
public void | bindRemoteViewsService(java.lang.String callingPackage, int appWidgetId, android.content.Intent intent, android.os.IBinder callbacks)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "bindRemoteViewsService() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget == null) {
throw new IllegalArgumentException("Bad widget id");
}
// Make sure the widget has a provider.
if (widget.provider == null) {
throw new IllegalArgumentException("No provider for widget "
+ appWidgetId);
}
ComponentName componentName = intent.getComponent();
// Ensure that the service belongs to the same package as the provider.
// But this is not enough as they may be under different users - see below...
String providerPackage = widget.provider.id.componentName.getPackageName();
String servicePackage = componentName.getPackageName();
if (!servicePackage.equals(providerPackage)) {
throw new SecurityException("The taget service not in the same package"
+ " as the widget provider");
}
// Make sure this service exists under the same user as the provider and
// requires a permission which allows only the system to bind to it.
mSecurityPolicy.enforceServiceExistsAndRequiresBindRemoteViewsPermission(
componentName, widget.provider.getUserId());
// Good to go - the service pakcage is correct, it exists for the correct
// user, and requires the bind permission.
// 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 connection = null;
FilterComparison fc = new FilterComparison(intent);
Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, fc);
if (mBoundRemoteViewsServices.containsKey(key)) {
connection = (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key);
connection.disconnect();
unbindService(connection);
mBoundRemoteViewsServices.remove(key);
}
// Bind to the RemoteViewsService (which will trigger a callback to the
// RemoteViewsAdapter.onServiceConnected())
connection = new ServiceConnectionProxy(callbacks);
bindService(intent, connection, widget.provider.info.getProfile());
mBoundRemoteViewsServices.put(key, connection);
// Add it to the mapping of RemoteViewsService to appWidgetIds so that we
// can determine when we can call back to the RemoteViewsService later to
// destroy associated factories.
Pair<Integer, FilterComparison> serviceId = Pair.create(widget.provider.id.uid, fc);
incrementAppWidgetServiceRefCount(appWidgetId, serviceId);
}
|
private void | bindService(android.content.Intent intent, android.content.ServiceConnection connection, android.os.UserHandle userHandle)
final long token = Binder.clearCallingIdentity();
try {
mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE,
userHandle);
} finally {
Binder.restoreCallingIdentity(token);
}
|
private void | cancelBroadcasts(com.android.server.appwidget.AppWidgetServiceImpl$Provider provider)
if (DEBUG) {
Slog.i(TAG, "cancelBroadcasts() for " + provider);
}
if (provider.broadcast != null) {
mAlarmManager.cancel(provider.broadcast);
long token = Binder.clearCallingIdentity();
try {
provider.broadcast.cancel();
} finally {
Binder.restoreCallingIdentity(token);
}
provider.broadcast = null;
}
|
private void | clearProvidersAndHostsTagsLocked()
final int providerCount = mProviders.size();
for (int i = 0; i < providerCount; i++) {
Provider provider = mProviders.get(i);
provider.tag = TAG_UNDEFINED;
}
final int hostCount = mHosts.size();
for (int i = 0; i < hostCount; i++) {
Host host = mHosts.get(i);
host.tag = TAG_UNDEFINED;
}
|
private static android.widget.RemoteViews | cloneIfLocalBinder(android.widget.RemoteViews rv)
if (isLocalBinder() && rv != null) {
return rv.clone();
}
return rv;
|
private static android.appwidget.AppWidgetProviderInfo | cloneIfLocalBinder(android.appwidget.AppWidgetProviderInfo info)
if (isLocalBinder() && info != null) {
return info.clone();
}
return info;
|
private static android.os.Bundle | cloneIfLocalBinder(android.os.Bundle bundle)
// Note: this is only a shallow copy. For now this will be fine, but it could be problematic
// if we start adding objects to the options. Further, it would only be an issue if keyguard
// used such options.
if (isLocalBinder() && bundle != null) {
return (Bundle) bundle.clone();
}
return bundle;
|
private void | computeMaximumWidgetBitmapMemory()
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getRealSize(size);
// Cap memory usage at 1.5 times the size of the display
// 1.5 * 4 bytes/pixel * w * h ==> 6 * w * h
mMaxWidgetBitmapMemory = 6 * size.x * size.y;
|
public android.content.IntentSender | createAppWidgetConfigIntentSender(java.lang.String callingPackage, int appWidgetId, int intentFlags)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "createAppWidgetConfigIntentSender() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget == null) {
throw new IllegalArgumentException("Bad widget id " + appWidgetId);
}
Provider provider = widget.provider;
if (provider == null) {
throw new IllegalArgumentException("Widget not bound " + appWidgetId);
}
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setComponent(provider.info.configure);
intent.setFlags(intentFlags);
// All right, create the sender.
final long identity = Binder.clearCallingIdentity();
try {
return PendingIntent.getActivityAsUser(
mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
| PendingIntent.FLAG_CANCEL_CURRENT, null,
new UserHandle(provider.getUserId()))
.getIntentSender();
} finally {
Binder.restoreCallingIdentity(identity);
}
}
|
private void | decrementAppWidgetServiceRefCount(com.android.server.appwidget.AppWidgetServiceImpl$Widget widget)
Iterator<Pair<Integer, FilterComparison>> it = mRemoteViewsServicesAppWidgets
.keySet().iterator();
while (it.hasNext()) {
final Pair<Integer, FilterComparison> key = it.next();
final HashSet<Integer> ids = mRemoteViewsServicesAppWidgets.get(key);
if (ids.remove(widget.appWidgetId)) {
// If we have removed the last app widget referencing this service, then we
// should destroy it and remove it from this set
if (ids.isEmpty()) {
destroyRemoteViewsService(key.second.getIntent(), widget);
it.remove();
}
}
}
|
public void | deleteAllHosts()
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "deleteAllHosts() " + userId);
}
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
boolean changed = false;
final int N = mHosts.size();
for (int i = N - 1; i >= 0; i--) {
Host host = mHosts.get(i);
// Delete only hosts in the calling uid.
if (host.id.uid == Binder.getCallingUid()) {
deleteHostLocked(host);
changed = true;
if (DEBUG) {
Slog.i(TAG, "Deleted host " + host.id);
}
}
}
if (changed) {
saveGroupStateAsync(userId);
}
}
|
public void | deleteAppWidgetId(java.lang.String callingPackage, int appWidgetId)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "deleteAppWidgetId() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget == null) {
return;
}
deleteAppWidgetLocked(widget);
saveGroupStateAsync(userId);
if (DEBUG) {
Slog.i(TAG, "Deleted widget id " + appWidgetId
+ " for host " + widget.host.id);
}
}
|
private void | deleteAppWidgetLocked(com.android.server.appwidget.AppWidgetServiceImpl$Widget widget)
// We first unbind all services that are bound to this id
unbindAppWidgetRemoteViewsServicesLocked(widget);
Host host = widget.host;
host.widgets.remove(widget);
pruneHostLocked(host);
mWidgets.remove(widget);
Provider provider = widget.provider;
if (provider != null) {
provider.widgets.remove(widget);
if (!provider.zombie) {
// send the broacast saying that this appWidgetId has been deleted
sendDeletedIntentLocked(widget);
if (provider.widgets.isEmpty()) {
// cancel the future updates
cancelBroadcasts(provider);
// send the broacast saying that the provider is not in use any more
sendDisabledIntentLocked(provider);
}
}
}
|
public void | deleteHost(java.lang.String callingPackage, int hostId)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "deleteHost() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access hosts in its uid and package.
HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
Host host = lookupHostLocked(id);
if (host == null) {
return;
}
deleteHostLocked(host);
saveGroupStateAsync(userId);
if (DEBUG) {
Slog.i(TAG, "Deleted host " + host.id);
}
}
|
private void | deleteHostLocked(com.android.server.appwidget.AppWidgetServiceImpl$Host host)
final int N = host.widgets.size();
for (int i = N - 1; i >= 0; i--) {
Widget widget = host.widgets.remove(i);
deleteAppWidgetLocked(widget);
}
mHosts.remove(host);
// it's gone or going away, abruptly drop the callback connection
host.callbacks = null;
|
private void | deleteProviderLocked(com.android.server.appwidget.AppWidgetServiceImpl$Provider provider)
int N = provider.widgets.size();
for (int i = N - 1; i >= 0; i--) {
Widget widget = provider.widgets.remove(i);
// Call back with empty RemoteViews
updateAppWidgetInstanceLocked(widget, null, false);
// clear out references to this appWidgetId
widget.host.widgets.remove(widget);
mWidgets.remove(widget);
widget.provider = null;
pruneHostLocked(widget.host);
widget.host = null;
}
mProviders.remove(provider);
// no need to send the DISABLE broadcast, since the receiver is gone anyway
cancelBroadcasts(provider);
|
private void | destroyRemoteViewsService(android.content.Intent intent, com.android.server.appwidget.AppWidgetServiceImpl$Widget widget)
final ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
final IRemoteViewsFactory cb = IRemoteViewsFactory.Stub.asInterface(service);
try {
cb.onDestroy(intent);
} catch (RemoteException re) {
Slog.e(TAG, "Error calling remove view factory", re);
}
mContext.unbindService(this);
}
@Override
public void onServiceDisconnected(ComponentName name) {
// Do nothing
}
};
// Bind to the service and remove the static intent->factory mapping in the
// RemoteViewsService.
final long token = Binder.clearCallingIdentity();
try {
mContext.bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE,
widget.provider.info.getProfile());
} finally {
Binder.restoreCallingIdentity(token);
}
|
public void | dump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
"Permission Denial: can't dump from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
synchronized (mLock) {
int N = mProviders.size();
pw.println("Providers:");
for (int i = 0; i < N; i++) {
dumpProvider(mProviders.get(i), i, pw);
}
N = mWidgets.size();
pw.println(" ");
pw.println("Widgets:");
for (int i = 0; i < N; i++) {
dumpWidget(mWidgets.get(i), i, pw);
}
N = mHosts.size();
pw.println(" ");
pw.println("Hosts:");
for (int i = 0; i < N; i++) {
dumpHost(mHosts.get(i), i, pw);
}
N = mPackagesWithBindWidgetPermission.size();
pw.println(" ");
pw.println("Grants:");
for (int i = 0; i < N; i++) {
Pair<Integer, String> grant = mPackagesWithBindWidgetPermission.valueAt(i);
dumpGrant(grant, i, pw);
}
}
|
private static void | dumpGrant(android.util.Pair grant, int index, java.io.PrintWriter pw)
pw.print(" ["); pw.print(index); pw.print(']");
pw.print(" user="); pw.print(grant.first);
pw.print(" package="); pw.println(grant.second);
|
private static void | dumpHost(com.android.server.appwidget.AppWidgetServiceImpl$Host host, int index, java.io.PrintWriter pw)
pw.print(" ["); pw.print(index); pw.print("] hostId=");
pw.println(host.id);
pw.print(" callbacks="); pw.println(host.callbacks);
pw.print(" widgets.size="); pw.print(host.widgets.size());
pw.print(" zombie="); pw.println(host.zombie);
|
private static void | dumpProvider(com.android.server.appwidget.AppWidgetServiceImpl$Provider provider, int index, java.io.PrintWriter pw)
AppWidgetProviderInfo info = provider.info;
pw.print(" ["); pw.print(index); pw.print("] provider ");
pw.println(provider.id);
pw.print(" min=("); pw.print(info.minWidth);
pw.print("x"); pw.print(info.minHeight);
pw.print(") minResize=("); pw.print(info.minResizeWidth);
pw.print("x"); pw.print(info.minResizeHeight);
pw.print(") updatePeriodMillis=");
pw.print(info.updatePeriodMillis);
pw.print(" resizeMode=");
pw.print(info.resizeMode);
pw.print(info.widgetCategory);
pw.print(" autoAdvanceViewId=");
pw.print(info.autoAdvanceViewId);
pw.print(" initialLayout=#");
pw.print(Integer.toHexString(info.initialLayout));
pw.print(" initialKeyguardLayout=#");
pw.print(Integer.toHexString(info.initialKeyguardLayout));
pw.print(" zombie="); pw.println(provider.zombie);
|
private static void | dumpWidget(com.android.server.appwidget.AppWidgetServiceImpl$Widget widget, int index, java.io.PrintWriter pw)
pw.print(" ["); pw.print(index); pw.print("] id=");
pw.println(widget.appWidgetId);
pw.print(" host=");
pw.println(widget.host.id);
if (widget.provider != null) {
pw.print(" provider="); pw.println(widget.provider.id);
}
if (widget.host != null) {
pw.print(" host.callbacks="); pw.println(widget.host.callbacks);
}
if (widget.views != null) {
pw.print(" views="); pw.println(widget.views);
}
|
private void | ensureGroupStateLoadedLocked(int userId)
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++;
}
}
if (newMemberCount <= 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++;
}
}
clearProvidersAndHostsTagsLocked();
loadGroupWidgetProvidersLocked(newProfileIds);
loadGroupStateLocked(newProfileIds);
|
private com.android.server.appwidget.AppWidgetServiceImpl$Host | findHostByTag(int tag)
if (tag < 0) {
return null;
}
final int hostCount = mHosts.size();
for (int i = 0; i < hostCount; i++) {
Host host = mHosts.get(i);
if (host.tag == tag) {
return host;
}
}
return null;
|
private com.android.server.appwidget.AppWidgetServiceImpl$Provider | findProviderByTag(int tag)
if (tag < 0) {
return null;
}
final int providerCount = mProviders.size();
for (int i = 0; i < providerCount; i++) {
Provider provider = mProviders.get(i);
if (provider.tag == tag) {
return provider;
}
}
return null;
|
public int[] | getAppWidgetIds(android.content.ComponentName componentName)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "getAppWidgetIds() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(componentName.getPackageName());
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can access only its providers.
ProviderId providerId = new ProviderId(Binder.getCallingUid(), componentName);
Provider provider = lookupProviderLocked(providerId);
if (provider != null) {
return getWidgetIds(provider.widgets);
}
return new int[0];
}
|
public int[] | getAppWidgetIdsForHost(java.lang.String callingPackage, int hostId)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "getAppWidgetIdsForHost() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access its hosts.
HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
Host host = lookupHostLocked(id);
if (host != null) {
return getWidgetIds(host.widgets);
}
return new int[0];
}
|
public android.appwidget.AppWidgetProviderInfo | getAppWidgetInfo(java.lang.String callingPackage, int appWidgetId)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "getAppWidgetInfo() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget != null && widget.provider != null && !widget.provider.zombie) {
return cloneIfLocalBinder(widget.provider.info);
}
return null;
}
|
public android.os.Bundle | getAppWidgetOptions(java.lang.String callingPackage, int appWidgetId)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "getAppWidgetOptions() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget != null && widget.options != null) {
return cloneIfLocalBinder(widget.options);
}
return Bundle.EMPTY;
}
|
public android.widget.RemoteViews | getAppWidgetViews(java.lang.String callingPackage, int appWidgetId)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "getAppWidgetViews() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget != null) {
return cloneIfLocalBinder(widget.views);
}
return null;
}
|
private java.lang.String | getCanonicalPackageName(java.lang.String packageName, java.lang.String className, int userId)
final long identity = Binder.clearCallingIdentity();
try {
try {
AppGlobals.getPackageManager().getReceiverInfo(new ComponentName(packageName,
className), 0, userId);
return packageName;
} catch (RemoteException re) {
String[] packageNames = mContext.getPackageManager()
.currentToCanonicalPackageNames(new String[]{packageName});
if (packageNames != null && packageNames.length > 0) {
return packageNames[0];
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
return null;
|
public java.util.List | getInstalledProvidersForProfile(int categoryFilter, int profileId)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "getInstalledProvidersForProfiles() " + userId);
}
// Ensure the profile is in the group and enabled.
if (!mSecurityPolicy.isEnabledGroupProfile(profileId)) {
return null;
}
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
ArrayList<AppWidgetProviderInfo> result = null;
final int providerCount = mProviders.size();
for (int i = 0; i < providerCount; i++) {
Provider provider = mProviders.get(i);
AppWidgetProviderInfo info = provider.info;
// Ignore an invalid provider or one not matching the filter.
if (provider.zombie || (info.widgetCategory & categoryFilter) == 0) {
continue;
}
// Add providers only for the requested profile that are white-listed.
final int providerProfileId = info.getProfile().getIdentifier();
if (providerProfileId == profileId
&& mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed(
provider.id.componentName.getPackageName(), providerProfileId)) {
if (result == null) {
result = new ArrayList<>();
}
result.add(cloneIfLocalBinder(info));
}
}
return result;
}
|
private android.content.pm.ActivityInfo | getProviderInfo(android.content.ComponentName componentName, int userId)
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.setComponent(componentName);
List<ResolveInfo> receivers = queryIntentReceivers(intent, userId);
// We are setting component, so there is only one or none.
if (!receivers.isEmpty()) {
return receivers.get(0).activityInfo;
}
return null;
|
private static android.util.AtomicFile | getSavedStateFile(int userId)
File dir = Environment.getUserSystemDirectory(userId);
File settingsFile = getStateFile(userId);
if (!settingsFile.exists() && userId == UserHandle.USER_OWNER) {
if (!dir.exists()) {
dir.mkdirs();
}
// Migrate old data
File oldFile = new File("/data/system/" + STATE_FILENAME);
// Method doesn't throw an exception on failure. Ignore any errors
// in moving the file (like non-existence)
oldFile.renameTo(settingsFile);
}
return new AtomicFile(settingsFile);
|
private static java.io.File | getStateFile(int userId)
return new File(Environment.getUserSystemDirectory(userId), STATE_FILENAME);
|
private int | getUidForPackage(java.lang.String packageName, int userId)
PackageInfo pkgInfo = null;
final long identity = Binder.clearCallingIdentity();
try {
pkgInfo = mPackageManager.getPackageInfo(packageName, 0, userId);
} catch (RemoteException re) {
// Shouldn't happen, local call
} finally {
Binder.restoreCallingIdentity(identity);
}
if (pkgInfo == null || pkgInfo.applicationInfo == null) {
return -1;
}
return pkgInfo.applicationInfo.uid;
|
private static int[] | getWidgetIds(java.util.ArrayList widgets)
int instancesSize = widgets.size();
int appWidgetIds[] = new int[instancesSize];
for (int i = 0; i < instancesSize; i++) {
appWidgetIds[i] = widgets.get(i).appWidgetId;
}
return appWidgetIds;
|
public java.util.List | getWidgetParticipants(int userId)
return mBackupRestoreController.getWidgetParticipants(userId);
|
public byte[] | getWidgetState(java.lang.String packageName, int userId)
return mBackupRestoreController.getWidgetState(packageName, userId);
|
private void | handleNotifyAppWidgetViewDataChanged(com.android.server.appwidget.AppWidgetServiceImpl$Host host, com.android.internal.appwidget.IAppWidgetHost callbacks, int appWidgetId, int viewId)
try {
callbacks.viewDataChanged(appWidgetId, viewId);
} catch (RemoteException re) {
// It failed; remove the callback. No need to prune because
// we know that this host is still referenced by this instance.
callbacks = null;
}
// If the host is unavailable, then we call the associated
// RemoteViewsFactory.onDataSetChanged() directly
synchronized (mLock) {
if (callbacks == null) {
host.callbacks = null;
Set<Pair<Integer, FilterComparison>> keys = mRemoteViewsServicesAppWidgets.keySet();
for (Pair<Integer, FilterComparison> key : keys) {
if (mRemoteViewsServicesAppWidgets.get(key).contains(appWidgetId)) {
final ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IRemoteViewsFactory cb = IRemoteViewsFactory.Stub
.asInterface(service);
try {
cb.onDataSetChangedAsync();
} catch (RemoteException e) {
Slog.e(TAG, "Error calling onDataSetChangedAsync()", e);
}
mContext.unbindService(this);
}
@Override
public void onServiceDisconnected(android.content.ComponentName name) {
// Do nothing
}
};
final int userId = UserHandle.getUserId(key.first);
Intent intent = key.second.getIntent();
// Bind to the service and call onDataSetChanged()
bindService(intent, connection, new UserHandle(userId));
}
}
}
}
|
private void | handleNotifyProviderChanged(com.android.server.appwidget.AppWidgetServiceImpl$Host host, com.android.internal.appwidget.IAppWidgetHost callbacks, int appWidgetId, android.appwidget.AppWidgetProviderInfo info)
try {
callbacks.providerChanged(appWidgetId, info);
} catch (RemoteException re) {
synchronized (mLock){
Slog.e(TAG, "Widget host dead: " + host.id, re);
host.callbacks = null;
}
}
|
private void | handleNotifyProvidersChanged(com.android.server.appwidget.AppWidgetServiceImpl$Host host, com.android.internal.appwidget.IAppWidgetHost callbacks)
try {
callbacks.providersChanged();
} catch (RemoteException re) {
synchronized (mLock) {
Slog.e(TAG, "Widget host dead: " + host.id, re);
host.callbacks = null;
}
}
|
private void | handleNotifyUpdateAppWidget(com.android.server.appwidget.AppWidgetServiceImpl$Host host, com.android.internal.appwidget.IAppWidgetHost callbacks, int appWidgetId, android.widget.RemoteViews views)
try {
callbacks.updateAppWidget(appWidgetId, views);
} catch (RemoteException re) {
synchronized (mLock) {
Slog.e(TAG, "Widget host dead: " + host.id, re);
host.callbacks = null;
}
}
|
public boolean | hasBindAppWidgetPermission(java.lang.String packageName, int grantId)
if (DEBUG) {
Slog.i(TAG, "hasBindAppWidgetPermission() " + UserHandle.getCallingUserId());
}
// A special permission is required for managing white listing.
mSecurityPolicy.enforceModifyAppWidgetBindPermissions(packageName);
synchronized (mLock) {
// The grants are stored in user state wich gets the grant.
ensureGroupStateLoadedLocked(grantId);
final int packageUid = getUidForPackage(packageName, grantId);
if (packageUid < 0) {
return false;
}
Pair<Integer, String> packageId = Pair.create(grantId, packageName);
return mPackagesWithBindWidgetPermission.contains(packageId);
}
|
private int | incrementAndGetAppWidgetIdLocked(int userId)
final int appWidgetId = peekNextAppWidgetIdLocked(userId) + 1;
mNextAppWidgetIds.put(userId, appWidgetId);
return appWidgetId;
|
private void | incrementAppWidgetServiceRefCount(int appWidgetId, android.util.Pair serviceId)
HashSet<Integer> appWidgetIds = null;
if (mRemoteViewsServicesAppWidgets.containsKey(serviceId)) {
appWidgetIds = mRemoteViewsServicesAppWidgets.get(serviceId);
} else {
appWidgetIds = new HashSet<>();
mRemoteViewsServicesAppWidgets.put(serviceId, appWidgetIds);
}
appWidgetIds.add(appWidgetId);
|
private static boolean | isLocalBinder()
return Process.myPid() == Binder.getCallingPid();
|
private void | loadGroupStateLocked(int[] profileIds)
// We can bind the widgets to host and providers only after
// reading the host and providers for all users since a widget
// can have a host and a provider in different users.
List<LoadedWidgetState> loadedWidgets = new ArrayList<>();
int version = 0;
final int profileIdCount = profileIds.length;
for (int i = 0; i < profileIdCount; i++) {
final int profileId = profileIds[i];
// No file written for this user - nothing to do.
AtomicFile file = getSavedStateFile(profileId);
try {
FileInputStream stream = file.openRead();
version = readProfileStateFromFileLocked(stream, profileId, loadedWidgets);
IoUtils.closeQuietly(stream);
} catch (FileNotFoundException e) {
Slog.w(TAG, "Failed to read state: " + e);
}
}
if (version >= 0) {
// Hooke'm up...
bindLoadedWidgets(loadedWidgets);
// upgrade the database if needed
performUpgradeLocked(version);
} else {
// failed reading, clean up
Slog.w(TAG, "Failed to read state, clearing widgets and hosts.");
mWidgets.clear();
mHosts.clear();
final int N = mProviders.size();
for (int i = 0; i < N; i++) {
mProviders.get(i).widgets.clear();
}
}
|
private void | loadGroupWidgetProvidersLocked(int[] profileIds)
List<ResolveInfo> allReceivers = null;
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
final int profileCount = profileIds.length;
for (int i = 0; i < profileCount; i++) {
final int profileId = profileIds[i];
List<ResolveInfo> receivers = queryIntentReceivers(intent, profileId);
if (receivers != null && !receivers.isEmpty()) {
if (allReceivers == null) {
allReceivers = new ArrayList<>();
}
allReceivers.addAll(receivers);
}
}
final int N = (allReceivers == null) ? 0 : allReceivers.size();
for (int i = 0; i < N; i++) {
ResolveInfo receiver = allReceivers.get(i);
addProviderLocked(receiver);
}
|
private com.android.server.appwidget.AppWidgetServiceImpl$Host | lookupHostLocked(com.android.server.appwidget.AppWidgetServiceImpl$HostId hostId)
final int N = mHosts.size();
for (int i = 0; i < N; i++) {
Host host = mHosts.get(i);
if (host.id.equals(hostId)) {
return host;
}
}
return null;
|
private com.android.server.appwidget.AppWidgetServiceImpl$Host | lookupOrAddHostLocked(com.android.server.appwidget.AppWidgetServiceImpl$HostId id)
Host host = lookupHostLocked(id);
if (host != null) {
return host;
}
host = new Host();
host.id = id;
mHosts.add(host);
return host;
|
private com.android.server.appwidget.AppWidgetServiceImpl$Provider | lookupProviderLocked(com.android.server.appwidget.AppWidgetServiceImpl$ProviderId id)
final int N = mProviders.size();
for (int i = 0; i < N; i++) {
Provider provider = mProviders.get(i);
if (provider.id.equals(id)) {
return provider;
}
}
return null;
|
private com.android.server.appwidget.AppWidgetServiceImpl$Widget | lookupWidgetLocked(int appWidgetId, int uid, java.lang.String packageName)
final int N = mWidgets.size();
for (int i = 0; i < N; i++) {
Widget widget = mWidgets.get(i);
if (widget.appWidgetId == appWidgetId
&& mSecurityPolicy.canAccessAppWidget(widget, uid, packageName)) {
return widget;
}
}
return null;
|
public void | notifyAppWidgetViewDataChanged(java.lang.String callingPackage, int[] appWidgetIds, int viewId)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "notifyAppWidgetViewDataChanged() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
if (appWidgetIds == null || appWidgetIds.length == 0) {
return;
}
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++) {
final int appWidgetId = appWidgetIds[i];
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget != null) {
scheduleNotifyAppWidgetViewDataChanged(widget, viewId);
}
}
}
|
private void | onConfigurationChanged()
if (DEBUG) {
Slog.i(TAG, "onConfigurationChanged()");
}
Locale revised = Locale.getDefault();
if (revised == null || mLocale == null || !revised.equals(mLocale)) {
mLocale = revised;
synchronized (mLock) {
SparseIntArray changedGroups = null;
// Note: updateProvidersForPackageLocked() may remove providers, so we must copy the
// list of installed providers and skip providers that we don't need to update.
// Also note that remove the provider does not clear the Provider component data.
ArrayList<Provider> installedProviders = new ArrayList<>(mProviders);
HashSet<ProviderId> removedProviders = new HashSet<>();
int N = installedProviders.size();
for (int i = N - 1; i >= 0; i--) {
Provider provider = installedProviders.get(i);
ensureGroupStateLoadedLocked(provider.getUserId());
if (!removedProviders.contains(provider.id)) {
final boolean changed = updateProvidersForPackageLocked(
provider.id.componentName.getPackageName(),
provider.getUserId(), removedProviders);
if (changed) {
if (changedGroups == null) {
changedGroups = new SparseIntArray();
}
final int groupId = mSecurityPolicy.getGroupParent(
provider.getUserId());
changedGroups.put(groupId, groupId);
}
}
}
if (changedGroups != null) {
final int groupCount = changedGroups.size();
for (int i = 0; i < groupCount; i++) {
final int groupId = changedGroups.get(i);
saveGroupStateAsync(groupId);
}
}
}
}
|
public void | onCrossProfileWidgetProvidersChanged(int userId, java.util.List packages)
final int parentId = mSecurityPolicy.getProfileParent(userId);
// We care only if the white-listed package is in a profile of
// the group parent as only the parent can add widgets from the
// profile and not the other way around.
if (parentId != userId) {
synchronized (mLock) {
boolean providersChanged = false;
final int packageCount = packages.size();
for (int i = 0; i < packageCount; i++) {
String packageName = packages.get(i);
providersChanged |= updateProvidersForPackageLocked(packageName,
userId, null);
}
if (providersChanged) {
saveGroupStateAsync(userId);
scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
}
}
}
|
private void | onPackageBroadcastReceived(android.content.Intent intent, int userId)
final String action = intent.getAction();
boolean added = false;
boolean changed = false;
boolean componentsModified = false;
String pkgList[] = null;
if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
added = true;
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
added = false;
} else {
Uri uri = intent.getData();
if (uri == null) {
return;
}
String pkgName = uri.getSchemeSpecificPart();
if (pkgName == null) {
return;
}
pkgList = new String[] { pkgName };
added = Intent.ACTION_PACKAGE_ADDED.equals(action);
changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
}
if (pkgList == null || pkgList.length == 0) {
return;
}
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
Bundle extras = intent.getExtras();
if (added || changed) {
final boolean newPackageAdded = added && (extras == null
|| !extras.getBoolean(Intent.EXTRA_REPLACING, false));
for (String pkgName : pkgList) {
// Fix up the providers - add/remove/update.
componentsModified |= updateProvidersForPackageLocked(pkgName, userId, null);
// ... and see if these are hosts we've been awaiting.
// NOTE: We are backing up and restoring only the owner.
if (newPackageAdded && userId == UserHandle.USER_OWNER) {
final int uid = getUidForPackage(pkgName, userId);
if (uid >= 0 ) {
resolveHostUidLocked(pkgName, uid);
}
}
}
} else {
// If the package is being updated, we'll receive a PACKAGE_ADDED
// shortly, otherwise it is removed permanently.
final boolean packageRemovedPermanently = (extras == null
|| !extras.getBoolean(Intent.EXTRA_REPLACING, false));
if (packageRemovedPermanently) {
for (String pkgName : pkgList) {
componentsModified |= removeHostsAndProvidersForPackageLocked(
pkgName, userId);
}
}
}
if (componentsModified) {
saveGroupStateAsync(userId);
// If the set of providers has been modified, notify each active AppWidgetHost
scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
}
}
|
private void | onUserStarted(int userId)
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
final int N = mProviders.size();
for (int i = 0; i < N; i++) {
Provider provider = mProviders.get(i);
// Send broadcast only to the providers of the user.
if (provider.getUserId() != userId) {
continue;
}
if (provider.widgets.size() > 0) {
sendEnableIntentLocked(provider);
int[] appWidgetIds = getWidgetIds(provider.widgets);
sendUpdateIntentLocked(provider, appWidgetIds);
registerForBroadcastsLocked(provider, appWidgetIds);
}
}
}
|
private void | onUserStopped(int userId)
synchronized (mLock) {
boolean providersChanged = false;
boolean crossProfileWidgetsChanged = false;
// Remove widgets that have both host and provider in the user.
final int widgetCount = mWidgets.size();
for (int i = widgetCount - 1; i >= 0; i--) {
Widget widget = mWidgets.get(i);
final boolean hostInUser = widget.host.getUserId() == userId;
final boolean hasProvider = widget.provider != null;
final boolean providerInUser = hasProvider && widget.provider.getUserId() == userId;
// If both host and provider are in the user, just drop the widgets
// as we do not want to make host callbacks and provider broadcasts
// as the host and the provider will be killed.
if (hostInUser && (!hasProvider || providerInUser)) {
mWidgets.remove(i);
widget.host.widgets.remove(widget);
widget.host = null;
if (hasProvider) {
widget.provider.widgets.remove(widget);
widget.provider = null;
}
}
}
// Remove hosts and notify providers in other profiles.
final int hostCount = mHosts.size();
for (int i = hostCount - 1; i >= 0; i--) {
Host host = mHosts.get(i);
if (host.getUserId() == userId) {
crossProfileWidgetsChanged |= !host.widgets.isEmpty();
deleteHostLocked(host);
}
}
// Remove the providers and notify hosts in other profiles.
final int providerCount = mProviders.size();
for (int i = providerCount - 1; i >= 0; i--) {
Provider provider = mProviders.get(i);
if (provider.getUserId() == userId) {
crossProfileWidgetsChanged |= !provider.widgets.isEmpty();
providersChanged = true;
deleteProviderLocked(provider);
}
}
// Remove grants for this user.
final int grantCount = mPackagesWithBindWidgetPermission.size();
for (int i = grantCount - 1; i >= 0; i--) {
Pair<Integer, String> packageId = mPackagesWithBindWidgetPermission.valueAt(i);
if (packageId.first == userId) {
mPackagesWithBindWidgetPermission.removeAt(i);
}
}
// Take a note we no longer have state for this user.
final int userIndex = mLoadedUserIds.indexOfKey(userId);
if (userIndex >= 0) {
mLoadedUserIds.removeAt(userIndex);
}
// Remove the widget id counter.
final int nextIdIndex = mNextAppWidgetIds.indexOfKey(userId);
if (nextIdIndex >= 0) {
mNextAppWidgetIds.removeAt(nextIdIndex);
}
// Announce removed provider changes to all hosts in the group.
if (providersChanged) {
scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
}
// Save state if removing a profile changed the group state.
// Nothing will be saved if the group parent was removed.
if (crossProfileWidgetsChanged) {
saveGroupStateAsync(userId);
}
}
|
private com.android.server.appwidget.AppWidgetServiceImpl$Provider | parseProviderInfoXml(com.android.server.appwidget.AppWidgetServiceImpl$ProviderId providerId, android.content.pm.ResolveInfo ri)
Provider provider = null;
ActivityInfo activityInfo = ri.activityInfo;
XmlResourceParser parser = null;
try {
parser = activityInfo.loadXmlMetaData(mContext.getPackageManager(),
AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
if (parser == null) {
Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER
+ " meta-data for " + "AppWidget provider '" + providerId + '\'");
return null;
}
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
// drain whitespace, comments, etc.
}
String nodeName = parser.getName();
if (!"appwidget-provider".equals(nodeName)) {
Slog.w(TAG, "Meta-data does not start with appwidget-provider tag for"
+ " AppWidget provider " + providerId.componentName
+ " for user " + providerId.uid);
return null;
}
provider = new Provider();
provider.id = providerId;
AppWidgetProviderInfo info = provider.info = new AppWidgetProviderInfo();
info.provider = providerId.componentName;
info.providerInfo = activityInfo;
final Resources resources;
final long identity = Binder.clearCallingIdentity();
try {
resources = mContext.getPackageManager()
.getResourcesForApplicationAsUser(activityInfo.packageName,
UserHandle.getUserId(providerId.uid));
} finally {
Binder.restoreCallingIdentity(identity);
}
TypedArray sa = resources.obtainAttributes(attrs,
com.android.internal.R.styleable.AppWidgetProviderInfo);
// These dimensions has to be resolved in the application's context.
// We simply send back the raw complex data, which will be
// converted to dp in {@link AppWidgetManager#getAppWidgetInfo}.
TypedValue value = sa
.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minWidth);
info.minWidth = value != null ? value.data : 0;
value = sa.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight);
info.minHeight = value != null ? value.data : 0;
value = sa.peekValue(
com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeWidth);
info.minResizeWidth = value != null ? value.data : info.minWidth;
value = sa.peekValue(
com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeHeight);
info.minResizeHeight = value != null ? value.data : info.minHeight;
info.updatePeriodMillis = sa.getInt(
com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0);
info.initialLayout = sa.getResourceId(
com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, 0);
info.initialKeyguardLayout = sa.getResourceId(com.android.internal.R.styleable.
AppWidgetProviderInfo_initialKeyguardLayout, 0);
String className = sa
.getString(com.android.internal.R.styleable.AppWidgetProviderInfo_configure);
if (className != null) {
info.configure = new ComponentName(providerId.componentName.getPackageName(),
className);
}
info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString();
info.icon = ri.getIconResource();
info.previewImage = sa.getResourceId(
com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
info.autoAdvanceViewId = sa.getResourceId(
com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId, -1);
info.resizeMode = sa.getInt(
com.android.internal.R.styleable.AppWidgetProviderInfo_resizeMode,
AppWidgetProviderInfo.RESIZE_NONE);
info.widgetCategory = sa.getInt(
com.android.internal.R.styleable.AppWidgetProviderInfo_widgetCategory,
AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
sa.recycle();
} catch (IOException | PackageManager.NameNotFoundException | XmlPullParserException e) {
// Ok to catch Exception here, because anything going wrong because
// of what a client process passes to us should not be fatal for the
// system process.
Slog.w(TAG, "XML parsing failed for AppWidget provider "
+ providerId.componentName + " for user " + providerId.uid, e);
return null;
} finally {
if (parser != null) {
parser.close();
}
}
return provider;
|
public void | partiallyUpdateAppWidgetIds(java.lang.String callingPackage, int[] appWidgetIds, android.widget.RemoteViews views)
if (DEBUG) {
Slog.i(TAG, "partiallyUpdateAppWidgetIds() " + UserHandle.getCallingUserId());
}
updateAppWidgetIds(callingPackage, appWidgetIds, views, true);
|
private int | peekNextAppWidgetIdLocked(int userId)
if (mNextAppWidgetIds.indexOfKey(userId) < 0) {
return AppWidgetManager.INVALID_APPWIDGET_ID + 1;
} else {
return mNextAppWidgetIds.get(userId);
}
|
private void | performUpgradeLocked(int fromVersion)
if (fromVersion < CURRENT_VERSION) {
Slog.v(TAG, "Upgrading widget database from " + fromVersion + " to "
+ CURRENT_VERSION);
}
int version = fromVersion;
// Update 1: keyguard moved from package "android" to "com.android.keyguard"
if (version == 0) {
HostId oldHostId = new HostId(Process.myUid(),
KEYGUARD_HOST_ID, OLD_KEYGUARD_HOST_PACKAGE);
Host host = lookupHostLocked(oldHostId);
if (host != null) {
final int uid = getUidForPackage(NEW_KEYGUARD_HOST_PACKAGE,
UserHandle.USER_OWNER);
if (uid >= 0) {
host.id = new HostId(uid, KEYGUARD_HOST_ID, NEW_KEYGUARD_HOST_PACKAGE);
}
}
version = 1;
}
if (version != CURRENT_VERSION) {
throw new IllegalStateException("Failed to upgrade widget database");
}
|
private void | pruneHostLocked(com.android.server.appwidget.AppWidgetServiceImpl$Host host)
if (host.widgets.size() == 0 && host.callbacks == null) {
if (DEBUG) {
Slog.i(TAG, "Pruning host " + host.id);
}
mHosts.remove(host);
}
|
private java.util.List | queryIntentReceivers(android.content.Intent intent, int userId)
final long identity = Binder.clearCallingIdentity();
try {
int flags = PackageManager.GET_META_DATA;
// Widgets referencing shared libraries need to have their
// dependencies loaded.
flags |= PackageManager.GET_SHARED_LIBRARY_FILES;
return mPackageManager.queryIntentReceivers(intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags, userId);
} catch (RemoteException re) {
return Collections.emptyList();
} finally {
Binder.restoreCallingIdentity(identity);
}
|
private int | readProfileStateFromFileLocked(java.io.FileInputStream stream, int userId, java.util.List outLoadedWidgets)
int version = -1;
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(stream, null);
int legacyProviderIndex = -1;
int legacyHostIndex = -1;
int type;
do {
type = parser.next();
if (type == XmlPullParser.START_TAG) {
String tag = parser.getName();
if ("gs".equals(tag)) {
String attributeValue = parser.getAttributeValue(null, "version");
try {
version = Integer.parseInt(attributeValue);
} catch (NumberFormatException e) {
version = 0;
}
} else if ("p".equals(tag)) {
legacyProviderIndex++;
// TODO: do we need to check that this package has the same signature
// as before?
String pkg = parser.getAttributeValue(null, "pkg");
String cl = parser.getAttributeValue(null, "cl");
pkg = getCanonicalPackageName(pkg, cl, userId);
if (pkg == null) {
continue;
}
final int uid = getUidForPackage(pkg, userId);
if (uid < 0) {
continue;
}
ComponentName componentName = new ComponentName(pkg, cl);
ActivityInfo providerInfo = getProviderInfo(componentName, userId);
if (providerInfo == null) {
continue;
}
ProviderId providerId = new ProviderId(uid, componentName);
Provider provider = lookupProviderLocked(providerId);
if (provider == null && mSafeMode) {
// if we're in safe mode, make a temporary one
provider = new Provider();
provider.info = new AppWidgetProviderInfo();
provider.info.provider = providerId.componentName;
provider.info.providerInfo = providerInfo;
provider.zombie = true;
provider.id = providerId;
mProviders.add(provider);
}
String tagAttribute = parser.getAttributeValue(null, "tag");
final int providerTag = !TextUtils.isEmpty(tagAttribute)
? Integer.parseInt(tagAttribute, 16) : legacyProviderIndex;
provider.tag = providerTag;
} else if ("h".equals(tag)) {
legacyHostIndex++;
Host host = new Host();
// TODO: do we need to check that this package has the same signature
// as before?
String pkg = parser.getAttributeValue(null, "pkg");
final int uid = getUidForPackage(pkg, userId);
if (uid < 0) {
host.zombie = true;
}
if (!host.zombie || mSafeMode) {
// In safe mode, we don't discard the hosts we don't recognize
// so that they're not pruned from our list. Otherwise, we do.
final int hostId = Integer.parseInt(parser.getAttributeValue(
null, "id"), 16);
String tagAttribute = parser.getAttributeValue(null, "tag");
final int hostTag = !TextUtils.isEmpty(tagAttribute)
? Integer.parseInt(tagAttribute, 16) : legacyHostIndex;
host.tag = hostTag;
host.id = new HostId(uid, hostId, pkg);
mHosts.add(host);
}
} else if ("b".equals(tag)) {
String packageName = parser.getAttributeValue(null, "packageName");
final int uid = getUidForPackage(packageName, userId);
if (uid >= 0) {
Pair<Integer, String> packageId = Pair.create(userId, packageName);
mPackagesWithBindWidgetPermission.add(packageId);
}
} else if ("g".equals(tag)) {
Widget widget = new Widget();
widget.appWidgetId = Integer.parseInt(parser.getAttributeValue(
null, "id"), 16);
setMinAppWidgetIdLocked(userId, widget.appWidgetId + 1);
// restored ID is allowed to be absent
String restoredIdString = parser.getAttributeValue(null, "rid");
widget.restoredId = (restoredIdString == null) ? 0
: Integer.parseInt(restoredIdString, 16);
Bundle options = new Bundle();
String minWidthString = parser.getAttributeValue(null, "min_width");
if (minWidthString != null) {
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
Integer.parseInt(minWidthString, 16));
}
String minHeightString = parser.getAttributeValue(null, "min_height");
if (minHeightString != null) {
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
Integer.parseInt(minHeightString, 16));
}
String maxWidthString = parser.getAttributeValue(null, "max_width");
if (maxWidthString != null) {
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
Integer.parseInt(maxWidthString, 16));
}
String maxHeightString = parser.getAttributeValue(null, "max_height");
if (maxHeightString != null) {
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
Integer.parseInt(maxHeightString, 16));
}
String categoryString = parser.getAttributeValue(null, "host_category");
if (categoryString != null) {
options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
Integer.parseInt(categoryString, 16));
}
widget.options = options;
final int hostTag = Integer.parseInt(parser.getAttributeValue(
null, "h"), 16);
String providerString = parser.getAttributeValue(null, "p");
final int providerTag = (providerString != null) ? Integer.parseInt(
parser.getAttributeValue(null, "p"), 16) : TAG_UNDEFINED;
// We can match widgets with hosts and providers only after hosts
// and providers for all users have been loaded since the widget
// host and provider can be in different user profiles.
LoadedWidgetState loadedWidgets = new LoadedWidgetState(widget,
hostTag, providerTag);
outLoadedWidgets.add(loadedWidgets);
}
}
} while (type != XmlPullParser.END_DOCUMENT);
} catch (NullPointerException
| NumberFormatException
| XmlPullParserException
| IOException
| IndexOutOfBoundsException e) {
Slog.w(TAG, "failed parsing " + e);
return -1;
}
return version;
|
private void | registerBroadcastReceiver()
// Register for configuration changes so we can update the names
// of the widgets when the locale changes.
IntentFilter configFilter = new IntentFilter();
configFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
configFilter, null, null);
// Register for broadcasts about package install, etc., so we can
// update the provider list.
IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
packageFilter.addDataScheme("package");
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
packageFilter, null, null);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
sdFilter, null, null);
IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_STARTED);
userFilter.addAction(Intent.ACTION_USER_STOPPED);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
userFilter, null, null);
|
private void | registerForBroadcastsLocked(com.android.server.appwidget.AppWidgetServiceImpl$Provider provider, int[] appWidgetIds)
if (provider.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);
long token = Binder.clearCallingIdentity();
try {
provider.broadcast = PendingIntent.getBroadcastAsUser(mContext, 1, intent,
PendingIntent.FLAG_UPDATE_CURRENT, provider.info.getProfile());
} finally {
Binder.restoreCallingIdentity(token);
}
if (!alreadyRegistered) {
long period = provider.info.updatePeriodMillis;
if (period < MIN_UPDATE_PERIOD) {
period = MIN_UPDATE_PERIOD;
}
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + period, period, provider.broadcast);
}
}
|
private void | registerOnCrossProfileProvidersChangedListener()
DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
DevicePolicyManagerInternal.class);
// The device policy is an optional component.
if (devicePolicyManager != null) {
devicePolicyManager.addOnCrossProfileWidgetProvidersChangeListener(this);
}
|
private boolean | removeHostsAndProvidersForPackageLocked(java.lang.String pkgName, int userId)
boolean removed = false;
int N = mProviders.size();
for (int i = N - 1; i >= 0; i--) {
Provider provider = mProviders.get(i);
if (pkgName.equals(provider.info.provider.getPackageName())
&& provider.getUserId() == userId) {
deleteProviderLocked(provider);
removed = true;
}
}
// Delete the hosts for this package too
// By now, we have removed any AppWidgets that were in any hosts here,
// so we don't need to worry about sending DISABLE broadcasts to them.
N = mHosts.size();
for (int i = N - 1; i >= 0; i--) {
Host host = mHosts.get(i);
if (pkgName.equals(host.id.packageName)
&& host.getUserId() == userId) {
deleteHostLocked(host);
removed = true;
}
}
return removed;
|
private void | resolveHostUidLocked(java.lang.String pkg, int uid)
final int N = mHosts.size();
for (int i = 0; i < N; i++) {
Host host = mHosts.get(i);
if (host.id.uid == UNKNOWN_UID && pkg.equals(host.id.packageName)) {
if (DEBUG) {
Slog.i(TAG, "host " + host.id + " resolved to uid " + uid);
}
host.id = new HostId(uid, host.id.hostId, host.id.packageName);
return;
}
}
|
public void | restoreFinished(int userId)
mBackupRestoreController.restoreFinished(userId);
|
public void | restoreStarting(int userId)
mBackupRestoreController.restoreStarting(userId);
|
public void | restoreWidgetState(java.lang.String packageName, byte[] restoredState, int userId)
mBackupRestoreController.restoreWidgetState(packageName, restoredState, userId);
|
private void | saveGroupStateAsync(int groupId)
mSaveStateHandler.post(new SaveStateRunnable(groupId));
|
private void | saveStateLocked(int userId)
tagProvidersAndHosts();
final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId);
final int profileCount = profileIds.length;
for (int i = 0; i < profileCount; i++) {
final int profileId = profileIds[i];
AtomicFile file = getSavedStateFile(profileId);
FileOutputStream stream;
try {
stream = file.startWrite();
if (writeProfileStateToFileLocked(stream, profileId)) {
file.finishWrite(stream);
} else {
file.failWrite(stream);
Slog.w(TAG, "Failed to save state, restoring backup.");
}
} catch (IOException e) {
Slog.w(TAG, "Failed open state file for write: " + e);
}
}
|
private void | scheduleNotifyAppWidgetViewDataChanged(com.android.server.appwidget.AppWidgetServiceImpl$Widget widget, int viewId)
if (widget == null || widget.host == null || widget.host.zombie
|| widget.host.callbacks == null || widget.provider == null
|| widget.provider.zombie) {
return;
}
SomeArgs args = SomeArgs.obtain();
args.arg1 = widget.host;
args.arg2 = widget.host.callbacks;
args.argi1 = widget.appWidgetId;
args.argi2 = viewId;
mCallbackHandler.obtainMessage(
CallbackHandler.MSG_NOTIFY_VIEW_DATA_CHANGED,
args).sendToTarget();
|
private void | scheduleNotifyGroupHostsForProvidersChangedLocked(int userId)
final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId);
final int N = mHosts.size();
for (int i = N - 1; i >= 0; i--) {
Host host = mHosts.get(i);
boolean hostInGroup = false;
final int M = profileIds.length;
for (int j = 0; j < M; j++) {
final int profileId = profileIds[j];
if (host.getUserId() == profileId) {
hostInGroup = true;
break;
}
}
if (!hostInGroup) {
continue;
}
if (host == null || host.zombie || host.callbacks == null) {
continue;
}
SomeArgs args = SomeArgs.obtain();
args.arg1 = host;
args.arg2 = host.callbacks;
mCallbackHandler.obtainMessage(
CallbackHandler.MSG_NOTIFY_PROVIDERS_CHANGED,
args).sendToTarget();
}
|
private void | scheduleNotifyProviderChangedLocked(com.android.server.appwidget.AppWidgetServiceImpl$Widget widget)
if (widget == null || widget.provider == null || widget.provider.zombie
|| widget.host.callbacks == null || widget.host.zombie) {
return;
}
SomeArgs args = SomeArgs.obtain();
args.arg1 = widget.host;
args.arg2 = widget.host.callbacks;
args.arg3 = widget.provider.info;
args.argi1 = widget.appWidgetId;
mCallbackHandler.obtainMessage(
CallbackHandler.MSG_NOTIFY_PROVIDER_CHANGED,
args).sendToTarget();
|
private void | scheduleNotifyUpdateAppWidgetLocked(com.android.server.appwidget.AppWidgetServiceImpl$Widget widget, android.widget.RemoteViews updateViews)
if (widget == null || widget.provider == null || widget.provider.zombie
|| widget.host.callbacks == null || widget.host.zombie) {
return;
}
SomeArgs args = SomeArgs.obtain();
args.arg1 = widget.host;
args.arg2 = widget.host.callbacks;
args.arg3 = updateViews;
args.argi1 = widget.appWidgetId;
mCallbackHandler.obtainMessage(
CallbackHandler.MSG_NOTIFY_UPDATE_APP_WIDGET,
args).sendToTarget();
|
private void | sendBroadcastAsUser(android.content.Intent intent, android.os.UserHandle userHandle)
final long identity = Binder.clearCallingIdentity();
try {
mContext.sendBroadcastAsUser(intent, userHandle);
} finally {
Binder.restoreCallingIdentity(identity);
}
|
private void | sendDeletedIntentLocked(com.android.server.appwidget.AppWidgetServiceImpl$Widget widget)
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED);
intent.setComponent(widget.provider.info.provider);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId);
sendBroadcastAsUser(intent, widget.provider.info.getProfile());
|
private void | sendDisabledIntentLocked(com.android.server.appwidget.AppWidgetServiceImpl$Provider provider)
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED);
intent.setComponent(provider.info.provider);
sendBroadcastAsUser(intent, provider.info.getProfile());
|
private void | sendEnableIntentLocked(com.android.server.appwidget.AppWidgetServiceImpl$Provider p)
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED);
intent.setComponent(p.info.provider);
sendBroadcastAsUser(intent, p.info.getProfile());
|
public void | sendOptionsChangedIntentLocked(com.android.server.appwidget.AppWidgetServiceImpl$Widget widget)
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED);
intent.setComponent(widget.provider.info.provider);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, widget.options);
sendBroadcastAsUser(intent, widget.provider.info.getProfile());
|
private void | sendUpdateIntentLocked(com.android.server.appwidget.AppWidgetServiceImpl$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());
|
private static void | serializeAppWidget(org.xmlpull.v1.XmlSerializer out, com.android.server.appwidget.AppWidgetServiceImpl$Widget widget)
out.startTag(null, "g");
out.attribute(null, "id", Integer.toHexString(widget.appWidgetId));
out.attribute(null, "rid", Integer.toHexString(widget.restoredId));
out.attribute(null, "h", Integer.toHexString(widget.host.tag));
if (widget.provider != null) {
out.attribute(null, "p", Integer.toHexString(widget.provider.tag));
}
if (widget.options != null) {
out.attribute(null, "min_width", Integer.toHexString(widget.options.getInt(
AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)));
out.attribute(null, "min_height", Integer.toHexString(widget.options.getInt(
AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)));
out.attribute(null, "max_width", Integer.toHexString(widget.options.getInt(
AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)));
out.attribute(null, "max_height", Integer.toHexString(widget.options.getInt(
AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)));
out.attribute(null, "host_category", Integer.toHexString(widget.options.getInt(
AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)));
}
out.endTag(null, "g");
|
private static void | serializeHost(org.xmlpull.v1.XmlSerializer out, com.android.server.appwidget.AppWidgetServiceImpl$Host host)
out.startTag(null, "h");
out.attribute(null, "pkg", host.id.packageName);
out.attribute(null, "id", Integer.toHexString(host.id.hostId));
out.attribute(null, "tag", Integer.toHexString(host.tag));
out.endTag(null, "h");
|
private static void | serializeProvider(org.xmlpull.v1.XmlSerializer out, com.android.server.appwidget.AppWidgetServiceImpl$Provider p)
out.startTag(null, "p");
out.attribute(null, "pkg", p.info.provider.getPackageName());
out.attribute(null, "cl", p.info.provider.getClassName());
out.attribute(null, "tag", Integer.toHexString(p.tag));
out.endTag(null, "p");
|
public void | setBindAppWidgetPermission(java.lang.String packageName, int grantId, boolean grantPermission)
if (DEBUG) {
Slog.i(TAG, "setBindAppWidgetPermission() " + UserHandle.getCallingUserId());
}
// A special permission is required for managing white listing.
mSecurityPolicy.enforceModifyAppWidgetBindPermissions(packageName);
synchronized (mLock) {
// The grants are stored in user state wich gets the grant.
ensureGroupStateLoadedLocked(grantId);
final int packageUid = getUidForPackage(packageName, grantId);
if (packageUid < 0) {
return;
}
Pair<Integer, String> packageId = Pair.create(grantId, packageName);
if (grantPermission) {
mPackagesWithBindWidgetPermission.add(packageId);
} else {
mPackagesWithBindWidgetPermission.remove(packageId);
}
saveGroupStateAsync(grantId);
}
|
private void | setMinAppWidgetIdLocked(int userId, int minWidgetId)
final int nextAppWidgetId = peekNextAppWidgetIdLocked(userId);
if (nextAppWidgetId < minWidgetId) {
mNextAppWidgetIds.put(userId, minWidgetId);
}
|
public void | setSafeMode(boolean safeMode)
mSafeMode = safeMode;
|
public int[] | startListening(com.android.internal.appwidget.IAppWidgetHost callbacks, java.lang.String callingPackage, int hostId, java.util.List updatedViews)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "startListening() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// 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];
for (int i = 0; i < N; i++) {
Widget widget = instances.get(i);
updatedIds[i] = widget.appWidgetId;
updatedViews.add(cloneIfLocalBinder(widget.views));
}
return updatedIds;
}
|
public void | stopListening(java.lang.String callingPackage, int hostId)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "stopListening() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access hosts it owns.
HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
Host host = lookupHostLocked(id);
if (host != null) {
host.callbacks = null;
pruneHostLocked(host);
}
}
|
private void | tagProvidersAndHosts()
final int providerCount = mProviders.size();
for (int i = 0; i < providerCount; i++) {
Provider provider = mProviders.get(i);
provider.tag = i;
}
final int hostCount = mHosts.size();
for (int i = 0; i < hostCount; i++) {
Host host = mHosts.get(i);
host.tag = i;
}
|
private void | unbindAppWidgetRemoteViewsServicesLocked(com.android.server.appwidget.AppWidgetServiceImpl$Widget widget)
int appWidgetId = widget.appWidgetId;
// Unbind all connections to Services bound to this AppWidgetId
Iterator<Pair<Integer, Intent.FilterComparison>> it = mBoundRemoteViewsServices.keySet()
.iterator();
while (it.hasNext()) {
final Pair<Integer, Intent.FilterComparison> key = it.next();
if (key.first == appWidgetId) {
final ServiceConnectionProxy conn = (ServiceConnectionProxy)
mBoundRemoteViewsServices.get(key);
conn.disconnect();
mContext.unbindService(conn);
it.remove();
}
}
// Check if we need to destroy any services (if no other app widgets are
// referencing the same service)
decrementAppWidgetServiceRefCount(widget);
|
public void | unbindRemoteViewsService(java.lang.String callingPackage, int appWidgetId, android.content.Intent intent)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "unbindRemoteViewsService() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// 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)) {
// 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.
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget == null) {
throw new IllegalArgumentException("Bad widget id " + appWidgetId);
}
ServiceConnectionProxy connection = (ServiceConnectionProxy)
mBoundRemoteViewsServices.get(key);
connection.disconnect();
mContext.unbindService(connection);
mBoundRemoteViewsServices.remove(key);
}
}
|
private void | unbindService(android.content.ServiceConnection connection)
final long token = Binder.clearCallingIdentity();
try {
mContext.unbindService(connection);
} finally {
Binder.restoreCallingIdentity(token);
}
|
public void | updateAppWidgetIds(java.lang.String callingPackage, int[] appWidgetIds, android.widget.RemoteViews views)
if (DEBUG) {
Slog.i(TAG, "updateAppWidgetIds() " + UserHandle.getCallingUserId());
}
updateAppWidgetIds(callingPackage, appWidgetIds, views, false);
|
private void | updateAppWidgetIds(java.lang.String callingPackage, int[] appWidgetIds, android.widget.RemoteViews views, boolean partially)
final int userId = UserHandle.getCallingUserId();
if (appWidgetIds == null || appWidgetIds.length == 0) {
return;
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
final int bitmapMemoryUsage = (views != null) ? views.estimateMemoryUsage() : 0;
if (bitmapMemoryUsage > mMaxWidgetBitmapMemory) {
throw new IllegalArgumentException("RemoteViews for widget update exceeds"
+ " maximum bitmap memory usage (used: " + bitmapMemoryUsage
+ ", max: " + mMaxWidgetBitmapMemory + ")");
}
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++) {
final int appWidgetId = appWidgetIds[i];
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget != null) {
updateAppWidgetInstanceLocked(widget, views, partially);
}
}
}
|
private void | updateAppWidgetInstanceLocked(com.android.server.appwidget.AppWidgetServiceImpl$Widget widget, android.widget.RemoteViews views, boolean isPartialUpdate)
if (widget != null && widget.provider != null
&& !widget.provider.zombie && !widget.host.zombie) {
if (isPartialUpdate && widget.views != null) {
// For a partial update, we merge the new RemoteViews with the old.
widget.views.mergeRemoteViews(views);
} else {
// For a full update we replace the RemoteViews completely.
widget.views = views;
}
scheduleNotifyUpdateAppWidgetLocked(widget, views);
}
|
public void | updateAppWidgetOptions(java.lang.String callingPackage, int appWidgetId, android.os.Bundle options)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "updateAppWidgetOptions() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access widgets it hosts or provides.
Widget widget = lookupWidgetLocked(appWidgetId,
Binder.getCallingUid(), callingPackage);
if (widget == null) {
return;
}
// Merge the options.
widget.options.putAll(options);
// Send the broacast to notify the provider that options changed.
sendOptionsChangedIntentLocked(widget);
saveGroupStateAsync(userId);
}
|
public void | updateAppWidgetProvider(android.content.ComponentName componentName, android.widget.RemoteViews views)
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "updateAppWidgetProvider() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(componentName.getPackageName());
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can access only its providers.
ProviderId providerId = new ProviderId(Binder.getCallingUid(), componentName);
Provider provider = lookupProviderLocked(providerId);
if (provider == null) {
Slog.w(TAG, "Provider doesn't exist " + providerId);
return;
}
ArrayList<Widget> instances = provider.widgets;
final int N = instances.size();
for (int i = 0; i < N; i++) {
Widget widget = instances.get(i);
updateAppWidgetInstanceLocked(widget, views, false);
}
}
|
private boolean | updateProvidersForPackageLocked(java.lang.String packageName, int userId, java.util.Set removedProviders)Updates all providers with the specified package names, and records any providers that were
pruned.
boolean providersUpdated = false;
HashSet<ProviderId> keep = new HashSet<>();
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.setPackage(packageName);
List<ResolveInfo> broadcastReceivers = queryIntentReceivers(intent, userId);
// add the missing ones and collect which ones to keep
int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
for (int i = 0; i < N; i++) {
ResolveInfo ri = broadcastReceivers.get(i);
ActivityInfo ai = ri.activityInfo;
if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
continue;
}
if (packageName.equals(ai.packageName)) {
ProviderId providerId = new ProviderId(ai.applicationInfo.uid,
new ComponentName(ai.packageName, ai.name));
Provider provider = lookupProviderLocked(providerId);
if (provider == null) {
if (addProviderLocked(ri)) {
keep.add(providerId);
providersUpdated = true;
}
} else {
Provider parsed = parseProviderInfoXml(providerId, ri);
if (parsed != null) {
keep.add(providerId);
// Use the new AppWidgetProviderInfo.
provider.info = parsed.info;
// If it's enabled
final int M = provider.widgets.size();
if (M > 0) {
int[] appWidgetIds = getWidgetIds(provider.widgets);
// Reschedule for the new updatePeriodMillis (don't worry about handling
// it specially if updatePeriodMillis didn't change because we just sent
// an update, and the next one will be updatePeriodMillis from now).
cancelBroadcasts(provider);
registerForBroadcastsLocked(provider, appWidgetIds);
// If it's currently showing, call back with the new
// AppWidgetProviderInfo.
for (int j = 0; j < M; j++) {
Widget widget = provider.widgets.get(j);
widget.views = null;
scheduleNotifyProviderChangedLocked(widget);
}
// Now that we've told the host, push out an update.
sendUpdateIntentLocked(provider, appWidgetIds);
providersUpdated = true;
}
}
}
}
}
// prune the ones we don't want to keep
N = mProviders.size();
for (int i = N - 1; i >= 0; i--) {
Provider provider = mProviders.get(i);
if (packageName.equals(provider.info.provider.getPackageName())
&& provider.getUserId() == userId
&& !keep.contains(provider.id)) {
if (removedProviders != null) {
removedProviders.add(provider.id);
}
deleteProviderLocked(provider);
providersUpdated = true;
}
}
return providersUpdated;
|
private boolean | writeProfileStateToFileLocked(java.io.FileOutputStream stream, int userId)
int N;
try {
XmlSerializer out = new FastXmlSerializer();
out.setOutput(stream, "utf-8");
out.startDocument(null, true);
out.startTag(null, "gs");
out.attribute(null, "version", String.valueOf(CURRENT_VERSION));
N = mProviders.size();
for (int i = 0; i < N; i++) {
Provider provider = mProviders.get(i);
// Save only providers for the user.
if (provider.getUserId() != userId) {
continue;
}
if (provider.widgets.size() > 0) {
serializeProvider(out, provider);
}
}
N = mHosts.size();
for (int i = 0; i < N; i++) {
Host host = mHosts.get(i);
// Save only hosts for the user.
if (host.getUserId() != userId) {
continue;
}
serializeHost(out, host);
}
N = mWidgets.size();
for (int i = 0; i < N; i++) {
Widget widget = mWidgets.get(i);
// Save only widgets hosted by the user.
if (widget.host.getUserId() != userId) {
continue;
}
serializeAppWidget(out, widget);
}
Iterator<Pair<Integer, String>> it = mPackagesWithBindWidgetPermission.iterator();
while (it.hasNext()) {
Pair<Integer, String> binding = it.next();
// Save only white listings for the user.
if (binding.first != userId) {
continue;
}
out.startTag(null, "b");
out.attribute(null, "packageName", binding.second);
out.endTag(null, "b");
}
out.endTag(null, "gs");
out.endDocument();
return true;
} catch (IOException e) {
Slog.w(TAG, "Failed to write state: " + e);
return false;
}
|