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.HandlerThread;
     31 import android.os.IBinder;
     32 import android.os.RemoteException;
     33 import android.os.UserHandle;
     34 import android.util.Slog;
     35 import android.util.SparseArray;
     36 import android.widget.RemoteViews;
     37 
     38 import com.android.internal.appwidget.IAppWidgetHost;
     39 import com.android.internal.appwidget.IAppWidgetService;
     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         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     @Override
    125     public int allocateAppWidgetId(String packageName, int hostId, int userId)
    126             throws RemoteException {
    127         return getImplForUser(userId).allocateAppWidgetId(packageName, hostId);
    128     }
    129 
    130     @Override
    131     public int[] getAppWidgetIdsForHost(int hostId, int userId) throws RemoteException {
    132         return getImplForUser(userId).getAppWidgetIdsForHost(hostId);
    133     }
    134 
    135     @Override
    136     public void deleteAppWidgetId(int appWidgetId, int userId) throws RemoteException {
    137         getImplForUser(userId).deleteAppWidgetId(appWidgetId);
    138     }
    139 
    140     @Override
    141     public void deleteHost(int hostId, int userId) throws RemoteException {
    142         getImplForUser(userId).deleteHost(hostId);
    143     }
    144 
    145     @Override
    146     public void deleteAllHosts(int userId) throws RemoteException {
    147         getImplForUser(userId).deleteAllHosts();
    148     }
    149 
    150     @Override
    151     public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options, int userId)
    152             throws RemoteException {
    153         getImplForUser(userId).bindAppWidgetId(appWidgetId, provider, options);
    154     }
    155 
    156     @Override
    157     public boolean bindAppWidgetIdIfAllowed(
    158             String packageName, int appWidgetId, ComponentName provider, Bundle options, int userId)
    159                     throws RemoteException {
    160         return getImplForUser(userId).bindAppWidgetIdIfAllowed(
    161                 packageName, appWidgetId, provider, options);
    162     }
    163 
    164     @Override
    165     public boolean hasBindAppWidgetPermission(String packageName, int userId)
    166             throws RemoteException {
    167         return getImplForUser(userId).hasBindAppWidgetPermission(packageName);
    168     }
    169 
    170     @Override
    171     public void setBindAppWidgetPermission(String packageName, boolean permission, int userId)
    172             throws RemoteException {
    173         getImplForUser(userId).setBindAppWidgetPermission(packageName, permission);
    174     }
    175 
    176     @Override
    177     public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection,
    178             int userId) throws RemoteException {
    179         getImplForUser(userId).bindRemoteViewsService(appWidgetId, intent, connection);
    180     }
    181 
    182     @Override
    183     public int[] startListening(IAppWidgetHost host, String packageName, int hostId,
    184             List<RemoteViews> updatedViews, int userId) throws RemoteException {
    185         return getImplForUser(userId).startListening(host, packageName, hostId, updatedViews);
    186     }
    187 
    188     public void onUserRemoved(int userId) {
    189         if (userId < 1) return;
    190         synchronized (mAppWidgetServices) {
    191             AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
    192             mAppWidgetServices.remove(userId);
    193 
    194             if (impl == null) {
    195                 AppWidgetServiceImpl.getSettingsFile(userId).delete();
    196             } else {
    197                 impl.onUserRemoved();
    198             }
    199         }
    200     }
    201 
    202     public void onUserStopping(int userId) {
    203         if (userId < 1) return;
    204         synchronized (mAppWidgetServices) {
    205             AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
    206             if (impl != null) {
    207                 mAppWidgetServices.remove(userId);
    208                 impl.onUserStopping();
    209             }
    210         }
    211     }
    212 
    213     private void checkPermission(int userId) {
    214         int realUserId = ActivityManager.handleIncomingUser(
    215                 Binder.getCallingPid(),
    216                 Binder.getCallingUid(),
    217                 userId,
    218                 false, /* allowAll */
    219                 true, /* requireFull */
    220                 this.getClass().getSimpleName(),
    221                 this.getClass().getPackage().getName());
    222     }
    223 
    224     private AppWidgetServiceImpl getImplForUser(int userId) {
    225         checkPermission(userId);
    226         boolean sendInitial = false;
    227         AppWidgetServiceImpl service;
    228         synchronized (mAppWidgetServices) {
    229             service = mAppWidgetServices.get(userId);
    230             if (service == null) {
    231                 Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + ", adding");
    232                 // TODO: Verify that it's a valid user
    233                 service = new AppWidgetServiceImpl(mContext, userId, mSaveStateHandler);
    234                 service.systemReady(mSafeMode);
    235                 // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
    236                 mAppWidgetServices.append(userId, service);
    237                 sendInitial = true;
    238             }
    239         }
    240         if (sendInitial) {
    241             service.sendInitialBroadcasts();
    242         }
    243         return service;
    244     }
    245 
    246     @Override
    247     public int[] getAppWidgetIds(ComponentName provider, int userId) throws RemoteException {
    248         return getImplForUser(userId).getAppWidgetIds(provider);
    249     }
    250 
    251     @Override
    252     public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId, int userId)
    253             throws RemoteException {
    254         return getImplForUser(userId).getAppWidgetInfo(appWidgetId);
    255     }
    256 
    257     @Override
    258     public RemoteViews getAppWidgetViews(int appWidgetId, int userId) throws RemoteException {
    259         return getImplForUser(userId).getAppWidgetViews(appWidgetId);
    260     }
    261 
    262     @Override
    263     public void updateAppWidgetOptions(int appWidgetId, Bundle options, int userId) {
    264         getImplForUser(userId).updateAppWidgetOptions(appWidgetId, options);
    265     }
    266 
    267     @Override
    268     public Bundle getAppWidgetOptions(int appWidgetId, int userId) {
    269         return getImplForUser(userId).getAppWidgetOptions(appWidgetId);
    270     }
    271 
    272     @Override
    273     public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter, int userId)
    274             throws RemoteException {
    275         return getImplForUser(userId).getInstalledProviders(categoryFilter);
    276     }
    277 
    278     @Override
    279     public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId, int userId)
    280             throws RemoteException {
    281         getImplForUser(userId).notifyAppWidgetViewDataChanged(
    282                 appWidgetIds, viewId);
    283     }
    284 
    285     @Override
    286     public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId)
    287             throws RemoteException {
    288         getImplForUser(userId).partiallyUpdateAppWidgetIds(
    289                 appWidgetIds, views);
    290     }
    291 
    292     @Override
    293     public void stopListening(int hostId, int userId) throws RemoteException {
    294         getImplForUser(userId).stopListening(hostId);
    295     }
    296 
    297     @Override
    298     public void unbindRemoteViewsService(int appWidgetId, Intent intent, int userId)
    299             throws RemoteException {
    300         getImplForUser(userId).unbindRemoteViewsService(
    301                 appWidgetId, intent);
    302     }
    303 
    304     @Override
    305     public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId)
    306             throws RemoteException {
    307         getImplForUser(userId).updateAppWidgetIds(appWidgetIds, views);
    308     }
    309 
    310     @Override
    311     public void updateAppWidgetProvider(ComponentName provider, RemoteViews views, int userId)
    312             throws RemoteException {
    313         getImplForUser(userId).updateAppWidgetProvider(provider, views);
    314     }
    315 
    316     @Override
    317     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    318         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
    319 
    320         // Dump the state of all the app widget providers
    321         synchronized (mAppWidgetServices) {
    322             IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
    323             for (int i = 0; i < mAppWidgetServices.size(); i++) {
    324                 pw.println("User: " + mAppWidgetServices.keyAt(i));
    325                 ipw.increaseIndent();
    326                 AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
    327                 service.dump(fd, ipw, args);
    328                 ipw.decreaseIndent();
    329             }
    330         }
    331     }
    332 
    333     BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    334         public void onReceive(Context context, Intent intent) {
    335             String action = intent.getAction();
    336             // Slog.d(TAG, "received " + action);
    337             if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
    338                 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
    339                 if (userId >= 0) {
    340                     getImplForUser(userId).sendInitialBroadcasts();
    341                 } else {
    342                     Slog.w(TAG, "Incorrect user handle supplied in " + intent);
    343                 }
    344             } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
    345                 for (int i = 0; i < mAppWidgetServices.size(); i++) {
    346                     AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
    347                     service.onConfigurationChanged();
    348                 }
    349             } else {
    350                 int sendingUser = getSendingUserId();
    351                 if (sendingUser == UserHandle.USER_ALL) {
    352                     for (int i = 0; i < mAppWidgetServices.size(); i++) {
    353                         AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
    354                         service.onBroadcastReceived(intent);
    355                     }
    356                 } else {
    357                     AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser);
    358                     if (service != null) {
    359                         service.onBroadcastReceived(intent);
    360                     }
    361                 }
    362             }
    363         }
    364     };
    365 }
    366