• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.server.wifi;
18 
19 import android.annotation.SuppressLint;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.net.wifi.util.Environment;
25 import android.os.Handler;
26 import android.os.PowerManager;
27 import android.security.Flags;
28 import android.security.advancedprotection.AdvancedProtectionManager;
29 import android.text.TextUtils;
30 import android.util.ArraySet;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 import com.android.modules.utils.HandlerExecutor;
34 import com.android.wifi.flags.FeatureFlags;
35 
36 import java.util.Set;
37 
38 /** A centralized manager to handle all the device state changes */
39 public class WifiDeviceStateChangeManager {
40     private final Handler mHandler;
41     private final Context mContext;
42 
43     private final PowerManager mPowerManager;
44     private final WifiInjector mWifiInjector;
45     private AdvancedProtectionManager mAdvancedProtectionManager;
46     private FeatureFlags mFeatureFlags;
47 
48     private final Set<StateChangeCallback> mChangeCallbackList = new ArraySet<>();
49     private boolean mIsWifiServiceStarted = false;
50 
51     /**
52      * Callback to receive the device state change event. Caller should implement the method to
53      * listen to the interested event
54      */
55     public interface StateChangeCallback {
56         /**
57          * Called when the screen state changes
58          *
59          * @param screenOn true for ON, false otherwise
60          */
onScreenStateChanged(boolean screenOn)61         default void onScreenStateChanged(boolean screenOn) {}
62 
63         /**
64          * Called when the Advanced protection mode state changes
65          *
66          * @param apmOn true for ON, false otherwise
67          */
onAdvancedProtectionModeStateChanged(boolean apmOn)68         default void onAdvancedProtectionModeStateChanged(boolean apmOn) {}
69     }
70 
71     /** Create the instance of WifiDeviceStateChangeManager. */
WifiDeviceStateChangeManager(Context context, Handler handler, WifiInjector wifiInjector)72     public WifiDeviceStateChangeManager(Context context, Handler handler,
73             WifiInjector wifiInjector) {
74         mHandler = handler;
75         mContext = context;
76         mWifiInjector = wifiInjector;
77         mPowerManager = mContext.getSystemService(PowerManager.class);
78     }
79 
80     /** Handle the boot completed event. Start to register the receiver and callback. */
81     @SuppressLint("NewApi")
handleBootCompleted()82     public void handleBootCompleted() {
83         mFeatureFlags = mWifiInjector.getDeviceConfigFacade().getFeatureFlags();
84         IntentFilter filter = new IntentFilter();
85         filter.addAction(Intent.ACTION_SCREEN_ON);
86         filter.addAction(Intent.ACTION_SCREEN_OFF);
87         mContext.registerReceiver(
88                 new BroadcastReceiver() {
89                     @Override
90                     public void onReceive(Context context, Intent intent) {
91                         String action = intent.getAction();
92                         if (TextUtils.equals(action, Intent.ACTION_SCREEN_ON)
93                                 || TextUtils.equals(action, Intent.ACTION_SCREEN_OFF)) {
94                             mHandler.post(() ->
95                                     handleScreenStateChanged(TextUtils.equals(action,
96                                             Intent.ACTION_SCREEN_ON)));
97                         }
98                     }
99                 },
100                 filter);
101         handleScreenStateChanged(mPowerManager.isInteractive());
102         if (Environment.isSdkAtLeastB() && mFeatureFlags.wepDisabledInApm()
103                 && isAapmApiFlagEnabled()) {
104             mAdvancedProtectionManager =
105                     mContext.getSystemService(AdvancedProtectionManager.class);
106             if (mAdvancedProtectionManager != null) {
107                 mAdvancedProtectionManager.registerAdvancedProtectionCallback(
108                         new HandlerExecutor(mHandler),
109                         state -> {
110                             handleAdvancedProtectionModeStateChanged(state);
111                         });
112                 handleAdvancedProtectionModeStateChanged(
113                         mAdvancedProtectionManager.isAdvancedProtectionEnabled());
114             } else {
115                 handleAdvancedProtectionModeStateChanged(false);
116             }
117         } else {
118             handleAdvancedProtectionModeStateChanged(false);
119         }
120         mIsWifiServiceStarted = true;
121     }
122 
123     @VisibleForTesting
isAapmApiFlagEnabled()124     public boolean isAapmApiFlagEnabled() {
125         return Flags.aapmApi();
126     }
127     /**
128      * Register a state change callback. When the state is changed, caller with receive the callback
129      * event
130      */
131     @SuppressLint("NewApi")
registerStateChangeCallback(StateChangeCallback callback)132     public void registerStateChangeCallback(StateChangeCallback callback) {
133         mChangeCallbackList.add(callback);
134         if (!mIsWifiServiceStarted) return;
135         callback.onScreenStateChanged(mPowerManager.isInteractive());
136         if (Environment.isSdkAtLeastB() && mAdvancedProtectionManager != null) {
137             callback.onAdvancedProtectionModeStateChanged(
138                     mAdvancedProtectionManager.isAdvancedProtectionEnabled());
139         } else {
140             callback.onAdvancedProtectionModeStateChanged(false);
141         }
142     }
143 
144     /**
145      * Unregister a state change callback when caller is not interested the state change anymore.
146      */
unregisterStateChangeCallback(StateChangeCallback callback)147     public void unregisterStateChangeCallback(StateChangeCallback callback) {
148         mChangeCallbackList.remove(callback);
149     }
150 
handleScreenStateChanged(boolean screenOn)151     private void handleScreenStateChanged(boolean screenOn) {
152         for (StateChangeCallback callback : mChangeCallbackList) {
153             callback.onScreenStateChanged(screenOn);
154         }
155     }
156 
handleAdvancedProtectionModeStateChanged(boolean apmOn)157     private void handleAdvancedProtectionModeStateChanged(boolean apmOn) {
158         for (StateChangeCallback callback : mChangeCallbackList) {
159             callback.onAdvancedProtectionModeStateChanged(apmOn);
160         }
161     }
162 }
163