From dc664edb2f1df58333f6c05c65b0d566f86d58ca Mon Sep 17 00:00:00 2001 From: Mehdi Alizadeh Date: Wed, 29 May 2019 10:40:28 -0700 Subject: [PATCH] Show notifications when default launcher changes Shows a notification when we have to switch away from Gesture Nav because the new launcher doesn't support it. Also shows another notification when previously we had to switch away from Gesture Nav, but now the new launcher supports it. Bug: 129532605 Test: Manual test Change-Id: Ie954dd5dea1b45795f5c0e22ab7cc1cffde4aabe --- .../phone/NavigationModeController.java | 128 ++++++++++++++---- 1 file changed, 104 insertions(+), 24 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java index 7cd8f7b6687fc..77eb469c4b29e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java @@ -24,6 +24,9 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVE import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -38,13 +41,16 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Secure; +import android.text.TextUtils; import android.util.Log; import android.util.SparseBooleanArray; import com.android.systemui.Dumpable; +import com.android.systemui.R; import com.android.systemui.UiOffloadThread; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.util.NotificationChannels; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -63,6 +69,9 @@ public class NavigationModeController implements Dumpable { private static final String TAG = NavigationModeController.class.getSimpleName(); private static final boolean DEBUG = false; + static final String SHARED_PREFERENCES_NAME = "navigation_mode_controller_preferences"; + static final String PREFS_SWITCHED_FROM_GESTURE_NAV_KEY = "switched_from_gesture_nav"; + public interface ModeChangedListener { void onNavigationModeChanged(int mode); } @@ -78,6 +87,8 @@ public class NavigationModeController implements Dumpable { private int mMode = NAV_BAR_MODE_3BUTTON; private ArrayList mListeners = new ArrayList<>(); + private String mLastDefaultLauncher; + private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -92,7 +103,13 @@ public class NavigationModeController implements Dumpable { if (DEBUG) { Log.d(TAG, "ACTION_PREFERRED_ACTIVITY_CHANGED"); } - switchFromGestureNavModeIfNotSupportedByDefaultLauncher(); + final String launcher = getDefaultLauncherPackageName(mCurrentUserContext); + // Check if it is a default launcher change + if (!TextUtils.equals(mLastDefaultLauncher, launcher)) { + switchFromGestureNavModeIfNotSupportedByDefaultLauncher(); + showNotificationIfDefaultLauncherSupportsGestureNav(); + mLastDefaultLauncher = launcher; + } break; } } @@ -157,6 +174,8 @@ public class NavigationModeController implements Dumpable { IntentFilter preferredActivityFilter = new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED); mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, preferredActivityFilter, null, null); + // We are only interested in launcher changes, so keeping track of the current default. + mLastDefaultLauncher = getDefaultLauncherPackageName(mContext); updateCurrentInteractionMode(false /* notify */); switchFromGestureNavModeIfNotSupportedByDefaultLauncher(); @@ -287,6 +306,84 @@ public class NavigationModeController implements Dumpable { }); } + private void switchFromGestureNavModeIfNotSupportedByDefaultLauncher() { + if (getCurrentInteractionMode(mCurrentUserContext) != NAV_BAR_MODE_GESTURAL) { + return; + } + final Boolean supported = isGestureNavSupportedByDefaultLauncher(mCurrentUserContext); + if (supported == null || supported) { + return; + } + + setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT); + showNotification(mCurrentUserContext, R.string.notification_content_system_nav_changed); + mCurrentUserContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) + .edit().putBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, true).apply(); + } + + private void showNotificationIfDefaultLauncherSupportsGestureNav() { + boolean previouslySwitchedFromGestureNav = mCurrentUserContext + .getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) + .getBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, false); + if (!previouslySwitchedFromGestureNav) { + return; + } + if (getCurrentInteractionMode(mCurrentUserContext) == NAV_BAR_MODE_GESTURAL) { + return; + } + final Boolean supported = isGestureNavSupportedByDefaultLauncher(mCurrentUserContext); + if (supported == null || !supported) { + return; + } + + showNotification(mCurrentUserContext, R.string.notification_content_gesture_nav_available); + mCurrentUserContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) + .edit().putBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, false).apply(); + } + + /** + * Returns null if there is no default launcher set for the current user. Returns true if the + * current default launcher supports Gesture Navigation. Returns false otherwise. + */ + private Boolean isGestureNavSupportedByDefaultLauncher(Context context) { + final String defaultLauncherPackageName = getDefaultLauncherPackageName(context); + if (DEBUG) { + Log.d(TAG, "isGestureNavSupportedByDefaultLauncher:" + + " defaultLauncher=" + defaultLauncherPackageName + + " contextUser=" + context.getUserId()); + } + if (defaultLauncherPackageName == null) { + return null; + } + ComponentName recentsComponentName = ComponentName.unflattenFromString( + context.getString(com.android.internal.R.string.config_recentsComponentName)); + return recentsComponentName.getPackageName().equals(defaultLauncherPackageName); + } + + private String getDefaultLauncherPackageName(Context context) { + final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>()); + if (cn == null) { + return null; + } + return cn.getPackageName(); + } + + private void showNotification(Context context, int resId) { + final CharSequence message = context.getResources().getString(resId); + if (DEBUG) { + Log.d(TAG, "showNotification: message=" + message); + } + + final Notification.Builder builder = + new Notification.Builder(mContext, NotificationChannels.ALERTS) + .setContentText(message) + .setStyle(new Notification.BigTextStyle()) + .setSmallIcon(R.drawable.ic_info) + .setAutoCancel(true) + .setContentIntent(PendingIntent.getActivity(context, 0, new Intent(), 0)); + context.getSystemService(NotificationManager.class).notify(TAG, 0, builder.build()); + } + @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("NavigationModeController:"); @@ -299,6 +396,12 @@ public class NavigationModeController implements Dumpable { } pw.println(" defaultOverlays=" + defaultOverlays); dumpAssetPaths(mCurrentUserContext); + + pw.println(" defaultLauncher=" + mLastDefaultLauncher); + boolean previouslySwitchedFromGestureNav = mCurrentUserContext + .getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) + .getBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, false); + pw.println(" previouslySwitchedFromGestureNav=" + previouslySwitchedFromGestureNav); } private void dumpAssetPaths(Context context) { @@ -308,27 +411,4 @@ public class NavigationModeController implements Dumpable { Log.d(TAG, " " + a.getAssetPath()); } } - - private void switchFromGestureNavModeIfNotSupportedByDefaultLauncher() { - if (getCurrentInteractionMode(mCurrentUserContext) == NAV_BAR_MODE_GESTURAL - && !isGestureNavSupportedByDefaultLauncher(mCurrentUserContext)) { - setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT); - } - } - - private boolean isGestureNavSupportedByDefaultLauncher(Context context) { - final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>()); - if (cn == null) { - // There is no default home app set for the current user, don't make any changes yet. - return true; - } - if (DEBUG) { - Log.d(TAG, "isGestureNavSupportedByDefaultLauncher: launcher=" + cn.getPackageName() - + " contextUser=" + context.getUserId()); - } - - ComponentName recentsComponentName = ComponentName.unflattenFromString(context.getString( - com.android.internal.R.string.config_recentsComponentName)); - return recentsComponentName.getPackageName().equals(cn.getPackageName()); - } }