/*
 * Copyright (C) 2020 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.systemui.people.widget;

import static android.Manifest.permission.READ_CONTACTS;
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.content.Intent.ACTION_BOOT_COMPLETED;
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE;

import static com.android.systemui.people.NotificationHelper.getContactUri;
import static com.android.systemui.people.NotificationHelper.getHighestPriorityNotification;
import static com.android.systemui.people.NotificationHelper.shouldFilterOut;
import static com.android.systemui.people.NotificationHelper.shouldMatchNotificationByUri;
import static com.android.systemui.people.PeopleBackupFollowUpJob.SHARED_FOLLOW_UP;
import static com.android.systemui.people.PeopleSpaceUtils.EMPTY_STRING;
import static com.android.systemui.people.PeopleSpaceUtils.INVALID_USER_ID;
import static com.android.systemui.people.PeopleSpaceUtils.PACKAGE_NAME;
import static com.android.systemui.people.PeopleSpaceUtils.SHORTCUT_ID;
import static com.android.systemui.people.PeopleSpaceUtils.USER_ID;
import static com.android.systemui.people.PeopleSpaceUtils.augmentTileFromNotification;
import static com.android.systemui.people.PeopleSpaceUtils.getMessagesCount;
import static com.android.systemui.people.PeopleSpaceUtils.getNotificationsByUri;
import static com.android.systemui.people.PeopleSpaceUtils.removeNotificationFields;
import static com.android.systemui.people.widget.PeopleBackupHelper.getEntryType;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.INotificationManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Person;
import android.app.backup.BackupManager;
import android.app.job.JobScheduler;
import android.app.people.ConversationChannel;
import android.app.people.IPeopleManager;
import android.app.people.PeopleManager;
import android.app.people.PeopleSpaceTile;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.PreferenceManager;
import android.service.notification.ConversationChannelWrapper;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
import android.text.TextUtils;
import android.util.Log;
import android.widget.RemoteViews;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.people.NotificationHelper;
import com.android.systemui.people.PeopleBackupFollowUpJob;
import com.android.systemui.people.PeopleSpaceUtils;
import com.android.systemui.people.PeopleTileViewHelper;
import com.android.systemui.people.SharedPreferencesHelper;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.wm.shell.bubbles.Bubbles;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.inject.Inject;

/** Manager for People Space widget. */
@SysUISingleton
public class PeopleSpaceWidgetManager {
    private static final String TAG = "PeopleSpaceWidgetMgr";
    private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;

    private final Object mLock = new Object();
    private final Context mContext;
    private LauncherApps mLauncherApps;
    private AppWidgetManager mAppWidgetManager;
    private IPeopleManager mIPeopleManager;
    private SharedPreferences mSharedPrefs;
    private PeopleManager mPeopleManager;
    private NotificationEntryManager mNotificationEntryManager;
    private PackageManager mPackageManager;
    private INotificationManager mINotificationManager;
    private Optional<Bubbles> mBubblesOptional;
    private UserManager mUserManager;
    private PeopleSpaceWidgetManager mManager;
    private BackupManager mBackupManager;
    public UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
    private NotificationManager mNotificationManager;
    private BroadcastDispatcher mBroadcastDispatcher;
    private Executor mBgExecutor;
    @GuardedBy("mLock")
    public static Map<PeopleTileKey, TileConversationListener>
            mListeners = new HashMap<>();

    @GuardedBy("mLock")
    // Map of notification key mapped to widget IDs previously updated by the contact Uri field.
    // This is required because on notification removal, the contact Uri field is stripped and we
    // only have the notification key to determine which widget IDs should be updated.
    private Map<String, Set<String>> mNotificationKeyToWidgetIdsMatchedByUri = new HashMap<>();
    private boolean mRegisteredReceivers;

    @GuardedBy("mLock")
    public static Map<Integer, PeopleSpaceTile> mTiles = new HashMap<>();

    @Inject
    public PeopleSpaceWidgetManager(Context context, LauncherApps launcherApps,
            NotificationEntryManager notificationEntryManager,
            PackageManager packageManager, Optional<Bubbles> bubblesOptional,
            UserManager userManager, NotificationManager notificationManager,
            BroadcastDispatcher broadcastDispatcher, @Background Executor bgExecutor) {
        if (DEBUG) Log.d(TAG, "constructor");
        mContext = context;
        mAppWidgetManager = AppWidgetManager.getInstance(context);
        mIPeopleManager = IPeopleManager.Stub.asInterface(
                ServiceManager.getService(Context.PEOPLE_SERVICE));
        mLauncherApps = launcherApps;
        mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
        mPeopleManager = context.getSystemService(PeopleManager.class);
        mNotificationEntryManager = notificationEntryManager;
        mPackageManager = packageManager;
        mINotificationManager = INotificationManager.Stub.asInterface(
                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
        mBubblesOptional = bubblesOptional;
        mUserManager = userManager;
        mBackupManager = new BackupManager(context);
        mNotificationManager = notificationManager;
        mManager = this;
        mBroadcastDispatcher = broadcastDispatcher;
        mBgExecutor = bgExecutor;
    }

    /** Initializes {@PeopleSpaceWidgetManager}. */
    public void init() {
        synchronized (mLock) {
            if (!mRegisteredReceivers) {
                if (DEBUG) Log.d(TAG, "Register receivers");
                IntentFilter filter = new IntentFilter();
                filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
                filter.addAction(ACTION_BOOT_COMPLETED);
                filter.addAction(Intent.ACTION_LOCALE_CHANGED);
                filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
                filter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
                filter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
                filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
                filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
                filter.addAction(Intent.ACTION_USER_UNLOCKED);
                mBroadcastDispatcher.registerReceiver(mBaseBroadcastReceiver, filter,

                        null /* executor */, UserHandle.ALL);
                IntentFilter perAppFilter = new IntentFilter(ACTION_PACKAGE_REMOVED);
                perAppFilter.addAction(ACTION_PACKAGE_ADDED);
                perAppFilter.addDataScheme("package");
                // BroadcastDispatcher doesn't allow data schemes.
                mContext.registerReceiver(mBaseBroadcastReceiver, perAppFilter);
                IntentFilter bootComplete = new IntentFilter(ACTION_BOOT_COMPLETED);
                bootComplete.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
                // BroadcastDispatcher doesn't allow priority.
                mContext.registerReceiver(mBaseBroadcastReceiver, bootComplete);
                mRegisteredReceivers = true;
            }
        }
    }

    /** Listener for the shortcut data changes. */
    public class TileConversationListener implements PeopleManager.ConversationListener {

        @Override
        public void onConversationUpdate(@NonNull ConversationChannel conversation) {
            if (DEBUG) {
                Log.d(TAG,
                        "Received updated conversation: "
                                + conversation.getShortcutInfo().getLabel());
            }
            mBgExecutor.execute(() ->
                    updateWidgetsWithConversationChanged(conversation));
        }
    }

    /**
     * PeopleSpaceWidgetManager setter used for testing.
     */
    @VisibleForTesting
    PeopleSpaceWidgetManager(Context context,
            AppWidgetManager appWidgetManager, IPeopleManager iPeopleManager,
            PeopleManager peopleManager, LauncherApps launcherApps,
            NotificationEntryManager notificationEntryManager, PackageManager packageManager,
            Optional<Bubbles> bubblesOptional, UserManager userManager, BackupManager backupManager,
            INotificationManager iNotificationManager, NotificationManager notificationManager,
            @Background Executor executor) {
        mContext = context;
        mAppWidgetManager = appWidgetManager;
        mIPeopleManager = iPeopleManager;
        mPeopleManager = peopleManager;
        mLauncherApps = launcherApps;
        mNotificationEntryManager = notificationEntryManager;
        mPackageManager = packageManager;
        mBubblesOptional = bubblesOptional;
        mUserManager = userManager;
        mBackupManager = backupManager;
        mINotificationManager = iNotificationManager;
        mNotificationManager = notificationManager;
        mManager = this;
        mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
        mBgExecutor = executor;
    }

    /**
     * Updates People Space widgets.
     */
    public void updateWidgets(int[] widgetIds) {
        mBgExecutor.execute(() -> updateWidgetsInBackground(widgetIds));
    }

    private void updateWidgetsInBackground(int[] widgetIds) {
        try {
            if (DEBUG) Log.d(TAG, "updateWidgets called");
            if (widgetIds.length == 0) {
                if (DEBUG) Log.d(TAG, "no widgets to update");
                return;
            }
            synchronized (mLock) {
                updateSingleConversationWidgets(widgetIds);
            }
        } catch (Exception e) {
            Log.e(TAG, "Exception: " + e);
        }
    }

    /**
     * Updates {@code appWidgetIds} with their associated conversation stored, handling a
     * notification being posted or removed.
     */
    public void updateSingleConversationWidgets(int[] appWidgetIds) {
        Map<Integer, PeopleSpaceTile> widgetIdToTile = new HashMap<>();
        for (int appWidgetId : appWidgetIds) {
            if (DEBUG) Log.d(TAG, "Updating widget: " + appWidgetId);
            PeopleSpaceTile tile = getTileForExistingWidget(appWidgetId);
            if (tile == null) {
                Log.e(TAG, "Matching conversation not found for shortcut ID");
            }
            updateAppWidgetOptionsAndView(appWidgetId, tile);
            widgetIdToTile.put(appWidgetId, tile);
            if (tile != null) {
                registerConversationListenerIfNeeded(appWidgetId,
                        new PeopleTileKey(tile));
            }
        }
        PeopleSpaceUtils.getDataFromContactsOnBackgroundThread(
                mContext, mManager, widgetIdToTile, appWidgetIds);
    }

    /** Updates the current widget view with provided {@link PeopleSpaceTile}. */
    private void updateAppWidgetViews(int appWidgetId, PeopleSpaceTile tile, Bundle options) {
        PeopleTileKey key = getKeyFromStorageByWidgetId(appWidgetId);
        if (DEBUG) Log.d(TAG, "Widget: " + appWidgetId + " for: " + key.toString());

        if (!PeopleTileKey.isValid(key)) {
            Log.e(TAG, "Cannot update invalid widget");
            return;
        }
        RemoteViews views = PeopleTileViewHelper.createRemoteViews(mContext, tile, appWidgetId,
                options, key);

        // Tell the AppWidgetManager to perform an update on the current app widget.
        if (DEBUG) Log.d(TAG, "Calling update widget for widgetId: " + appWidgetId);
        mAppWidgetManager.updateAppWidget(appWidgetId, views);
    }

    /** Updates tile in app widget options and the current view. */
    public void updateAppWidgetOptionsAndViewOptional(int appWidgetId,
            Optional<PeopleSpaceTile> tile) {
        if (tile.isPresent()) {
            updateAppWidgetOptionsAndView(appWidgetId, tile.get());
        }
    }

    /** Updates tile in app widget options and the current view. */
    public void updateAppWidgetOptionsAndView(int appWidgetId, PeopleSpaceTile tile) {
        if (tile == null) {
            if (DEBUG) Log.w(TAG, "Storing null tile");
        }
        synchronized (mTiles) {
            mTiles.put(appWidgetId, tile);
        }
        Bundle options = mAppWidgetManager.getAppWidgetOptions(appWidgetId);
        updateAppWidgetViews(appWidgetId, tile, options);
    }

    /**
     * Returns a {@link PeopleSpaceTile} based on the {@code appWidgetId}.
     * Widget already exists, so fetch {@link PeopleTileKey} from {@link SharedPreferences}.
     */
    @Nullable
    public PeopleSpaceTile getTileForExistingWidget(int appWidgetId) {
        try {
            return getTileForExistingWidgetThrowing(appWidgetId);
        } catch (Exception e) {
            Log.e(TAG, "Failed to retrieve conversation for tile: " + e);
            return null;
        }
    }

    @Nullable
    private PeopleSpaceTile getTileForExistingWidgetThrowing(int appWidgetId) throws
            PackageManager.NameNotFoundException {
        // First, check if tile is cached in memory.
        PeopleSpaceTile tile;
        synchronized (mTiles) {
            tile = mTiles.get(appWidgetId);
        }
        if (tile != null) {
            if (DEBUG) Log.d(TAG, "People Tile is cached for widget: " + appWidgetId);
            return tile;
        }

        // If tile is null, we need to retrieve from persistent storage.
        if (DEBUG) Log.d(TAG, "Fetching key from sharedPreferences: " + appWidgetId);
        SharedPreferences widgetSp = mContext.getSharedPreferences(
                String.valueOf(appWidgetId),
                Context.MODE_PRIVATE);
        PeopleTileKey key = new PeopleTileKey(
                widgetSp.getString(SHORTCUT_ID, EMPTY_STRING),
                widgetSp.getInt(USER_ID, INVALID_USER_ID),
                widgetSp.getString(PACKAGE_NAME, EMPTY_STRING));

        return getTileFromPersistentStorage(key, appWidgetId, /* supplementFromStorage= */ true);
    }

    /**
     * Returns a {@link PeopleSpaceTile} based on the {@code appWidgetId}.
     * If a {@link PeopleTileKey} is not provided, fetch one from {@link SharedPreferences}.
     */
    @Nullable
    public PeopleSpaceTile getTileFromPersistentStorage(PeopleTileKey key, int appWidgetId,
            boolean supplementFromStorage) throws
            PackageManager.NameNotFoundException {
        if (!PeopleTileKey.isValid(key)) {
            Log.e(TAG, "PeopleTileKey invalid: " + key.toString());
            return null;
        }

        if (mIPeopleManager == null || mLauncherApps == null) {
            Log.d(TAG, "System services are null");
            return null;
        }
        try {
            if (DEBUG) Log.d(TAG, "Retrieving Tile from storage: " + key.toString());
            ConversationChannel channel = mIPeopleManager.getConversation(
                    key.getPackageName(), key.getUserId(), key.getShortcutId());
            if (channel == null) {
                if (DEBUG) Log.d(TAG, "Could not retrieve conversation from storage");
                return null;
            }

            // Get tile from shortcut & conversation storage.
            PeopleSpaceTile.Builder storedTile = new PeopleSpaceTile.Builder(channel,
                    mLauncherApps);
            if (storedTile == null) {
                return storedTile.build();
            }

            // Supplement with our storage.
            String contactUri = mSharedPrefs.getString(String.valueOf(appWidgetId), null);
            if (supplementFromStorage && contactUri != null
                    && storedTile.build().getContactUri() == null) {
                if (DEBUG) Log.d(TAG, "Restore contact uri from storage: " + contactUri);
                storedTile.setContactUri(Uri.parse(contactUri));
            }

            // Add current state.
            return getTileWithCurrentState(storedTile.build(), ACTION_BOOT_COMPLETED);
        } catch (RemoteException e) {
            Log.e(TAG, "Could not retrieve data: " + e);
            return null;
        }
    }

    /**
     * Check if any existing People tiles match the incoming notification change, and store the
     * change in the tile if so.
     */
    public void updateWidgetsWithNotificationChanged(StatusBarNotification sbn,
            PeopleSpaceUtils.NotificationAction notificationAction) {
        if (DEBUG) {
            if (notificationAction == PeopleSpaceUtils.NotificationAction.POSTED) {
                Log.d(TAG, "Notification posted, key: " + sbn.getKey());
            } else {
                Log.d(TAG, "Notification removed, key: " + sbn.getKey());
            }
        }
        mBgExecutor.execute(
                () -> updateWidgetsWithNotificationChangedInBackground(sbn, notificationAction));
    }

    private void updateWidgetsWithNotificationChangedInBackground(StatusBarNotification sbn,
            PeopleSpaceUtils.NotificationAction action) {
        try {
            PeopleTileKey key = new PeopleTileKey(
                    sbn.getShortcutId(), sbn.getUser().getIdentifier(), sbn.getPackageName());
            if (!PeopleTileKey.isValid(key)) {
                Log.d(TAG, "Sbn doesn't contain valid PeopleTileKey: " + key.toString());
                return;
            }
            int[] widgetIds = mAppWidgetManager.getAppWidgetIds(
                    new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
            );
            if (widgetIds.length == 0) {
                Log.d(TAG, "No app widget ids returned");
                return;
            }
            synchronized (mLock) {
                Set<String> tilesUpdated = getMatchingKeyWidgetIds(key);
                Set<String> tilesUpdatedByUri = getMatchingUriWidgetIds(sbn, action);
                if (DEBUG) {
                    Log.d(TAG, "Widgets by key to be updated:" + tilesUpdated.toString());
                    Log.d(TAG, "Widgets by URI to be updated:" + tilesUpdatedByUri.toString());
                }
                tilesUpdated.addAll(tilesUpdatedByUri);
                updateWidgetIdsBasedOnNotifications(tilesUpdated);
            }
        } catch (Exception e) {
            Log.e(TAG, "Throwing exception: " + e);
        }
    }

    /** Updates {@code widgetIdsToUpdate} with {@code action}. */
    private void updateWidgetIdsBasedOnNotifications(Set<String> widgetIdsToUpdate) {
        if (widgetIdsToUpdate.isEmpty()) {
            if (DEBUG) Log.d(TAG, "No widgets to update, returning.");
            return;
        }
        try {
            if (DEBUG) Log.d(TAG, "Fetching grouped notifications");
            Map<PeopleTileKey, Set<NotificationEntry>> groupedNotifications =
                    getGroupedConversationNotifications();

            widgetIdsToUpdate
                    .stream()
                    .map(Integer::parseInt)
                    .collect(Collectors.toMap(
                            Function.identity(),
                            id -> getAugmentedTileForExistingWidget(id, groupedNotifications)))
                    .forEach((id, tile) -> updateAppWidgetOptionsAndViewOptional(id, tile));
        } catch (Exception e) {
            Log.e(TAG, "Exception updating widgets: " + e);
        }
    }

    /**
     * Augments {@code tile} based on notifications returned from {@code notificationEntryManager}.
     */
    public PeopleSpaceTile augmentTileFromNotificationEntryManager(PeopleSpaceTile tile,
            Optional<Integer> appWidgetId) {
        PeopleTileKey key = new PeopleTileKey(tile);
        if (DEBUG) {
            Log.d(TAG,
                    "Augmenting tile from NotificationEntryManager widget: " + key.toString());
        }
        Map<PeopleTileKey, Set<NotificationEntry>> notifications =
                getGroupedConversationNotifications();
        String contactUri = null;
        if (tile.getContactUri() != null) {
            contactUri = tile.getContactUri().toString();
        }
        return augmentTileFromNotifications(tile, key, contactUri, notifications, appWidgetId);
    }

    /** Returns active and pending notifications grouped by {@link PeopleTileKey}. */
    public Map<PeopleTileKey, Set<NotificationEntry>> getGroupedConversationNotifications() {
        List<NotificationEntry> notifications =
                new ArrayList<>(mNotificationEntryManager.getVisibleNotifications());
        Iterable<NotificationEntry> pendingNotifications =
                mNotificationEntryManager.getPendingNotificationsIterator();
        for (NotificationEntry entry : pendingNotifications) {
            notifications.add(entry);
        }
        if (DEBUG) Log.d(TAG, "Number of total notifications: " + notifications.size());
        Map<PeopleTileKey, Set<NotificationEntry>> groupedNotifications =
                notifications
                        .stream()
                        .filter(entry -> NotificationHelper.isValid(entry)
                                && NotificationHelper.isMissedCallOrHasContent(entry)
                                && !shouldFilterOut(mBubblesOptional, entry))
                        .collect(Collectors.groupingBy(
                                PeopleTileKey::new,
                                Collectors.mapping(Function.identity(), Collectors.toSet())));
        if (DEBUG) {
            Log.d(TAG, "Number of grouped conversation notifications keys: "
                    + groupedNotifications.keySet().size());
        }
        return groupedNotifications;
    }

    /** Augments {@code tile} based on {@code notifications}, matching {@code contactUri}. */
    public PeopleSpaceTile augmentTileFromNotifications(PeopleSpaceTile tile, PeopleTileKey key,
            String contactUri,
            Map<PeopleTileKey, Set<NotificationEntry>> notifications,
            Optional<Integer> appWidgetId) {
        if (DEBUG) Log.d(TAG, "Augmenting tile from notifications. Tile key: " + key.toString());
        boolean hasReadContactsPermission = mPackageManager.checkPermission(READ_CONTACTS,
                tile.getPackageName()) == PackageManager.PERMISSION_GRANTED;

        List<NotificationEntry> notificationsByUri = new ArrayList<>();
        if (hasReadContactsPermission) {
            notificationsByUri = getNotificationsByUri(mPackageManager, contactUri, notifications);
            if (!notificationsByUri.isEmpty()) {
                if (DEBUG) {
                    Log.d(TAG, "Number of notifications matched by contact URI: "
                            + notificationsByUri.size());
                }
            }
        }

        Set<NotificationEntry> allNotifications = notifications.get(key);
        if (allNotifications == null) {
            allNotifications = new HashSet<>();
        }
        if (allNotifications.isEmpty() && notificationsByUri.isEmpty()) {
            if (DEBUG) Log.d(TAG, "No existing notifications for tile: " + key.toString());
            return removeNotificationFields(tile);
        }

        // Merge notifications matched by key and by contact URI.
        allNotifications.addAll(notificationsByUri);
        if (DEBUG) Log.d(TAG, "Total notifications matching tile: " + allNotifications.size());

        int messagesCount = getMessagesCount(allNotifications);
        NotificationEntry highestPriority = getHighestPriorityNotification(allNotifications);

        if (DEBUG) Log.d(TAG, "Augmenting tile from notification, key: " + key.toString());
        return augmentTileFromNotification(mContext, tile, key, highestPriority, messagesCount,
                appWidgetId, mBackupManager);
    }

    /** Returns an augmented tile for an existing widget. */
    @Nullable
    public Optional<PeopleSpaceTile> getAugmentedTileForExistingWidget(int widgetId,
            Map<PeopleTileKey, Set<NotificationEntry>> notifications) {
        if (DEBUG) Log.d(TAG, "Augmenting tile for existing widget: " + widgetId);
        PeopleSpaceTile tile = getTileForExistingWidget(widgetId);
        if (tile == null) {
            if (DEBUG) {
                Log.w(TAG, "Widget: " + widgetId
                        + ". Null tile for existing widget, skipping update.");
            }
            return Optional.empty();
        }
        String contactUriString = mSharedPrefs.getString(String.valueOf(widgetId), null);
        // Should never be null, but using ofNullable for extra safety.
        PeopleTileKey key = new PeopleTileKey(tile);
        if (DEBUG) Log.d(TAG, "Existing widget: " + widgetId + ". Tile key: " + key.toString());
        return Optional.ofNullable(
                augmentTileFromNotifications(tile, key, contactUriString, notifications,
                        Optional.of(widgetId)));
    }

    /** Returns stored widgets for the conversation specified. */
    public Set<String> getMatchingKeyWidgetIds(PeopleTileKey key) {
        if (!PeopleTileKey.isValid(key)) {
            return new HashSet<>();
        }
        return new HashSet<>(mSharedPrefs.getStringSet(key.toString(), new HashSet<>()));
    }

    /**
     * Updates in-memory map of tiles with matched Uris, dependent on the {@code action}.
     *
     * <p>If the notification was added, adds the notification based on the contact Uri within
     * {@code sbn}.
     * <p>If the notification was removed, removes the notification based on the in-memory map of
     * widgets previously updated by Uri (since the contact Uri is stripped from the {@code sbn}).
     */
    @Nullable
    private Set<String> getMatchingUriWidgetIds(StatusBarNotification sbn,
            PeopleSpaceUtils.NotificationAction action) {
        if (action.equals(PeopleSpaceUtils.NotificationAction.POSTED)) {
            Set<String> widgetIdsUpdatedByUri = fetchMatchingUriWidgetIds(sbn);
            if (widgetIdsUpdatedByUri != null && !widgetIdsUpdatedByUri.isEmpty()) {
                mNotificationKeyToWidgetIdsMatchedByUri.put(sbn.getKey(), widgetIdsUpdatedByUri);
                return widgetIdsUpdatedByUri;
            }
        } else {
            // Remove the notification on any widgets where the notification was added
            // purely based on the Uri.
            Set<String> widgetsPreviouslyUpdatedByUri =
                    mNotificationKeyToWidgetIdsMatchedByUri.remove(sbn.getKey());
            if (widgetsPreviouslyUpdatedByUri != null && !widgetsPreviouslyUpdatedByUri.isEmpty()) {
                return widgetsPreviouslyUpdatedByUri;
            }
        }
        return new HashSet<>();
    }

    /** Fetches widget Ids that match the contact URI in {@code sbn}. */
    @Nullable
    private Set<String> fetchMatchingUriWidgetIds(StatusBarNotification sbn) {
        // Check if it's a missed call notification
        if (!shouldMatchNotificationByUri(sbn)) {
            if (DEBUG) Log.d(TAG, "Should not supplement conversation");
            return null;
        }

        // Try to get the Contact Uri from the Missed Call notification directly.
        String contactUri = getContactUri(sbn);
        if (contactUri == null) {
            if (DEBUG) Log.d(TAG, "No contact uri");
            return null;
        }

        // Supplement any tiles with the same Uri.
        Set<String> storedWidgetIdsByUri =
                new HashSet<>(mSharedPrefs.getStringSet(contactUri, new HashSet<>()));
        if (storedWidgetIdsByUri.isEmpty()) {
            if (DEBUG) Log.d(TAG, "No tiles for contact");
            return null;
        }
        return storedWidgetIdsByUri;
    }

    /**
     * Update the tiles associated with the incoming conversation update.
     */
    public void updateWidgetsWithConversationChanged(ConversationChannel conversation) {
        ShortcutInfo info = conversation.getShortcutInfo();
        synchronized (mLock) {
            PeopleTileKey key = new PeopleTileKey(
                    info.getId(), info.getUserId(), info.getPackage());
            Set<String> storedWidgetIds = getMatchingKeyWidgetIds(key);
            for (String widgetIdString : storedWidgetIds) {
                if (DEBUG) {
                    Log.d(TAG,
                            "Conversation update for widget " + widgetIdString + " , "
                                    + info.getLabel());
                }
                updateStorageAndViewWithConversationData(conversation,
                        Integer.parseInt(widgetIdString));
            }
        }
    }

    /**
     * Update {@code appWidgetId} with the new data provided by {@code conversation}.
     */
    private void updateStorageAndViewWithConversationData(ConversationChannel conversation,
            int appWidgetId) {
        PeopleSpaceTile storedTile = getTileForExistingWidget(appWidgetId);
        if (storedTile == null) {
            if (DEBUG) Log.d(TAG, "Could not find stored tile to add conversation to");
            return;
        }
        PeopleSpaceTile.Builder updatedTile = storedTile.toBuilder();
        ShortcutInfo info = conversation.getShortcutInfo();
        Uri uri = null;
        if (info.getPersons() != null && info.getPersons().length > 0) {
            Person person = info.getPersons()[0];
            uri = person.getUri() == null ? null : Uri.parse(person.getUri());
        }
        CharSequence label = info.getLabel();
        if (label != null) {
            updatedTile.setUserName(label);
        }
        Icon icon = PeopleSpaceTile.convertDrawableToIcon(mLauncherApps.getShortcutIconDrawable(
                info, 0));
        if (icon != null) {
            updatedTile.setUserIcon(icon);
        }
        if (DEBUG) Log.d(TAG, "Statuses: " + conversation.getStatuses());
        NotificationChannel channel = conversation.getNotificationChannel();
        if (channel != null) {
            if (DEBUG) Log.d(TAG, "Important:" + channel.isImportantConversation());
            updatedTile.setIsImportantConversation(channel.isImportantConversation());
        }
        updatedTile
                .setContactUri(uri)
                .setStatuses(conversation.getStatuses())
                .setLastInteractionTimestamp(conversation.getLastEventTimestamp());
        updateAppWidgetOptionsAndView(appWidgetId, updatedTile.build());
    }

    /**
     * Attaches the manager to the pipeline, making it ready to receive events. Should only be
     * called once.
     */
    public void attach(NotificationListener listenerService) {
        if (DEBUG) Log.d(TAG, "attach");
        listenerService.addNotificationHandler(mListener);
    }

    private final NotificationHandler mListener = new NotificationHandler() {
        @Override
        public void onNotificationPosted(
                StatusBarNotification sbn, NotificationListenerService.RankingMap rankingMap) {
            updateWidgetsWithNotificationChanged(sbn, PeopleSpaceUtils.NotificationAction.POSTED);
        }

        @Override
        public void onNotificationRemoved(
                StatusBarNotification sbn,
                NotificationListenerService.RankingMap rankingMap
        ) {
            updateWidgetsWithNotificationChanged(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
        }

        @Override
        public void onNotificationRemoved(
                StatusBarNotification sbn,
                NotificationListenerService.RankingMap rankingMap,
                int reason) {
            updateWidgetsWithNotificationChanged(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
        }

        @Override
        public void onNotificationRankingUpdate(
                NotificationListenerService.RankingMap rankingMap) {
        }

        @Override
        public void onNotificationsInitialized() {
            if (DEBUG) Log.d(TAG, "onNotificationsInitialized");
        }

        @Override
        public void onNotificationChannelModified(
                String pkgName,
                UserHandle user,
                NotificationChannel channel,
                int modificationType) {
            if (channel.isConversation()) {
                updateWidgets(mAppWidgetManager.getAppWidgetIds(
                        new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
                ));
            }
        }
    };

    /**
     * Checks if this widget has been added externally, and this the first time we are learning
     * about the widget. If so, the widget adder should have populated options with PeopleTileKey
     * arguments.
     */
    public void onAppWidgetOptionsChanged(int appWidgetId, Bundle newOptions) {
        // Check if this widget has been added externally, and this the first time we are
        // learning about the widget. If so, the widget adder should have populated options with
        // PeopleTileKey arguments.
        if (DEBUG) Log.d(TAG, "onAppWidgetOptionsChanged called for widget: " + appWidgetId);
        PeopleTileKey optionsKey = AppWidgetOptionsHelper.getPeopleTileKeyFromBundle(newOptions);
        if (PeopleTileKey.isValid(optionsKey)) {
            if (DEBUG) {
                Log.d(TAG, "PeopleTileKey was present in Options, shortcutId: "
                        + optionsKey.getShortcutId());
            }
            AppWidgetOptionsHelper.removePeopleTileKey(mAppWidgetManager, appWidgetId);
            addNewWidget(appWidgetId, optionsKey);
        }
        // Update views for new widget dimensions.
        updateWidgets(new int[]{appWidgetId});
    }

    /** Adds a widget based on {@code key} mapped to {@code appWidgetId}. */
    public void addNewWidget(int appWidgetId, PeopleTileKey key) {
        if (DEBUG) Log.d(TAG, "addNewWidget called with key for appWidgetId: " + appWidgetId);
        PeopleSpaceTile tile = null;
        try {
            tile = getTileFromPersistentStorage(key, appWidgetId,  /* supplementFromStorage= */
                    false);
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Cannot add widget since app was uninstalled");
            return;
        }
        if (tile == null) {
            return;
        }
        tile = augmentTileFromNotificationEntryManager(tile, Optional.of(appWidgetId));

        PeopleTileKey existingKeyIfStored;
        synchronized (mLock) {
            existingKeyIfStored = getKeyFromStorageByWidgetId(appWidgetId);
        }
        // Delete previous storage if the widget already existed and is just reconfigured.
        if (PeopleTileKey.isValid(existingKeyIfStored)) {
            if (DEBUG) Log.d(TAG, "Remove previous storage for widget: " + appWidgetId);
            deleteWidgets(new int[]{appWidgetId});
        } else {
            // Widget newly added.
            mUiEventLogger.log(
                    PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_ADDED);
        }

        synchronized (mLock) {
            if (DEBUG) Log.d(TAG, "Add storage for : " + key.toString());
            PeopleSpaceUtils.setSharedPreferencesStorageForTile(mContext, key, appWidgetId,
                    tile.getContactUri(), mBackupManager);
        }
        if (DEBUG) Log.d(TAG, "Ensure listener is registered for widget: " + appWidgetId);
        registerConversationListenerIfNeeded(appWidgetId, key);
        try {
            if (DEBUG) Log.d(TAG, "Caching shortcut for PeopleTile: " + key.toString());
            mLauncherApps.cacheShortcuts(tile.getPackageName(),
                    Collections.singletonList(tile.getId()),
                    tile.getUserHandle(), LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS);
        } catch (Exception e) {
            Log.w(TAG, "Exception caching shortcut:" + e);
        }
        PeopleSpaceTile finalTile = tile;
        mBgExecutor.execute(
                () -> updateAppWidgetOptionsAndView(appWidgetId, finalTile));
    }

    /** Registers a conversation listener for {@code appWidgetId} if not already registered. */
    public void registerConversationListenerIfNeeded(int widgetId, PeopleTileKey key) {
        // Retrieve storage needed for registration.
        if (!PeopleTileKey.isValid(key)) {
            if (DEBUG) Log.w(TAG, "Could not register listener for widget: " + widgetId);
            return;
        }
        TileConversationListener newListener = new TileConversationListener();
        synchronized (mListeners) {
            if (mListeners.containsKey(key)) {
                if (DEBUG) Log.d(TAG, "Already registered listener");
                return;
            }
            if (DEBUG) Log.d(TAG, "Register listener for " + widgetId + " with " + key.toString());
            mListeners.put(key, newListener);
        }
        mPeopleManager.registerConversationListener(key.getPackageName(),
                key.getUserId(),
                key.getShortcutId(), newListener,
                mContext.getMainExecutor());
    }

    /**
     * Attempts to get a key from storage for {@code widgetId}, returning null if an invalid key is
     * found.
     */
    private PeopleTileKey getKeyFromStorageByWidgetId(int widgetId) {
        SharedPreferences widgetSp = mContext.getSharedPreferences(String.valueOf(widgetId),
                Context.MODE_PRIVATE);
        PeopleTileKey key = new PeopleTileKey(
                widgetSp.getString(SHORTCUT_ID, EMPTY_STRING),
                widgetSp.getInt(USER_ID, INVALID_USER_ID),
                widgetSp.getString(PACKAGE_NAME, EMPTY_STRING));
        return key;
    }

    /** Deletes all storage, listeners, and caching for {@code appWidgetIds}. */
    public void deleteWidgets(int[] appWidgetIds) {
        for (int widgetId : appWidgetIds) {
            if (DEBUG) Log.d(TAG, "Widget removed: " + widgetId);
            mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_DELETED);
            // Retrieve storage needed for widget deletion.
            PeopleTileKey key;
            Set<String> storedWidgetIdsForKey;
            String contactUriString;
            synchronized (mLock) {
                SharedPreferences widgetSp = mContext.getSharedPreferences(String.valueOf(widgetId),
                        Context.MODE_PRIVATE);
                key = new PeopleTileKey(
                        widgetSp.getString(SHORTCUT_ID, null),
                        widgetSp.getInt(USER_ID, INVALID_USER_ID),
                        widgetSp.getString(PACKAGE_NAME, null));
                if (!PeopleTileKey.isValid(key)) {
                    if (DEBUG) Log.e(TAG, "Could not delete " + widgetId);
                    return;
                }
                storedWidgetIdsForKey = new HashSet<>(
                        mSharedPrefs.getStringSet(key.toString(), new HashSet<>()));
                contactUriString = mSharedPrefs.getString(String.valueOf(widgetId), null);
            }
            synchronized (mLock) {
                PeopleSpaceUtils.removeSharedPreferencesStorageForTile(mContext, key, widgetId,
                        contactUriString);
            }
            // If another tile with the conversation is still stored, we need to keep the listener.
            if (DEBUG) Log.d(TAG, "Stored widget IDs: " + storedWidgetIdsForKey.toString());
            if (storedWidgetIdsForKey.contains(String.valueOf(widgetId))
                    && storedWidgetIdsForKey.size() == 1) {
                if (DEBUG) Log.d(TAG, "Remove caching and listener");
                unregisterConversationListener(key, widgetId);
                uncacheConversationShortcut(key);
            }
        }
    }

    /** Unregisters the conversation listener for {@code appWidgetId}. */
    private void unregisterConversationListener(PeopleTileKey key, int appWidgetId) {
        TileConversationListener registeredListener;
        synchronized (mListeners) {
            registeredListener = mListeners.get(key);
            if (registeredListener == null) {
                if (DEBUG) Log.d(TAG, "Cannot find listener to unregister");
                return;
            }
            if (DEBUG) {
                Log.d(TAG, "Unregister listener for " + appWidgetId + " with " + key.toString());
            }
            mListeners.remove(key);
        }
        mPeopleManager.unregisterConversationListener(registeredListener);
    }

    /** Uncaches the conversation shortcut. */
    private void uncacheConversationShortcut(PeopleTileKey key) {
        try {
            if (DEBUG) Log.d(TAG, "Uncaching shortcut for PeopleTile: " + key.getShortcutId());
            mLauncherApps.uncacheShortcuts(key.getPackageName(),
                    Collections.singletonList(key.getShortcutId()),
                    UserHandle.of(key.getUserId()),
                    LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS);
        } catch (Exception e) {
            Log.d(TAG, "Exception uncaching shortcut:" + e);
        }
    }

    /**
     * Builds a request to pin a People Tile app widget, with a preview and storing necessary
     * information as the callback.
     */
    public boolean requestPinAppWidget(ShortcutInfo shortcutInfo, Bundle options) {
        if (DEBUG) Log.d(TAG, "Requesting pin widget, shortcutId: " + shortcutInfo.getId());

        RemoteViews widgetPreview = getPreview(shortcutInfo.getId(),
                shortcutInfo.getUserHandle(), shortcutInfo.getPackage(), options);
        if (widgetPreview == null) {
            Log.w(TAG, "Skipping pinning widget: no tile for shortcutId: " + shortcutInfo.getId());
            return false;
        }
        Bundle extras = new Bundle();
        extras.putParcelable(AppWidgetManager.EXTRA_APPWIDGET_PREVIEW, widgetPreview);

        PendingIntent successCallback =
                PeopleSpaceWidgetPinnedReceiver.getPendingIntent(mContext, shortcutInfo);

        ComponentName componentName = new ComponentName(mContext, PeopleSpaceWidgetProvider.class);
        return mAppWidgetManager.requestPinAppWidget(componentName, extras, successCallback);
    }

    /** Returns a list of map entries corresponding to user's priority conversations. */
    @NonNull
    public List<PeopleSpaceTile> getPriorityTiles()
            throws Exception {
        List<ConversationChannelWrapper> conversations =
                mINotificationManager.getConversations(true).getList();
        // Add priority conversations to tiles list.
        Stream<ShortcutInfo> priorityConversations = conversations.stream()
                .filter(c -> c.getNotificationChannel() != null
                        && c.getNotificationChannel().isImportantConversation())
                .map(c -> c.getShortcutInfo());
        List<PeopleSpaceTile> priorityTiles = PeopleSpaceUtils.getSortedTiles(mIPeopleManager,
                mLauncherApps, mUserManager,
                priorityConversations);
        return priorityTiles;
    }

    /** Returns a list of map entries corresponding to user's recent conversations. */
    @NonNull
    public List<PeopleSpaceTile> getRecentTiles()
            throws Exception {
        if (DEBUG) Log.d(TAG, "Add recent conversations");
        List<ConversationChannelWrapper> conversations =
                mINotificationManager.getConversations(false).getList();
        Stream<ShortcutInfo> nonPriorityConversations = conversations.stream()
                .filter(c -> c.getNotificationChannel() == null
                        || !c.getNotificationChannel().isImportantConversation())
                .map(c -> c.getShortcutInfo());

        List<ConversationChannel> recentConversationsList =
                mIPeopleManager.getRecentConversations().getList();
        Stream<ShortcutInfo> recentConversations = recentConversationsList
                .stream()
                .map(c -> c.getShortcutInfo());

        Stream<ShortcutInfo> mergedStream = Stream.concat(nonPriorityConversations,
                recentConversations);
        List<PeopleSpaceTile> recentTiles =
                PeopleSpaceUtils.getSortedTiles(mIPeopleManager, mLauncherApps, mUserManager,
                        mergedStream);
        return recentTiles;
    }

    /**
     * Returns a {@link RemoteViews} preview of a Conversation's People Tile. Returns null if one
     * is not available.
     */
    public RemoteViews getPreview(String shortcutId, UserHandle userHandle, String packageName,
            Bundle options) {
        PeopleSpaceTile tile;
        ConversationChannel channel;
        try {
            channel = mIPeopleManager.getConversation(
                    packageName, userHandle.getIdentifier(), shortcutId);
            tile = PeopleSpaceUtils.getTile(channel, mLauncherApps);
        } catch (Exception e) {
            Log.w(TAG, "Exception getting tiles: " + e);
            return null;
        }
        if (tile == null) {
            if (DEBUG) Log.i(TAG, "No tile was returned");
            return null;
        }

        PeopleSpaceTile augmentedTile = augmentTileFromNotificationEntryManager(tile,
                Optional.empty());

        if (DEBUG) Log.i(TAG, "Returning tile preview for shortcutId: " + shortcutId);
        return PeopleTileViewHelper.createRemoteViews(mContext, augmentedTile, 0, options,
                new PeopleTileKey(augmentedTile));
    }

    protected final BroadcastReceiver mBaseBroadcastReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (DEBUG) Log.d(TAG, "Update widgets from: " + intent.getAction());
            mBgExecutor.execute(() -> updateWidgetsFromBroadcastInBackground(intent.getAction()));
        }
    };

    /** Updates any app widget to the current state, triggered by a broadcast update. */
    @VisibleForTesting
    void updateWidgetsFromBroadcastInBackground(String entryPoint) {
        int[] appWidgetIds = mAppWidgetManager.getAppWidgetIds(
                new ComponentName(mContext, PeopleSpaceWidgetProvider.class));
        if (appWidgetIds == null) {
            return;
        }
        for (int appWidgetId : appWidgetIds) {
            if (DEBUG) Log.d(TAG, "Updating widget from broadcast, widget id: " + appWidgetId);
            PeopleSpaceTile existingTile = null;
            PeopleSpaceTile updatedTile = null;
            try {
                synchronized (mLock) {
                    existingTile = getTileForExistingWidgetThrowing(appWidgetId);
                    if (existingTile == null) {
                        Log.e(TAG, "Matching conversation not found for shortcut ID");
                        continue;
                    }
                    updatedTile = getTileWithCurrentState(existingTile, entryPoint);
                    updateAppWidgetOptionsAndView(appWidgetId, updatedTile);
                }
            } catch (PackageManager.NameNotFoundException e) {
                // Delete data for uninstalled widgets.
                Log.e(TAG, "Package no longer found for tile: " + e);
                JobScheduler jobScheduler = mContext.getSystemService(JobScheduler.class);
                if (jobScheduler != null
                        && jobScheduler.getPendingJob(PeopleBackupFollowUpJob.JOB_ID) != null) {
                    if (DEBUG) {
                        Log.d(TAG, "Device was recently restored, wait before deleting storage.");
                    }
                    continue;
                }
                synchronized (mLock) {
                    updateAppWidgetOptionsAndView(appWidgetId, updatedTile);
                }
                deleteWidgets(new int[]{appWidgetId});
            }
        }
    }

    /** Checks the current state of {@code tile} dependencies, modifying fields as necessary. */
    @Nullable
    private PeopleSpaceTile getTileWithCurrentState(PeopleSpaceTile tile,
            String entryPoint) throws
            PackageManager.NameNotFoundException {
        PeopleSpaceTile.Builder updatedTile = tile.toBuilder();
        switch (entryPoint) {
            case NotificationManager
                    .ACTION_INTERRUPTION_FILTER_CHANGED:
                updatedTile.setNotificationPolicyState(getNotificationPolicyState());
                break;
            case Intent.ACTION_PACKAGES_SUSPENDED:
            case Intent.ACTION_PACKAGES_UNSUSPENDED:
                updatedTile.setIsPackageSuspended(getPackageSuspended(tile));
                break;
            case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
            case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
            case Intent.ACTION_USER_UNLOCKED:
                updatedTile.setIsUserQuieted(getUserQuieted(tile));
                break;
            case Intent.ACTION_LOCALE_CHANGED:
                break;
            case ACTION_BOOT_COMPLETED:
            default:
                updatedTile.setIsUserQuieted(getUserQuieted(tile)).setIsPackageSuspended(
                        getPackageSuspended(tile)).setNotificationPolicyState(
                        getNotificationPolicyState());
        }
        return updatedTile.build();
    }

    private boolean getPackageSuspended(PeopleSpaceTile tile) throws
            PackageManager.NameNotFoundException {
        boolean packageSuspended = !TextUtils.isEmpty(tile.getPackageName())
                && mPackageManager.isPackageSuspended(tile.getPackageName());
        if (DEBUG) Log.d(TAG, "Package suspended: " + packageSuspended);
        // isPackageSuspended() only throws an exception if the app has been uninstalled, and the
        // app data has also been cleared. We want to empty the layout when the app is uninstalled
        // regardless of app data clearing, which getApplicationInfoAsUser() handles.
        mPackageManager.getApplicationInfoAsUser(
                tile.getPackageName(), PackageManager.GET_META_DATA,
                PeopleSpaceUtils.getUserId(tile));
        return packageSuspended;
    }

    private boolean getUserQuieted(PeopleSpaceTile tile) {
        boolean workProfileQuieted =
                tile.getUserHandle() != null && mUserManager.isQuietModeEnabled(
                        tile.getUserHandle());
        if (DEBUG) Log.d(TAG, "Work profile quiet: " + workProfileQuieted);
        return workProfileQuieted;
    }

    private int getNotificationPolicyState() {
        NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy();
        boolean suppressVisualEffects =
                NotificationManager.Policy.areAllVisualEffectsSuppressed(
                        policy.suppressedVisualEffects);
        int notificationPolicyState = 0;
        // If the user sees notifications in DND, we do not need to evaluate the current DND
        // state, just always show notifications.
        if (!suppressVisualEffects) {
            if (DEBUG) Log.d(TAG, "Visual effects not suppressed.");
            return PeopleSpaceTile.SHOW_CONVERSATIONS;
        }
        switch (mNotificationManager.getCurrentInterruptionFilter()) {
            case INTERRUPTION_FILTER_ALL:
                if (DEBUG) Log.d(TAG, "All interruptions allowed");
                return PeopleSpaceTile.SHOW_CONVERSATIONS;
            case INTERRUPTION_FILTER_PRIORITY:
                if (policy.allowConversations()) {
                    if (policy.priorityConversationSenders == CONVERSATION_SENDERS_ANYONE) {
                        if (DEBUG) Log.d(TAG, "All conversations allowed");
                        // We only show conversations, so we can show everything.
                        return PeopleSpaceTile.SHOW_CONVERSATIONS;
                    } else if (policy.priorityConversationSenders
                            == NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT) {
                        if (DEBUG) Log.d(TAG, "Important conversations allowed");
                        notificationPolicyState |= PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS;
                    }
                }
                if (policy.allowMessages()) {
                    switch (policy.allowMessagesFrom()) {
                        case ZenModeConfig.SOURCE_CONTACT:
                            if (DEBUG) Log.d(TAG, "All contacts allowed");
                            notificationPolicyState |= PeopleSpaceTile.SHOW_CONTACTS;
                            return notificationPolicyState;
                        case ZenModeConfig.SOURCE_STAR:
                            if (DEBUG) Log.d(TAG, "Starred contacts allowed");
                            notificationPolicyState |= PeopleSpaceTile.SHOW_STARRED_CONTACTS;
                            return notificationPolicyState;
                        case ZenModeConfig.SOURCE_ANYONE:
                        default:
                            if (DEBUG) Log.d(TAG, "All messages allowed");
                            return PeopleSpaceTile.SHOW_CONVERSATIONS;
                    }
                }
                if (notificationPolicyState != 0) {
                    if (DEBUG) Log.d(TAG, "Return block state: " + notificationPolicyState);
                    return notificationPolicyState;
                }
                // If only alarms or nothing can bypass DND, the tile shouldn't show conversations.
            case INTERRUPTION_FILTER_NONE:
            case INTERRUPTION_FILTER_ALARMS:
            default:
                if (DEBUG) Log.d(TAG, "Block conversations");
                return PeopleSpaceTile.BLOCK_CONVERSATIONS;
        }
    }

    /**
     * Modifies widgets storage after a restore operation, since widget ids get remapped on restore.
     * This is guaranteed to run after the PeopleBackupHelper restore operation.
     */
    public void remapWidgets(int[] oldWidgetIds, int[] newWidgetIds) {
        if (DEBUG) {
            Log.d(TAG, "Remapping widgets, old: " + Arrays.toString(oldWidgetIds) + ". new: "
                    + Arrays.toString(newWidgetIds));
        }

        Map<String, String> widgets = new HashMap<>();
        for (int i = 0; i < oldWidgetIds.length; i++) {
            widgets.put(String.valueOf(oldWidgetIds[i]), String.valueOf(newWidgetIds[i]));
        }

        remapWidgetFiles(widgets);
        remapSharedFile(widgets);
        remapFollowupFile(widgets);

        int[] widgetIds = mAppWidgetManager.getAppWidgetIds(
                new ComponentName(mContext, PeopleSpaceWidgetProvider.class));
        Bundle b = new Bundle();
        b.putBoolean(AppWidgetManager.OPTION_APPWIDGET_RESTORE_COMPLETED, true);
        for (int id : widgetIds) {
            if (DEBUG) Log.d(TAG, "Setting widget as restored, widget id:" + id);
            mAppWidgetManager.updateAppWidgetOptions(id, b);
        }

        updateWidgets(widgetIds);
    }

    /** Remaps widget ids in widget specific files. */
    public void remapWidgetFiles(Map<String, String> widgets) {
        if (DEBUG) Log.d(TAG, "Remapping widget files");
        Map<String, PeopleTileKey> remapped = new HashMap<>();
        for (Map.Entry<String, String> entry : widgets.entrySet()) {
            String from = String.valueOf(entry.getKey());
            String to = String.valueOf(entry.getValue());
            if (Objects.equals(from, to)) {
                continue;
            }

            SharedPreferences src = mContext.getSharedPreferences(from, Context.MODE_PRIVATE);
            PeopleTileKey key = SharedPreferencesHelper.getPeopleTileKey(src);
            if (PeopleTileKey.isValid(key)) {
                if (DEBUG) {
                    Log.d(TAG, "Moving PeopleTileKey: " + key.toString() + " from file: "
                            + from + ", to file: " + to);
                }
                remapped.put(to, key);
                SharedPreferencesHelper.clear(src);
            } else {
                if (DEBUG) Log.d(TAG, "Widget file has invalid key: " + key);
            }
        }
        for (Map.Entry<String, PeopleTileKey> entry : remapped.entrySet()) {
            SharedPreferences dest = mContext.getSharedPreferences(
                    entry.getKey(), Context.MODE_PRIVATE);
            SharedPreferencesHelper.setPeopleTileKey(dest, entry.getValue());
        }
    }

    /** Remaps widget ids in default shared storage. */
    public void remapSharedFile(Map<String, String> widgets) {
        if (DEBUG) Log.d(TAG, "Remapping shared file");
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
        SharedPreferences.Editor editor = sp.edit();
        Map<String, ?> all = sp.getAll();
        for (Map.Entry<String, ?> entry : all.entrySet()) {
            String key = entry.getKey();
            PeopleBackupHelper.SharedFileEntryType keyType = getEntryType(entry);
            if (DEBUG) Log.d(TAG, "Remapping key:" + key);
            switch (keyType) {
                case WIDGET_ID:
                    String newId = widgets.get(key);
                    if (TextUtils.isEmpty(newId)) {
                        Log.w(TAG, "Key is widget id without matching new id, skipping: " + key);
                        break;
                    }
                    if (DEBUG) Log.d(TAG, "Key is widget id: " + key + ", replace with: " + newId);
                    try {
                        editor.putString(newId, (String) entry.getValue());
                    } catch (Exception e) {
                        Log.e(TAG, "Malformed entry value: " + entry.getValue());
                    }
                    editor.remove(key);
                    break;
                case PEOPLE_TILE_KEY:
                case CONTACT_URI:
                    Set<String> oldWidgetIds;
                    try {
                        oldWidgetIds = (Set<String>) entry.getValue();
                    } catch (Exception e) {
                        Log.e(TAG, "Malformed entry value: " + entry.getValue());
                        editor.remove(key);
                        break;
                    }
                    Set<String> newWidgets = getNewWidgets(oldWidgetIds, widgets);
                    if (DEBUG) {
                        Log.d(TAG, "Key is PeopleTileKey or contact URI: " + key
                                + ", replace values with new ids: " + newWidgets);
                    }
                    editor.putStringSet(key, newWidgets);
                    break;
                case UNKNOWN:
                    Log.e(TAG, "Key not identified:" + key);
            }
        }
        editor.apply();
    }

    /** Remaps widget ids in follow-up job file. */
    public void remapFollowupFile(Map<String, String> widgets) {
        if (DEBUG) Log.d(TAG, "Remapping follow up file");
        SharedPreferences followUp = mContext.getSharedPreferences(
                SHARED_FOLLOW_UP, Context.MODE_PRIVATE);
        SharedPreferences.Editor followUpEditor = followUp.edit();
        Map<String, ?> followUpAll = followUp.getAll();
        for (Map.Entry<String, ?> entry : followUpAll.entrySet()) {
            String key = entry.getKey();
            Set<String> oldWidgetIds;
            try {
                oldWidgetIds = (Set<String>) entry.getValue();
            } catch (Exception e) {
                Log.e(TAG, "Malformed entry value: " + entry.getValue());
                followUpEditor.remove(key);
                continue;
            }
            Set<String> newWidgets = getNewWidgets(oldWidgetIds, widgets);
            if (DEBUG) {
                Log.d(TAG, "Follow up key: " + key + ", replace with new ids: " + newWidgets);
            }
            followUpEditor.putStringSet(key, newWidgets);
        }
        followUpEditor.apply();
    }

    private Set<String> getNewWidgets(Set<String> oldWidgets, Map<String, String> widgetsMapping) {
        return oldWidgets
                .stream()
                .map(widgetsMapping::get)
                .filter(id -> !TextUtils.isEmpty(id))
                .collect(Collectors.toSet());
    }
}
