安卓8.0 WIFI休眠策略分析

本文深入分析了安卓8.0系统的WiFi休眠策略,包括不同休眠模式,如默认、插电时不休眠和从不休眠。通过`Settings.java`和`WifiController.java`中的代码展示了如何根据充电状态决定是否让WiFi保持清醒。同时,当设备熄屏且满足特定条件时,会设置一个15分钟的定时器。在充电状态改变时,会调整WiFi的休眠策略。此外,`WifiStateMachine.java`中的`WakeLock`用于保持WiFi连接,并与电池统计相关联,确保准确记录电源使用情况。
http://androidxref.com/8.0.0_r4
============================================================
/frameworks/base/core/java/android/provider/Settings.java

public static final String WIFI_SLEEP_POLICY = "wifi_sleep_policy";

public static final int WIFI_SLEEP_POLICY_DEFAULT = 0;
public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1;
public static final int WIFI_SLEEP_POLICY_NEVER = 2;

============================================================
/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java

private int mSleepPolicy; // 当前休眠策略
private int mPluggedType; // 当前充电状态  可选值如下
{
private static final int BATTERY_PLUGGED_NONE = 0;  // 手机没有充电
private static final int BATTERY_PLUGGED_AC = 1; // 注册充电
private static final int BATTERY_PLUGGED_USB = 2; // 连接电脑USB充电
private static final int BATTERY_PLUGGED_WIRELESS= 4;  // 无线充电
public static final int BATTERY_PLUGGED_ANY = 7;
}


    /**
     * Determines whether the Wi-Fi chipset should stay awake or be put to
     * sleep. Looks at the setting for the sleep policy and the current
     * conditions.  
     *
     * @see #shouldDeviceStayAwake(int)
     */
    private boolean shouldWifiStayAwake(int pluggedType) { //依据参数pluggedType和mSleepPolicy值 确定是否休眠
        if (mSleepPolicy == Settings.Global.WIFI_SLEEP_POLICY_NEVER) {
            // Never sleep
            return true;
        } else if ((mSleepPolicy == Settings.Global.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED) && (pluggedType != 0)) {
            // Never sleep while plugged, and we're plugged
            return true;
        } else {
            // Default
            return shouldDeviceStayAwake(pluggedType);
       }
  }
			
    /**
     * Observes changes to wifi sleep policy
     */
    private void registerForWifiSleepPolicyChange(Handler handler) {
        ContentObserver contentObserver = new ContentObserver(handler) {
            @Override
            public void onChange(boolean selfChange) {
                readWifiSleepPolicy();
            }
        };
        mFacade.registerContentObserver(mContext,Settings.Global.getUriFor(Settings.Global.WIFI_SLEEP_POLICY), false,
                contentObserver);
    }
	
    private void readWifiSleepPolicy() {
        mSleepPolicy = mFacade.getIntegerSetting(mContext,
                Settings.Global.WIFI_SLEEP_POLICY,
                Settings.Global.WIFI_SLEEP_POLICY_NEVER);
    }
	
	
	
	
 class DefaultState extends State {
        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case CMD_SCREEN_OFF:  // 灭屏情况下
                    mScreenOff = true;

                    if (!shouldWifiStayAwake(mPluggedType)) {
//private static final long DEFAULT_IDLE_MS = 15 * 60 * 1000  // 15分钟
//   private static final String ACTION_DEVICE_IDLE ="com.android.server.WifiManager.action.DEVICE_IDLE";
//public static final String WIFI_IDLE_MS = "wifi_idle_ms";
// mIdleMillis = mFacade.getLongSetting(mContext,Settings.Global.WIFI_IDLE_MS, DEFAULT_IDLE_MS); 
// Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);  private static final int IDLE_REQUEST = 0;
// private PendingIntentmIdleIntent = mFacade.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);
// 【如果不保持连接,那么设置mIdleMillis 15分钟之后发送 ACTION_DEVICE_IDLE的广播】
                        if (mNetworkInfo.getDetailedState() ==NetworkInfo.DetailedState.CONNECTED) {
                            if (DBG) Slog.d(TAG, "set idle timer: " + mIdleMillis + " ms");
                            mAlarmManager.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis() + mIdleMillis, mIdleIntent);
                        } else {
						//需要使机器不保持连接 当前连接状态不为连接那么就 直接使发送CMD_DEVICE_IDLE消息
                            sendMessage(CMD_DEVICE_IDLE);
                        }
                    }
                    break;

                case CMD_BATTERY_CHANGED:
                    int pluggedType = msg.arg1;
                    // 如果当前灭屏  
                    if (mScreenOff && shouldWifiStayAwake(mPluggedType)【CMD_BATTERY_CHANGED消息前记录的PluggedType】 
					&&!shouldWifiStayAwake(pluggedType) 【CMD_BATTERY_CHANGED携带的PluggedType】 ) {
					 // 以上条件满足 那么就发送 mIdleIntent 广播
                        long triggerTime = System.currentTimeMillis() + mIdleMillis;
                        if (DBG) Slog.d(TAG, "set idle timer for " + mIdleMillis + "ms");
                        mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
                    }

                    mPluggedType = pluggedType;
                    break;
					
					
					case CMD_DEVICE_IDLE:
                    mDeviceIdle = true;
       
### 配置 WiFi P2P 连接的 Android 开发设置 在 Android 平台上,配置和开发 WiFi P2P 连接涉及多个关键步骤,包括初始化、发现设备、建立连接和数据传输。以下是对这些步骤的详细说明。 #### 1. 初始设置 在开发 WiFi P2P 应用之前,需要确保应用具备必要的权限,并初始化 WiFi P2P 管理器。以下是相关代码: ```java import android.content.Context; import android.net.wifi.p2p.WifiP2pManager; import android.net.wifi.p2p.WifiP2pManager.Channel; public class WiFiP2PSetup { private WifiP2pManager wifiP2pManager; private Channel wifiP2pChannel; public void initializeWiFiP2P(Context context) { wifiP2pManager = (WifiP2pManager) context.getSystemService(Context.WIFI_P2P_SERVICE); wifiP2pChannel = wifiP2pManager.initialize(context, context.getMainLooper(), null); } } ``` 此外,需要在 `AndroidManifest.xml` 文件中添加以下权限: ```xml <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> ``` #### 2. 发现对等设备 通过 `WifiP2pManager` 的 `discoverPeers` 方法,可以启动对等设备的发现过程。发现到的设备会通过广播通知应用。 ```java public void discoverPeers() { wifiP2pManager.discoverPeers(wifiP2pChannel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { // 发现设备成功 } @Override public void onFailure(int reason) { // 发现设备失败 } }); } ``` #### 3. 连接到对等设备 当发现设备后,可以通过 `connect` 方法与目标设备建立连接。以下是连接设备的代码示例: ```java public void connectToDevice(WifiP2pDevice device) { WifiP2pConfig config = new WifiP2pConfig(); config.deviceAddress = device.deviceAddress; wifiP2pManager.connect(wifiP2pChannel, config, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { // 连接成功 } @Override public void onFailure(int reason) { // 连接失败 } }); } ``` #### 4. 获取对端设备的 IP 地址 一旦连接成功,可以通过 `WIFI_P2P_CONNECTION_CHANGED_ACTION` 广播获取对端设备的 IP 地址。以下是相关代码: ```java if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO); WifiP2pInfo p2pInfo = (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO); if (networkInfo.isConnected()) { String groupOwnerAddress = p2pInfo.groupOwnerAddress.getHostAddress(); // 使用 groupOwnerAddress 与对端设备通信 } } ``` #### 5. 数据传输 建立连接后,可以通过 `Socket` 或其他网络通信方式实现数据传输。以下是通过 `Socket` 发送数据的示例代码: ```java public void sendData(String ipAddress, int port, String data) { new Thread(() -> { try { Socket socket = new Socket(ipAddress, port); OutputStream outputStream = socket.getOutputStream(); outputStream.write(data.getBytes()); outputStream.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); } ``` #### 6. 休眠时保持 WiFi 连接 为了确保设备在休眠时不关闭 WiFi 连接,可以修改系统设置: ```java import android.content.Context; import android.provider.Settings; public class WifiSettingsUtils { public static void setWifiStayAwake(Context context) { try { Settings.Global.putInt(context.getContentResolver(), Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_NEVER); } catch (Exception e) { e.printStackTrace(); } } } ``` #### 7. 注意事项 - **动态权限请求**:从 Android 6.0 开始,需要动态请求 `ACCESS_FINE_LOCATION` 权限。 - **电池优化**:某些设备可能会因电池优化策略而断开 WiFi 连接,可以在设备设置中禁用特定应用的电池优化。 - **后台运行限制**:从 Android 8.0 开始,后台运行的网络访问可能受到限制,可以使用前台服务确保应用不受限制。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值