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
197643f7e399a7d9004d77fe72f88e9947414860e4Svetoslavimport java.lang.ref.WeakReference;
20d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohenimport java.util.ArrayList;
21d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohenimport java.util.HashMap;
22d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen
238e1d299da27da534b508b1da51ebe351a689cefaSvetoslavimport android.annotation.NonNull;
248e1d299da27da534b508b1da51ebe351a689cefaSvetoslavimport android.annotation.Nullable;
25976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.app.Activity;
26976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.content.ActivityNotFoundException;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
28976e8bd2017d0263216c62111454438cc0f130e3Svetoslavimport android.content.IntentSender;
293ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohenimport android.os.Binder;
308e1d299da27da534b508b1da51ebe351a689cefaSvetoslavimport android.os.Bundle;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
35f229e4d3eb8f910c181f96416c6798f6f305a395Jim Millerimport android.os.Process;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
38d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohenimport android.util.DisplayMetrics;
39d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohenimport android.util.TypedValue;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.RemoteViews;
41e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Millerimport android.widget.RemoteViews.OnClickHandler;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
43c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport com.android.internal.appwidget.IAppWidgetHost;
44c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport com.android.internal.appwidget.IAppWidgetService;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
47c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * AppWidgetHost provides the interaction with the AppWidget service for apps,
48c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * like the home screen, that want to embed AppWidgets in their UI.
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
50c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectpublic class AppWidgetHost {
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int HANDLE_UPDATE = 1;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int HANDLE_PROVIDER_CHANGED = 2;
547fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung    static final int HANDLE_PROVIDERS_CHANGED = 3;
557fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung    static final int HANDLE_VIEW_DATA_CHANGED = 4;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
57a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy    final static Object sServiceLock = new Object();
58c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    static IAppWidgetService sService;
59d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen    private DisplayMetrics mDisplayMetrics;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
617a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung    private String mContextOpPackageName;
627643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav    private final Handler mHandler;
637643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav    private final int mHostId;
647643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav    private final Callbacks mCallbacks;
657643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav    private final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<>();
66a75a883fe9ea1790803148f0a561473073e3f264Jim Miller    private OnClickHandler mOnClickHandler;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
687643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav    static class Callbacks extends IAppWidgetHost.Stub {
697643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav        private final WeakReference<Handler> mWeakHandler;
707643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav
717643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav        public Callbacks(Handler handler) {
727643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            mWeakHandler = new WeakReference<>(handler);
737643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav        }
747643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav
75976e8bd2017d0263216c62111454438cc0f130e3Svetoslav        public void updateAppWidget(int appWidgetId, RemoteViews views) {
763ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen            if (isLocalBinder() && views != null) {
773ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen                views = views.clone();
783ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen            }
797643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            Handler handler = mWeakHandler.get();
807643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            if (handler == null) {
817643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav                return;
827643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            }
837643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            Message msg = handler.obtainMessage(HANDLE_UPDATE, appWidgetId, 0, views);
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            msg.sendToTarget();
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
87976e8bd2017d0263216c62111454438cc0f130e3Svetoslav        public void providerChanged(int appWidgetId, AppWidgetProviderInfo info) {
883ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen            if (isLocalBinder() && info != null) {
893ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen                info = info.clone();
903ff2d867d46067132890a5a6ad68be8a4314d7f6Adam Cohen            }
917643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            Handler handler = mWeakHandler.get();
927643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            if (handler == null) {
937643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav                return;
947643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            }
957643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            Message msg = handler.obtainMessage(HANDLE_PROVIDER_CHANGED,
96976e8bd2017d0263216c62111454438cc0f130e3Svetoslav                    appWidgetId, 0, info);
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            msg.sendToTarget();
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
99499cb9f516062b654952d282f211bee44c31a3c2Winson Chung
100976e8bd2017d0263216c62111454438cc0f130e3Svetoslav        public void providersChanged() {
1017643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            Handler handler = mWeakHandler.get();
1027643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            if (handler == null) {
1037643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav                return;
1047643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            }
1057643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            handler.obtainMessage(HANDLE_PROVIDERS_CHANGED).sendToTarget();
1067fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung        }
1077fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung
108976e8bd2017d0263216c62111454438cc0f130e3Svetoslav        public void viewDataChanged(int appWidgetId, int viewId) {
1097643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            Handler handler = mWeakHandler.get();
1107643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            if (handler == null) {
1117643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav                return;
1127643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            }
1137643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            Message msg = handler.obtainMessage(HANDLE_VIEW_DATA_CHANGED,
114976e8bd2017d0263216c62111454438cc0f130e3Svetoslav                    appWidgetId, viewId);
115499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            msg.sendToTarget();
116499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        }
1177643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav
1187643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav        private static boolean isLocalBinder() {
1197643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav            return Process.myPid() == Binder.getCallingPid();
1207643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav        }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class UpdateHandler extends Handler {
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public UpdateHandler(Looper looper) {
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(looper);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
127e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (msg.what) {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case HANDLE_UPDATE: {
131976e8bd2017d0263216c62111454438cc0f130e3Svetoslav                    updateAppWidgetView(msg.arg1, (RemoteViews)msg.obj);
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case HANDLE_PROVIDER_CHANGED: {
135c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                    onProviderChanged(msg.arg1, (AppWidgetProviderInfo)msg.obj);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1387fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                case HANDLE_PROVIDERS_CHANGED: {
139eeb4ff4d137a2ff2d25340c2b0396f2c3fd5068bWinson Chung                    onProvidersChanged();
1407fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                    break;
1417fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung                }
142499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                case HANDLE_VIEW_DATA_CHANGED: {
143976e8bd2017d0263216c62111454438cc0f130e3Svetoslav                    viewDataChanged(msg.arg1, msg.arg2);
144499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                    break;
145499cb9f516062b654952d282f211bee44c31a3c2Winson Chung                }
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
149e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller
150c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public AppWidgetHost(Context context, int hostId) {
151e6d5545a539068dcfdd62d43ee0ef6789bb76a8eMichael Jurka        this(context, hostId, null, context.getMainLooper());
152e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller    }
153e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller
154e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller    /**
155e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller     * @hide
156e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller     */
157f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller    public AppWidgetHost(Context context, int hostId, OnClickHandler handler, Looper looper) {
1587a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung        mContextOpPackageName = context.getOpPackageName();
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHostId = hostId;
160e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller        mOnClickHandler = handler;
161f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller        mHandler = new UpdateHandler(looper);
1627643f7e399a7d9004d77fe72f88e9947414860e4Svetoslav        mCallbacks = new Callbacks(mHandler);
163d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen        mDisplayMetrics = context.getResources().getDisplayMetrics();
164f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller        bindService();
165f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller    }
166f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller
16794022e8997084be458a1faf46e72efab1d59e973Amith Yamasani
168f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller    private static void bindService() {
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (sServiceLock) {
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sService == null) {
171c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE);
172c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project                sService = IAppWidgetService.Stub.asInterface(b);
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
178c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     * Start receiving onAppWidgetChanged calls for your AppWidgets.  Call this when your activity
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * becomes visible, i.e. from onStart() in your Activity.
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startListening() {
182a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy        int[] updatedIds;
183a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy        ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1857a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung            updatedIds = sService.startListening(mCallbacks, mContextOpPackageName, mHostId,
186976e8bd2017d0263216c62111454438cc0f130e3Svetoslav                    updatedViews);
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        catch (RemoteException e) {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("system server dead?", e);
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = updatedIds.length;
193976e8bd2017d0263216c62111454438cc0f130e3Svetoslav        for (int i = 0; i < N; i++) {
194976e8bd2017d0263216c62111454438cc0f130e3Svetoslav            updateAppWidgetView(updatedIds[i], updatedViews.get(i));
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
199c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     * Stop receiving onAppWidgetChanged calls for your AppWidgets.  Call this when your activity is
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * no longer visible, i.e. from onStop() in your Activity.
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stopListening() {
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2047a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung            sService.stopListening(mContextOpPackageName, mHostId);
205c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani        }
206c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani        catch (RemoteException e) {
207c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani            throw new RuntimeException("system server dead?", e);
208c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani        }
209c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani
210a75a883fe9ea1790803148f0a561473073e3f264Jim Miller        // This is here because keyguard needs it since it'll be switching users after this call.
211a75a883fe9ea1790803148f0a561473073e3f264Jim Miller        // If it turns out other apps need to call this often, we should re-think how this works.
212c566b43d02596cba437e9a2723e9f989297cca72Amith Yamasani        clearViews();
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
216c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     * Get a appWidgetId for a host in the calling process.
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
218c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     * @return a appWidgetId
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
220c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public int allocateAppWidgetId() {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2227a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung            return sService.allocateAppWidgetId(mContextOpPackageName, mHostId);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        catch (RemoteException e) {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("system server dead?", e);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
230976e8bd2017d0263216c62111454438cc0f130e3Svetoslav     * Starts an app widget provider configure activity for result on behalf of the caller.
231976e8bd2017d0263216c62111454438cc0f130e3Svetoslav     * Use this method if the provider is in another profile as you are not allowed to start
2328e1d299da27da534b508b1da51ebe351a689cefaSvetoslav     * an activity in another profile. You can optionally provide a request code that is
2338e1d299da27da534b508b1da51ebe351a689cefaSvetoslav     * returned in {@link Activity#onActivityResult(int, int, android.content.Intent)} and
2348e1d299da27da534b508b1da51ebe351a689cefaSvetoslav     * an options bundle to be passed to the started activity.
2358e1d299da27da534b508b1da51ebe351a689cefaSvetoslav     * <p>
2368e1d299da27da534b508b1da51ebe351a689cefaSvetoslav     * Note that the provided app widget has to be bound for this method to work.
2378e1d299da27da534b508b1da51ebe351a689cefaSvetoslav     * </p>
238f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller     *
239976e8bd2017d0263216c62111454438cc0f130e3Svetoslav     * @param activity The activity from which to start the configure one.
2408e1d299da27da534b508b1da51ebe351a689cefaSvetoslav     * @param appWidgetId The bound app widget whose provider's config activity to start.
241976e8bd2017d0263216c62111454438cc0f130e3Svetoslav     * @param requestCode Optional request code retuned with the result.
2428e1d299da27da534b508b1da51ebe351a689cefaSvetoslav     * @param intentFlags Optional intent flags.
243976e8bd2017d0263216c62111454438cc0f130e3Svetoslav     *
244976e8bd2017d0263216c62111454438cc0f130e3Svetoslav     * @throws android.content.ActivityNotFoundException If the activity is not found.
245976e8bd2017d0263216c62111454438cc0f130e3Svetoslav     *
246976e8bd2017d0263216c62111454438cc0f130e3Svetoslav     * @see AppWidgetProviderInfo#getProfile()
247f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller     */
2488e1d299da27da534b508b1da51ebe351a689cefaSvetoslav    public final void startAppWidgetConfigureActivityForResult(@NonNull Activity activity,
2498e1d299da27da534b508b1da51ebe351a689cefaSvetoslav            int appWidgetId, int intentFlags, int requestCode, @Nullable Bundle options) {
250f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller        try {
251976e8bd2017d0263216c62111454438cc0f130e3Svetoslav            IntentSender intentSender = sService.createAppWidgetConfigIntentSender(
2527a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung                    mContextOpPackageName, appWidgetId, intentFlags);
253976e8bd2017d0263216c62111454438cc0f130e3Svetoslav            if (intentSender != null) {
2548e1d299da27da534b508b1da51ebe351a689cefaSvetoslav                activity.startIntentSenderForResult(intentSender, requestCode, null, 0, 0, 0,
2558e1d299da27da534b508b1da51ebe351a689cefaSvetoslav                        options);
256976e8bd2017d0263216c62111454438cc0f130e3Svetoslav            } else {
257976e8bd2017d0263216c62111454438cc0f130e3Svetoslav                throw new ActivityNotFoundException();
258f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller            }
259976e8bd2017d0263216c62111454438cc0f130e3Svetoslav        } catch (IntentSender.SendIntentException e) {
260976e8bd2017d0263216c62111454438cc0f130e3Svetoslav            throw new ActivityNotFoundException();
261f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller        } catch (RemoteException e) {
262f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller            throw new RuntimeException("system server dead?", e);
263f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller        }
264f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller    }
265f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller
26675b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka    /**
26775b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka     * Gets a list of all the appWidgetIds that are bound to the current host
26875b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka     *
26975b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka     * @hide
27075b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka     */
27175b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka    public int[] getAppWidgetIds() {
27275b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka        try {
27375b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka            if (sService == null) {
27475b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka                bindService();
27575b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka            }
2767a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung            return sService.getAppWidgetIdsForHost(mContextOpPackageName, mHostId);
27775b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka        } catch (RemoteException e) {
27875b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka            throw new RuntimeException("system server dead?", e);
27975b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka        }
28075b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka    }
28175b5cfb4a41030333820d072578a288d4ec9899cMichael Jurka
282f229e4d3eb8f910c181f96416c6798f6f305a395Jim Miller    /**
283e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller     * Stop listening to changes for this AppWidget.
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
285c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    public void deleteAppWidgetId(int appWidgetId) {
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mViews) {
287c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            mViews.remove(appWidgetId);
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2897a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung                sService.deleteAppWidgetId(mContextOpPackageName, appWidgetId);
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            catch (RemoteException e) {
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new RuntimeException("system server dead?", e);
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
298c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     * Remove all records about this host from the AppWidget manager.
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Call this when initializing your database, as it might be because of a data wipe.</li>
301c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     *   <li>Call this to have the AppWidget manager release all resources associated with your
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   host.  Any future calls about this host will cause the records to be re-allocated.</li>
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void deleteHost() {
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3077a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung            sService.deleteHost(mContextOpPackageName, mHostId);
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        catch (RemoteException e) {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("system server dead?", e);
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove all records about all hosts for your package.
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Call this when initializing your database, as it might be because of a data wipe.</li>
318c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     *   <li>Call this to have the AppWidget manager release all resources associated with your
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   host.  Any future calls about this host will cause the records to be re-allocated.</li>
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void deleteAllHosts() {
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
324976e8bd2017d0263216c62111454438cc0f130e3Svetoslav            sService.deleteAllHosts();
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) {
3377a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung        AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
338e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller        view.setOnClickHandler(mOnClickHandler);
339c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        view.setAppWidget(appWidgetId, appWidget);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mViews) {
341c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            mViews.put(appWidgetId, view);
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
343a54755962ca7725d1e2b6cacbbaece6f1cbf5af4Romain Guy        RemoteViews views;
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3457a96f3c917e0001ee739b65da37b2fadec7d7765Winson Chung            views = sService.getAppWidgetViews(mContextOpPackageName, appWidgetId);
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("system server dead?", e);
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
349c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        view.updateAppWidget(views);
350e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return view;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
355c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     * Called to create the AppWidgetHostView.  Override to return a custom subclass if you
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * need it.  {@more}
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
358c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
359c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            AppWidgetProviderInfo appWidget) {
360e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller        return new AppWidgetHostView(context, mOnClickHandler);
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
362d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
364c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project     * Called when the AppWidget provider for a AppWidget has been upgraded to a new apk.
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
366c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project    protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) {
367f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato        AppWidgetHostView v;
368d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen
369d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen        // Convert complex to dp -- we are getting the AppWidgetProviderInfo from the
370e667a7add46a6389c64f2105bd33943cfe6a3fa4Jim Miller        // AppWidgetService, which doesn't have our context, hence we need to do the
371d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen        // conversion here.
372d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen        appWidget.minWidth =
373d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen            TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics);
374d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen        appWidget.minHeight =
375d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen            TypedValue.complexToDimensionPixelSize(appWidget.minHeight, mDisplayMetrics);
3761bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen        appWidget.minResizeWidth =
3771bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen            TypedValue.complexToDimensionPixelSize(appWidget.minResizeWidth, mDisplayMetrics);
3781bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen        appWidget.minResizeHeight =
3791bfaf561b7c09388311f1834f17e057739cf587aAdam Cohen            TypedValue.complexToDimensionPixelSize(appWidget.minResizeHeight, mDisplayMetrics);
380d2e20de64b6de8b6391c63e2f5b02ce7698bf4bfAdam Cohen
381f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato        synchronized (mViews) {
382f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato            v = mViews.get(appWidgetId);
383f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato        }
384f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato        if (v != null) {
385c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato            v.resetAppWidget(appWidget);
386f140be6c3c21dd0f6d2214929e89d60de31d2c04Joe Onorato        }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3897fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung    /**
3907fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung     * Called when the set of available widgets changes (ie. widget containing packages
3917fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung     * are added, updated or removed, or widget components are enabled or disabled.)
3927fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung     */
3937fbd28438c2322973c77f31f0721a24fe1c35039Winson Chung    protected void onProvidersChanged() {
394a75a883fe9ea1790803148f0a561473073e3f264Jim Miller        // Does nothing
395a75a883fe9ea1790803148f0a561473073e3f264Jim Miller    }
396a75a883fe9ea1790803148f0a561473073e3f264Jim Miller
397976e8bd2017d0263216c62111454438cc0f130e3Svetoslav    void updateAppWidgetView(int appWidgetId, RemoteViews views) {
398c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        AppWidgetHostView v;
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mViews) {
400c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            v = mViews.get(appWidgetId);
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (v != null) {
403c27bb559805ae5cd06f7ecf575959c60c51a22aaJoe Onorato            v.updateAppWidget(views);
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
406499cb9f516062b654952d282f211bee44c31a3c2Winson Chung
407976e8bd2017d0263216c62111454438cc0f130e3Svetoslav    void viewDataChanged(int appWidgetId, int viewId) {
408499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        AppWidgetHostView v;
409499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        synchronized (mViews) {
410499cb9f516062b654952d282f211bee44c31a3c2Winson Chung            v = mViews.get(appWidgetId);
411499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        }
412499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        if (v != null) {
4136394c0e52cf641d93f678fd052499aa952e3595dWinson Chung            v.viewDataChanged(viewId);
414499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        }
415499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    }
416ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy
417ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy    /**
418ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy     * Clear the list of Views that have been created by this AppWidgetHost.
419ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy     */
420ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy    protected void clearViews() {
421ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy        mViews.clear();
422ec84c3a189e4aa70aa6ea8ba712e5a4f260a153bPatrick Dubroy    }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
426