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