首先无论是froyo,gingerbrand还是ics,wifi上层有默认设置有三个睡眠策略
以ics为例,在休眠状态下保持WLAN连接
1:始终 --代码中是wow模式睡眠,在待机状态下保持wifi连接
2:仅限充电时--在充电时才始终保持
3:从不 --采用deepsleep模式睡眠,不断电但是断网的模式睡眠,下次唤醒再重新连接。
有些android手机睡眠策略调节无效,就是这部分功能没有实现。没有一下代码,很多手机有这种Bug。
无论是gb还是ics qct上的代码都不能直接与上层联系的,它只选用一个固定模式,要么是deepsleep要么是wow模式。但是在高通qrd代码则实现了关联。
实现方法:通过kobject在sys下创建虚拟文件系统/sys/android_wlan/wlan_power/sleep_policy通过上层设置传如不同值。以下是实现代码。通过store和show来实现上层写入和读出。
很值得学习,故把代码贴出来了。
gb上的store
static ssize_t ar6000_sleep_policy_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t size)
{
if (sysfs_streq(buf, "0")) //判断buf?=0
sleep_policy = EARLY_SLEEP;
else if (sysfs_streq(buf, "1"))要是1则调度deepsleep模式睡眠函数
sleep_policy = DEEP_SLEEP;
else if (sysfs_streq(buf, "2"))要是2则调度wow模式睡眠
sleep_policy = NEVER_SLEEP;
else {
pr_err("%s: invalid value %d\n", __func__, *buf);
}
return 0;
}
ics上的store函数
static ssize_t ath6kl_sleep_policy_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
struct sdio_func *func = dev_to_sdio_func(dev);
struct ath6kl_sdio *ar_sdio = sdio_get_drvdata(func);
unsigned int new_policy;
new_policy = simple_strtoul(buf, NULL, 10); //在buf中读出上层传下的值 0,1deepsleep 2 wow
ath6kl_err("invalid new_policy(%d)\n", (int)new_policy);
switch (new_policy) {
case 0:
case 1:
ar_sdio->ar->suspend_mode = WLAN_POWER_STATE_DEEP_SLEEP;//new_policy 0和1都是deepsleep,通过传入suspend_mode不同的值进入不同的模式
break;
case 2:
ar_sdio->ar->suspend_mode = WLAN_POWER_STATE_WOW; //2是wow模式
break;
default:
ath6kl_err("invalid new_policy(%d)\n", (int)new_policy);
return -EINVAL;
}
return size;
}
suspend_mode:
/* WLAN low power state */
enum {
WLAN_POWER_STATE_ON = 0,
WLAN_POWER_STATE_CUT_PWR = 1,
WLAN_POWER_STATE_DEEP_SLEEP,
WLAN_POWER_STATE_WOW
};
show函数
static ssize_t ath6kl_sleep_policy_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sdio_func *func = dev_to_sdio_func(dev);
struct ath6kl_sdio *ar_sdio = sdio_get_drvdata(func);
return sprintf(buf, "%d\n", ar_sdio->ar->suspend_mode);
}
static DEVICE_ATTR(sleep_policy, S_IRUGO | S_IWUSR | S_IWGRP,
ath6kl_sleep_policy_show, ath6kl_sleep_policy_store);//创建最终的sleep_policy
static struct attribute *ath6kl_sleep_policy_attrs[] = {
&dev_attr_sleep_policy.attr,
NULL
};
static struct attribute_group ath6kl_sleep_policy_attribute = {
.attrs = ath6kl_sleep_policy_attrs,
};
tatic struct kobject *wlan_properties_kobj = NULL;
static int ath6kl_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
int ret;
struct ath6kl_sdio *ar_sdio;
struct ath6kl *ar;
int count;
ath6kl_dbg(ATH6KL_DBG_BOOT,
"sdio new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n",
func->num, func->vendor, func->device,
func->max_blksize, func->cur_blksize);
ar_sdio = kzalloc(sizeof(struct ath6kl_sdio), GFP_KERNEL);//申请结构体内存
if (!ar_sdio)
return -ENOMEM;
ar_sdio->dma_buffer = kzalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL); //申请dma缓冲区
if (!ar_sdio->dma_buffer) {
ret = -ENOMEM;
goto err_hif;
}
//初始化
ar_sdio->func = func;
sdio_set_drvdata(func, ar_sdio);
ar_sdio->id = id;
ar_sdio->is_disabled = true;
spin_lock_init(&ar_sdio->lock);
spin_lock_init(&ar_sdio->scat_lock);
spin_lock_init(&ar_sdio->wr_async_lock);
mutex_init(&ar_sdio->dma_buffer_mutex);
INIT_LIST_HEAD(&ar_sdio->scat_req);
INIT_LIST_HEAD(&ar_sdio->bus_req_freeq);
INIT_LIST_HEAD(&ar_sdio->wr_asyncq);
INIT_WORK(&ar_sdio->wr_async_work, ath6kl_sdio_write_async_work);
init_waitqueue_head(&ar_sdio->irq_wq);
for (count = 0; count < BUS_REQUEST_MAX_NUM; count++)
ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]);
ar = ath6kl_core_alloc(&ar_sdio->func->dev);
if (!ar) {
ath6kl_err("Failed to alloc ath6kl core\n");
ret = -ENOMEM;
goto err_dma;
}
ar_sdio->ar = ar;
ar->hif_type = ATH6KL_HIF_TYPE_SDIO;
ar->hif_priv = ar_sdio;
ar->hif_ops = &ath6kl_sdio_ops;
ar->bmi.max_data_size = 256;
wlan_properties_kobj = kobject_create_and_add( \
"android_wlan", NULL);//创建sys目录下android_wlan
if (wlan_properties_kobj) {
ret = sysfs_create_group(&ar_sdio->func->dev.kobj, \
&ath6kl_sleep_policy_attribute);
if (ret) {
ath6kl_err("Fail to create sysfs android_wlan dir\n");
goto err_create_group;
}
ret = sysfs_create_link(wlan_properties_kobj, \
&ar_sdio->func->dev.kobj, "wlan_power");创建/sys/android_wlan/wlan_power
if (ret) {
ath6kl_err("Fail to create sleep_policy link\n");
goto err_create_link;
}
} else {
ath6kl_err("Fail to create sleep_policy link\n");
ret = -ENOMEM;
goto err_create_properties;
}
ath6kl_sdio_set_mbox_info(ar);
ret = ath6kl_sdio_config(ar);
if (ret) {
ath6kl_err("Failed to config sdio: %d\n", ret);
goto err_sdio_config;
}
ret = ath6kl_core_init(ar);
if (ret) {
ath6kl_err("Failed to init ath6kl core\n");
goto err_sdio_config;
}
return ret;
err_sdio_config:
sysfs_remove_link(wlan_properties_kobj, "sleep_policy");
err_create_link:
sysfs_remove_group(&ar_sdio->func->dev.kobj,
&ath6kl_sleep_policy_attribute);
err_create_group:
kobject_put(wlan_properties_kobj);
err_create_properties:
ath6kl_core_free(ar_sdio->ar);
err_dma:
kfree(ar_sdio->dma_buffer);
err_hif:
kfree(ar_sdio);
return ret;
}
static void ath6kl_sdio_remove(struct sdio_func *func)
{
struct ath6kl_sdio *ar_sdio;
ath6kl_dbg(ATH6KL_DBG_BOOT,
"sdio removed func %d vendor 0x%x device 0x%x\n",
func->num, func->vendor, func->device);
ar_sdio = sdio_get_drvdata(func);
sysfs_remove_link(wlan_properties_kobj, "sleep_policy");
sysfs_remove_group(&ar_sdio->func->dev.kobj,
&ath6kl_sleep_policy_attribute);
kobject_put(wlan_properties_kobj);
ath6kl_stop_txrx(ar_sdio->ar);
cancel_work_sync(&ar_sdio->wr_async_work);
ath6kl_core_cleanup(ar_sdio->ar);
kfree(ar_sdio->dma_buffer);
kfree(ar_sdio);
}
上层代码位置wifi sleep_policy 代码位置 wifiservice.java advancedwifisetting.java
gb实现传递的代码 wifiservice.java
/**
* 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, int)
*/
private void writeSleepOptions(int policy) {
try {
FileOutputStream os = new FileOutputStream(
"/sys/android_wlan/sleep_policy", true);
if(policy == 2)
os.write(new byte[] { (byte)'2' });
else if(policy == 1)
os.write(new byte[] { (byte)'1' });
else
os.write(new byte[] { (byte)'0' });
os.close();
} catch (Exception e) {
Slog.w(TAG, "Failed setting sleep policy");
}
}
private boolean shouldWifiStayAwake(int stayAwakeConditions, int
pluggedType) {
int wifiSleepPolicy =
Settings.System.getInt(mContext.getContentResolver(),
Settings.System.WIFI_SLEEP_POLICY,
Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
if (wifiSleepPolicy ==
Settings.System.WIFI_SLEEP_POLICY_NEVER) {
// Never sleep
writeSleepOptions(2);
return true;
} else if ((wifiSleepPolicy ==
Settings.System.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED) &&
(pluggedType != 0)) {
// Never sleep while plugged, and we're plugged
writeSleepOptions(1);
return true;
} else {
// Default
writeSleepOptions(0);
return shouldDeviceStayAwake(stayAwakeConditions,
pluggedType);
}
}
gb sleep_policy高级设置默认属性 代码位置advancedwifisetting.java
private void initSleepPolicyPreference() {
ListPreference pref = (ListPreference) findPreference(KEY_SLEEP_POLICY);
pref.setOnPreferenceChangeListener(this);
int value = Settings.System.getInt(getContentResolver(),
Settings.System.WIFI_SLEEP_POLICY,Settings. System.WIFI_SLEEP_POLICY_NEVER);
pref.setValue(String.valueOf(value));
}
好了,知道了睡眠策略,就可以更改默认的睡眠策略了,本人最喜欢默认为WOW。
thanks.