/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server;

import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.Intent.FilterComparison;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Point;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.AtomicFile;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.TypedValue;
import android.util.Xml;
import android.view.Display;
import android.view.WindowManager;
import android.widget.RemoteViews;

import com.android.internal.appwidget.IAppWidgetHost;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.widget.IRemoteViewsAdapterConnection;
import com.android.internal.widget.IRemoteViewsFactory;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;

class AppWidgetServiceImpl {

    private static final String KEYGUARD_HOST_PACKAGE = "com.android.keyguard";
    private static final int KEYGUARD_HOST_ID = 0x4b455947;
    private static final String TAG = "AppWidgetServiceImpl";
    private static final String SETTINGS_FILENAME = "appwidgets.xml";
    private static final int MIN_UPDATE_PERIOD = 30 * 60 * 1000; // 30 minutes
    private static final int CURRENT_VERSION = 1; // Bump if the stored widgets need to be upgraded.

    private static boolean DBG = false;

    /*
     * When identifying a Host or Provider based on the calling process, use the uid field. When
     * identifying a Host or Provider based on a package manager broadcast, use the package given.
     */

    static class Provider {
        int uid;
        AppWidgetProviderInfo info;
        ArrayList<AppWidgetId> instances = new ArrayList<AppWidgetId>();
        PendingIntent broadcast;
        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it

        int tag; // for use while saving state (the index)
    }

    static class Host {
        int uid;
        int hostId;
        String packageName;
        ArrayList<AppWidgetId> instances = new ArrayList<AppWidgetId>();
        IAppWidgetHost callbacks;
        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it

        int tag; // for use while saving state (the index)

        boolean uidMatches(int callingUid) {
            if (UserHandle.getAppId(callingUid) == Process.myUid()) {
                // For a host that's in the system process, ignore the user id
                return UserHandle.isSameApp(this.uid, callingUid);
            } else {
                return this.uid == callingUid;
            }
        }
    }

    static class AppWidgetId {
        int appWidgetId;
        Provider provider;
        RemoteViews views;
        Bundle options;
        Host host;
    }

    /**
     * Acts as a proxy between the ServiceConnection and the RemoteViewsAdapterConnection. This
     * needs to be a static inner class since a reference to the ServiceConnection is held globally
     * and may lead us to leak AppWidgetService instances (if there were more than one).
     */
    static class ServiceConnectionProxy implements ServiceConnection {
        private final IBinder mConnectionCb;

        ServiceConnectionProxy(Pair<Integer, Intent.FilterComparison> key, IBinder connectionCb) {
            mConnectionCb = connectionCb;
        }

        public void onServiceConnected(ComponentName name, IBinder service) {
            final IRemoteViewsAdapterConnection cb = IRemoteViewsAdapterConnection.Stub
                    .asInterface(mConnectionCb);
            try {
                cb.onServiceConnected(service);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void onServiceDisconnected(ComponentName name) {
            disconnect();
        }

        public void disconnect() {
            final IRemoteViewsAdapterConnection cb = IRemoteViewsAdapterConnection.Stub
                    .asInterface(mConnectionCb);
            try {
                cb.onServiceDisconnected();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // Manages active connections to RemoteViewsServices
    private final HashMap<Pair<Integer, FilterComparison>, ServiceConnection> mBoundRemoteViewsServices = new HashMap<Pair<Integer, FilterComparison>, ServiceConnection>();
    // Manages persistent references to RemoteViewsServices from different App Widgets
    private final HashMap<FilterComparison, HashSet<Integer>> mRemoteViewsServicesAppWidgets = new HashMap<FilterComparison, HashSet<Integer>>();

    final Context mContext;
    final IPackageManager mPm;
    final AlarmManager mAlarmManager;
    final ArrayList<Provider> mInstalledProviders = new ArrayList<Provider>();
    final int mUserId;
    final boolean mHasFeature;

    Locale mLocale;
    int mNextAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + 1;
    final ArrayList<AppWidgetId> mAppWidgetIds = new ArrayList<AppWidgetId>();
    final ArrayList<Host> mHosts = new ArrayList<Host>();
    // set of package names
    final HashSet<String> mPackagesWithBindWidgetPermission = new HashSet<String>();
    boolean mSafeMode;
    boolean mStateLoaded;
    int mMaxWidgetBitmapMemory;

    private final Handler mSaveStateHandler;

    // These are for debugging only -- widgets are going missing in some rare instances
    ArrayList<Provider> mDeletedProviders = new ArrayList<Provider>();
    ArrayList<Host> mDeletedHosts = new ArrayList<Host>();

    AppWidgetServiceImpl(Context context, int userId, Handler saveStateHandler) {
        mContext = context;
        mPm = AppGlobals.getPackageManager();
        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        mUserId = userId;
        mSaveStateHandler = saveStateHandler;
        mHasFeature = context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_APP_WIDGETS);
        computeMaximumWidgetBitmapMemory();
    }

    void computeMaximumWidgetBitmapMemory() {
        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point size = new Point();
        display.getRealSize(size);
        // Cap memory usage at 1.5 times the size of the display
        // 1.5 * 4 bytes/pixel * w * h ==> 6 * w * h
        mMaxWidgetBitmapMemory = 6 * size.x * size.y;
    }

    public void systemReady(boolean safeMode) {
        mSafeMode = safeMode;

        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
        }
    }

    private void log(String msg) {
        Slog.i(TAG, "u=" + mUserId + ": " + msg);
    }

    void onConfigurationChanged() {
        if (DBG) log("Got onConfigurationChanged()");
        Locale revised = Locale.getDefault();
        if (revised == null || mLocale == null || !(revised.equals(mLocale))) {
            mLocale = revised;

            synchronized (mAppWidgetIds) {
                ensureStateLoadedLocked();
                // Note: updateProvidersForPackageLocked() may remove providers, so we must copy the
                // list of installed providers and skip providers that we don't need to update.
                // Also note that remove the provider does not clear the Provider component data.
                ArrayList<Provider> installedProviders =
                        new ArrayList<Provider>(mInstalledProviders);
                HashSet<ComponentName> removedProviders = new HashSet<ComponentName>();
                int N = installedProviders.size();
                for (int i = N - 1; i >= 0; i--) {
                    Provider p = installedProviders.get(i);
                    ComponentName cn = p.info.provider;
                    if (!removedProviders.contains(cn)) {
                        updateProvidersForPackageLocked(cn.getPackageName(), removedProviders);
                    }
                }
                saveStateAsync();
            }
        }
    }

    void onBroadcastReceived(Intent intent) {
        if (DBG) log("onBroadcast " + intent);
        final String action = intent.getAction();
        boolean added = false;
        boolean changed = false;
        boolean providersModified = false;
        String pkgList[] = null;
        if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
            pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
            added = true;
        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
            pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
            added = false;
        } else {
            Uri uri = intent.getData();
            if (uri == null) {
                return;
            }
            String pkgName = uri.getSchemeSpecificPart();
            if (pkgName == null) {
                return;
            }
            pkgList = new String[] { pkgName };
            added = Intent.ACTION_PACKAGE_ADDED.equals(action);
            changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
        }
        if (pkgList == null || pkgList.length == 0) {
            return;
        }
        if (added || changed) {
            synchronized (mAppWidgetIds) {
                ensureStateLoadedLocked();
                Bundle extras = intent.getExtras();
                if (changed
                        || (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false))) {
                    for (String pkgName : pkgList) {
                        // The package was just upgraded
                        providersModified |= updateProvidersForPackageLocked(pkgName, null);
                    }
                } else {
                    // The package was just added
                    for (String pkgName : pkgList) {
                        providersModified |= addProvidersForPackageLocked(pkgName);
                    }
                }
                saveStateAsync();
            }
        } else {
            Bundle extras = intent.getExtras();
            if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
                // The package is being updated. We'll receive a PACKAGE_ADDED shortly.
            } else {
                synchronized (mAppWidgetIds) {
                    ensureStateLoadedLocked();
                    for (String pkgName : pkgList) {
                        providersModified |= removeProvidersForPackageLocked(pkgName);
                        saveStateAsync();
                    }
                }
            }
        }

        if (providersModified) {
            // If the set of providers has been modified, notify each active AppWidgetHost
            synchronized (mAppWidgetIds) {
                ensureStateLoadedLocked();
                notifyHostsForProvidersChangedLocked();
            }
        }
    }

    private void dumpProvider(Provider p, int index, PrintWriter pw) {
        AppWidgetProviderInfo info = p.info;
        pw.print("  ["); pw.print(index); pw.print("] provider ");
                pw.print(info.provider.flattenToShortString());
                pw.println(':');
        pw.print("    min=("); pw.print(info.minWidth);
                pw.print("x"); pw.print(info.minHeight);
        pw.print(")   minResize=("); pw.print(info.minResizeWidth);
                pw.print("x"); pw.print(info.minResizeHeight);
                pw.print(") updatePeriodMillis=");
                pw.print(info.updatePeriodMillis);
                pw.print(" resizeMode=");
                pw.print(info.resizeMode);
                pw.print(info.widgetCategory);
                pw.print(" autoAdvanceViewId=");
                pw.print(info.autoAdvanceViewId);
                pw.print(" initialLayout=#");
                pw.print(Integer.toHexString(info.initialLayout));
                pw.print(" uid="); pw.print(p.uid);
                pw.print(" zombie="); pw.println(p.zombie);
    }

    private void dumpHost(Host host, int index, PrintWriter pw) {
        pw.print("  ["); pw.print(index); pw.print("] hostId=");
                pw.print(host.hostId); pw.print(' ');
                pw.print(host.packageName); pw.print('/');
        pw.print(host.uid); pw.println(':');
        pw.print("    callbacks="); pw.println(host.callbacks);
        pw.print("    instances.size="); pw.print(host.instances.size());
                pw.print(" zombie="); pw.println(host.zombie);
    }

    private void dumpAppWidgetId(AppWidgetId id, int index, PrintWriter pw) {
        pw.print("  ["); pw.print(index); pw.print("] id=");
                pw.println(id.appWidgetId);
        pw.print("    hostId=");
                pw.print(id.host.hostId); pw.print(' ');
                pw.print(id.host.packageName); pw.print('/');
                pw.println(id.host.uid);
        if (id.provider != null) {
            pw.print("    provider=");
                    pw.println(id.provider.info.provider.flattenToShortString());
        }
        if (id.host != null) {
            pw.print("    host.callbacks="); pw.println(id.host.callbacks);
        }
        if (id.views != null) {
            pw.print("    views="); pw.println(id.views);
        }
    }

    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                != PackageManager.PERMISSION_GRANTED) {
            pw.println("Permission Denial: can't dump from from pid="
                    + Binder.getCallingPid()
                    + ", uid=" + Binder.getCallingUid());
            return;
        }

        synchronized (mAppWidgetIds) {
            int N = mInstalledProviders.size();
            pw.println("Providers:");
            for (int i=0; i<N; i++) {
                dumpProvider(mInstalledProviders.get(i), i, pw);
            }

            N = mAppWidgetIds.size();
            pw.println(" ");
            pw.println("AppWidgetIds:");
            for (int i=0; i<N; i++) {
                dumpAppWidgetId(mAppWidgetIds.get(i), i, pw);
            }

            N = mHosts.size();
            pw.println(" ");
            pw.println("Hosts:");
            for (int i=0; i<N; i++) {
                dumpHost(mHosts.get(i), i, pw);
            }

            N = mDeletedProviders.size();
            pw.println(" ");
            pw.println("Deleted Providers:");
            for (int i=0; i<N; i++) {
                dumpProvider(mDeletedProviders.get(i), i, pw);
            }

            N = mDeletedHosts.size();
            pw.println(" ");
            pw.println("Deleted Hosts:");
            for (int i=0; i<N; i++) {
                dumpHost(mDeletedHosts.get(i), i, pw);
            }
        }
    }

    private void ensureStateLoadedLocked() {
        if (!mStateLoaded) {
            if (!mHasFeature) {
                return;
            }
            loadAppWidgetListLocked();
            loadStateLocked();
            mStateLoaded = true;
        }
    }

    public int allocateAppWidgetId(String packageName, int hostId) {
        int callingUid = enforceSystemOrCallingUid(packageName);
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return -1;
            }
            ensureStateLoadedLocked();
            int appWidgetId = mNextAppWidgetId++;

            Host host = lookupOrAddHostLocked(callingUid, packageName, hostId);

            AppWidgetId id = new AppWidgetId();
            id.appWidgetId = appWidgetId;
            id.host = host;

            host.instances.add(id);
            mAppWidgetIds.add(id);

            saveStateAsync();
            if (DBG) log("Allocating AppWidgetId for " + packageName + " host=" + hostId
                    + " id=" + appWidgetId);
            return appWidgetId;
        }
    }

    public void deleteAppWidgetId(int appWidgetId) {
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return;
            }
            ensureStateLoadedLocked();
            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
            if (id != null) {
                deleteAppWidgetLocked(id);
                saveStateAsync();
            }
        }
    }

    public void deleteHost(int hostId) {
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return;
            }
            ensureStateLoadedLocked();
            int callingUid = Binder.getCallingUid();
            Host host = lookupHostLocked(callingUid, hostId);
            if (host != null) {
                deleteHostLocked(host);
                saveStateAsync();
            }
        }
    }

    public void deleteAllHosts() {
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return;
            }
            ensureStateLoadedLocked();
            int callingUid = Binder.getCallingUid();
            final int N = mHosts.size();
            boolean changed = false;
            for (int i = N - 1; i >= 0; i--) {
                Host host = mHosts.get(i);
                if (host.uidMatches(callingUid)) {
                    deleteHostLocked(host);
                    changed = true;
                }
            }
            if (changed) {
                saveStateAsync();
            }
        }
    }

    void deleteHostLocked(Host host) {
        final int N = host.instances.size();
        for (int i = N - 1; i >= 0; i--) {
            AppWidgetId id = host.instances.get(i);
            deleteAppWidgetLocked(id);
        }
        host.instances.clear();
        mHosts.remove(host);
        mDeletedHosts.add(host);
        // it's gone or going away, abruptly drop the callback connection
        host.callbacks = null;
    }

    void deleteAppWidgetLocked(AppWidgetId id) {
        // We first unbind all services that are bound to this id
        unbindAppWidgetRemoteViewsServicesLocked(id);

        Host host = id.host;
        host.instances.remove(id);
        pruneHostLocked(host);

        mAppWidgetIds.remove(id);

        Provider p = id.provider;
        if (p != null) {
            p.instances.remove(id);
            if (!p.zombie) {
                // send the broacast saying that this appWidgetId has been deleted
                Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED);
                intent.setComponent(p.info.provider);
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
                mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
                if (p.instances.size() == 0) {
                    // cancel the future updates
                    cancelBroadcasts(p);

                    // send the broacast saying that the provider is not in use any more
                    intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED);
                    intent.setComponent(p.info.provider);
                    mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
                }
            }
        }
    }

    void cancelBroadcasts(Provider p) {
        if (DBG) log("cancelBroadcasts for " + p);
        if (p.broadcast != null) {
            mAlarmManager.cancel(p.broadcast);
            long token = Binder.clearCallingIdentity();
            try {
                p.broadcast.cancel();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
            p.broadcast = null;
        }
    }

    private void bindAppWidgetIdImpl(int appWidgetId, ComponentName provider, Bundle options) {
        if (DBG) log("bindAppWidgetIdImpl appwid=" + appWidgetId
                + " provider=" + provider);
        final long ident = Binder.clearCallingIdentity();
        try {
            synchronized (mAppWidgetIds) {
                if (!mHasFeature) {
                    return;
                }
                options = cloneIfLocalBinder(options);
                ensureStateLoadedLocked();
                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
                if (id == null) {
                    throw new IllegalArgumentException("bad appWidgetId");
                }
                if (id.provider != null) {
                    throw new IllegalArgumentException("appWidgetId " + appWidgetId
                            + " already bound to " + id.provider.info.provider);
                }
                Provider p = lookupProviderLocked(provider);
                if (p == null) {
                    throw new IllegalArgumentException("not a appwidget provider: " + provider);
                }
                if (p.zombie) {
                    throw new IllegalArgumentException("can't bind to a 3rd party provider in"
                            + " safe mode: " + provider);
                }

                id.provider = p;
                if (options == null) {
                    options = new Bundle();
                }
                id.options = options;

                // We need to provide a default value for the widget category if it is not specified
                if (!options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) {
                    options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
                            AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
                }

                p.instances.add(id);
                int instancesSize = p.instances.size();
                if (instancesSize == 1) {
                    // tell the provider that it's ready
                    sendEnableIntentLocked(p);
                }

                // send an update now -- We need this update now, and just for this appWidgetId.
                // It's less critical when the next one happens, so when we schedule the next one,
                // we add updatePeriodMillis to its start time. That time will have some slop,
                // but that's okay.
                sendUpdateIntentLocked(p, new int[] { appWidgetId });

                // schedule the future updates
                registerForBroadcastsLocked(p, getAppWidgetIds(p));
                saveStateAsync();
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

    public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET,
            "bindAppWidgetId appWidgetId=" + appWidgetId + " provider=" + provider);
        bindAppWidgetIdImpl(appWidgetId, provider, options);
    }

    public boolean bindAppWidgetIdIfAllowed(
            String packageName, int appWidgetId, ComponentName provider, Bundle options) {
        if (!mHasFeature) {
            return false;
        }
        try {
            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET, null);
        } catch (SecurityException se) {
            if (!callerHasBindAppWidgetPermission(packageName)) {
                return false;
            }
        }
        bindAppWidgetIdImpl(appWidgetId, provider, options);
        return true;
    }

    private boolean callerHasBindAppWidgetPermission(String packageName) {
        int callingUid = Binder.getCallingUid();
        try {
            if (!UserHandle.isSameApp(callingUid, getUidForPackage(packageName))) {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            return mPackagesWithBindWidgetPermission.contains(packageName);
        }
    }

    public boolean hasBindAppWidgetPermission(String packageName) {
        if (!mHasFeature) {
            return false;
        }
        mContext.enforceCallingPermission(
                android.Manifest.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS,
                "hasBindAppWidgetPermission packageName=" + packageName);

        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            return mPackagesWithBindWidgetPermission.contains(packageName);
        }
    }

    public void setBindAppWidgetPermission(String packageName, boolean permission) {
        if (!mHasFeature) {
            return;
        }
        mContext.enforceCallingPermission(
                android.Manifest.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS,
                "setBindAppWidgetPermission packageName=" + packageName);

        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            if (permission) {
                mPackagesWithBindWidgetPermission.add(packageName);
            } else {
                mPackagesWithBindWidgetPermission.remove(packageName);
            }
            saveStateAsync();
        }
    }

    // Binds to a specific RemoteViewsService
    public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection) {
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return;
            }
            ensureStateLoadedLocked();
            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
            if (id == null) {
                throw new IllegalArgumentException("bad appWidgetId");
            }
            final ComponentName componentName = intent.getComponent();
            try {
                final ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(componentName,
                        PackageManager.GET_PERMISSIONS, mUserId);
                if (!android.Manifest.permission.BIND_REMOTEVIEWS.equals(si.permission)) {
                    throw new SecurityException("Selected service does not require "
                            + android.Manifest.permission.BIND_REMOTEVIEWS + ": " + componentName);
                }
            } catch (RemoteException e) {
                throw new IllegalArgumentException("Unknown component " + componentName);
            }

            // If there is already a connection made for this service intent, then disconnect from
            // that first. (This does not allow multiple connections to the same service under
            // the same key)
            ServiceConnectionProxy conn = null;
            FilterComparison fc = new FilterComparison(intent);
            Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, fc);
            if (mBoundRemoteViewsServices.containsKey(key)) {
                conn = (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key);
                conn.disconnect();
                mContext.unbindService(conn);
                mBoundRemoteViewsServices.remove(key);
            }

            int userId = UserHandle.getUserId(id.provider.uid);
            if (userId != mUserId) {
                Slog.w(TAG, "AppWidgetServiceImpl of user " + mUserId
                        + " binding to provider on user " + userId);
            }
            // Bind to the RemoteViewsService (which will trigger a callback to the
            // RemoteViewsAdapter.onServiceConnected())
            final long token = Binder.clearCallingIdentity();
            try {
                conn = new ServiceConnectionProxy(key, connection);
                mContext.bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE,
                        new UserHandle(userId));
                mBoundRemoteViewsServices.put(key, conn);
            } finally {
                Binder.restoreCallingIdentity(token);
            }

            // Add it to the mapping of RemoteViewsService to appWidgetIds so that we can determine
            // when we can call back to the RemoteViewsService later to destroy associated
            // factories.
            incrementAppWidgetServiceRefCount(appWidgetId, fc);
        }
    }

    // Unbinds from a specific RemoteViewsService
    public void unbindRemoteViewsService(int appWidgetId, Intent intent) {
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return;
            }
            ensureStateLoadedLocked();
            // Unbind from the RemoteViewsService (which will trigger a callback to the bound
            // RemoteViewsAdapter)
            Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, new FilterComparison(
                    intent));
            if (mBoundRemoteViewsServices.containsKey(key)) {
                // We don't need to use the appWidgetId until after we are sure there is something
                // to unbind. Note that this may mask certain issues with apps calling unbind()
                // more than necessary.
                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
                if (id == null) {
                    throw new IllegalArgumentException("bad appWidgetId");
                }

                ServiceConnectionProxy conn = (ServiceConnectionProxy) mBoundRemoteViewsServices
                        .get(key);
                conn.disconnect();
                mContext.unbindService(conn);
                mBoundRemoteViewsServices.remove(key);
            }
        }
    }

    // Unbinds from a RemoteViewsService when we delete an app widget
    private void unbindAppWidgetRemoteViewsServicesLocked(AppWidgetId id) {
        int appWidgetId = id.appWidgetId;
        // Unbind all connections to Services bound to this AppWidgetId
        Iterator<Pair<Integer, Intent.FilterComparison>> it = mBoundRemoteViewsServices.keySet()
                .iterator();
        while (it.hasNext()) {
            final Pair<Integer, Intent.FilterComparison> key = it.next();
            if (key.first.intValue() == appWidgetId) {
                final ServiceConnectionProxy conn = (ServiceConnectionProxy) mBoundRemoteViewsServices
                        .get(key);
                conn.disconnect();
                mContext.unbindService(conn);
                it.remove();
            }
        }

        // Check if we need to destroy any services (if no other app widgets are
        // referencing the same service)
        decrementAppWidgetServiceRefCount(id);
    }

    // Destroys the cached factory on the RemoteViewsService's side related to the specified intent
    private void destroyRemoteViewsService(final Intent intent, AppWidgetId id) {
        final ServiceConnection conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                final IRemoteViewsFactory cb = IRemoteViewsFactory.Stub.asInterface(service);
                try {
                    cb.onDestroy(intent);
                } catch (RemoteException e) {
                    e.printStackTrace();
                } catch (RuntimeException e) {
                    e.printStackTrace();
                }
                mContext.unbindService(this);
            }

            @Override
            public void onServiceDisconnected(android.content.ComponentName name) {
                // Do nothing
            }
        };

        int userId = UserHandle.getUserId(id.provider.uid);
        // Bind to the service and remove the static intent->factory mapping in the
        // RemoteViewsService.
        final long token = Binder.clearCallingIdentity();
        try {
            mContext.bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE,
                    new UserHandle(userId));
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    // Adds to the ref-count for a given RemoteViewsService intent
    private void incrementAppWidgetServiceRefCount(int appWidgetId, FilterComparison fc) {
        HashSet<Integer> appWidgetIds = null;
        if (mRemoteViewsServicesAppWidgets.containsKey(fc)) {
            appWidgetIds = mRemoteViewsServicesAppWidgets.get(fc);
        } else {
            appWidgetIds = new HashSet<Integer>();
            mRemoteViewsServicesAppWidgets.put(fc, appWidgetIds);
        }
        appWidgetIds.add(appWidgetId);
    }

    // Subtracts from the ref-count for a given RemoteViewsService intent, prompting a delete if
    // the ref-count reaches zero.
    private void decrementAppWidgetServiceRefCount(AppWidgetId id) {
        Iterator<FilterComparison> it = mRemoteViewsServicesAppWidgets.keySet().iterator();
        while (it.hasNext()) {
            final FilterComparison key = it.next();
            final HashSet<Integer> ids = mRemoteViewsServicesAppWidgets.get(key);
            if (ids.remove(id.appWidgetId)) {
                // If we have removed the last app widget referencing this service, then we
                // should destroy it and remove it from this set
                if (ids.isEmpty()) {
                    destroyRemoteViewsService(key.getIntent(), id);
                    it.remove();
                }
            }
        }
    }

    public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return null;
            }
            ensureStateLoadedLocked();
            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
            if (id != null && id.provider != null && !id.provider.zombie) {
                return cloneIfLocalBinder(id.provider.info);
            }
            return null;
        }
    }

    public RemoteViews getAppWidgetViews(int appWidgetId) {
        if (DBG) log("getAppWidgetViews id=" + appWidgetId);
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return null;
            }
            ensureStateLoadedLocked();
            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
            if (id != null) {
                return cloneIfLocalBinder(id.views);
            }
            if (DBG) log("   couldn't find appwidgetid");
            return null;
        }
    }

    public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return new ArrayList<AppWidgetProviderInfo>(0);
            }
            ensureStateLoadedLocked();
            final int N = mInstalledProviders.size();
            ArrayList<AppWidgetProviderInfo> result = new ArrayList<AppWidgetProviderInfo>(N);
            for (int i = 0; i < N; i++) {
                Provider p = mInstalledProviders.get(i);
                if (!p.zombie && (p.info.widgetCategory & categoryFilter) != 0) {
                    result.add(cloneIfLocalBinder(p.info));
                }
            }
            return result;
        }
    }

    public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) {
        if (!mHasFeature) {
            return;
        }
        if (appWidgetIds == null) {
            return;
        }
        if (DBG) log("updateAppWidgetIds views: " + views);
        int bitmapMemoryUsage = 0;
        if (views != null) {
            bitmapMemoryUsage = views.estimateMemoryUsage();
        }
        if (bitmapMemoryUsage > mMaxWidgetBitmapMemory) {
            throw new IllegalArgumentException("RemoteViews for widget update exceeds maximum" +
                    " bitmap memory usage (used: " + bitmapMemoryUsage + ", max: " +
                    mMaxWidgetBitmapMemory + ") The total memory cannot exceed that required to" +
                    " fill the device's screen once.");
        }

        if (appWidgetIds.length == 0) {
            return;
        }
        final int N = appWidgetIds.length;

        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            for (int i = 0; i < N; i++) {
                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
                updateAppWidgetInstanceLocked(id, views);
            }
        }
    }

    private void saveStateAsync() {
        mSaveStateHandler.post(mSaveStateRunnable);
    }

    private final Runnable mSaveStateRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (mAppWidgetIds) {
                ensureStateLoadedLocked();
                saveStateLocked();
            }
        }
    };

    public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return;
            }
            options = cloneIfLocalBinder(options);
            ensureStateLoadedLocked();
            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);

            if (id == null) {
                return;
            }

            Provider p = id.provider;
            // Merge the options
            id.options.putAll(options);

            // send the broacast saying that this appWidgetId has been deleted
            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED);
            intent.setComponent(p.info.provider);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, id.options);
            mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
            saveStateAsync();
        }
    }

    public Bundle getAppWidgetOptions(int appWidgetId) {
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return Bundle.EMPTY;
            }
            ensureStateLoadedLocked();
            AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
            if (id != null && id.options != null) {
                return cloneIfLocalBinder(id.options);
            } else {
                return Bundle.EMPTY;
            }
        }
    }

    public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views) {
        if (!mHasFeature) {
            return;
        }
        if (appWidgetIds == null) {
            return;
        }
        if (appWidgetIds.length == 0) {
            return;
        }
        final int N = appWidgetIds.length;

        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            for (int i = 0; i < N; i++) {
                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
                if (id == null) {
                    Slog.w(TAG, "widget id " + appWidgetIds[i] + " not found!");
                } else if (id.views != null) {
                    // Only trigger a partial update for a widget if it has received a full update
                    updateAppWidgetInstanceLocked(id, views, true);
                }
            }
        }
    }

    public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
        if (!mHasFeature) {
            return;
        }
        if (appWidgetIds == null) {
            return;
        }
        if (appWidgetIds.length == 0) {
            return;
        }
        final int N = appWidgetIds.length;

        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            for (int i = 0; i < N; i++) {
                AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
                notifyAppWidgetViewDataChangedInstanceLocked(id, viewId);
            }
        }
    }

    public void updateAppWidgetProvider(ComponentName provider, RemoteViews views) {
        if (!mHasFeature) {
            return;
        }
        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            Provider p = lookupProviderLocked(provider);
            if (p == null) {
                Slog.w(TAG, "updateAppWidgetProvider: provider doesn't exist: " + provider);
                return;
            }
            ArrayList<AppWidgetId> instances = p.instances;
            final int callingUid = Binder.getCallingUid();
            final int N = instances.size();
            for (int i = 0; i < N; i++) {
                AppWidgetId id = instances.get(i);
                if (canAccessAppWidgetId(id, callingUid)) {
                    updateAppWidgetInstanceLocked(id, views);
                }
            }
        }
    }

    void updateAppWidgetInstanceLocked(AppWidgetId id, RemoteViews views) {
        updateAppWidgetInstanceLocked(id, views, false);
    }

    void updateAppWidgetInstanceLocked(AppWidgetId id, RemoteViews views, boolean isPartialUpdate) {
        // allow for stale appWidgetIds and other badness
        // lookup also checks that the calling process can access the appWidgetId
        // drop unbound appWidgetIds (shouldn't be possible under normal circumstances)
        if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) {

            if (!isPartialUpdate) {
                // For a full update we replace the RemoteViews completely.
                id.views = views;
            } else {
                // For a partial update, we merge the new RemoteViews with the old.
                id.views.mergeRemoteViews(views);
            }

            // is anyone listening?
            if (id.host.callbacks != null) {
                try {
                    // the lock is held, but this is a oneway call
                    id.host.callbacks.updateAppWidget(id.appWidgetId, views, mUserId);
                } catch (RemoteException e) {
                    // It failed; remove the callback. No need to prune because
                    // we know that this host is still referenced by this instance.
                    id.host.callbacks = null;
                }
            }
        }
    }

    void notifyAppWidgetViewDataChangedInstanceLocked(AppWidgetId id, int viewId) {
        // allow for stale appWidgetIds and other badness
        // lookup also checks that the calling process can access the appWidgetId
        // drop unbound appWidgetIds (shouldn't be possible under normal circumstances)
        if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) {
            // is anyone listening?
            if (id.host.callbacks != null) {
                try {
                    // the lock is held, but this is a oneway call
                    id.host.callbacks.viewDataChanged(id.appWidgetId, viewId, mUserId);
                } catch (RemoteException e) {
                    // It failed; remove the callback. No need to prune because
                    // we know that this host is still referenced by this instance.
                    id.host.callbacks = null;
                }
            }

            // If the host is unavailable, then we call the associated
            // RemoteViewsFactory.onDataSetChanged() directly
            if (id.host.callbacks == null) {
                Set<FilterComparison> keys = mRemoteViewsServicesAppWidgets.keySet();
                for (FilterComparison key : keys) {
                    if (mRemoteViewsServicesAppWidgets.get(key).contains(id.appWidgetId)) {
                        Intent intent = key.getIntent();

                        final ServiceConnection conn = new ServiceConnection() {
                            @Override
                            public void onServiceConnected(ComponentName name, IBinder service) {
                                IRemoteViewsFactory cb = IRemoteViewsFactory.Stub
                                        .asInterface(service);
                                try {
                                    cb.onDataSetChangedAsync();
                                } catch (RemoteException e) {
                                    e.printStackTrace();
                                } catch (RuntimeException e) {
                                    e.printStackTrace();
                                }
                                mContext.unbindService(this);
                            }

                            @Override
                            public void onServiceDisconnected(android.content.ComponentName name) {
                                // Do nothing
                            }
                        };

                        int userId = UserHandle.getUserId(id.provider.uid);
                        // Bind to the service and call onDataSetChanged()
                        final long token = Binder.clearCallingIdentity();
                        try {
                            mContext.bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE,
                                    new UserHandle(userId));
                        } finally {
                            Binder.restoreCallingIdentity(token);
                        }
                    }
                }
            }
        }
    }

    private boolean isLocalBinder() {
        return Process.myPid() == Binder.getCallingPid();
    }

    private RemoteViews cloneIfLocalBinder(RemoteViews rv) {
        if (isLocalBinder() && rv != null) {
            return rv.clone();
        }
        return rv;
    }

    private AppWidgetProviderInfo cloneIfLocalBinder(AppWidgetProviderInfo info) {
        if (isLocalBinder() && info != null) {
            return info.clone();
        }
        return info;
    }

    private Bundle cloneIfLocalBinder(Bundle bundle) {
        // Note: this is only a shallow copy. For now this will be fine, but it could be problematic
        // if we start adding objects to the options. Further, it would only be an issue if keyguard
        // used such options.
        if (isLocalBinder() && bundle != null) {
            return (Bundle) bundle.clone();
        }
        return bundle;
    }

    public int[] startListening(IAppWidgetHost callbacks, String packageName, int hostId,
            List<RemoteViews> updatedViews) {
        if (!mHasFeature) {
            return new int[0];
        }
        int callingUid = enforceCallingUid(packageName);
        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            Host host = lookupOrAddHostLocked(callingUid, packageName, hostId);
            host.callbacks = callbacks;

            updatedViews.clear();

            ArrayList<AppWidgetId> instances = host.instances;
            int N = instances.size();
            int[] updatedIds = new int[N];
            for (int i = 0; i < N; i++) {
                AppWidgetId id = instances.get(i);
                updatedIds[i] = id.appWidgetId;
                updatedViews.add(cloneIfLocalBinder(id.views));
            }
            return updatedIds;
        }
    }

    public void stopListening(int hostId) {
        synchronized (mAppWidgetIds) {
            if (!mHasFeature) {
                return;
            }
            ensureStateLoadedLocked();
            Host host = lookupHostLocked(Binder.getCallingUid(), hostId);
            if (host != null) {
                host.callbacks = null;
                pruneHostLocked(host);
            }
        }
    }

    boolean canAccessAppWidgetId(AppWidgetId id, int callingUid) {
        if (id.host.uidMatches(callingUid)) {
            // Apps hosting the AppWidget have access to it.
            return true;
        }
        if (id.provider != null && id.provider.uid == callingUid) {
            // Apps providing the AppWidget have access to it (if the appWidgetId has been bound)
            return true;
        }
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET) == PackageManager.PERMISSION_GRANTED) {
            // Apps that can bind have access to all appWidgetIds.
            return true;
        }
        // Nobody else can access it.
        return false;
    }

    AppWidgetId lookupAppWidgetIdLocked(int appWidgetId) {
        int callingUid = Binder.getCallingUid();
        final int N = mAppWidgetIds.size();
        for (int i = 0; i < N; i++) {
            AppWidgetId id = mAppWidgetIds.get(i);
            if (id.appWidgetId == appWidgetId && canAccessAppWidgetId(id, callingUid)) {
                return id;
            }
        }
        return null;
    }

    Provider lookupProviderLocked(ComponentName provider) {
        final int N = mInstalledProviders.size();
        for (int i = 0; i < N; i++) {
            Provider p = mInstalledProviders.get(i);
            if (p.info.provider.equals(provider)) {
                return p;
            }
        }
        return null;
    }

    Host lookupHostLocked(int uid, int hostId) {
        final int N = mHosts.size();
        for (int i = 0; i < N; i++) {
            Host h = mHosts.get(i);
            if (h.uidMatches(uid) && h.hostId == hostId) {
                return h;
            }
        }
        return null;
    }

    Host lookupOrAddHostLocked(int uid, String packageName, int hostId) {
        final int N = mHosts.size();
        for (int i = 0; i < N; i++) {
            Host h = mHosts.get(i);
            if (h.hostId == hostId && h.packageName.equals(packageName)) {
                return h;
            }
        }
        Host host = new Host();
        host.packageName = packageName;
        host.uid = uid;
        host.hostId = hostId;
        mHosts.add(host);
        return host;
    }

    void pruneHostLocked(Host host) {
        if (host.instances.size() == 0 && host.callbacks == null) {
            mHosts.remove(host);
        }
    }

    void loadAppWidgetListLocked() {
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        try {
            List<ResolveInfo> broadcastReceivers = mPm.queryIntentReceivers(intent,
                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                    PackageManager.GET_META_DATA, mUserId);

            final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
            for (int i = 0; i < N; i++) {
                ResolveInfo ri = broadcastReceivers.get(i);
                addProviderLocked(ri);
            }
        } catch (RemoteException re) {
            // Shouldn't happen, local call
        }
    }

    boolean addProviderLocked(ResolveInfo ri) {
        if ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
            return false;
        }
        if (!ri.activityInfo.isEnabled()) {
            return false;
        }
        Provider p = parseProviderInfoXml(new ComponentName(ri.activityInfo.packageName,
                ri.activityInfo.name), ri);
        if (p != null) {
            mInstalledProviders.add(p);
            return true;
        } else {
            return false;
        }
    }

    void removeProviderLocked(int index, Provider p) {
        int N = p.instances.size();
        for (int i = 0; i < N; i++) {
            AppWidgetId id = p.instances.get(i);
            // Call back with empty RemoteViews
            updateAppWidgetInstanceLocked(id, null);
            // Stop telling the host about updates for this from now on
            cancelBroadcasts(p);
            // clear out references to this appWidgetId
            id.host.instances.remove(id);
            mAppWidgetIds.remove(id);
            id.provider = null;
            pruneHostLocked(id.host);
            id.host = null;
        }
        p.instances.clear();
        mInstalledProviders.remove(index);
        mDeletedProviders.add(p);
        // no need to send the DISABLE broadcast, since the receiver is gone anyway
        cancelBroadcasts(p);
    }

    void sendEnableIntentLocked(Provider p) {
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED);
        intent.setComponent(p.info.provider);
        mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
    }

    void sendUpdateIntentLocked(Provider p, int[] appWidgetIds) {
        if (appWidgetIds != null && appWidgetIds.length > 0) {
            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
            intent.setComponent(p.info.provider);
            mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
        }
    }

    void registerForBroadcastsLocked(Provider p, int[] appWidgetIds) {
        if (p.info.updatePeriodMillis > 0) {
            // if this is the first instance, set the alarm. otherwise,
            // rely on the fact that we've already set it and that
            // PendingIntent.getBroadcast will update the extras.
            boolean alreadyRegistered = p.broadcast != null;
            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
            intent.setComponent(p.info.provider);
            long token = Binder.clearCallingIdentity();
            try {
                p.broadcast = PendingIntent.getBroadcastAsUser(mContext, 1, intent,
                        PendingIntent.FLAG_UPDATE_CURRENT, new UserHandle(mUserId));
            } finally {
                Binder.restoreCallingIdentity(token);
            }
            if (!alreadyRegistered) {
                long period = p.info.updatePeriodMillis;
                if (period < MIN_UPDATE_PERIOD) {
                    period = MIN_UPDATE_PERIOD;
                }
                mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock
                        .elapsedRealtime()
                        + period, period, p.broadcast);
            }
        }
    }

    static int[] getAppWidgetIds(Provider p) {
        int instancesSize = p.instances.size();
        int appWidgetIds[] = new int[instancesSize];
        for (int i = 0; i < instancesSize; i++) {
            appWidgetIds[i] = p.instances.get(i).appWidgetId;
        }
        return appWidgetIds;
    }

    public int[] getAppWidgetIds(ComponentName provider) {
        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            Provider p = lookupProviderLocked(provider);
            if (p != null && Binder.getCallingUid() == p.uid) {
                return getAppWidgetIds(p);
            } else {
                return new int[0];
            }
        }
    }

    static int[] getAppWidgetIds(Host h) {
        int instancesSize = h.instances.size();
        int appWidgetIds[] = new int[instancesSize];
        for (int i = 0; i < instancesSize; i++) {
            appWidgetIds[i] = h.instances.get(i).appWidgetId;
        }
        return appWidgetIds;
    }

    public int[] getAppWidgetIdsForHost(int hostId) {
        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            int callingUid = Binder.getCallingUid();
            Host host = lookupHostLocked(callingUid, hostId);
            if (host != null) {
                return getAppWidgetIds(host);
            } else {
                return new int[0];
            }
        }
    }

    private Provider parseProviderInfoXml(ComponentName component, ResolveInfo ri) {
        Provider p = null;

        ActivityInfo activityInfo = ri.activityInfo;
        XmlResourceParser parser = null;
        try {
            parser = activityInfo.loadXmlMetaData(mContext.getPackageManager(),
                    AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
            if (parser == null) {
                Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER
                        + " meta-data for " + "AppWidget provider '" + component + '\'');
                return null;
            }

            AttributeSet attrs = Xml.asAttributeSet(parser);

            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && type != XmlPullParser.START_TAG) {
                // drain whitespace, comments, etc.
            }

            String nodeName = parser.getName();
            if (!"appwidget-provider".equals(nodeName)) {
                Slog.w(TAG, "Meta-data does not start with appwidget-provider tag for"
                        + " AppWidget provider '" + component + '\'');
                return null;
            }

            p = new Provider();
            AppWidgetProviderInfo info = p.info = new AppWidgetProviderInfo();
            info.provider = component;
            p.uid = activityInfo.applicationInfo.uid;

            Resources res = mContext.getPackageManager()
                    .getResourcesForApplicationAsUser(activityInfo.packageName, mUserId);

            TypedArray sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AppWidgetProviderInfo);

            // These dimensions has to be resolved in the application's context.
            // We simply send back the raw complex data, which will be
            // converted to dp in {@link AppWidgetManager#getAppWidgetInfo}.
            TypedValue value = sa
                    .peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minWidth);
            info.minWidth = value != null ? value.data : 0;
            value = sa.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight);
            info.minHeight = value != null ? value.data : 0;
            value = sa.peekValue(
                    com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeWidth);
            info.minResizeWidth = value != null ? value.data : info.minWidth;
            value = sa.peekValue(
                    com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeHeight);
            info.minResizeHeight = value != null ? value.data : info.minHeight;
            info.updatePeriodMillis = sa.getInt(
                    com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0);
            info.initialLayout = sa.getResourceId(
                    com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, 0);
            info.initialKeyguardLayout = sa.getResourceId(com.android.internal.R.styleable.
                    AppWidgetProviderInfo_initialKeyguardLayout, 0);
            String className = sa
                    .getString(com.android.internal.R.styleable.AppWidgetProviderInfo_configure);
            if (className != null) {
                info.configure = new ComponentName(component.getPackageName(), className);
            }
            info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString();
            info.icon = ri.getIconResource();
            info.previewImage = sa.getResourceId(
                    com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
            info.autoAdvanceViewId = sa.getResourceId(
                    com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId, -1);
            info.resizeMode = sa.getInt(
                    com.android.internal.R.styleable.AppWidgetProviderInfo_resizeMode,
                    AppWidgetProviderInfo.RESIZE_NONE);
            info.widgetCategory = sa.getInt(
                    com.android.internal.R.styleable.AppWidgetProviderInfo_widgetCategory,
                    AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);

            sa.recycle();
        } catch (Exception e) {
            // Ok to catch Exception here, because anything going wrong because
            // of what a client process passes to us should not be fatal for the
            // system process.
            Slog.w(TAG, "XML parsing failed for AppWidget provider '" + component + '\'', e);
            return null;
        } finally {
            if (parser != null)
                parser.close();
        }
        return p;
    }

    int getUidForPackage(String packageName) throws PackageManager.NameNotFoundException {
        PackageInfo pkgInfo = null;
        try {
            pkgInfo = mPm.getPackageInfo(packageName, 0, mUserId);
        } catch (RemoteException re) {
            // Shouldn't happen, local call
        }
        if (pkgInfo == null || pkgInfo.applicationInfo == null) {
            throw new PackageManager.NameNotFoundException();
        }
        return pkgInfo.applicationInfo.uid;
    }

    int enforceSystemOrCallingUid(String packageName) throws IllegalArgumentException {
        int callingUid = Binder.getCallingUid();
        if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID || callingUid == 0) {
            return callingUid;
        }
        return enforceCallingUid(packageName);
    }

    int enforceCallingUid(String packageName) throws IllegalArgumentException {
        int callingUid = Binder.getCallingUid();
        int packageUid;
        try {
            packageUid = getUidForPackage(packageName);
        } catch (PackageManager.NameNotFoundException ex) {
            throw new IllegalArgumentException("packageName and uid don't match packageName="
                    + packageName);
        }
        if (!UserHandle.isSameApp(callingUid, packageUid)) {
            throw new IllegalArgumentException("packageName and uid don't match packageName="
                    + packageName);
        }
        return callingUid;
    }

    void sendInitialBroadcasts() {
        synchronized (mAppWidgetIds) {
            ensureStateLoadedLocked();
            final int N = mInstalledProviders.size();
            for (int i = 0; i < N; i++) {
                Provider p = mInstalledProviders.get(i);
                if (p.instances.size() > 0) {
                    sendEnableIntentLocked(p);
                    int[] appWidgetIds = getAppWidgetIds(p);
                    sendUpdateIntentLocked(p, appWidgetIds);
                    registerForBroadcastsLocked(p, appWidgetIds);
                }
            }
        }
    }

    // only call from initialization -- it assumes that the data structures are all empty
    void loadStateLocked() {
        AtomicFile file = savedStateFile();
        try {
            FileInputStream stream = file.openRead();
            readStateFromFileLocked(stream);

            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    Slog.w(TAG, "Failed to close state FileInputStream " + e);
                }
            }
        } catch (FileNotFoundException e) {
            Slog.w(TAG, "Failed to read state: " + e);
        }
    }

    void saveStateLocked() {
        if (!mHasFeature) {
            return;
        }
        AtomicFile file = savedStateFile();
        FileOutputStream stream;
        try {
            stream = file.startWrite();
            if (writeStateToFileLocked(stream)) {
                file.finishWrite(stream);
            } else {
                file.failWrite(stream);
                Slog.w(TAG, "Failed to save state, restoring backup.");
            }
        } catch (IOException e) {
            Slog.w(TAG, "Failed open state file for write: " + e);
        }
    }

    boolean writeStateToFileLocked(FileOutputStream stream) {
        int N;

        try {
            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(stream, "utf-8");
            out.startDocument(null, true);
            out.startTag(null, "gs");
            out.attribute(null, "version", String.valueOf(CURRENT_VERSION));
            int providerIndex = 0;
            N = mInstalledProviders.size();
            for (int i = 0; i < N; i++) {
                Provider p = mInstalledProviders.get(i);
                if (p.instances.size() > 0) {
                    out.startTag(null, "p");
                    out.attribute(null, "pkg", p.info.provider.getPackageName());
                    out.attribute(null, "cl", p.info.provider.getClassName());
                    out.endTag(null, "p");
                    p.tag = providerIndex;
                    providerIndex++;
                }
            }

            N = mHosts.size();
            for (int i = 0; i < N; i++) {
                Host host = mHosts.get(i);
                out.startTag(null, "h");
                out.attribute(null, "pkg", host.packageName);
                out.attribute(null, "id", Integer.toHexString(host.hostId));
                out.endTag(null, "h");
                host.tag = i;
            }

            N = mAppWidgetIds.size();
            for (int i = 0; i < N; i++) {
                AppWidgetId id = mAppWidgetIds.get(i);
                out.startTag(null, "g");
                out.attribute(null, "id", Integer.toHexString(id.appWidgetId));
                out.attribute(null, "h", Integer.toHexString(id.host.tag));
                if (id.provider != null) {
                    out.attribute(null, "p", Integer.toHexString(id.provider.tag));
                }
                if (id.options != null) {
                    out.attribute(null, "min_width", Integer.toHexString(id.options.getInt(
                            AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)));
                    out.attribute(null, "min_height", Integer.toHexString(id.options.getInt(
                            AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)));
                    out.attribute(null, "max_width", Integer.toHexString(id.options.getInt(
                            AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)));
                    out.attribute(null, "max_height", Integer.toHexString(id.options.getInt(
                            AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)));
                    out.attribute(null, "host_category", Integer.toHexString(id.options.getInt(
                            AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)));
                }
                out.endTag(null, "g");
            }

            Iterator<String> it = mPackagesWithBindWidgetPermission.iterator();
            while (it.hasNext()) {
                out.startTag(null, "b");
                out.attribute(null, "packageName", it.next());
                out.endTag(null, "b");
            }

            out.endTag(null, "gs");

            out.endDocument();
            return true;
        } catch (IOException e) {
            Slog.w(TAG, "Failed to write state: " + e);
            return false;
        }
    }

    @SuppressWarnings("unused")
    void readStateFromFileLocked(FileInputStream stream) {
        boolean success = false;
        int version = 0;
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(stream, null);

            int type;
            int providerIndex = 0;
            HashMap<Integer, Provider> loadedProviders = new HashMap<Integer, Provider>();
            do {
                type = parser.next();
                if (type == XmlPullParser.START_TAG) {
                    String tag = parser.getName();
                    if ("gs".equals(tag)) {
                        String attributeValue = parser.getAttributeValue(null, "version");
                        try {
                            version = Integer.parseInt(attributeValue);
                        } catch (NumberFormatException e) {
                            version = 0;
                        }
                    } else if ("p".equals(tag)) {
                        // TODO: do we need to check that this package has the same signature
                        // as before?
                        String pkg = parser.getAttributeValue(null, "pkg");
                        String cl = parser.getAttributeValue(null, "cl");

                        final IPackageManager packageManager = AppGlobals.getPackageManager();
                        try {
                            packageManager.getReceiverInfo(new ComponentName(pkg, cl), 0, mUserId);
                        } catch (RemoteException e) {
                            String[] pkgs = mContext.getPackageManager()
                                    .currentToCanonicalPackageNames(new String[] { pkg });
                            pkg = pkgs[0];
                        }

                        Provider p = lookupProviderLocked(new ComponentName(pkg, cl));
                        if (p == null && mSafeMode) {
                            // if we're in safe mode, make a temporary one
                            p = new Provider();
                            p.info = new AppWidgetProviderInfo();
                            p.info.provider = new ComponentName(pkg, cl);
                            p.zombie = true;
                            mInstalledProviders.add(p);
                        }
                        if (p != null) {
                            // if it wasn't uninstalled or something
                            loadedProviders.put(providerIndex, p);
                        }
                        providerIndex++;
                    } else if ("h".equals(tag)) {
                        Host host = new Host();

                        // TODO: do we need to check that this package has the same signature
                        // as before?
                        host.packageName = parser.getAttributeValue(null, "pkg");
                        try {
                            host.uid = getUidForPackage(host.packageName);
                        } catch (PackageManager.NameNotFoundException ex) {
                            host.zombie = true;
                        }
                        if (!host.zombie || mSafeMode) {
                            // In safe mode, we don't discard the hosts we don't recognize
                            // so that they're not pruned from our list. Otherwise, we do.
                            host.hostId = Integer
                                    .parseInt(parser.getAttributeValue(null, "id"), 16);
                            mHosts.add(host);
                        }
                    } else if ("b".equals(tag)) {
                        String packageName = parser.getAttributeValue(null, "packageName");
                        if (packageName != null) {
                            mPackagesWithBindWidgetPermission.add(packageName);
                        }
                    } else if ("g".equals(tag)) {
                        AppWidgetId id = new AppWidgetId();
                        id.appWidgetId = Integer.parseInt(parser.getAttributeValue(null, "id"), 16);
                        if (id.appWidgetId >= mNextAppWidgetId) {
                            mNextAppWidgetId = id.appWidgetId + 1;
                        }

                        Bundle options = new Bundle();
                        String minWidthString = parser.getAttributeValue(null, "min_width");
                        if (minWidthString != null) {
                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
                                    Integer.parseInt(minWidthString, 16));
                        }
                        String minHeightString = parser.getAttributeValue(null, "min_height");
                        if (minHeightString != null) {
                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
                                    Integer.parseInt(minHeightString, 16));
                        }
                        String maxWidthString = parser.getAttributeValue(null, "max_width");
                        if (maxWidthString != null) {
                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
                                    Integer.parseInt(maxWidthString, 16));
                        }
                        String maxHeightString = parser.getAttributeValue(null, "max_height");
                        if (maxHeightString != null) {
                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
                                    Integer.parseInt(maxHeightString, 16));
                        }
                        String categoryString = parser.getAttributeValue(null, "host_category");
                        if (categoryString != null) {
                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
                                    Integer.parseInt(categoryString, 16));
                        }
                        id.options = options;

                        String providerString = parser.getAttributeValue(null, "p");
                        if (providerString != null) {
                            // there's no provider if it hasn't been bound yet.
                            // maybe we don't have to save this, but it brings the system
                            // to the state it was in.
                            int pIndex = Integer.parseInt(providerString, 16);
                            id.provider = loadedProviders.get(pIndex);
                            if (false) {
                                Slog.d(TAG, "bound appWidgetId=" + id.appWidgetId + " to provider "
                                        + pIndex + " which is " + id.provider);
                            }
                            if (id.provider == null) {
                                // This provider is gone. We just let the host figure out
                                // that this happened when it fails to load it.
                                continue;
                            }
                        }

                        int hIndex = Integer.parseInt(parser.getAttributeValue(null, "h"), 16);
                        id.host = mHosts.get(hIndex);
                        if (id.host == null) {
                            // This host is gone.
                            continue;
                        }

                        if (id.provider != null) {
                            id.provider.instances.add(id);
                        }
                        id.host.instances.add(id);
                        mAppWidgetIds.add(id);
                    }
                }
            } while (type != XmlPullParser.END_DOCUMENT);
            success = true;
        } catch (NullPointerException e) {
            Slog.w(TAG, "failed parsing " + e);
        } catch (NumberFormatException e) {
            Slog.w(TAG, "failed parsing " + e);
        } catch (XmlPullParserException e) {
            Slog.w(TAG, "failed parsing " + e);
        } catch (IOException e) {
            Slog.w(TAG, "failed parsing " + e);
        } catch (IndexOutOfBoundsException e) {
            Slog.w(TAG, "failed parsing " + e);
        }

        if (success) {
            // delete any hosts that didn't manage to get connected (should happen)
            // if it matters, they'll be reconnected.
            for (int i = mHosts.size() - 1; i >= 0; i--) {
                pruneHostLocked(mHosts.get(i));
            }
            // upgrade the database if needed
            performUpgrade(version);
        } else {
            // failed reading, clean up
            Slog.w(TAG, "Failed to read state, clearing widgets and hosts.");

            mAppWidgetIds.clear();
            mHosts.clear();
            final int N = mInstalledProviders.size();
            for (int i = 0; i < N; i++) {
                mInstalledProviders.get(i).instances.clear();
            }
        }
    }

    private void performUpgrade(int fromVersion) {
        if (fromVersion < CURRENT_VERSION) {
            Slog.v(TAG, "Upgrading widget database from " + fromVersion + " to " + CURRENT_VERSION
                    + " for user " + mUserId);
        }

        int version = fromVersion;

        // Update 1: keyguard moved from package "android" to "com.android.keyguard"
        if (version == 0) {
            for (int i = 0; i < mHosts.size(); i++) {
                Host host = mHosts.get(i);
                if (host != null && "android".equals(host.packageName)
                        && host.hostId == KEYGUARD_HOST_ID) {
                    host.packageName = KEYGUARD_HOST_PACKAGE;
                }
            }
            version = 1;
        }

        if (version != CURRENT_VERSION) {
            throw new IllegalStateException("Failed to upgrade widget database");
        }
    }

    static File getSettingsFile(int userId) {
        return new File(Environment.getUserSystemDirectory(userId), SETTINGS_FILENAME);
    }

    AtomicFile savedStateFile() {
        File dir = Environment.getUserSystemDirectory(mUserId);
        File settingsFile = getSettingsFile(mUserId);
        if (!settingsFile.exists() && mUserId == 0) {
            if (!dir.exists()) {
                dir.mkdirs();
            }
            // Migrate old data
            File oldFile = new File("/data/system/" + SETTINGS_FILENAME);
            // Method doesn't throw an exception on failure. Ignore any errors
            // in moving the file (like non-existence)
            oldFile.renameTo(settingsFile);
        }
        return new AtomicFile(settingsFile);
    }

    void onUserStopping() {
        // prune the ones we don't want to keep
        int N = mInstalledProviders.size();
        for (int i = N - 1; i >= 0; i--) {
            Provider p = mInstalledProviders.get(i);
            cancelBroadcasts(p);
        }
    }

    void onUserRemoved() {
        getSettingsFile(mUserId).delete();
    }

    boolean addProvidersForPackageLocked(String pkgName) {
        boolean providersAdded = false;
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        intent.setPackage(pkgName);
        List<ResolveInfo> broadcastReceivers;
        try {
            broadcastReceivers = mPm.queryIntentReceivers(intent,
                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                    PackageManager.GET_META_DATA, mUserId);
        } catch (RemoteException re) {
            // Shouldn't happen, local call
            return false;
        }
        final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
        for (int i = 0; i < N; i++) {
            ResolveInfo ri = broadcastReceivers.get(i);
            ActivityInfo ai = ri.activityInfo;
            if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                continue;
            }
            if (pkgName.equals(ai.packageName)) {
                addProviderLocked(ri);
                providersAdded = true;
            }
        }

        return providersAdded;
    }

    /**
     * Updates all providers with the specified package names, and records any providers that were
     * pruned.
     *
     * @return whether any providers were updated
     */
    boolean updateProvidersForPackageLocked(String pkgName, Set<ComponentName> removedProviders) {
        boolean providersUpdated = false;
        HashSet<String> keep = new HashSet<String>();
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        intent.setPackage(pkgName);
        List<ResolveInfo> broadcastReceivers;
        try {
            broadcastReceivers = mPm.queryIntentReceivers(intent,
                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                PackageManager.GET_META_DATA, mUserId);
        } catch (RemoteException re) {
            // Shouldn't happen, local call
            return false;
        }

        // add the missing ones and collect which ones to keep
        int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
        for (int i = 0; i < N; i++) {
            ResolveInfo ri = broadcastReceivers.get(i);
            ActivityInfo ai = ri.activityInfo;
            if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                continue;
            }
            if (pkgName.equals(ai.packageName)) {
                ComponentName component = new ComponentName(ai.packageName, ai.name);
                Provider p = lookupProviderLocked(component);
                if (p == null) {
                    if (addProviderLocked(ri)) {
                        keep.add(ai.name);
                        providersUpdated = true;
                    }
                } else {
                    Provider parsed = parseProviderInfoXml(component, ri);
                    if (parsed != null) {
                        keep.add(ai.name);
                        // Use the new AppWidgetProviderInfo.
                        p.info = parsed.info;
                        // If it's enabled
                        final int M = p.instances.size();
                        if (M > 0) {
                            int[] appWidgetIds = getAppWidgetIds(p);
                            // Reschedule for the new updatePeriodMillis (don't worry about handling
                            // it specially if updatePeriodMillis didn't change because we just sent
                            // an update, and the next one will be updatePeriodMillis from now).
                            cancelBroadcasts(p);
                            registerForBroadcastsLocked(p, appWidgetIds);
                            // If it's currently showing, call back with the new
                            // AppWidgetProviderInfo.
                            for (int j = 0; j < M; j++) {
                                AppWidgetId id = p.instances.get(j);
                                id.views = null;
                                if (id.host != null && id.host.callbacks != null) {
                                    try {
                                        id.host.callbacks.providerChanged(id.appWidgetId, p.info,
                                                mUserId);
                                    } catch (RemoteException ex) {
                                        // It failed; remove the callback. No need to prune because
                                        // we know that this host is still referenced by this
                                        // instance.
                                        id.host.callbacks = null;
                                    }
                                }
                            }
                            // Now that we've told the host, push out an update.
                            sendUpdateIntentLocked(p, appWidgetIds);
                            providersUpdated = true;
                        }
                    }
                }
            }
        }

        // prune the ones we don't want to keep
        N = mInstalledProviders.size();
        for (int i = N - 1; i >= 0; i--) {
            Provider p = mInstalledProviders.get(i);
            if (pkgName.equals(p.info.provider.getPackageName())
                    && !keep.contains(p.info.provider.getClassName())) {
                if (removedProviders != null) {
                    removedProviders.add(p.info.provider);
                }
                removeProviderLocked(i, p);
                providersUpdated = true;
            }
        }

        return providersUpdated;
    }

    boolean removeProvidersForPackageLocked(String pkgName) {
        boolean providersRemoved = false;
        int N = mInstalledProviders.size();
        for (int i = N - 1; i >= 0; i--) {
            Provider p = mInstalledProviders.get(i);
            if (pkgName.equals(p.info.provider.getPackageName())) {
                removeProviderLocked(i, p);
                providersRemoved = true;
            }
        }

        // Delete the hosts for this package too
        //
        // By now, we have removed any AppWidgets that were in any hosts here,
        // so we don't need to worry about sending DISABLE broadcasts to them.
        N = mHosts.size();
        for (int i = N - 1; i >= 0; i--) {
            Host host = mHosts.get(i);
            if (pkgName.equals(host.packageName)) {
                deleteHostLocked(host);
            }
        }

        return providersRemoved;
    }

    void notifyHostsForProvidersChangedLocked() {
        final int N = mHosts.size();
        for (int i = N - 1; i >= 0; i--) {
            Host host = mHosts.get(i);
            try {
                if (host.callbacks != null) {
                    host.callbacks.providersChanged(mUserId);
                }
            } catch (RemoteException ex) {
                // It failed; remove the callback. No need to prune because
                // we know that this host is still referenced by this
                // instance.
                host.callbacks = null;
            }
        }
    }
}
