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