Extract Instant Apps notification code into InstantAppNotifier

The code to show notifications of Instant App was in
PhoneStatsuBarPolicy. This CL moves these code into new class
named InstantAppNotifier.

Bug: 123917211
Test: build passes

Change-Id: Ib4bd988c94e2382d776c5c0b1886c8d20d3a1b16
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
new file mode 100644
index 0000000..7748532
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2019 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.statusbar.notification;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
+import android.app.AppGlobals;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.SynchronousUserSwitchObserver;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+import android.util.Pair;
+
+import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.systemui.Dependency;
+import com.android.systemui.DockedStackExistsListener;
+import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.SystemUI;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.util.NotificationChannels;
+
+import java.util.List;
+
+/** The clsss to show notification(s) of instant apps. This may show multiple notifications on
+ * splitted screen.
+ */
+public class InstantAppNotifier extends SystemUI
+        implements CommandQueue.Callbacks, KeyguardMonitor.Callback {
+    private static final String TAG = "InstantAppNotifier";
+    public static final int NUM_TASKS_FOR_INSTANT_APP_INFO = 5;
+
+    private final Handler mHandler = new Handler();
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+    private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
+    private boolean mDockedStackExists;
+    private KeyguardMonitor mKeyguardMonitor;
+
+    public InstantAppNotifier() {}
+
+    @Override
+    public void start() {
+        mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+
+        // listen for user / profile change.
+        try {
+            ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
+        } catch (RemoteException e) {
+            // Ignore
+        }
+
+        SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
+        mKeyguardMonitor.addCallback(this);
+
+        DockedStackExistsListener.register(
+                exists -> {
+                    mDockedStackExists = exists;
+                    updateForegroundInstantApps();
+                });
+
+        // Clear out all old notifications on startup (only present in the case where sysui dies)
+        NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
+        for (StatusBarNotification notification : noMan.getActiveNotifications()) {
+            if (notification.getId() == SystemMessage.NOTE_INSTANT_APPS) {
+                noMan.cancel(notification.getTag(), notification.getId());
+            }
+        }
+    }
+
+    @Override
+    public void appTransitionStarting(
+            int displayId, long startTime, long duration, boolean forced) {
+        if (mContext.getDisplayId() == displayId) {
+            updateForegroundInstantApps();
+        }
+    }
+
+    @Override
+    public void onKeyguardShowingChanged() {
+        updateForegroundInstantApps();
+    }
+
+    @Override
+    public void preloadRecentApps() {
+        updateForegroundInstantApps();
+    }
+
+    private final SynchronousUserSwitchObserver mUserSwitchListener =
+            new SynchronousUserSwitchObserver() {
+                @Override
+                public void onUserSwitching(int newUserId) throws RemoteException {}
+
+                @Override
+                public void onUserSwitchComplete(int newUserId) throws RemoteException {
+                    mHandler.post(
+                            () -> {
+                                updateForegroundInstantApps();
+                            });
+                }
+            };
+
+    private final TaskStackChangeListener mTaskListener =
+            new TaskStackChangeListener() {
+                @Override
+                public void onTaskStackChanged() {
+                    // Listen for changes to stacks and then check which instant apps are
+                    // foreground.
+                    updateForegroundInstantApps();
+                }
+            };
+
+    private void updateForegroundInstantApps() {
+        NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
+        IPackageManager pm = AppGlobals.getPackageManager();
+        mUiOffloadThread.submit(
+                () -> {
+                    ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs);
+                    try {
+                        final ActivityManager.StackInfo focusedStack =
+                                ActivityTaskManager.getService().getFocusedStackInfo();
+                        if (focusedStack != null) {
+                            final int windowingMode =
+                                    focusedStack.configuration.windowConfiguration
+                                            .getWindowingMode();
+                            if (windowingMode == WINDOWING_MODE_FULLSCREEN
+                                    || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+                                checkAndPostForStack(focusedStack, notifs, noMan, pm);
+                            }
+                        }
+                        if (mDockedStackExists) {
+                            checkAndPostForPrimaryScreen(notifs, noMan, pm);
+                        }
+                    } catch (RemoteException e) {
+                        e.rethrowFromSystemServer();
+                    }
+
+                    // Cancel all the leftover notifications that don't have a foreground
+                    // process anymore.
+                    notifs.forEach(
+                            v -> {
+                                mCurrentNotifs.remove(v);
+
+                                noMan.cancelAsUser(
+                                        v.first,
+                                        SystemMessageProto.SystemMessage.NOTE_INSTANT_APPS,
+                                        new UserHandle(v.second));
+                            });
+                });
+    }
+
+    /**
+     * Posts an instant app notification if the top activity of the primary container in the
+     * splitted screen is an instant app and the corresponding instant app notification is not
+     * posted yet. If the notification already exists, this method removes it from {@code
+     * notifs} in the arguments.
+     */
+    private void checkAndPostForPrimaryScreen(
+            @NonNull ArraySet<Pair<String, Integer>> notifs,
+            @NonNull NotificationManager noMan,
+            @NonNull IPackageManager pm) {
+        try {
+            final ActivityManager.StackInfo info =
+                    ActivityTaskManager.getService()
+                            .getStackInfo(
+                                    WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+            checkAndPostForStack(info, notifs, noMan, pm);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Posts an instant app notification if the top activity of the given stack is an instant app
+     * and the corresponding instant app notification is not posted yet. If the notification already
+     * exists, this method removes it from {@code notifs} in the arguments.
+     */
+    private void checkAndPostForStack(
+            @Nullable ActivityManager.StackInfo info,
+            @NonNull ArraySet<Pair<String, Integer>> notifs,
+            @NonNull NotificationManager noMan,
+            @NonNull IPackageManager pm) {
+        try {
+            if (info == null || info.topActivity == null) return;
+            String pkg = info.topActivity.getPackageName();
+            Pair<String, Integer> key = new Pair<>(pkg, info.userId);
+            if (!notifs.remove(key)) {
+                // TODO: Optimize by not always needing to get application info.
+                // Maybe cache non-instant-app packages?
+                ApplicationInfo appInfo =
+                        pm.getApplicationInfo(
+                                pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, info.userId);
+                if (appInfo.isInstantApp()) {
+                    postInstantAppNotif(
+                            pkg,
+                            info.userId,
+                            appInfo,
+                            noMan,
+                            info.taskIds[info.taskIds.length - 1]);
+                }
+            }
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /** Posts an instant app notification. */
+    private void postInstantAppNotif(
+            @NonNull String pkg,
+            int userId,
+            @NonNull ApplicationInfo appInfo,
+            @NonNull NotificationManager noMan,
+            int taskId) {
+        final Bundle extras = new Bundle();
+        extras.putString(
+                Notification.EXTRA_SUBSTITUTE_APP_NAME, mContext.getString(R.string.instant_apps));
+        mCurrentNotifs.add(new Pair<>(pkg, userId));
+
+        String helpUrl = mContext.getString(R.string.instant_apps_help_url);
+        boolean hasHelpUrl = !helpUrl.isEmpty();
+        String message =
+                mContext.getString(
+                        hasHelpUrl
+                                ? R.string.instant_apps_message_with_help
+                                : R.string.instant_apps_message);
+
+        UserHandle user = UserHandle.of(userId);
+        PendingIntent appInfoAction =
+                PendingIntent.getActivityAsUser(
+                        mContext,
+                        0,
+                        new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+                                .setData(Uri.fromParts("package", pkg, null)),
+                        0,
+                        null,
+                        user);
+        Notification.Action action =
+                new Notification.Action.Builder(
+                                null, mContext.getString(R.string.app_info), appInfoAction)
+                        .build();
+        PendingIntent helpCenterIntent =
+                hasHelpUrl
+                        ? PendingIntent.getActivityAsUser(
+                                mContext,
+                                0,
+                                new Intent(Intent.ACTION_VIEW).setData(Uri.parse(helpUrl)),
+                                0,
+                                null,
+                                user)
+                        : null;
+
+        Intent browserIntent = getTaskIntent(taskId, userId);
+        Notification.Builder builder =
+                new Notification.Builder(mContext, NotificationChannels.GENERAL);
+        if (browserIntent != null && browserIntent.isWebIntent()) {
+            // Make sure that this doesn't resolve back to an instant app
+            browserIntent
+                    .setComponent(null)
+                    .setPackage(null)
+                    .addFlags(Intent.FLAG_IGNORE_EPHEMERAL)
+                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            PendingIntent pendingIntent =
+                    PendingIntent.getActivityAsUser(
+                            mContext,
+                            0 /* requestCode */,
+                            browserIntent,
+                            0 /* flags */,
+                            null,
+                            user);
+            ComponentName aiaComponent = null;
+            try {
+                aiaComponent = AppGlobals.getPackageManager().getInstantAppInstallerComponent();
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+            Intent goToWebIntent =
+                    new Intent()
+                            .setComponent(aiaComponent)
+                            .setAction(Intent.ACTION_VIEW)
+                            .addCategory(Intent.CATEGORY_BROWSABLE)
+                            .addCategory("unique:" + System.currentTimeMillis())
+                            .putExtra(Intent.EXTRA_PACKAGE_NAME, appInfo.packageName)
+                            .putExtra(
+                                    Intent.EXTRA_VERSION_CODE,
+                                    (int) (appInfo.versionCode & 0x7fffffff))
+                            .putExtra(Intent.EXTRA_LONG_VERSION_CODE, appInfo.versionCode)
+                            .putExtra(Intent.EXTRA_INSTANT_APP_FAILURE, pendingIntent);
+
+            PendingIntent webPendingIntent =
+                    PendingIntent.getActivityAsUser(mContext, 0, goToWebIntent, 0, null, user);
+            Notification.Action webAction =
+                    new Notification.Action.Builder(
+                                    null, mContext.getString(R.string.go_to_web), webPendingIntent)
+                            .build();
+            builder.addAction(webAction);
+        }
+
+        noMan.notifyAsUser(
+                pkg,
+                SystemMessage.NOTE_INSTANT_APPS,
+                builder.addExtras(extras)
+                        .addAction(action)
+                        .setContentIntent(helpCenterIntent)
+                        .setColor(mContext.getColor(R.color.instant_apps_color))
+                        .setContentTitle(
+                                mContext.getString(
+                                        R.string.instant_apps_title,
+                                        appInfo.loadLabel(mContext.getPackageManager())))
+                        .setLargeIcon(Icon.createWithResource(pkg, appInfo.icon))
+                        .setSmallIcon(
+                                Icon.createWithResource(
+                                        mContext.getPackageName(), R.drawable.instant_icon))
+                        .setContentText(message)
+                        .setStyle(new Notification.BigTextStyle().bigText(message))
+                        .setOngoing(true)
+                        .build(),
+                new UserHandle(userId));
+    }
+
+    @Nullable
+    private Intent getTaskIntent(int taskId, int userId) {
+        try {
+            final List<ActivityManager.RecentTaskInfo> tasks =
+                    ActivityTaskManager.getService()
+                            .getRecentTasks(NUM_TASKS_FOR_INSTANT_APP_INFO, 0, userId)
+                            .getList();
+            for (int i = 0; i < tasks.size(); i++) {
+                if (tasks.get(i).id == taskId) {
+                    return tasks.get(i).baseIntent;
+                }
+            }
+        } catch (RemoteException e) {
+            // Fall through
+        }
+        return null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index e0c5e59..4a86484 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -16,53 +16,29 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-
 import android.app.ActivityManager;
-import android.app.ActivityManager.StackInfo;
 import android.app.ActivityTaskManager;
 import android.app.AlarmManager;
 import android.app.AlarmManager.AlarmClockInfo;
-import android.app.AppGlobals;
-import android.app.Notification;
-import android.app.Notification.Action;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.app.SynchronousUserSwitchObserver;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Icon;
 import android.media.AudioManager;
-import android.net.Uri;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.provider.Settings;
 import android.provider.Settings.Global;
-import android.service.notification.StatusBarNotification;
 import android.service.notification.ZenModeConfig;
 import android.telecom.TelecomManager;
 import android.text.format.DateFormat;
-import android.util.ArraySet;
 import android.util.Log;
-import android.util.Pair;
 
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.systemui.Dependency;
-import com.android.systemui.DockedStackExistsListener;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.UiOffloadThread;
@@ -70,12 +46,8 @@
 import com.android.systemui.privacy.PrivacyItemController;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.RotationLockTile;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.BluetoothController.Callback;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.CastController.CastDevice;
 import com.android.systemui.statusbar.policy.DataSaverController;
@@ -90,7 +62,6 @@
 import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.NotificationChannels;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -98,18 +69,22 @@
 import java.util.Locale;
 
 /**
- * This class contains all of the policy about which icons are installed in the status
- * bar at boot time.  It goes through the normal API for icons, even though it probably
- * strictly doesn't need to.
+ * This class contains all of the policy about which icons are installed in the status bar at boot
+ * time. It goes through the normal API for icons, even though it probably strictly doesn't need to.
  */
-public class PhoneStatusBarPolicy implements Callback, Callbacks,
-        RotationLockControllerCallback, Listener, ZenModeController.Callback,
-        DeviceProvisionedListener, KeyguardMonitor.Callback, PrivacyItemController.Callback {
+public class PhoneStatusBarPolicy
+        implements BluetoothController.Callback,
+                CommandQueue.Callbacks,
+                RotationLockControllerCallback,
+                Listener,
+                ZenModeController.Callback,
+                DeviceProvisionedListener,
+                KeyguardMonitor.Callback,
+                PrivacyItemController.Callback {
     private static final String TAG = "PhoneStatusBarPolicy";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
-    public static final int NUM_TASKS_FOR_INSTANT_APP_INFO = 5;
 
     private final String mSlotCast;
     private final String mSlotHotspot;
@@ -142,7 +117,6 @@
     private final KeyguardMonitor mKeyguardMonitor;
     private final LocationController mLocationController;
     private final PrivacyItemController mPrivacyItemController;
-    private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
     private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     // Assume it's all good unless we hear otherwise.  We don't always seem
@@ -152,7 +126,6 @@
     private boolean mZenVisible;
     private boolean mVolumeVisible;
     private boolean mCurrentUserSetup;
-    private boolean mDockedStackExists;
 
     private boolean mManagedProfileIconVisible = false;
 
@@ -271,19 +244,6 @@
         mPrivacyItemController.addCallback(this);
 
         SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
-        ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);
-
-        // Clear out all old notifications on startup (only present in the case where sysui dies)
-        NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
-        for (StatusBarNotification notification : noMan.getActiveNotifications()) {
-            if (notification.getId() == SystemMessage.NOTE_INSTANT_APPS) {
-                noMan.cancel(notification.getTag(), notification.getId());
-            }
-        }
-        DockedStackExistsListener.register(exists -> {
-            mDockedStackExists = exists;
-            updateForegroundInstantApps();
-        });
     }
 
     @Override
@@ -515,169 +475,6 @@
         });
     }
 
-    private void updateForegroundInstantApps() {
-        NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
-        ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs);
-        IPackageManager pm = AppGlobals.getPackageManager();
-        mCurrentNotifs.clear();
-        mUiOffloadThread.submit(() -> {
-            try {
-                final StackInfo focusedStack =
-                        ActivityTaskManager.getService().getFocusedStackInfo();
-                if (focusedStack != null) {
-                    final int windowingMode =
-                            focusedStack.configuration.windowConfiguration.getWindowingMode();
-                    if (windowingMode == WINDOWING_MODE_FULLSCREEN
-                            || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
-                        checkStack(focusedStack, notifs, noMan, pm);
-                    }
-                }
-                if (mDockedStackExists) {
-                    checkStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED,
-                            notifs, noMan, pm);
-                }
-            } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
-            }
-            // Cancel all the leftover notifications that don't have a foreground process anymore.
-            notifs.forEach(v -> noMan.cancelAsUser(v.first, SystemMessage.NOTE_INSTANT_APPS,
-                    new UserHandle(v.second)));
-        });
-    }
-
-    private void checkStack(int windowingMode, int activityType,
-            ArraySet<Pair<String, Integer>> notifs, NotificationManager noMan, IPackageManager pm) {
-        try {
-            final StackInfo info =
-                    ActivityTaskManager.getService().getStackInfo(windowingMode, activityType);
-            checkStack(info, notifs, noMan, pm);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-    private void checkStack(StackInfo info, ArraySet<Pair<String, Integer>> notifs,
-            NotificationManager noMan, IPackageManager pm) {
-        try {
-            if (info == null || info.topActivity == null) return;
-            String pkg = info.topActivity.getPackageName();
-            if (!hasNotif(notifs, pkg, info.userId)) {
-                // TODO: Optimize by not always needing to get application info.
-                // Maybe cache non-ephemeral packages?
-                ApplicationInfo appInfo = pm.getApplicationInfo(pkg,
-                        PackageManager.MATCH_UNINSTALLED_PACKAGES, info.userId);
-                if (appInfo.isInstantApp()) {
-                    postEphemeralNotif(pkg, info.userId, appInfo, noMan, info.taskIds[info.taskIds.length - 1]);
-                }
-            }
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    private void postEphemeralNotif(String pkg, int userId, ApplicationInfo appInfo,
-            NotificationManager noMan, int taskId) {
-        final Bundle extras = new Bundle();
-        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
-                mContext.getString(R.string.instant_apps));
-        mCurrentNotifs.add(new Pair<>(pkg, userId));
-
-        String helpUrl = mContext.getString(R.string.instant_apps_help_url);
-        boolean hasHelpUrl = !helpUrl.isEmpty();
-        String message = mContext.getString(hasHelpUrl
-                ? R.string.instant_apps_message_with_help
-                : R.string.instant_apps_message);
-
-        UserHandle user = UserHandle.of(userId);
-        PendingIntent appInfoAction = PendingIntent.getActivityAsUser(mContext, 0,
-                new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
-                        .setData(Uri.fromParts("package", pkg, null)), 0, null, user);
-        Action action = new Notification.Action.Builder(null, mContext.getString(R.string.app_info),
-                appInfoAction).build();
-        PendingIntent helpCenterIntent = hasHelpUrl
-                ? PendingIntent.getActivityAsUser(mContext, 0,
-                new Intent(Intent.ACTION_VIEW).setData(Uri.parse(
-                        helpUrl)),
-                0, null, user)
-                : null;
-
-        Intent browserIntent = getTaskIntent(taskId, userId);
-        Notification.Builder builder = new Notification.Builder(mContext,
-                NotificationChannels.GENERAL);
-        if (browserIntent != null && browserIntent.isWebIntent()) {
-            // Make sure that this doesn't resolve back to an instant app
-            browserIntent.setComponent(null)
-                    .setPackage(null)
-                    .addFlags(Intent.FLAG_IGNORE_EPHEMERAL)
-                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-            PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext,
-                    0 /* requestCode */, browserIntent, 0 /* flags */, null, user);
-            ComponentName aiaComponent = null;
-            try {
-                aiaComponent = AppGlobals.getPackageManager().getInstantAppInstallerComponent();
-            } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
-            }
-            Intent goToWebIntent = new Intent()
-                    .setComponent(aiaComponent)
-                    .setAction(Intent.ACTION_VIEW)
-                    .addCategory(Intent.CATEGORY_BROWSABLE)
-                    .addCategory("unique:" + System.currentTimeMillis())
-                    .putExtra(Intent.EXTRA_PACKAGE_NAME, appInfo.packageName)
-                    .putExtra(Intent.EXTRA_VERSION_CODE, (int) (appInfo.versionCode & 0x7fffffff))
-                    .putExtra(Intent.EXTRA_LONG_VERSION_CODE, appInfo.versionCode)
-                    .putExtra(Intent.EXTRA_INSTANT_APP_FAILURE, pendingIntent);
-
-            PendingIntent webPendingIntent = PendingIntent.getActivityAsUser(mContext, 0,
-                    goToWebIntent, 0, null, user);
-            Action webAction = new Notification.Action.Builder(null,
-                    mContext.getString(R.string.go_to_web),
-                    webPendingIntent).build();
-            builder.addAction(webAction);
-        }
-
-        noMan.notifyAsUser(pkg, SystemMessage.NOTE_INSTANT_APPS, builder
-                        .addExtras(extras)
-                        .addAction(action)
-                        .setContentIntent(helpCenterIntent)
-                        .setColor(mContext.getColor(R.color.instant_apps_color))
-                        .setContentTitle(mContext.getString(R.string.instant_apps_title,
-                                appInfo.loadLabel(mContext.getPackageManager())))
-                        .setLargeIcon(Icon.createWithResource(pkg, appInfo.icon))
-                        .setSmallIcon(Icon.createWithResource(mContext.getPackageName(),
-                                R.drawable.instant_icon))
-                        .setContentText(message)
-                        .setStyle(new Notification.BigTextStyle().bigText(message))
-                        .setOngoing(true)
-                        .build(),
-                new UserHandle(userId));
-    }
-
-    private Intent getTaskIntent(int taskId, int userId) {
-        try {
-            final List<ActivityManager.RecentTaskInfo> tasks =
-                    ActivityTaskManager.getService().getRecentTasks(
-                            NUM_TASKS_FOR_INSTANT_APP_INFO, 0, userId).getList();
-            for (int i = 0; i < tasks.size(); i++) {
-                if (tasks.get(i).id == taskId) {
-                    return tasks.get(i).baseIntent;
-                }
-            }
-        } catch (RemoteException e) {
-            // Fall through
-        }
-        return null;
-    }
-
-    private boolean hasNotif(ArraySet<Pair<String, Integer>> notifs, String pkg, int userId) {
-        Pair<String, Integer> key = new Pair<>(pkg, userId);
-        if (notifs.remove(key)) {
-            mCurrentNotifs.add(key);
-            return true;
-        }
-        return false;
-    }
-
     private final SynchronousUserSwitchObserver mUserSwitchListener =
             new SynchronousUserSwitchObserver() {
                 @Override
@@ -690,7 +487,6 @@
                     mHandler.post(() -> {
                         updateAlarm();
                         updateManagedProfile();
-                        updateForegroundInstantApps();
                     });
                 }
             };
@@ -723,14 +519,12 @@
             boolean forced) {
         if (mContext.getDisplayId() == displayId) {
             updateManagedProfile();
-            updateForegroundInstantApps();
         }
     }
 
     @Override
     public void onKeyguardShowingChanged() {
         updateManagedProfile();
-        updateForegroundInstantApps();
     }
 
     @Override
@@ -743,11 +537,6 @@
     }
 
     @Override
-    public void preloadRecentApps() {
-        updateForegroundInstantApps();
-    }
-
-    @Override
     public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
         boolean portrait = RotationLockTile.isCurrentOrientationLockPortrait(
                 mRotationLockController, mContext);
@@ -822,14 +611,6 @@
         mIconController.setIconVisibility(mSlotLocation, showLocation);
     }
 
-    private final TaskStackChangeListener mTaskListener = new TaskStackChangeListener() {
-        @Override
-        public void onTaskStackChanged() {
-            // Listen for changes to stacks and then check which instant apps are foreground.
-            updateForegroundInstantApps();
-        }
-    };
-
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {