/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server; import android.app.ActivityManager; import android.appwidget.AppWidgetProviderInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.util.Slog; import android.util.SparseArray; import android.widget.RemoteViews; import com.android.internal.appwidget.IAppWidgetHost; import com.android.internal.appwidget.IAppWidgetService; import com.android.internal.os.BackgroundThread; import com.android.internal.util.IndentingPrintWriter; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.List; import java.util.Locale; /** * Redirects calls to this service to the instance of the service for the appropriate user. */ class AppWidgetService extends IAppWidgetService.Stub { private static final String TAG = "AppWidgetService"; Context mContext; Locale mLocale; PackageManager mPackageManager; boolean mSafeMode; private final Handler mSaveStateHandler; private final SparseArray mAppWidgetServices; AppWidgetService(Context context) { mContext = context; mSaveStateHandler = BackgroundThread.getHandler(); mAppWidgetServices = new SparseArray(5); AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0, mSaveStateHandler); mAppWidgetServices.append(0, primary); } public void systemRunning(boolean safeMode) { mSafeMode = safeMode; mAppWidgetServices.get(0).systemReady(safeMode); // Register for the boot completed broadcast, so we can send the // ENABLE broacasts. If we try to send them now, they time out, // because the system isn't ready to handle them yet. mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); // Register for configuration changes so we can update the names // of the widgets when the locale changes. mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, null); // Register for broadcasts about package install, etc., so we can // update the provider list. IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, 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_REMOVED); userFilter.addAction(Intent.ACTION_USER_STOPPING); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL)); } else if (Intent.ACTION_USER_STOPPING.equals(intent.getAction())) { onUserStopping(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL)); } } }, userFilter); } @Override public int allocateAppWidgetId(String packageName, int hostId, int userId) throws RemoteException { return getImplForUser(userId).allocateAppWidgetId(packageName, hostId); } @Override public int[] getAppWidgetIdsForHost(int hostId, int userId) throws RemoteException { return getImplForUser(userId).getAppWidgetIdsForHost(hostId); } @Override public void deleteAppWidgetId(int appWidgetId, int userId) throws RemoteException { getImplForUser(userId).deleteAppWidgetId(appWidgetId); } @Override public void deleteHost(int hostId, int userId) throws RemoteException { getImplForUser(userId).deleteHost(hostId); } @Override public void deleteAllHosts(int userId) throws RemoteException { getImplForUser(userId).deleteAllHosts(); } @Override public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options, int userId) throws RemoteException { getImplForUser(userId).bindAppWidgetId(appWidgetId, provider, options); } @Override public boolean bindAppWidgetIdIfAllowed( String packageName, int appWidgetId, ComponentName provider, Bundle options, int userId) throws RemoteException { return getImplForUser(userId).bindAppWidgetIdIfAllowed( packageName, appWidgetId, provider, options); } @Override public boolean hasBindAppWidgetPermission(String packageName, int userId) throws RemoteException { return getImplForUser(userId).hasBindAppWidgetPermission(packageName); } @Override public void setBindAppWidgetPermission(String packageName, boolean permission, int userId) throws RemoteException { getImplForUser(userId).setBindAppWidgetPermission(packageName, permission); } @Override public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection, int userId) throws RemoteException { getImplForUser(userId).bindRemoteViewsService(appWidgetId, intent, connection); } @Override public int[] startListening(IAppWidgetHost host, String packageName, int hostId, List updatedViews, int userId) throws RemoteException { return getImplForUser(userId).startListening(host, packageName, hostId, updatedViews); } public void onUserRemoved(int userId) { if (userId < 1) return; synchronized (mAppWidgetServices) { AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); mAppWidgetServices.remove(userId); if (impl == null) { AppWidgetServiceImpl.getSettingsFile(userId).delete(); } else { impl.onUserRemoved(); } } } public void onUserStopping(int userId) { if (userId < 1) return; synchronized (mAppWidgetServices) { AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); if (impl != null) { mAppWidgetServices.remove(userId); impl.onUserStopping(); } } } private void checkPermission(int userId) { int realUserId = ActivityManager.handleIncomingUser( Binder.getCallingPid(), Binder.getCallingUid(), userId, false, /* allowAll */ true, /* requireFull */ this.getClass().getSimpleName(), this.getClass().getPackage().getName()); } private AppWidgetServiceImpl getImplForUser(int userId) { checkPermission(userId); boolean sendInitial = false; AppWidgetServiceImpl service; synchronized (mAppWidgetServices) { service = mAppWidgetServices.get(userId); if (service == null) { Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + ", adding"); // TODO: Verify that it's a valid user service = new AppWidgetServiceImpl(mContext, userId, mSaveStateHandler); service.systemReady(mSafeMode); // Assume that BOOT_COMPLETED was received, as this is a non-primary user. mAppWidgetServices.append(userId, service); sendInitial = true; } } if (sendInitial) { service.sendInitialBroadcasts(); } return service; } @Override public int[] getAppWidgetIds(ComponentName provider, int userId) throws RemoteException { return getImplForUser(userId).getAppWidgetIds(provider); } @Override public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId, int userId) throws RemoteException { return getImplForUser(userId).getAppWidgetInfo(appWidgetId); } @Override public RemoteViews getAppWidgetViews(int appWidgetId, int userId) throws RemoteException { return getImplForUser(userId).getAppWidgetViews(appWidgetId); } @Override public void updateAppWidgetOptions(int appWidgetId, Bundle options, int userId) { getImplForUser(userId).updateAppWidgetOptions(appWidgetId, options); } @Override public Bundle getAppWidgetOptions(int appWidgetId, int userId) { return getImplForUser(userId).getAppWidgetOptions(appWidgetId); } @Override public List getInstalledProviders(int categoryFilter, int userId) throws RemoteException { return getImplForUser(userId).getInstalledProviders(categoryFilter); } @Override public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId, int userId) throws RemoteException { getImplForUser(userId).notifyAppWidgetViewDataChanged( appWidgetIds, viewId); } @Override public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId) throws RemoteException { getImplForUser(userId).partiallyUpdateAppWidgetIds( appWidgetIds, views); } @Override public void stopListening(int hostId, int userId) throws RemoteException { getImplForUser(userId).stopListening(hostId); } @Override public void unbindRemoteViewsService(int appWidgetId, Intent intent, int userId) throws RemoteException { getImplForUser(userId).unbindRemoteViewsService( appWidgetId, intent); } @Override public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId) throws RemoteException { getImplForUser(userId).updateAppWidgetIds(appWidgetIds, views); } @Override public void updateAppWidgetProvider(ComponentName provider, RemoteViews views, int userId) throws RemoteException { getImplForUser(userId).updateAppWidgetProvider(provider, views); } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); // Dump the state of all the app widget providers synchronized (mAppWidgetServices) { IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); for (int i = 0; i < mAppWidgetServices.size(); i++) { pw.println("User: " + mAppWidgetServices.keyAt(i)); ipw.increaseIndent(); AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); service.dump(fd, ipw, args); ipw.decreaseIndent(); } } } BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // Slog.d(TAG, "received " + action); if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); if (userId >= 0) { getImplForUser(userId).sendInitialBroadcasts(); } else { Slog.w(TAG, "Incorrect user handle supplied in " + intent); } } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { for (int i = 0; i < mAppWidgetServices.size(); i++) { AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); service.onConfigurationChanged(); } } else { int sendingUser = getSendingUserId(); if (sendingUser == UserHandle.USER_ALL) { for (int i = 0; i < mAppWidgetServices.size(); i++) { AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); service.onBroadcastReceived(intent); } } else { AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser); if (service != null) { service.onBroadcastReceived(intent); } } } } }; }