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; 18 19import android.app.ActivityManagerNative; 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.HandlerThread; 31import android.os.IBinder; 32import android.os.RemoteException; 33import android.os.UserHandle; 34import android.util.Slog; 35import android.util.SparseArray; 36import android.widget.RemoteViews; 37 38import com.android.internal.appwidget.IAppWidgetHost; 39import com.android.internal.appwidget.IAppWidgetService; 40import com.android.internal.util.IndentingPrintWriter; 41 42import java.io.FileDescriptor; 43import java.io.PrintWriter; 44import java.util.List; 45import java.util.Locale; 46 47 48/** 49 * Redirects calls to this service to the instance of the service for the appropriate user. 50 */ 51class AppWidgetService extends IAppWidgetService.Stub 52{ 53 private static final String TAG = "AppWidgetService"; 54 55 Context mContext; 56 Locale mLocale; 57 PackageManager mPackageManager; 58 boolean mSafeMode; 59 private final Handler mSaveStateHandler; 60 61 private final SparseArray<AppWidgetServiceImpl> mAppWidgetServices; 62 63 AppWidgetService(Context context) { 64 mContext = context; 65 66 HandlerThread handlerThread = new HandlerThread("AppWidgetService -- Save state"); 67 handlerThread.start(); 68 mSaveStateHandler = new Handler(handlerThread.getLooper()); 69 70 mAppWidgetServices = new SparseArray<AppWidgetServiceImpl>(5); 71 AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0, mSaveStateHandler); 72 mAppWidgetServices.append(0, primary); 73 } 74 75 public void systemReady(boolean safeMode) { 76 mSafeMode = safeMode; 77 78 mAppWidgetServices.get(0).systemReady(safeMode); 79 80 // Register for the boot completed broadcast, so we can send the 81 // ENABLE broacasts. If we try to send them now, they time out, 82 // because the system isn't ready to handle them yet. 83 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 84 new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); 85 86 // Register for configuration changes so we can update the names 87 // of the widgets when the locale changes. 88 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 89 new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, null); 90 91 // Register for broadcasts about package install, etc., so we can 92 // update the provider list. 93 IntentFilter filter = new IntentFilter(); 94 filter.addAction(Intent.ACTION_PACKAGE_ADDED); 95 filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 96 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 97 filter.addDataScheme("package"); 98 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 99 filter, null, null); 100 // Register for events related to sdcard installation. 101 IntentFilter sdFilter = new IntentFilter(); 102 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 103 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 104 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 105 sdFilter, null, null); 106 107 IntentFilter userFilter = new IntentFilter(); 108 userFilter.addAction(Intent.ACTION_USER_REMOVED); 109 userFilter.addAction(Intent.ACTION_USER_STOPPING); 110 mContext.registerReceiver(new BroadcastReceiver() { 111 @Override 112 public void onReceive(Context context, Intent intent) { 113 if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { 114 onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 115 UserHandle.USER_NULL)); 116 } else if (Intent.ACTION_USER_STOPPING.equals(intent.getAction())) { 117 onUserStopping(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 118 UserHandle.USER_NULL)); 119 } 120 } 121 }, userFilter); 122 } 123 124 /** 125 * This returns the user id of the caller, if the caller is not the system process, 126 * otherwise it assumes that the calls are from the lockscreen and hence are meant for the 127 * current user. TODO: Instead, have lockscreen make explicit calls with userId 128 */ 129 private int getCallingOrCurrentUserId() { 130 int callingUid = Binder.getCallingUid(); 131 // Also check the PID because Settings (power control widget) also runs as System UID 132 if (callingUid == android.os.Process.myUid() 133 && Binder.getCallingPid() == android.os.Process.myPid()) { 134 try { 135 return ActivityManagerNative.getDefault().getCurrentUser().id; 136 } catch (RemoteException re) { 137 return UserHandle.getUserId(callingUid); 138 } 139 } else { 140 return UserHandle.getUserId(callingUid); 141 } 142 } 143 144 @Override 145 public int allocateAppWidgetId(String packageName, int hostId) throws RemoteException { 146 return getImplForUser(getCallingOrCurrentUserId()).allocateAppWidgetId( 147 packageName, hostId); 148 } 149 150 @Override 151 public int[] getAppWidgetIdsForHost(int hostId) throws RemoteException { 152 return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetIdsForHost(hostId); 153 } 154 155 @Override 156 public void deleteAppWidgetId(int appWidgetId) throws RemoteException { 157 getImplForUser(getCallingOrCurrentUserId()).deleteAppWidgetId(appWidgetId); 158 } 159 160 @Override 161 public void deleteHost(int hostId) throws RemoteException { 162 getImplForUser(getCallingOrCurrentUserId()).deleteHost(hostId); 163 } 164 165 @Override 166 public void deleteAllHosts() throws RemoteException { 167 getImplForUser(getCallingOrCurrentUserId()).deleteAllHosts(); 168 } 169 170 @Override 171 public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) 172 throws RemoteException { 173 getImplForUser(getCallingOrCurrentUserId()).bindAppWidgetId(appWidgetId, provider, 174 options); 175 } 176 177 @Override 178 public boolean bindAppWidgetIdIfAllowed( 179 String packageName, int appWidgetId, ComponentName provider, Bundle options) 180 throws RemoteException { 181 return getImplForUser(getCallingOrCurrentUserId()).bindAppWidgetIdIfAllowed( 182 packageName, appWidgetId, provider, options); 183 } 184 185 @Override 186 public boolean hasBindAppWidgetPermission(String packageName) throws RemoteException { 187 return getImplForUser(getCallingOrCurrentUserId()).hasBindAppWidgetPermission( 188 packageName); 189 } 190 191 @Override 192 public void setBindAppWidgetPermission(String packageName, boolean permission) 193 throws RemoteException { 194 getImplForUser(getCallingOrCurrentUserId()).setBindAppWidgetPermission( 195 packageName, permission); 196 } 197 198 @Override 199 public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection, 200 int userId) throws RemoteException { 201 if (Binder.getCallingPid() != android.os.Process.myPid() 202 && userId != UserHandle.getCallingUserId()) { 203 throw new SecurityException("Call from non-system process. Calling uid = " 204 + Binder.getCallingUid()); 205 } 206 getImplForUser(userId).bindRemoteViewsService( 207 appWidgetId, intent, connection); 208 } 209 210 @Override 211 public int[] startListening(IAppWidgetHost host, String packageName, int hostId, 212 List<RemoteViews> updatedViews) throws RemoteException { 213 return getImplForUser(getCallingOrCurrentUserId()).startListening(host, 214 packageName, hostId, updatedViews); 215 } 216 217 @Override 218 public int[] startListeningAsUser(IAppWidgetHost host, String packageName, int hostId, 219 List<RemoteViews> updatedViews, int userId) throws RemoteException { 220 if (Binder.getCallingPid() != android.os.Process.myPid() 221 && userId != UserHandle.getCallingUserId()) { 222 throw new SecurityException("Call from non-system process. Calling uid = " 223 + Binder.getCallingUid()); 224 } 225 return getImplForUser(userId).startListening(host, packageName, hostId, updatedViews); 226 } 227 228 public void onUserRemoved(int userId) { 229 if (userId < 1) return; 230 synchronized (mAppWidgetServices) { 231 AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); 232 mAppWidgetServices.remove(userId); 233 234 if (impl == null) { 235 AppWidgetServiceImpl.getSettingsFile(userId).delete(); 236 } else { 237 impl.onUserRemoved(); 238 } 239 } 240 } 241 242 public void onUserStopping(int userId) { 243 if (userId < 1) return; 244 synchronized (mAppWidgetServices) { 245 AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); 246 if (impl != null) { 247 mAppWidgetServices.remove(userId); 248 impl.onUserStopping(); 249 } 250 } 251 } 252 253 private AppWidgetServiceImpl getImplForUser(int userId) { 254 boolean sendInitial = false; 255 AppWidgetServiceImpl service; 256 synchronized (mAppWidgetServices) { 257 service = mAppWidgetServices.get(userId); 258 if (service == null) { 259 Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + ", adding"); 260 // TODO: Verify that it's a valid user 261 service = new AppWidgetServiceImpl(mContext, userId, mSaveStateHandler); 262 service.systemReady(mSafeMode); 263 // Assume that BOOT_COMPLETED was received, as this is a non-primary user. 264 mAppWidgetServices.append(userId, service); 265 sendInitial = true; 266 } 267 } 268 if (sendInitial) { 269 service.sendInitialBroadcasts(); 270 } 271 return service; 272 } 273 274 @Override 275 public int[] getAppWidgetIds(ComponentName provider) throws RemoteException { 276 return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetIds(provider); 277 } 278 279 @Override 280 public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) throws RemoteException { 281 return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetInfo(appWidgetId); 282 } 283 284 @Override 285 public RemoteViews getAppWidgetViews(int appWidgetId) throws RemoteException { 286 return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetViews(appWidgetId); 287 } 288 289 @Override 290 public void updateAppWidgetOptions(int appWidgetId, Bundle options) { 291 getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetOptions(appWidgetId, options); 292 } 293 294 @Override 295 public Bundle getAppWidgetOptions(int appWidgetId) { 296 return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetOptions(appWidgetId); 297 } 298 299 @Override 300 public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) 301 throws RemoteException { 302 return getImplForUser(getCallingOrCurrentUserId()).getInstalledProviders(categoryFilter); 303 } 304 305 @Override 306 public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) 307 throws RemoteException { 308 getImplForUser(getCallingOrCurrentUserId()).notifyAppWidgetViewDataChanged( 309 appWidgetIds, viewId); 310 } 311 312 @Override 313 public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views) 314 throws RemoteException { 315 getImplForUser(getCallingOrCurrentUserId()).partiallyUpdateAppWidgetIds( 316 appWidgetIds, views); 317 } 318 319 @Override 320 public void stopListening(int hostId) throws RemoteException { 321 getImplForUser(getCallingOrCurrentUserId()).stopListening(hostId); 322 } 323 324 @Override 325 public void stopListeningAsUser(int hostId, int userId) throws RemoteException { 326 if (Binder.getCallingPid() != android.os.Process.myPid() 327 && userId != UserHandle.getCallingUserId()) { 328 throw new SecurityException("Call from non-system process. Calling uid = " 329 + Binder.getCallingUid()); 330 } 331 getImplForUser(userId).stopListening(hostId); 332 } 333 334 @Override 335 public void unbindRemoteViewsService(int appWidgetId, Intent intent, int userId) 336 throws RemoteException { 337 if (Binder.getCallingPid() != android.os.Process.myPid() 338 && userId != UserHandle.getCallingUserId()) { 339 throw new SecurityException("Call from non-system process. Calling uid = " 340 + Binder.getCallingUid()); 341 } 342 getImplForUser(userId).unbindRemoteViewsService( 343 appWidgetId, intent); 344 } 345 346 @Override 347 public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) throws RemoteException { 348 getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetIds(appWidgetIds, views); 349 } 350 351 @Override 352 public void updateAppWidgetProvider(ComponentName provider, RemoteViews views) 353 throws RemoteException { 354 getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetProvider(provider, views); 355 } 356 357 @Override 358 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 359 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 360 361 // Dump the state of all the app widget providers 362 synchronized (mAppWidgetServices) { 363 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 364 for (int i = 0; i < mAppWidgetServices.size(); i++) { 365 pw.println("User: " + mAppWidgetServices.keyAt(i)); 366 ipw.increaseIndent(); 367 AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); 368 service.dump(fd, ipw, args); 369 ipw.decreaseIndent(); 370 } 371 } 372 } 373 374 BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 375 public void onReceive(Context context, Intent intent) { 376 String action = intent.getAction(); 377 // Slog.d(TAG, "received " + action); 378 if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 379 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); 380 if (userId >= 0) { 381 getImplForUser(userId).sendInitialBroadcasts(); 382 } else { 383 Slog.w(TAG, "Incorrect user handle supplied in " + intent); 384 } 385 } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { 386 for (int i = 0; i < mAppWidgetServices.size(); i++) { 387 AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); 388 service.onConfigurationChanged(); 389 } 390 } else { 391 int sendingUser = getSendingUserId(); 392 if (sendingUser == UserHandle.USER_ALL) { 393 for (int i = 0; i < mAppWidgetServices.size(); i++) { 394 AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); 395 service.onBroadcastReceived(intent); 396 } 397 } else { 398 AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser); 399 if (service != null) { 400 service.onBroadcastReceived(intent); 401 } 402 } 403 } 404 } 405 }; 406} 407