19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Copyright (C) 2009 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectpackage android.appwidget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohenimport java.util.ArrayList; 20d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohenimport java.util.HashMap; 21d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen 2260264730c1c730dbd184bc661fd398d97f5df31dAdam Cohenimport android.app.ActivityThread; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 243ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohenimport android.os.Binder; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 29f229e4d3eb8f910c181f96416c6798f6f305a395Jim Millerimport android.os.Process; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 32f229e4d3eb8f910c181f96416c6798f6f305a395Jim Millerimport android.os.UserHandle; 33d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohenimport android.util.DisplayMetrics; 34a75a883fe9ea1790803148f0a561473073e3f264Jim Millerimport android.util.Log; 35d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohenimport android.util.TypedValue; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.RemoteViews; 37e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Millerimport android.widget.RemoteViews.OnClickHandler; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport com.android.internal.appwidget.IAppWidgetHost; 40c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport com.android.internal.appwidget.IAppWidgetService; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 43c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * AppWidgetHost provides the interaction with the AppWidget service for apps, 44c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * like the home screen, that want to embed AppWidgets in their UI. 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 46c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectpublic class AppWidgetHost { 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int HANDLE_UPDATE = 1; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int HANDLE_PROVIDER_CHANGED = 2; 507fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung static final int HANDLE_PROVIDERS_CHANGED = 3; 517fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung static final int HANDLE_VIEW_DATA_CHANGED = 4; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 53a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy final static Object sServiceLock = new Object(); 54c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project static IAppWidgetService sService; 55d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen private DisplayMetrics mDisplayMetrics; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context mContext; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String mPackageName; 59a75a883fe9ea1790803148f0a561473073e3f264Jim Miller Handler mHandler; 60a75a883fe9ea1790803148f0a561473073e3f264Jim Miller int mHostId; 61a75a883fe9ea1790803148f0a561473073e3f264Jim Miller Callbacks mCallbacks = new Callbacks(); 62a75a883fe9ea1790803148f0a561473073e3f264Jim Miller final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>(); 63a75a883fe9ea1790803148f0a561473073e3f264Jim Miller private OnClickHandler mOnClickHandler; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 65c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project class Callbacks extends IAppWidgetHost.Stub { 66a75a883fe9ea1790803148f0a561473073e3f264Jim Miller public void updateAppWidget(int appWidgetId, RemoteViews views, int userId) { 673ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen if (isLocalBinder() && views != null) { 683ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen views = views.clone(); 69a75a883fe9ea1790803148f0a561473073e3f264Jim Miller views.setUser(new UserHandle(userId)); 703ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen } 71a75a883fe9ea1790803148f0a561473073e3f264Jim Miller Message msg = mHandler.obtainMessage(HANDLE_UPDATE, appWidgetId, userId, views); 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.sendToTarget(); 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 75a75a883fe9ea1790803148f0a561473073e3f264Jim Miller public void providerChanged(int appWidgetId, AppWidgetProviderInfo info, int userId) { 763ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen if (isLocalBinder() && info != null) { 773ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen info = info.clone(); 783ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen } 79a75a883fe9ea1790803148f0a561473073e3f264Jim Miller Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED, 80a75a883fe9ea1790803148f0a561473073e3f264Jim Miller appWidgetId, userId, info); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.sendToTarget(); 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 83499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 84a75a883fe9ea1790803148f0a561473073e3f264Jim Miller public void providersChanged(int userId) { 85a75a883fe9ea1790803148f0a561473073e3f264Jim Miller Message msg = mHandler.obtainMessage(HANDLE_PROVIDERS_CHANGED, userId, 0); 867fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung msg.sendToTarget(); 877fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 887fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung 89a75a883fe9ea1790803148f0a561473073e3f264Jim Miller public void viewDataChanged(int appWidgetId, int viewId, int userId) { 90a75a883fe9ea1790803148f0a561473073e3f264Jim Miller Message msg = mHandler.obtainMessage(HANDLE_VIEW_DATA_CHANGED, 91a75a883fe9ea1790803148f0a561473073e3f264Jim Miller appWidgetId, viewId, userId); 92499cb9f516062b654952d282f211bee44c31a3c2Winson Chung msg.sendToTarget(); 93499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class UpdateHandler extends Handler { 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public UpdateHandler(Looper looper) { 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(looper); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 100e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case HANDLE_UPDATE: { 104a75a883fe9ea1790803148f0a561473073e3f264Jim Miller updateAppWidgetView(msg.arg1, (RemoteViews)msg.obj, msg.arg2); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case HANDLE_PROVIDER_CHANGED: { 108c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project onProviderChanged(msg.arg1, (AppWidgetProviderInfo)msg.obj); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1117fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung case HANDLE_PROVIDERS_CHANGED: { 112eeb4ff4d137a2ff2d25340c2b0396f2c3fd5068bWinson Chung onProvidersChanged(); 1137fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung break; 1147fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung } 115499cb9f516062b654952d282f211bee44c31a3c2Winson Chung case HANDLE_VIEW_DATA_CHANGED: { 116a75a883fe9ea1790803148f0a561473073e3f264Jim Miller viewDataChanged(msg.arg1, msg.arg2, (Integer) msg.obj); 117499cb9f516062b654952d282f211bee44c31a3c2Winson Chung break; 118499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 122e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 123c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public AppWidgetHost(Context context, int hostId) { 124e6d5545a539068dcfdd62d43ee0ef6789bb76a8eMichael Jurka this(context, hostId, null, context.getMainLooper()); 125e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller } 126e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 127e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller /** 128e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller * @hide 129e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller */ 130f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller public AppWidgetHost(Context context, int hostId, OnClickHandler handler, Looper looper) { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHostId = hostId; 133e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller mOnClickHandler = handler; 134f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller mHandler = new UpdateHandler(looper); 135d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen mDisplayMetrics = context.getResources().getDisplayMetrics(); 136f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller bindService(); 137f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 138f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller 13994022e8997084be458a1faf46e72efab1d59e973Amith Yamasani 140f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller private static void bindService() { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (sServiceLock) { 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sService == null) { 143c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE); 144c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project sService = IAppWidgetService.Stub.asInterface(b); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 150c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Start receiving onAppWidgetChanged calls for your AppWidgets. Call this when your activity 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * becomes visible, i.e. from onStart() in your Activity. 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void startListening() { 154a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy int[] updatedIds; 155a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>(); 156e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 157a75a883fe9ea1790803148f0a561473073e3f264Jim Miller final int userId = mContext.getUserId(); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPackageName == null) { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPackageName = mContext.getPackageName(); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 162a75a883fe9ea1790803148f0a561473073e3f264Jim Miller updatedIds = sService.startListening( 163c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani mCallbacks, mPackageName, mHostId, updatedViews, userId); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (RemoteException e) { 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException("system server dead?", e); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int N = updatedIds.length; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 17194022e8997084be458a1faf46e72efab1d59e973Amith Yamasani if (updatedViews.get(i) != null) { 17294022e8997084be458a1faf46e72efab1d59e973Amith Yamasani updatedViews.get(i).setUser(new UserHandle(userId)); 17394022e8997084be458a1faf46e72efab1d59e973Amith Yamasani } 174a75a883fe9ea1790803148f0a561473073e3f264Jim Miller updateAppWidgetView(updatedIds[i], updatedViews.get(i), userId); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 179c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Stop receiving onAppWidgetChanged calls for your AppWidgets. Call this when your activity is 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * no longer visible, i.e. from onStop() in your Activity. 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void stopListening() { 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 184a75a883fe9ea1790803148f0a561473073e3f264Jim Miller sService.stopListening(mHostId, mContext.getUserId()); 185c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani } 186c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani catch (RemoteException e) { 187c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani throw new RuntimeException("system server dead?", e); 188c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani } 189c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani 190a75a883fe9ea1790803148f0a561473073e3f264Jim Miller // This is here because keyguard needs it since it'll be switching users after this call. 191a75a883fe9ea1790803148f0a561473073e3f264Jim Miller // If it turns out other apps need to call this often, we should re-think how this works. 192c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani clearViews(); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 196c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Get a appWidgetId for a host in the calling process. 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 198c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @return a appWidgetId 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 200c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public int allocateAppWidgetId() { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPackageName == null) { 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPackageName = mContext.getPackageName(); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 205a75a883fe9ea1790803148f0a561473073e3f264Jim Miller return sService.allocateAppWidgetId(mPackageName, mHostId, mContext.getUserId()); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (RemoteException e) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException("system server dead?", e); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 21321ace3f34f775a1e66c75ee32fb251e3c90c2e27Jim Miller * Get a appWidgetId for a host in the given package. 214f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller * 215f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller * @return a appWidgetId 216f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller * @hide 217f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller */ 21821ace3f34f775a1e66c75ee32fb251e3c90c2e27Jim Miller public static int allocateAppWidgetIdForPackage(int hostId, int userId, String packageName) { 219f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller checkCallerIsSystem(); 220f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller try { 221f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller if (sService == null) { 222f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller bindService(); 223f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 224a75a883fe9ea1790803148f0a561473073e3f264Jim Miller return sService.allocateAppWidgetId(packageName, hostId, userId); 225f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } catch (RemoteException e) { 226f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller throw new RuntimeException("system server dead?", e); 227f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 228f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 229f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller 23075b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka /** 23175b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka * Gets a list of all the appWidgetIds that are bound to the current host 23275b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka * 23375b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka * @hide 23475b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka */ 23575b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka public int[] getAppWidgetIds() { 23675b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka try { 23775b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka if (sService == null) { 23875b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka bindService(); 23975b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 240a75a883fe9ea1790803148f0a561473073e3f264Jim Miller return sService.getAppWidgetIdsForHost(mHostId, mContext.getUserId()); 24175b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } catch (RemoteException e) { 24275b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka throw new RuntimeException("system server dead?", e); 24375b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 24475b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka } 24575b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka 246f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller private static void checkCallerIsSystem() { 247f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller int uid = Process.myUid(); 248f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) { 249f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller return; 250f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 251f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller throw new SecurityException("Disallowed call for uid " + uid); 252f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 253f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller 2543ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen private boolean isLocalBinder() { 2553ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen return Process.myPid() == Binder.getCallingPid(); 2563ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen } 2573ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen 258f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller /** 259e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller * Stop listening to changes for this AppWidget. 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 261c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void deleteAppWidgetId(int appWidgetId) { 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mViews) { 263c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project mViews.remove(appWidgetId); 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 265a75a883fe9ea1790803148f0a561473073e3f264Jim Miller sService.deleteAppWidgetId(appWidgetId, mContext.getUserId()); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (RemoteException e) { 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException("system server dead?", e); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 274f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller * Stop listening to changes for this AppWidget. 275f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller * @hide 276f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller */ 277a75a883fe9ea1790803148f0a561473073e3f264Jim Miller public static void deleteAppWidgetIdForSystem(int appWidgetId, int userId) { 278f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller checkCallerIsSystem(); 279f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller try { 280f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller if (sService == null) { 281f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller bindService(); 282f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 283a75a883fe9ea1790803148f0a561473073e3f264Jim Miller sService.deleteAppWidgetId(appWidgetId, userId); 284f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } catch (RemoteException e) { 285f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller throw new RuntimeException("system server dead?", e); 286f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 287f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller } 288f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller 289f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller /** 290c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Remove all records about this host from the AppWidget manager. 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul> 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Call this when initializing your database, as it might be because of a data wipe.</li> 293c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * <li>Call this to have the AppWidget manager release all resources associated with your 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * host. Any future calls about this host will cause the records to be re-allocated.</li> 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul> 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void deleteHost() { 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 299a75a883fe9ea1790803148f0a561473073e3f264Jim Miller sService.deleteHost(mHostId, mContext.getUserId()); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (RemoteException e) { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException("system server dead?", e); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove all records about all hosts for your package. 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul> 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Call this when initializing your database, as it might be because of a data wipe.</li> 310c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * <li>Call this to have the AppWidget manager release all resources associated with your 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * host. Any future calls about this host will cause the records to be re-allocated.</li> 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul> 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void deleteAllHosts() { 315a75a883fe9ea1790803148f0a561473073e3f264Jim Miller deleteAllHosts(UserHandle.myUserId()); 316a75a883fe9ea1790803148f0a561473073e3f264Jim Miller } 317a75a883fe9ea1790803148f0a561473073e3f264Jim Miller 318a75a883fe9ea1790803148f0a561473073e3f264Jim Miller /** 319a75a883fe9ea1790803148f0a561473073e3f264Jim Miller * Private method containing a userId 320a75a883fe9ea1790803148f0a561473073e3f264Jim Miller * @hide 321a75a883fe9ea1790803148f0a561473073e3f264Jim Miller */ 322a75a883fe9ea1790803148f0a561473073e3f264Jim Miller public static void deleteAllHosts(int userId) { 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 324a75a883fe9ea1790803148f0a561473073e3f264Jim Miller sService.deleteAllHosts(userId); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (RemoteException e) { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException("system server dead?", e); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 331ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy /** 332ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy * Create the AppWidgetHostView for the given widget. 333ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy * The AppWidgetHost retains a pointer to the newly-created View. 334ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy */ 335c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public final AppWidgetHostView createView(Context context, int appWidgetId, 336c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project AppWidgetProviderInfo appWidget) { 3379831d188837fa20e125481d9ead4f916562562a7Jim Miller final int userId = mContext.getUserId(); 3389831d188837fa20e125481d9ead4f916562562a7Jim Miller AppWidgetHostView view = onCreateView(mContext, appWidgetId, appWidget); 339a75a883fe9ea1790803148f0a561473073e3f264Jim Miller view.setUserId(userId); 340e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller view.setOnClickHandler(mOnClickHandler); 341c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project view.setAppWidget(appWidgetId, appWidget); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mViews) { 343c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project mViews.put(appWidgetId, view); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 345a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy RemoteViews views; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 347a75a883fe9ea1790803148f0a561473073e3f264Jim Miller views = sService.getAppWidgetViews(appWidgetId, userId); 34894022e8997084be458a1faf46e72efab1d59e973Amith Yamasani if (views != null) { 349a75a883fe9ea1790803148f0a561473073e3f264Jim Miller views.setUser(new UserHandle(mContext.getUserId())); 35094022e8997084be458a1faf46e72efab1d59e973Amith Yamasani } 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException e) { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException("system server dead?", e); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 354c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project view.updateAppWidget(views); 355e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return view; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 360c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Called to create the AppWidgetHostView. Override to return a custom subclass if you 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * need it. {@more} 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 363c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project protected AppWidgetHostView onCreateView(Context context, int appWidgetId, 364c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project AppWidgetProviderInfo appWidget) { 365e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller return new AppWidgetHostView(context, mOnClickHandler); 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 367d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 369c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * Called when the AppWidget provider for a AppWidget has been upgraded to a new apk. 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 371c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) { 372f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato AppWidgetHostView v; 373d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen 374d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen // Convert complex to dp -- we are getting the AppWidgetProviderInfo from the 375e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller // AppWidgetService, which doesn't have our context, hence we need to do the 376d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen // conversion here. 377d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen appWidget.minWidth = 378d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics); 379d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen appWidget.minHeight = 380d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen TypedValue.complexToDimensionPixelSize(appWidget.minHeight, mDisplayMetrics); 3811bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen appWidget.minResizeWidth = 3821bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen TypedValue.complexToDimensionPixelSize(appWidget.minResizeWidth, mDisplayMetrics); 3831bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen appWidget.minResizeHeight = 3841bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen TypedValue.complexToDimensionPixelSize(appWidget.minResizeHeight, mDisplayMetrics); 385d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen 386f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato synchronized (mViews) { 387f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato v = mViews.get(appWidgetId); 388f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato } 389f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato if (v != null) { 390c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato v.resetAppWidget(appWidget); 391f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3947fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung /** 3957fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung * Called when the set of available widgets changes (ie. widget containing packages 3967fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung * are added, updated or removed, or widget components are enabled or disabled.) 3977fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung */ 3987fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung protected void onProvidersChanged() { 399a75a883fe9ea1790803148f0a561473073e3f264Jim Miller // Does nothing 400a75a883fe9ea1790803148f0a561473073e3f264Jim Miller } 401a75a883fe9ea1790803148f0a561473073e3f264Jim Miller 402a75a883fe9ea1790803148f0a561473073e3f264Jim Miller void updateAppWidgetView(int appWidgetId, RemoteViews views, int userId) { 403c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project AppWidgetHostView v; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mViews) { 405c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project v = mViews.get(appWidgetId); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v != null) { 408c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato v.updateAppWidget(views); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 411499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 412a75a883fe9ea1790803148f0a561473073e3f264Jim Miller void viewDataChanged(int appWidgetId, int viewId, int userId) { 413499cb9f516062b654952d282f211bee44c31a3c2Winson Chung AppWidgetHostView v; 414499cb9f516062b654952d282f211bee44c31a3c2Winson Chung synchronized (mViews) { 415499cb9f516062b654952d282f211bee44c31a3c2Winson Chung v = mViews.get(appWidgetId); 416499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 417499cb9f516062b654952d282f211bee44c31a3c2Winson Chung if (v != null) { 4186394c0e52cf641d93f678fd052499aa952e3595dWinson Chung v.viewDataChanged(viewId); 419499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 420499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 421ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy 422ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy /** 423ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy * Clear the list of Views that have been created by this AppWidgetHost. 424ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy */ 425ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy protected void clearViews() { 426ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy mViews.clear(); 427ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy } 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 431