AppWidgetService.java revision a00271533f639c8ed36429c663889ac9f654bc72
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.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;
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        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