• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Dependency;
32 import com.android.systemui.broadcast.BroadcastDispatcher;
33 import com.android.systemui.dagger.SysUISingleton;
34 import com.android.systemui.plugins.statusbar.StatusBarStateController;
35 import com.android.systemui.shared.system.ActivityManagerWrapper;
36 import com.android.systemui.shared.system.PackageManagerWrapper;
37 import com.android.systemui.shared.system.TaskStackChangeListener;
38 import com.android.systemui.shared.system.TaskStackChangeListeners;
39 import com.android.systemui.statusbar.StatusBarState;
40 import com.android.systemui.statusbar.phone.StatusBar;
41 
42 import java.util.ArrayList;
43 import java.util.List;
44 import java.util.Optional;
45 
46 import javax.inject.Inject;
47 
48 import dagger.Lazy;
49 
50 /** Class to monitor and report the state of the phone. */
51 @SysUISingleton
52 public final class PhoneStateMonitor {
53 
54     public static final int PHONE_STATE_AOD1 = 1;
55     public static final int PHONE_STATE_AOD2 = 2;
56     public static final int PHONE_STATE_BOUNCER = 3;
57     public static final int PHONE_STATE_UNLOCKED_LOCKSCREEN = 4;
58     public static final int PHONE_STATE_HOME = 5;
59     public static final int PHONE_STATE_OVERVIEW = 6;
60     public static final int PHONE_STATE_ALL_APPS = 7;
61     public static final int PHONE_STATE_APP_DEFAULT = 8;
62     public static final int PHONE_STATE_APP_IMMERSIVE = 9;
63     public static final int PHONE_STATE_APP_FULLSCREEN = 10;
64 
65     private static final String[] DEFAULT_HOME_CHANGE_ACTIONS = new String[] {
66             PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED,
67             Intent.ACTION_PACKAGE_ADDED,
68             Intent.ACTION_PACKAGE_CHANGED,
69             Intent.ACTION_PACKAGE_REMOVED
70     };
71 
72     private final Context mContext;
73     private final Optional<Lazy<StatusBar>> mStatusBarOptionalLazy;
74     private final StatusBarStateController mStatusBarStateController;
75 
76     private boolean mLauncherShowing;
77     @Nullable private ComponentName mDefaultHome;
78 
79     @Inject
PhoneStateMonitor(Context context, BroadcastDispatcher broadcastDispatcher, Optional<Lazy<StatusBar>> statusBarOptionalLazy, BootCompleteCache bootCompleteCache)80     PhoneStateMonitor(Context context, BroadcastDispatcher broadcastDispatcher,
81             Optional<Lazy<StatusBar>> statusBarOptionalLazy, BootCompleteCache bootCompleteCache) {
82         mContext = context;
83         mStatusBarOptionalLazy = statusBarOptionalLazy;
84         mStatusBarStateController = Dependency.get(StatusBarStateController.class);
85 
86         mDefaultHome = getCurrentDefaultHome();
87         bootCompleteCache.addListener(() -> mDefaultHome = getCurrentDefaultHome());
88         IntentFilter intentFilter = new IntentFilter();
89         for (String action : DEFAULT_HOME_CHANGE_ACTIONS) {
90             intentFilter.addAction(action);
91         }
92         broadcastDispatcher.registerReceiver(new BroadcastReceiver() {
93             @Override
94             public void onReceive(Context context, Intent intent) {
95                 mDefaultHome = getCurrentDefaultHome();
96             }
97         }, intentFilter);
98         mLauncherShowing = isLauncherShowing(ActivityManagerWrapper.getInstance().getRunningTask());
99         TaskStackChangeListeners.getInstance().registerTaskStackListener(
100                 new TaskStackChangeListener() {
101                     @Override
102                     public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
103                         mLauncherShowing = isLauncherShowing(taskInfo);
104                     }
105         });
106     }
107 
getPhoneState()108     public int getPhoneState() {
109         int phoneState;
110         if (isShadeFullscreen()) {
111             phoneState = getPhoneLockscreenState();
112         } else if (mLauncherShowing) {
113             phoneState = getPhoneLauncherState();
114         } else {
115             phoneState = PHONE_STATE_APP_IMMERSIVE;
116         }
117         return phoneState;
118     }
119 
120     @Nullable
getCurrentDefaultHome()121     private static ComponentName getCurrentDefaultHome() {
122         List<ResolveInfo> homeActivities = new ArrayList<>();
123         ComponentName defaultHome =
124                 PackageManagerWrapper.getInstance().getHomeActivities(homeActivities);
125         if (defaultHome != null) {
126             return defaultHome;
127         }
128 
129         int topPriority = Integer.MIN_VALUE;
130         ComponentName topComponent = null;
131         for (ResolveInfo resolveInfo : homeActivities) {
132             if (resolveInfo.priority > topPriority) {
133                 topComponent = resolveInfo.activityInfo.getComponentName();
134                 topPriority = resolveInfo.priority;
135             } else if (resolveInfo.priority == topPriority) {
136                 topComponent = null;
137             }
138         }
139         return topComponent;
140     }
141 
getPhoneLockscreenState()142     private int getPhoneLockscreenState() {
143         if (isDozing()) {
144             return PHONE_STATE_AOD1;
145         } else if (isBouncerShowing()) {
146             return PHONE_STATE_BOUNCER;
147         } else if (isKeyguardLocked()) {
148             return PHONE_STATE_AOD2;
149         } else {
150             return PHONE_STATE_UNLOCKED_LOCKSCREEN;
151         }
152     }
153 
getPhoneLauncherState()154     private int getPhoneLauncherState() {
155         if (isLauncherInOverview()) {
156             return PHONE_STATE_OVERVIEW;
157         } else if (isLauncherInAllApps()) {
158             return PHONE_STATE_ALL_APPS;
159         } else {
160             return PHONE_STATE_HOME;
161         }
162     }
163 
isShadeFullscreen()164     private boolean isShadeFullscreen() {
165         int statusBarState = mStatusBarStateController.getState();
166         return statusBarState == StatusBarState.KEYGUARD
167                 || statusBarState == StatusBarState.SHADE_LOCKED;
168     }
169 
isDozing()170     private boolean isDozing() {
171         return mStatusBarStateController.isDozing();
172     }
173 
isLauncherShowing(ActivityManager.RunningTaskInfo runningTaskInfo)174     private boolean isLauncherShowing(ActivityManager.RunningTaskInfo runningTaskInfo) {
175         if (runningTaskInfo == null) {
176             return false;
177         } else {
178             return runningTaskInfo.topActivity.equals(mDefaultHome);
179         }
180     }
181 
isBouncerShowing()182     private boolean isBouncerShowing() {
183         return mStatusBarOptionalLazy.map(
184                 statusBarLazy -> statusBarLazy.get().isBouncerShowing()).orElse(false);
185     }
186 
isKeyguardLocked()187     private boolean isKeyguardLocked() {
188         // TODO: Move binder call off of critical path
189         KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
190         return keyguardManager != null && keyguardManager.isKeyguardLocked();
191     }
192 
isLauncherInOverview()193     private boolean isLauncherInOverview() {
194         // TODO
195         return false;
196     }
197 
isLauncherInAllApps()198     private boolean isLauncherInAllApps() {
199         // TODO
200         return false;
201     }
202 }
203