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