From a2c88760a7048d89f07e602dfbb5e15011d72cc5 Mon Sep 17 00:00:00 2001 From: Govinda Wasserman Date: Wed, 8 May 2019 08:02:47 -0400 Subject: [PATCH] Adds a PhoneStateMonitor to the AssistManager This allows the AssistManager to determine the state of the phone when the Assistant is invoked. This will be used for logging and allowing the Assistant to alter its behavior based on the invokation state. Note that SysUI is currently unable to differentiate between Launcher states, so all Launcher states will be reported as PHONE_STATE_HOME. Test: Tested locally BUG:128982146 Change-Id: Iee40e42830f5a07845240c98bec5b87bd7c08eb7 --- .../systemui/assist/AssistManager.java | 4 + .../systemui/assist/PhoneStateMonitor.java | 170 ++++++++++++++++++ .../systemui/statusbar/phone/StatusBar.java | 14 ++ 3 files changed, 188 insertions(+) create mode 100644 packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index 68cf15d262de7..c2a4279cffa4a 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -59,6 +59,7 @@ public class AssistManager implements ConfigurationChangedReceiver { private static final String ASSIST_ICON_METADATA_NAME = "com.android.systemui.action_assist_icon"; private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms"; + private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state"; public static final String INVOCATION_TYPE_KEY = "invocation_type"; public static final int INVOCATION_TYPE_GESTURE = 1; @@ -74,6 +75,7 @@ public class AssistManager implements ConfigurationChangedReceiver { private final WindowManager mWindowManager; private final AssistDisclosure mAssistDisclosure; private final InterestingConfigChanges mInterestingConfigChanges; + private final PhoneStateMonitor mPhoneStateMonitor; private AssistOrbContainer mView; private final DeviceProvisionedController mDeviceProvisionedController; @@ -108,6 +110,7 @@ public class AssistManager implements ConfigurationChangedReceiver { mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); mAssistUtils = new AssistUtils(context); mAssistDisclosure = new AssistDisclosure(context, new Handler()); + mPhoneStateMonitor = new PhoneStateMonitor(context); registerVoiceInteractionSessionListener(); mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION @@ -187,6 +190,7 @@ public class AssistManager implements ConfigurationChangedReceiver { if (args == null) { args = new Bundle(); } + args.putInt(INVOCATION_PHONE_STATE_KEY, mPhoneStateMonitor.getPhoneState()); args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.uptimeMillis()); // Logs assistant start with invocation type. MetricsLogger.action( diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java new file mode 100644 index 0000000000000..8c070835f69ed --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2010 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.assist; + +import static com.android.systemui.shared.system.PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED; + +import android.app.ActivityManager; +import android.app.KeyguardManager; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +import androidx.annotation.Nullable; + +import com.android.systemui.Dependency; +import com.android.systemui.SysUiServiceProvider; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.PackageManagerWrapper; +import com.android.systemui.shared.system.TaskStackChangeListener; +import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.phone.StatusBar; + +import java.util.ArrayList; + +/** Class to monitor and report the state of the phone. */ +final class PhoneStateMonitor { + + private static final int PHONE_STATE_AOD1 = 1; + private static final int PHONE_STATE_AOD2 = 2; + private static final int PHONE_STATE_BOUNCER = 3; + private static final int PHONE_STATE_UNLOCKED_LOCKSCREEN = 4; + private static final int PHONE_STATE_HOME = 5; + private static final int PHONE_STATE_OVERVIEW = 6; + private static final int PHONE_STATE_ALL_APPS = 7; + private static final int PHONE_STATE_APP_DEFAULT = 8; + private static final int PHONE_STATE_APP_IMMERSIVE = 9; + private static final int PHONE_STATE_APP_FULLSCREEN = 10; + + private final Context mContext; + private final StatusBarStateController mStatusBarStateController; + + private boolean mLauncherShowing; + @Nullable private ComponentName mDefaultHome; + + PhoneStateMonitor(Context context) { + mContext = context; + mStatusBarStateController = Dependency.get(StatusBarStateController.class); + + ActivityManagerWrapper activityManagerWrapper = ActivityManagerWrapper.getInstance(); + mDefaultHome = PackageManagerWrapper.getInstance().getHomeActivities(new ArrayList<>()); + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + mDefaultHome = + PackageManagerWrapper.getInstance().getHomeActivities(new ArrayList<>()); + } + }, new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED)); + mLauncherShowing = isLauncherShowing(activityManagerWrapper.getRunningTask()); + activityManagerWrapper.registerTaskStackListener(new TaskStackChangeListener() { + @Override + public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) { + mLauncherShowing = isLauncherShowing(taskInfo); + } + }); + } + + int getPhoneState() { + int phoneState; + if (isShadeFullscreen()) { + phoneState = getPhoneLockscreenState(); + } else if (mLauncherShowing) { + phoneState = getPhoneLauncherState(); + } else { + phoneState = getPhoneAppState(); + } + return phoneState; + } + + private int getPhoneLockscreenState() { + if (isDozing()) { + return PHONE_STATE_AOD1; + } else if (isBouncerShowing()) { + return PHONE_STATE_BOUNCER; + } else if (isKeyguardLocked()) { + return PHONE_STATE_AOD2; + } else { + return PHONE_STATE_UNLOCKED_LOCKSCREEN; + } + } + + private int getPhoneLauncherState() { + if (isLauncherInOverview()) { + return PHONE_STATE_OVERVIEW; + } else if (isLauncherInAllApps()) { + return PHONE_STATE_ALL_APPS; + } else { + return PHONE_STATE_HOME; + } + } + + private int getPhoneAppState() { + if (isAppImmersive()) { + return PHONE_STATE_APP_IMMERSIVE; + } else if (isAppFullscreen()) { + return PHONE_STATE_APP_FULLSCREEN; + } else { + return PHONE_STATE_APP_DEFAULT; + } + } + + private boolean isShadeFullscreen() { + int statusBarState = mStatusBarStateController.getState(); + return statusBarState == StatusBarState.KEYGUARD + || statusBarState == StatusBarState.SHADE_LOCKED; + } + + private boolean isDozing() { + return mStatusBarStateController.isDozing(); + } + + private boolean isLauncherShowing(ActivityManager.RunningTaskInfo runningTaskInfo) { + return runningTaskInfo.topActivity.equals(mDefaultHome); + } + + private boolean isAppImmersive() { + return SysUiServiceProvider.getComponent(mContext, StatusBar.class).inImmersiveMode(); + } + + private boolean isAppFullscreen() { + return SysUiServiceProvider.getComponent(mContext, StatusBar.class).inFullscreenMode(); + } + + private boolean isBouncerShowing() { + StatusBar statusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class); + return statusBar != null && statusBar.isBouncerShowing(); + } + + private boolean isKeyguardLocked() { + // TODO: Move binder call off of critical path + KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class); + return keyguardManager != null && keyguardManager.isKeyguardLocked(); + } + + private boolean isLauncherInOverview() { + // TODO + return false; + } + + private boolean isLauncherInAllApps() { + // TODO + return false; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 17f0d5a790347..a2ea2c062a3fa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -2241,6 +2241,20 @@ public class StatusBar extends SystemUI implements DemoMode, } } + /** Returns whether the top activity is in fullscreen mode. */ + public boolean inFullscreenMode() { + return 0 + != (mSystemUiVisibility + & (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)); + } + + /** Returns whether the top activity is in immersive mode. */ + public boolean inImmersiveMode() { + return 0 + != (mSystemUiVisibility + & (View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)); + } + private boolean areLightsOn() { return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE); }