AppWidgetService.java revision 817ec49e7991d4cac50b2308cd7cf5f8641e1e29
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.appwidget; 18 19import android.app.ActivityManager; 20import android.appwidget.AppWidgetProviderInfo; 21import android.content.BroadcastReceiver; 22import android.content.ComponentName; 23import android.content.Context; 24import android.content.Intent; 25import android.content.IntentFilter; 26import android.content.pm.PackageManager; 27import android.os.Binder; 28import android.os.Bundle; 29import android.os.Handler; 30import android.os.IBinder; 31import android.os.RemoteException; 32import android.os.UserHandle; 33import android.util.Slog; 34import android.util.SparseArray; 35import android.widget.RemoteViews; 36 37import com.android.internal.appwidget.IAppWidgetHost; 38import com.android.internal.appwidget.IAppWidgetService; 39import com.android.internal.os.BackgroundThread; 40import com.android.internal.util.IndentingPrintWriter; 41import com.android.server.SystemService; 42 43import java.io.FileDescriptor; 44import java.io.PrintWriter; 45import java.util.List; 46import java.util.Locale; 47 48 49/** 50 * SystemService that publishes an IAppWidgetService. 51 */ 52public class AppWidgetService extends SystemService { 53 54 static final String TAG = "AppWidgetService"; 55 56 Context mContext; 57 Handler mSaveStateHandler; 58 59 SparseArray<AppWidgetServiceImpl> mAppWidgetServices; 60 61 @Override 62 public void onCreate(Context context) { 63 mContext = context; 64 65 mSaveStateHandler = BackgroundThread.getHandler(); 66 67 mAppWidgetServices = new SparseArray<AppWidgetServiceImpl>(5); 68 AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0, mSaveStateHandler); 69 mAppWidgetServices.append(0, primary); 70 } 71 72 @Override 73 public void onStart() { 74 publishBinderService(Context.APPWIDGET_SERVICE, mServiceImpl); 75 } 76 77 @Override 78 public void onBootPhase(int phase) { 79 if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { 80 mServiceImpl.systemRunning(isSafeMode()); 81 } 82 } 83 84 private final AppWidgetServiceStub mServiceImpl = new AppWidgetServiceStub(); 85 86 private class AppWidgetServiceStub extends IAppWidgetService.Stub { 87 88 private boolean mSafeMode; 89 private Locale mLocale; 90 private PackageManager mPackageManager; 91 92 public void systemRunning(boolean safeMode) { 93 mSafeMode = safeMode; 94 95 mAppWidgetServices.get(0).systemReady(safeMode); 96 97 // Register for the boot completed broadcast, so we can send the 98 // ENABLE broacasts. If we try to send them now, they time out, 99 // because the system isn't ready to handle them yet. 100 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 101 new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); 102 103 // Register for configuration changes so we can update the names 104 // of the widgets when the locale changes. 105 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 106 new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, null); 107 108 // Register for broadcasts about package install, etc., so we can 109 // update the provider list. 110 IntentFilter filter = new IntentFilter(); 111 filter.addAction(Intent.ACTION_PACKAGE_ADDED); 112 filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 113 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 114 filter.addDataScheme("package"); 115 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 116 filter, null, null); 117 // Register for events related to sdcard installation. 118 IntentFilter sdFilter = new IntentFilter(); 119 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 120 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 121 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 122 sdFilter, null, null); 123 124 IntentFilter userFilter = new IntentFilter(); 125 userFilter.addAction(Intent.ACTION_USER_REMOVED); 126 userFilter.addAction(Intent.ACTION_USER_STOPPING); 127 mContext.registerReceiver(new BroadcastReceiver() { 128 @Override 129 public void onReceive(Context context, Intent intent) { 130 if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { 131 onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 132 UserHandle.USER_NULL)); 133 } else if (Intent.ACTION_USER_STOPPING.equals(intent.getAction())) { 134 onUserStopping(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 135 UserHandle.USER_NULL)); 136 } 137 } 138 }, userFilter); 139 } 140 141 @Override 142 public int allocateAppWidgetId(String packageName, int hostId, int userId) 143 throws RemoteException { 144 return getImplForUser(userId).allocateAppWidgetId(packageName, hostId); 145 } 146 147 @Override 148 public int[] getAppWidgetIdsForHost(int hostId, int userId) throws RemoteException { 149 return getImplForUser(userId).getAppWidgetIdsForHost(hostId); 150 } 151 152 @Override 153 public void deleteAppWidgetId(int appWidgetId, int userId) throws RemoteException { 154 getImplForUser(userId).deleteAppWidgetId(appWidgetId); 155 } 156 157 @Override 158 public void deleteHost(int hostId, int userId) throws RemoteException { 159 getImplForUser(userId).deleteHost(hostId); 160 } 161 162 @Override 163 public void deleteAllHosts(int userId) throws RemoteException { 164 getImplForUser(userId).deleteAllHosts(); 165 } 166 167 @Override 168 public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options, 169 int userId) throws RemoteException { 170 getImplForUser(userId).bindAppWidgetId(appWidgetId, provider, options); 171 } 172 173 @Override 174 public boolean bindAppWidgetIdIfAllowed( 175 String packageName, int appWidgetId, ComponentName provider, Bundle options, 176 int userId) throws RemoteException { 177 return getImplForUser(userId).bindAppWidgetIdIfAllowed( 178 packageName, appWidgetId, provider, options); 179 } 180 181 @Override 182 public boolean hasBindAppWidgetPermission(String packageName, int userId) 183 throws RemoteException { 184 return getImplForUser(userId).hasBindAppWidgetPermission(packageName); 185 } 186 187 @Override 188 public void setBindAppWidgetPermission(String packageName, boolean permission, int userId) 189 throws RemoteException { 190 getImplForUser(userId).setBindAppWidgetPermission(packageName, permission); 191 } 192 193 @Override 194 public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection, 195 int userId) throws RemoteException { 196 getImplForUser(userId).bindRemoteViewsService(appWidgetId, intent, connection); 197 } 198 199 @Override 200 public int[] startListening(IAppWidgetHost host, String packageName, int hostId, 201 List<RemoteViews> updatedViews, int userId) throws RemoteException { 202 return getImplForUser(userId).startListening(host, packageName, hostId, updatedViews); 203 } 204 205 public void onUserRemoved(int userId) { 206 if (userId < 1) return; 207 synchronized (mAppWidgetServices) { 208 AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); 209 mAppWidgetServices.remove(userId); 210 211 if (impl == null) { 212 AppWidgetServiceImpl.getSettingsFile(userId).delete(); 213 } else { 214 impl.onUserRemoved(); 215 } 216 } 217 } 218 219 public void onUserStopping(int userId) { 220 if (userId < 1) return; 221 synchronized (mAppWidgetServices) { 222 AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); 223 if (impl != null) { 224 mAppWidgetServices.remove(userId); 225 impl.onUserStopping(); 226 } 227 } 228 } 229 230 private void checkPermission(int userId) { 231 int realUserId = ActivityManager.handleIncomingUser( 232 Binder.getCallingPid(), 233 Binder.getCallingUid(), 234 userId, 235 false, /* allowAll */ 236 true, /* requireFull */ 237 this.getClass().getSimpleName(), 238 this.getClass().getPackage().getName()); 239 } 240 241 private AppWidgetServiceImpl getImplForUser(int userId) { 242 checkPermission(userId); 243 boolean sendInitial = false; 244 AppWidgetServiceImpl service; 245 synchronized (mAppWidgetServices) { 246 service = mAppWidgetServices.get(userId); 247 if (service == null) { 248 Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId 249 + ", adding"); 250 // TODO: Verify that it's a valid user 251 service = new AppWidgetServiceImpl(mContext, userId, mSaveStateHandler); 252 service.systemReady(mSafeMode); 253 // Assume that BOOT_COMPLETED was received, as this is a non-primary user. 254 mAppWidgetServices.append(userId, service); 255 sendInitial = true; 256 } 257 } 258 if (sendInitial) { 259 service.sendInitialBroadcasts(); 260 } 261 return service; 262 } 263 264 @Override 265 public int[] getAppWidgetIds(ComponentName provider, int userId) throws RemoteException { 266 return getImplForUser(userId).getAppWidgetIds(provider); 267 } 268 269 @Override 270 public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId, int userId) 271 throws RemoteException { 272 return getImplForUser(userId).getAppWidgetInfo(appWidgetId); 273 } 274 275 @Override 276 public RemoteViews getAppWidgetViews(int appWidgetId, int userId) throws RemoteException { 277 return getImplForUser(userId).getAppWidgetViews(appWidgetId); 278 } 279 280 @Override 281 public void updateAppWidgetOptions(int appWidgetId, Bundle options, int userId) { 282 getImplForUser(userId).updateAppWidgetOptions(appWidgetId, options); 283 } 284 285 @Override 286 public Bundle getAppWidgetOptions(int appWidgetId, int userId) { 287 return getImplForUser(userId).getAppWidgetOptions(appWidgetId); 288 } 289 290 @Override 291 public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter, int userId) 292 throws RemoteException { 293 return getImplForUser(userId).getInstalledProviders(categoryFilter); 294 } 295 296 @Override 297 public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId, int userId) 298 throws RemoteException { 299 getImplForUser(userId).notifyAppWidgetViewDataChanged( 300 appWidgetIds, viewId); 301 } 302 303 @Override 304 public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId) 305 throws RemoteException { 306 getImplForUser(userId).partiallyUpdateAppWidgetIds( 307 appWidgetIds, views); 308 } 309 310 @Override 311 public void stopListening(int hostId, int userId) throws RemoteException { 312 getImplForUser(userId).stopListening(hostId); 313 } 314 315 @Override 316 public void unbindRemoteViewsService(int appWidgetId, Intent intent, int userId) 317 throws RemoteException { 318 getImplForUser(userId).unbindRemoteViewsService( 319 appWidgetId, intent); 320 } 321 322 @Override 323 public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId) 324 throws RemoteException { 325 getImplForUser(userId).updateAppWidgetIds(appWidgetIds, views); 326 } 327 328 @Override 329 public void updateAppWidgetProvider(ComponentName provider, RemoteViews views, int userId) 330 throws RemoteException { 331 getImplForUser(userId).updateAppWidgetProvider(provider, views); 332 } 333 334 @Override 335 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 336 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 337 338 // Dump the state of all the app widget providers 339 synchronized (mAppWidgetServices) { 340 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 341 for (int i = 0; i < mAppWidgetServices.size(); i++) { 342 pw.println("User: " + mAppWidgetServices.keyAt(i)); 343 ipw.increaseIndent(); 344 AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); 345 service.dump(fd, ipw, args); 346 ipw.decreaseIndent(); 347 } 348 } 349 } 350 351 BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 352 public void onReceive(Context context, Intent intent) { 353 String action = intent.getAction(); 354 // Slog.d(TAG, "received " + action); 355 if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 356 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); 357 if (userId >= 0) { 358 getImplForUser(userId).sendInitialBroadcasts(); 359 } else { 360 Slog.w(TAG, "Incorrect user handle supplied in " + intent); 361 } 362 } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { 363 for (int i = 0; i < mAppWidgetServices.size(); i++) { 364 AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); 365 service.onConfigurationChanged(); 366 } 367 } else { 368 int sendingUser = getSendingUserId(); 369 if (sendingUser == UserHandle.USER_ALL) { 370 for (int i = 0; i < mAppWidgetServices.size(); i++) { 371 AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); 372 service.onBroadcastReceived(intent); 373 } 374 } else { 375 AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser); 376 if (service != null) { 377 service.onBroadcastReceived(intent); 378 } 379 } 380 } 381 } 382 }; 383 } 384} 385