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