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) {