1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.assist; 18 19 import android.app.ActivityManager; 20 import android.app.KeyguardManager; 21 import android.content.BroadcastReceiver; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.content.pm.ResolveInfo; 27 28 import androidx.annotation.Nullable; 29 30 import com.android.systemui.BootCompleteCache; 31 import com.android.systemui.broadcast.BroadcastDispatcher; 32 import com.android.systemui.dagger.SysUISingleton; 33 import com.android.systemui.plugins.statusbar.StatusBarStateController; 34 import com.android.systemui.shared.system.ActivityManagerWrapper; 35 import com.android.systemui.shared.system.PackageManagerWrapper; 36 import com.android.systemui.shared.system.TaskStackChangeListener; 37 import com.android.systemui.shared.system.TaskStackChangeListeners; 38 import com.android.systemui.statusbar.StatusBarState; 39 import com.android.systemui.statusbar.phone.CentralSurfaces; 40 41 import dagger.Lazy; 42 43 import java.util.ArrayList; 44 import java.util.List; 45 import java.util.Optional; 46 47 import javax.inject.Inject; 48 49 /** Class to monitor and report the state of the phone. */ 50 @SysUISingleton 51 public final class PhoneStateMonitor { 52 53 public static final int PHONE_STATE_AOD1 = 1; 54 public static final int PHONE_STATE_AOD2 = 2; 55 public static final int PHONE_STATE_BOUNCER = 3; 56 public static final int PHONE_STATE_UNLOCKED_LOCKSCREEN = 4; 57 public static final int PHONE_STATE_HOME = 5; 58 public static final int PHONE_STATE_OVERVIEW = 6; 59 public static final int PHONE_STATE_ALL_APPS = 7; 60 public static final int PHONE_STATE_APP_DEFAULT = 8; 61 public static final int PHONE_STATE_APP_IMMERSIVE = 9; 62 public static final int PHONE_STATE_APP_FULLSCREEN = 10; 63 64 private static final String[] DEFAULT_HOME_CHANGE_ACTIONS = new String[] { 65 PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED, 66 Intent.ACTION_PACKAGE_ADDED, 67 Intent.ACTION_PACKAGE_CHANGED, 68 Intent.ACTION_PACKAGE_REMOVED 69 }; 70 71 private final Context mContext; 72 private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy; 73 private final StatusBarStateController mStatusBarStateController; 74 75 private boolean mLauncherShowing; 76 @Nullable private ComponentName mDefaultHome; 77 78 @Inject PhoneStateMonitor(Context context, BroadcastDispatcher broadcastDispatcher, Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy, BootCompleteCache bootCompleteCache, StatusBarStateController statusBarStateController)79 PhoneStateMonitor(Context context, BroadcastDispatcher broadcastDispatcher, 80 Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy, 81 BootCompleteCache bootCompleteCache, 82 StatusBarStateController statusBarStateController) { 83 mContext = context; 84 mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy; 85 mStatusBarStateController = statusBarStateController; 86 87 mDefaultHome = getCurrentDefaultHome(); 88 bootCompleteCache.addListener(() -> mDefaultHome = getCurrentDefaultHome()); 89 IntentFilter intentFilter = new IntentFilter(); 90 for (String action : DEFAULT_HOME_CHANGE_ACTIONS) { 91 intentFilter.addAction(action); 92 } 93 broadcastDispatcher.registerReceiver(new BroadcastReceiver() { 94 @Override 95 public void onReceive(Context context, Intent intent) { 96 mDefaultHome = getCurrentDefaultHome(); 97 } 98 }, intentFilter); 99 mLauncherShowing = isLauncherShowing(ActivityManagerWrapper.getInstance().getRunningTask()); 100 TaskStackChangeListeners.getInstance().registerTaskStackListener( 101 new TaskStackChangeListener() { 102 @Override 103 public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) { 104 mLauncherShowing = isLauncherShowing(taskInfo); 105 } 106 }); 107 } 108 getPhoneState()109 public int getPhoneState() { 110 int phoneState; 111 if (isShadeFullscreen()) { 112 phoneState = getPhoneLockscreenState(); 113 } else if (mLauncherShowing) { 114 phoneState = getPhoneLauncherState(); 115 } else { 116 phoneState = PHONE_STATE_APP_IMMERSIVE; 117 } 118 return phoneState; 119 } 120 121 @Nullable getCurrentDefaultHome()122 private static ComponentName getCurrentDefaultHome() { 123 List<ResolveInfo> homeActivities = new ArrayList<>(); 124 ComponentName defaultHome = 125 PackageManagerWrapper.getInstance().getHomeActivities(homeActivities); 126 if (defaultHome != null) { 127 return defaultHome; 128 } 129 130 int topPriority = Integer.MIN_VALUE; 131 ComponentName topComponent = null; 132 for (ResolveInfo resolveInfo : homeActivities) { 133 if (resolveInfo.priority > topPriority) { 134 topComponent = resolveInfo.activityInfo.getComponentName(); 135 topPriority = resolveInfo.priority; 136 } else if (resolveInfo.priority == topPriority) { 137 topComponent = null; 138 } 139 } 140 return topComponent; 141 } 142 getPhoneLockscreenState()143 private int getPhoneLockscreenState() { 144 if (isDozing()) { 145 return PHONE_STATE_AOD1; 146 } else if (isBouncerShowing()) { 147 return PHONE_STATE_BOUNCER; 148 } else if (isKeyguardLocked()) { 149 return PHONE_STATE_AOD2; 150 } else { 151 return PHONE_STATE_UNLOCKED_LOCKSCREEN; 152 } 153 } 154 getPhoneLauncherState()155 private int getPhoneLauncherState() { 156 if (isLauncherInOverview()) { 157 return PHONE_STATE_OVERVIEW; 158 } else if (isLauncherInAllApps()) { 159 return PHONE_STATE_ALL_APPS; 160 } else { 161 return PHONE_STATE_HOME; 162 } 163 } 164 isShadeFullscreen()165 private boolean isShadeFullscreen() { 166 int statusBarState = mStatusBarStateController.getState(); 167 return statusBarState == StatusBarState.KEYGUARD 168 || statusBarState == StatusBarState.SHADE_LOCKED; 169 } 170 isDozing()171 private boolean isDozing() { 172 return mStatusBarStateController.isDozing(); 173 } 174 isLauncherShowing(@ullable ActivityManager.RunningTaskInfo runningTaskInfo)175 private boolean isLauncherShowing(@Nullable ActivityManager.RunningTaskInfo runningTaskInfo) { 176 if (runningTaskInfo == null || runningTaskInfo.topActivity == null) { 177 return false; 178 } else { 179 return runningTaskInfo.topActivity.equals(mDefaultHome); 180 } 181 } 182 isBouncerShowing()183 private boolean isBouncerShowing() { 184 return mCentralSurfacesOptionalLazy.get() 185 .map(CentralSurfaces::isBouncerShowing).orElse(false); 186 } 187 isKeyguardLocked()188 private boolean isKeyguardLocked() { 189 // TODO: Move binder call off of critical path 190 KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class); 191 return keyguardManager != null && keyguardManager.isKeyguardLocked(); 192 } 193 isLauncherInOverview()194 private boolean isLauncherInOverview() { 195 // TODO 196 return false; 197 } 198 isLauncherInAllApps()199 private boolean isLauncherInAllApps() { 200 // TODO 201 return false; 202 } 203 } 204