• 1、Android设备屏幕暗下来的时候,并不是立即就进入了休眠模式;当所有唤醒源都处于de-avtive状态后,系统才会进入休眠。 2、Android设备连着adb线到其他设备的情况下,设备是不会进入休眠模式的。 3、有休眠操作...

    http://blog.csdn.net/u013686019/article/details/53645646

    一、休眠概述

    休眠,简而言之就是设备在不需要工作的时候把一些部件、外设关掉(掉电或让它进入低功耗模式)。

    为什么要休眠呢?一言以蔽之:省电。

    休眠分主动休眠和被动休眠。主动休眠:比如我电脑不用了,就通过设置让系统进入休眠模式;被动休眠:系统检测到自己闲的慌,为了节约故,自己就休眠去了。

    废话不叙。


    二、Android休眠

    休眠是内核的核心工作,而Android是基于Linux内核的,所以Android休眠和内核有着千丝万缕的联系;由于Android的特殊应用场景:移动设备,所以Android休眠和内核又有着特别的需求。

    1、联系:

    Android设备停止使用,系统没有什么事情可做,进入休眠状态的功能最终是由内核去实现的;每一类硬件都有自己的驱动,具体的驱动决定怎么进入休眠以及处于何种层次的休眠。比如:对于platform_device,就按照platform_driver定义的规则,在suspend调用的时候,去做上面提到的事情:

    struct platform_driver {
    	int (*probe)(struct platform_device *);
    	int (*remove)(struct platform_device *);
    	void (*shutdown)(struct platform_device *);
    	int (*suspend)(struct platform_device *, pm_message_t state);
    	int (*resume)(struct platform_device *);
    	struct device_driver driver;
    	const struct platform_device_id *id_table;
    };

    2、Android的特别需求:

    比如对于自己的电脑,不用让它休眠好了;但是对于我们形影不离的手机,在休眠的时候还要睁一只眼:来电了要通知你,QQ啊微信啊什么的由信息了也要通知你,所以Android在Linux内核休眠机制之上,提出了“Opportunistic Suspend”


    三、休眠实践

    絮絮叨叨这么多,下面让我们切切实实体验下休眠。

    1、休眠模式

    休眠是分好几种模式的,不同模式实现方式、耗电量不同,以下来自Documentation/power/states.txt

    The kernel supports four power management states generically, though
    one is generic and the other three are dependent on platform support
    code to implement the low-level details for each state.
    This file describes each state, what they are
    commonly called, what ACPI state they map to, and what string to write
    to /sys/power/state to enter that state
    
    state:		Freeze / Low-Power Idle
    ACPI state:	S0
    String:		"freeze"
    
    This state is a generic, pure software, light-weight, low-power state.
    It allows more energy to be saved relative to idle by freezing user
    space and putting all I/O devices into low-power states (possibly
    lower-power than available at run time), such that the processors can
    spend more time in their idle states.
    This state can be used for platforms without Standby/Suspend-to-RAM
    support, or it can be used in addition to Suspend-to-RAM (memory sleep)
    to provide reduced resume latency.
    
    
    State:		Standby / Power-On Suspend
    ACPI State:	S1
    String:		"standby"
    
    This state offers minimal, though real, power savings, while providing
    a very low-latency transition back to a working system. No operating
    state is lost (the CPU retains power), so the system easily starts up
    again where it left off. 
    
    We try to put devices in a low-power state equivalent to D1, which
    also offers low power savings, but low resume latency. Not all devices
    support D1, and those that don't are left on. 
    
    
    State:		Suspend-to-RAM
    ACPI State:	S3
    String:		"mem"
    
    This state offers significant power savings as everything in the
    system is put into a low-power state, except for memory, which is
    placed in self-refresh mode to retain its contents. 
    
    System and device state is saved and kept in memory. All devices are
    suspended and put into D3. In many cases, all peripheral buses lose
    power when entering STR, so devices must be able to handle the
    transition back to the On state. 
    
    For at least ACPI, STR requires some minimal boot-strapping code to
    resume the system from STR. This may be true on other platforms. 
    
    
    State:		Suspend-to-disk
    ACPI State:	S4
    String:		"disk"
    
    This state offers the greatest power savings, and can be used even in
    the absence of low-level platform support for power management. This
    state operates similarly to Suspend-to-RAM, but includes a final step
    of writing memory contents to disk. On resume, this is read and memory
    is restored to its pre-suspend state. 

    虽说kernel支持上述四种休眠模式,但具体哪几种可用取决于你的硬件。那么怎么知道自己的Android设备支持的休眠模式呢?

    答案:通过/sys/文件系统。查询支持的休眠模式可以cat文件/sys/power/state:

    cat /sys/power/state 
    freeze mem

    如果我们往/sys/power/state文件echo上面的某一种模式的字符串,系统就会进入相应的休眠模式:

    echo "mem" > /sys/power/state

    如果你搜索过Android休眠相关的内容,在老版本的Android(4.4版本之前)会见有提到PowerManager的setPowerState()方法,该方法即是通过以上方式使系统进入休眠。但自从引入Autosleep后,就不在这么做了,setPowerState()方法也销声匿迹。


    2、/sys/power/目录下文件


    文件简介:

    • /sys/power/state:用来控制系统的Power状态。读取该文件可以获取系统支持的休眠模式,写入该文件休眠模式的一种,系统进入到指定的休眠模式。如上所示例。
    • /sys/power/autosleep:从Android wakelocks补丁集中演化而来,用于取代Android wakelocks中的自动休眠功能。向该文件写入/sys/power/state返回值的某一种,系统会在适当的时候进入指定的休眠的模式;读取该文件返回之前写入的数值。
    • /sys/power/wake_lock、/sys/power/wake_unlock:即我们常说的休眠锁,如果应用持有休眠锁,系统将无法进入休眠模式。在Android wakelocks时代,写wake_lock获取锁,写wake_unlock释放锁;在AutoSleep时代,具体参见【Android休眠】之AutoSleep
    • wakeup_count:用于解决“system suspend和system wakeup events之间的同步问题”。
    • /sys/power/pm_async:状态切换开关,允许/禁止User空间对设备进行异步的suspend和resume操作。
    • /sys/power/pm_freeze_timeout:系统在执行休眠动作的时候要冻结(freeze)用户控件的进程和内核空间的允许冻结的内核线程,执行这些操作要耗时间吧?该文件指定所需时间的最大值。

    四、其他需要明了的问题

    1、Android设备屏幕暗下来的时候,并不是立即就进入了休眠模式;当所有唤醒源都处于de-avtive状态后,系统才会进入休眠。

    2、Android设备连着adb线到其他设备的情况下,设备是不会进入休眠模式的。

    3、有休眠操作就有唤醒,就需要唤醒源。唤醒源有很多种,在内核注册,比如常用的Power按键。

    4、曾经困惑的一个问题:系统怎么知道自己应该进入休眠模式了?它的判断依据是什么?

    • 在wakelock时代,系统休眠过程中去检测休眠锁;如果系统中没有其他部件持有休眠锁,就尝试进入休眠模式,没有异常事件发生的话就进入休眠模式。
    • Android从4.4开始使用autosleep机制,只要不存在任何active的唤醒源(wakeup_source)了,就进入休眠模式。

    5、系统Power Manager整体流程:


    展开全文
  • 一、休眠概述 休眠,简而言之就是设备在不需要工作的时候把一些部件、外设关掉(掉电或让它进入低功耗模式)。 为什么要休眠呢?一言以蔽之:省电。 休眠分主动休眠和被动休眠。主动休眠:比如我电脑不用了,就通过...

    一、休眠概述

    休眠,简而言之就是设备在不需要工作的时候把一些部件、外设关掉(掉电或让它进入低功耗模式)。

    为什么要休眠呢?一言以蔽之:省电。

    休眠分主动休眠和被动休眠。主动休眠:比如我电脑不用了,就通过设置让系统进入休眠模式;被动休眠:系统检测到自己闲的慌,为了节约故,自己就休眠去了。

    废话不叙。

     

    二、Android休眠

    休眠是内核的核心工作,而Android是基于Linux内核的,所以Android休眠和内核有着千丝万缕的联系;由于Android的特殊应用场景:移动设备,所以Android休眠和内核又有着特别的需求。

    1、联系:

    Android设备停止使用,系统没有什么事情可做,进入休眠状态的功能最终是由内核去实现的;每一类硬件都有自己的驱动,具体的驱动决定怎么进入休眠以及处于何种层次的休眠。比如:对于platform_device,就按照platform_driver定义的规则,在suspend调用的时候,去做上面提到的事情:

     

    
     
    1. struct platform_driver {

    2. int (*probe)(struct platform_device *);

    3. int (*remove)(struct platform_device *);

    4. void (*shutdown)(struct platform_device *);

    5. int (*suspend)(struct platform_device *, pm_message_t state);

    6. int (*resume)(struct platform_device *);

    7. struct device_driver driver;

    8. const struct platform_device_id *id_table;

    9. };

     

     

    2、Android的特别需求:

    比如对于自己的电脑,不用让它休眠好了;但是对于我们形影不离的手机,在休眠的时候还要睁一只眼:来电了要通知你,QQ啊微信啊什么的由信息了也要通知你,所以Android在Linux内核休眠机制之上,提出了“Opportunistic Suspend”。

     

    三、休眠实践

    絮絮叨叨这么多,下面让我们切切实实体验下休眠。

    1、休眠模式

    休眠是分好几种模式的,不同模式实现方式、耗电量不同,以下来自Documentation/power/states.txt:

     

    
     
    1. The kernel supports four power management states generically, though

    2. one is generic and the other three are dependent on platform support

    3. code to implement the low-level details for each state.

    4. This file describes each state, what they are

    5. commonly called, what ACPI state they map to, and what string to write

    6. to /sys/power/state to enter that state

    7.  
    8. state: Freeze / Low-Power Idle

    9. ACPI state: S0

    10. String: "freeze"

    11.  
    12. This state is a generic, pure software, light-weight, low-power state.

    13. It allows more energy to be saved relative to idle by freezing user

    14. space and putting all I/O devices into low-power states (possibly

    15. lower-power than available at run time), such that the processors can

    16. spend more time in their idle states.

    17. This state can be used for platforms without Standby/Suspend-to-RAM

    18. support, or it can be used in addition to Suspend-to-RAM (memory sleep)

    19. to provide reduced resume latency.

    20.  
    21.  
    22. State: Standby / Power-On Suspend

    23. ACPI State: S1

    24. String: "standby"

    25.  
    26. This state offers minimal, though real, power savings, while providing

    27. a very low-latency transition back to a working system. No operating

    28. state is lost (the CPU retains power), so the system easily starts up

    29. again where it left off.

    30.  
    31. We try to put devices in a low-power state equivalent to D1, which

    32. also offers low power savings, but low resume latency. Not all devices

    33. support D1, and those that don't are left on.

    34.  
    35.  
    36. State: Suspend-to-RAM

    37. ACPI State: S3

    38. String: "mem"

    39.  
    40. This state offers significant power savings as everything in the

    41. system is put into a low-power state, except for memory, which is

    42. placed in self-refresh mode to retain its contents.

    43.  
    44. System and device state is saved and kept in memory. All devices are

    45. suspended and put into D3. In many cases, all peripheral buses lose

    46. power when entering STR, so devices must be able to handle the

    47. transition back to the On state.

    48.  
    49. For at least ACPI, STR requires some minimal boot-strapping code to

    50. resume the system from STR. This may be true on other platforms.

    51.  
    52.  
    53. State: Suspend-to-disk

    54. ACPI State: S4

    55. String: "disk"

    56.  
    57. This state offers the greatest power savings, and can be used even in

    58. the absence of low-level platform support for power management. This

    59. state operates similarly to Suspend-to-RAM, but includes a final step

    60. of writing memory contents to disk. On resume, this is read and memory

    61. is restored to its pre-suspend state.


    虽说kernel支持上述四种休眠模式,但具体哪几种可用取决于你的硬件。那么怎么知道自己的Android设备支持的休眠模式呢?

     

    答案:通过/sys/文件系统。查询支持的休眠模式可以cat文件/sys/power/state:

     

    
     
    1. cat /sys/power/state

    2. freeze mem

     

    如果我们往/sys/power/state文件echo上面的某一种模式的字符串,系统就会进入相应的休眠模式:

     

    echo "mem" > /sys/power/state

     

     

    如果你搜索过Android休眠相关的内容,在老版本的Android(4.4版本之前)会见有提到PowerManager的setPowerState()方法,该方法即是通过以上方式使系统进入休眠。但自从引入Autosleep后,就不在这么做了,setPowerState()方法也销声匿迹。

     

    2、/sys/power/目录下文件

    文件简介:

    • /sys/power/state:用来控制系统的Power状态。读取该文件可以获取系统支持的休眠模式,写入该文件休眠模式的一种,系统进入到指定的休眠模式。如上所示例。
    • /sys/power/autosleep:从Android wakelocks补丁集中演化而来,用于取代Android wakelocks中的自动休眠功能。向该文件写入/sys/power/state返回值的某一种,系统会在适当的时候进入指定的休眠的模式;读取该文件返回之前写入的数值。
    • /sys/power/wake_lock、/sys/power/wake_unlock:即我们常说的休眠锁,如果应用持有休眠锁,系统将无法进入休眠模式。在Android wakelocks时代,写wake_lock获取锁,写wake_unlock释放锁;在AutoSleep时代,具体参见【Android休眠】之AutoSleep
    • wakeup_count:用于解决“system suspend和system wakeup events之间的同步问题”。
    • /sys/power/pm_async:状态切换开关,允许/禁止User空间对设备进行异步的suspend和resume操作。
    • /sys/power/pm_freeze_timeout:系统在执行休眠动作的时候要冻结(freeze)用户控件的进程和内核空间的允许冻结的内核线程,执行这些操作要耗时间吧?该文件指定所需时间的最大值。

    四、其他需要明了的问题

    1、Android设备屏幕暗下来的时候,并不是立即就进入了休眠模式;当所有唤醒源都处于de-avtive状态后,系统才会进入休眠。

    2、Android设备连着adb线到其他设备的情况下,设备是不会进入休眠模式的。

    3、有休眠操作就有唤醒,就需要唤醒源。唤醒源有很多种,在内核注册,比如常用的Power按键。

    4、曾经困惑的一个问题:系统怎么知道自己应该进入休眠模式了?它的判断依据是什么?

    • 在wakelock时代,系统休眠过程中去检测休眠锁;如果系统中没有其他部件持有休眠锁,就尝试进入休眠模式,没有异常事件发生的话就进入休眠模式。
    • Android从4.4开始使用autosleep机制,只要不存在任何active的唤醒源(wakeup_source)了,就进入休眠模式。

    5、系统Power Manager整体流程:

    转载地址:https://blog.csdn.net/u013686019/article/details/53645646

    展开全文
  • Android 开发,想要获取系统的休眠状态,在代码中,如何进行判断,请大神指点!
  • 1.分析解析 android系统有earlysuspend和suspend两种休眠,earlysuspend是浅度睡眠,suspend是深度休眠。这个是由linux电源管理控制的,电源管理的接口是“/sys/power/state”和"/sys/power/wake_lock",&...

    1.分析解析

          android系统有earlysuspend和suspend两种休眠,earlysuspend是浅度睡眠,suspend是深度休眠。这个是由linux电源管理控制的,电源管理的接口是“/sys/power/state”和"/sys/power/wake_lock","/sys/power/wake_unlock",这个是linux是否休眠和是否进入深度休眠的关键点。只有wake_lock上锁了,linux系统就不会进入深度休眠       

    2..问题解决

           从上分析可知,只要linux保持有一个唤醒锁,系统就不会进入深度休眠。那么解决问题的思路是在linux启动的时候添加一个唤醒锁就行了。在init.rc文件里面添加一个初始化项:

    echo "noSuspend" > /sys/power/wake_lock




    展开全文
  • Android休眠问题探讨Android推送服务的几种实现方式一、推送方式基础知识: 在移动互联网时代以前的手机,如果有事情发生需要通知用户,则会有一个窗口弹出,将告诉用户正在发生什么事情。可能是未接电话的提示,...

    转载请标明出处:http://blog.csdn.net/xx326664162/article/details/51611625 文章出自:薛瑄的博客

    你也可以查看我的其他同类文章,也会让你有一定的收货!

    Android推送服务的几种实现方式

    一、推送方式基础知识:

      在移动互联网时代以前的手机,如果有事情发生需要通知用户,则会有一个窗口弹出,将告诉用户正在发生什么事情。可能是未接电话的提示,日历的提醒,或是一封新的彩信。推送功能最早是被用于Email中,用来提示我们新的信息。由于时代的发展和移动互联网的热潮,推送功能更加地普及,已经不再仅仅用在推送邮件了,更多地用在我们的APP中了。

      当我们开发需要和服务器交互的应用程序时,基本上都需要获取服务器端的数据,比如《地震应急通》就需要及时获取服务器上最新的地震信息。
      要获取服务器上不定时更新的信息,一般来说有两种方法:

    • 第一种是客户端使用Pull(拉)的方式,就是隔一段时间就去服务器上获取一下信息,看是否有更新的信息出现。

    • 第二种就是 服务器使用Push(推送)的方式,当服务器端有新信息了,则把最新的信息Push到客户端上。这样,客户端就能自动的接收到消息。 

        虽然Pull和Push两种方式都能实现获取服务器端更新信息的功能,但是明显来说Push方式比Pull方式更优越。因为Pull方式更费客户端的网络流量,更主要的是费电量,还需要我们的程序不停地去监测服务端的变化。  

    在开发Android和iPhone应用程序时,我们往往需要从服务器不定的向手机客户端即时推送各种通知消息。我们只需要在Android或IPhone的通知栏处向下一拉,就展开了Notification Panel,可以集中一览各种各样通知消息。目前IOS平台上已经有了比较简单的和完美的推送通知解决方案,我会在以后详细介绍IPhone中的解决方案,可是Android平台上实现起来却相对比较麻烦。

    二、三种常见的解决方案实现原理:

      1)轮询(Pull)方式:应用程序应当阶段性的与服务器进行连接并查询是否有新的消息到达,你必须自己实现与服务器之间的通信,例如消息排队等。而且你还要考虑轮询的频率,如果太慢可能导致某些消息的延迟,如果太快,则会大量消耗网络带宽和电池。
      
      但对于即时通讯产品来说, 这种方案完全不能用. 假设即时通讯软件在网络畅通的情况下发送的消息要求对方10s内就能收到, 如果用轮询, 那么客户端要每隔5s连一次服务器, 如果在移动端, 手机的电量和流量很快就会被消耗殆尽.

      2)SMS(Push)方式:在Android平台上,你可以通过拦截SMS消息并且解析消息内容来了解服务器的意图,并获取其显示内容进行处理。这个方案的好处是,可以实现完全的实时操作。但是问题是这个方案的成本相对比较高,我们需要向运营商缴纳相应的费用。

      3)长连接(Push)方式:应用程序和服务器保持一个长连接,服务器的消息可以直接通过这个链接push到应用程序。这个方案可以解决由轮询带来的性能问题,但是还是会消耗手机的电池。

      Android操作系统允许在低内存情况下杀死系统服务,所以我们的推送通知服务很有可能就被操作系统Kill掉了。 轮询(Pull)方式和SMS(Push)方式这两个方案也存在明显的不足。至于持久连接(Push)方案也有不足,不过我们可以通过良好的设计来弥补,以便于让该方案可以有效的工作。毕竟,我们要知道GMail,GTalk以及GoogleVoice都可以实现实时更新的。


    在理论上使用SMS(Push)方式是最好的方法,这种方法手机客户端最省电(详情查看这里),但是碍于运营商高昂的费用,所以才去长连接(Push)的方式

    三、长连接(Push)的三种方法:

    3.1、GCM云端推送功能。

      在Android手机平台上,Google提供了GCM服务,2016 I/O大会发布了Firebase Cloud Messaging (FCM) 用来取代GCM。

      Google Cloud Messaging (GCM)是一个用来帮助开发者从服务器向Android应用程序发送数据的服务。GCM维护了一个与设备之间的长连接,该服务提供了一个简单的、轻量级的机制,允许服务器可以通知移动应用程序直接与服务器进行通信,以便于从服务器获取应用程序更新和用户数据。GCM服务负责处理诸如消息排队等事务并向运行于目标设备上的应用程序分发这些消息。

    这里写图片描述

    图片来自:http://blog.nkdroidsolutions.com/android-push-notification-with-image/

    GCM的使用流程:

    Step 1: Android device send sender id to GCM server for registering device

    Step 2: GCM Server generate registration id for android device

    Step 3: Now our device send registration id to server through API

    Step 4: Server save registration id in database for future use

    Step 5: For requesting push, our server send request with registration id to GCM server

    Step 6: GCM server send push notification to android device based on registration id.

    GCM特点

    a)Android2.2以下的手机不支持GCM,2.2到3.0需要安装Google Store并设置Google帐号,4.04及以上版本不需要设置帐号也能支持。
    b)GCM只传递数据(可以传递小于4kb的数据),对这些数据的处理可以全部由开发者控制。
    c)Android应用不需要运行就可以接收消息(通过Android广播)。
    d)GCM不保证发送的消息的顺序,也不保证消息一定能够推送到手机。

    GCM心跳策略以及存在的问题

    a)用心跳保活长连接,心跳间隔为WIFI下15分钟,数据网络下28分钟。
    b)Google可以改变所有Android设备的心跳间隔值(目前还未改变过)。
    c)GCM由于心跳间隔固定,并且较长,所以在NAT aging-time设置较小的网络(如联通2G,或有些WIFI环境下)会导致TCP长连接在下一次心跳前被网关释放。造成Push延迟接收。

    GCM的可用性及稳定性

    目前测试发现GCM在国内可用性不高,原因有:
    a) Android很多被手机厂商定制化,厂商可能会去掉GCM服务。
    b) Android2.2到3.0之间需要安装Google Store并设置Google帐号。
    c)由于国内2G和移动3G的NAT超时时间都小于GCM心跳时间(28分钟),TCP长连接必然无法保活,每次都要等28分钟心跳失败重连后才能收到Push。
    d)某些运营商可能限制了5228端口,移动3G/2G下,发现几乎无法连接上GCM服务器,也就无法获得GCM通知,WhatsApp放后台10分钟后,经常很长时间都收不到Push消息。

    在美国3G网络下抓包的24小时,GCM的连接极其稳定,24小时内GCM长连接未曾断过,
    在台湾3G网络下抓包14个小时,GCM连接也只断过一次。
    在中国电信3G下抓包,大部分时间GCM连接都比较稳定,只会因为偶尔的DHCP造成断连现象,由于频率很低(平均数小时才发生一次),对Push体验的影响不大。

    GCM Server类型

    GCM提供两种Server模型:
    a)HTTP Server : 使用同步接口发送HTTP请求,一次请求可以发给最多1000个设备。
    b)XMPP Server :使用异步接口发送请求,只支持对单个设备(或同一个用户的多个关联设备发送),发送请求并发数须小于1000,支持设备到云端Server发送数据。需要Google将我们的发送Server加入白名单。

    3.2、自己建立长连接

    见下面 第四点

    3.3、使用第三方推送平台

    第三方平台有商用的也有免费的,我们可以根据实现情况使用。
      
    推送平台:极光、信鸽、一推 等

    3.4 XMPP, MQTT等不算推送技术

    XMPP是网络即时通信协议, MQTT是IBM开发的一个即时通讯协议。工作在应用层,并不负责底层的连接是如何保持的。并不关心是使用TCP连接的还是UDP连接的。

    也可以使用HTTP协议进行数据传输。

    如下图

    这里写图片描述

    更多关于XMPP查看这里:http://www.cnblogs.com/hanyonglu/archive/2012/03/04/2378956.html

    更多关于MQTT查看这里:
    https://github.com/mcxiaoke/mqtt


    四、自己创建长连接

    4.1、什么是长连接

    先说短连接, 短连接是通讯双方有数据交互时就建立一个连接, 数据发送完成后,则断开此连接.

    这里写图片描述

    长连接就是大家建立连接之后, 不主动断开. 双方互相发送数据, 发完了也不主动断开连接, 之后有需要发送的数据就继续通过这个连接发送.

    TCP连接在默认的情况下就是所谓的长连接, 也就是说连接双方都不主动关闭连接, 这个连接就应该一直存在。TCP连接其实是一种虚拟连接,连接的状态信息是在两端维持的。

    4.2 影响TCP连接寿命的因素

    在Android下,不管是GCM,还是微信,都是通过TCP长连接来进行Push消息的,TCP长连接存活,消息Push就及时,所以要对影响TCP连接寿命的因素进行研究。

    4.2.1 NAT超时

    大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰 NAT 表中的对应项,造成链路中断(NAT超时的更多描述见附录A)。NAT超时是影响TCP连接寿命的一个重要因素(尤其是国内),所以客户端自动测算NAT超时时间,来动态调整心跳间隔,是一个重要的优化点。

    拓展阅读:
    微信收费事件背后被广泛忽略的技术细节
    微信的大规模使用真的会过多占用信令,影响通讯稳定吗?

    4.2.2、DHCP的租期

    目前测试发现安卓系统对DHCP的处理有Bug,DHCP租期到了不会主动续约并且会继续使用过期IP,这个问题会造成TCP长连接偶然的断连。

    关于DHCP租期的问题,原文的发布时Android 6.0还没有发布,不知道Android 6.0 还有没有这个bug(待测试)

    4.2.3、网络状态变化

    手机网络和WIFI网络切换、网络断开和连上等情况有网络状态的变化,也会使长连接变为无效连接,需要监听响应的网络状态变化事件,重新建立Push长连接。

    4.3、心跳包的作用

    https://www.zhihu.com/question/35013918

    我认为心跳包的真正作用有两个:

    4.3.1. 检测客户端和服务端的链接是否可用

    你ssh连上服务器的情况下,拔掉网线,你任然检测不到网络断开了(没有FIN),这时候把网线插回去,敲两下键盘,终端一样有反应,链接还活着。因为tcp的链接是否有效,依赖链接两端的状态确定,你在你机器上拔掉网线,你是知道这件事情的,但是中间网络设备拔掉网线,或者出现什么问题,你完全无法得知链接是否还有效,依赖tcp本身的keepalive机制需要半个小时以上才能检测得出来。

    4.3.2. 防止客户端和服务端之间的NAT表因超时而被清理

    明确一点, TCP长连接本质上不需要心跳包来维持, 大家可以试一试, 让两台电脑连上同一个wifi, 然后让其中一台做服务器, 另一台用一个普通的没有设置KeepAlive的Socket连上服务器, 只要两台电脑别断网, 路由器也别断电, DHCP正常续租, 就这么放着, 过几个小时再用其中一台电脑通过之前建立的TCP连接给另一台发消息, 另一台肯定能收到.

    那为什么要有心跳包呢? 其实主要是为了防止上面提到的NAT超时, 既然一些NAT设备判断是否淘汰NAT映射的依据是一定时间没有数据, 那么客户端就主动发一个数据,用来延续NAT映射的时长。

    4.4、心跳范围选择

    1、前后台区分处理:
    为了保证微信收消息及时性的体验,当微信处于前台活跃状态时,使用固定心跳。
    微信进入后台(或者前台关屏)时,先用几次最小心跳维持长链接。然后进入后台自适应心跳计算。这样做的目的是尽量选择用户不活跃的时间段,来减少心跳计算可能产生的消息不及时收取影响。

    2、后台自适应心跳选择区间:
    可根据自身产品的特点选择合适的心跳范围。

    4.5 智能心跳算法描述

    按网络类型区分计算:
    因为每个网络的NAT时间可能不一致。所以需要区分计算,数据网络按subType做关键字,WIFI按WIFI名做关键字。
    对稳定的网络,因为NAT老化(超时)时间的存在,在自适应计算态的时候,暂设计以下步骤在当前心跳区间逼近出最大可用的心跳。

    a) 变量说明:

    [MinHeart,MaxHeart]——心跳可选区间。
    successHeart——当前成功心跳,初始为MinHeart
    curHeart——当前心跳初始值为successHeart
    heartStep——心跳增加步长
    successStep——稳定期后的探测步长

    b) 最大值探测步骤:

    图4-1

    图4-1 自适应心跳计算流程

    自适应心跳计算流程如图4-1所示,经过该流程,会找到必然使心跳失败的curHeart(或者MaxHeart),为了保险起见,我们选择比前一个成功值稍微小一点的值作为后台稳定期的心跳间隔。
    影响手机网络测试的因素太多,为了尽量保证测试结果的可靠性,我们使用延迟心跳测试法:在我们重新建立TCP连接后,先使用 短心跳连续成功三次,我们才认为网络相对稳定,可以使用curHeart进行一次心跳测试。

    图4-2显示了一次有效心跳测试过程。

    图4-3显示了在没有达到稳定网络环境时,我们会一直使用固定短心跳直到满足三次连续短心跳成功。

    原文中缺少了图4-2和图4-3,不过通过描述也能理解

    使用延迟心跳测试的好处是,可以剔除偶然失败,和网络变化较大的情况(如地铁),使测试结果相对可靠(五次延迟测试确定结论)。同时在网络波动较大的情况,使用短心跳,保证收取消息相对及时。

    c) 运行时的动态调整策略(已经按测算心跳稳定值后)

    NAT超时值算出来后,在维持心跳的过程中的策略

    • 无网络、网络时好时坏、偶然失败、NAT超时变小:在后台稳定期发生心跳发生失败后,我们使用延迟心跳测试法测试五次。如果有一次成功,则保持当前心跳值不变;如果五次测试全失败,重新计算合理心跳值。该过程如图4-4所示,有一点需要注意,每个新建的长连接需要先用短心跳成功维持3次后才用successHeart进行心跳。

    这里写图片描述
    图4-4

    • NAT超时变大:以周为周期,每周三将后台稳定态调至自适应计算态,使用心跳延迟法往后探测心跳间隔。
    • successHeart是NAT超时临界值:因为我们现在选择的是一个比successHeart稍小的值作为稳定值,所以在计算过程中可以避开临界值。当运营商在我们后台稳定期将NAT超时调整为我们当前计算值,那么由于我们每周会去向下探索,所以下一周探测时也可以及时调整正确。

    4.6 冗余Sync和心跳

    在用户的一些主动操作以及联网状态改变时,增加冗余Sync和心跳,确保及时收到消息。
    1、当用户点亮屏幕的时候,做一次心跳。
    2、当微信切换到前台时,做一次Sync。
    3、联网时重建信令TCP,做一次Sync

    4.7、微信使用的推送方案:

    微信Push的优化主要有几个优化点:
    a) 公共Push通道
    b) 使用GCM Push作为辅助通道
    c) 自适应心跳间隔优化

    公共Push通道:
    由于GCM在国内的可靠性很低,现在国内Android上的Push基本上是各自为政,很多软件都自己实现Push。导致手机被经常性的唤醒,耗电耗流量严重。
    市面上已经有很多第三方的公共推送服务,大家可以选择一个适合自己应用的推送服务。腾讯也有信鸽和维纳斯组件,大家在选择方案的时候可以对比下。
    最终因为我们国内外使用一套方案,并且是辅助公道,所以我们选择使用GCM。

    使用GCM Push作为辅助通道:
    当前使用GCM的成本不大,可以使用GCM作为辅助通道来增加新消息的及时性。
    使用GCM作为辅助通道,在支持GCM的设备上微信上传自己的注册GCM ID给微信Server。
    微信Server在发现长连接失效的情况下,可以使用GCM 作为辅助通道通知客户端有新消息,客户端收到push通知后做一次sync。
    只利用GCM来激活微信,不传递消息的具体数据,要控制给同一设备发送GCM通知的时间间隔(如五分钟)。

    5、Android休眠带来的影响

    Android设备上解决耗电的一个策略就是休眠,手机在锁屏之后一段时间手机就会休眠,那个时候,无论是屏幕,CPU还是其他模块都会停止工作,这样导致了2个问题:

    1.一些通讯软件的心跳包中断,导致掉线

    2.若采用UDP连接的情况下,服务器过来的数据包不一定实时。

    我们来讲讲如何解决以上的两个问题。

    Android手机有两个处理器

    • Application Processor(AP)
    • Baseband Processor(BP)。

    AP是ARM架构的处理处理器,用于运行Linux+Android体系;
    BP用于运行及时操纵体系(RTOS),通信协议栈运行于BP的RTOS之上。非通话时候,BP的能耗基本在5mA以下,而AP只要处于非休眠状况,能耗至少在50mA以上,履行图形运算时会更高。别的LCD工作时功耗在100mA左右,WIFI也在100mA左右。一般手机待机时,AP、LCD、WIFI均进入休眠状况,这时Android中应用法度的代码也会停止运行。

    Android为了确保一些关键代码的正确运行,供给了Wake Lock的API,使得应用有权限经由过程代码阻拦AP进入休眠状况(iOS、WP7都没这种器材)。若是不懂得Android设计者的意图而滥用Wake Lock API,为了自身代码在后台的正常工作而长时候阻拦AP进入休眠状况,结果就相当严重了,手机的电量就犀利哗啦的被用完了。

    如果AP休眠了,手机不是接收不到消息了吗?

    完全不用担心,通信协议栈运行于BP,一旦收到数据包,BP会将AP唤醒,唤醒的时间足够AP完成对BP收到协议的处理,但是有一点需要大家注意的是,假如你处理协议包的时间很长的话,那么请加上wakelock,完成之后再释放掉。

    如果AP休眠了,程序如何执行向服务器发送心跳包的逻辑

    你显然不能靠AP来做心跳计时. Android提供的Alarm Manager就是来解决这个问题的. Alarm应该是BP计时(或其它某个带石英钟的芯片,不太确定,但绝对不是AP), 触发时唤醒AP执行程序代码.
    那么Wake Lock API有啥用呢? 比如心跳包从请求到应答, 比如断线重连重新登陆这些关键逻辑的执行过程, 就需要Wake Lock来保护. 而一旦一个关键逻辑执行成功, 就应该立即释放掉Wake Lock了. 两次心跳请求间隔5到10分钟, 基本不会怎么耗电. 除非网络不稳定. 频繁断线重连, 那种情况办法不多.

    上面所说的通信协议, 我猜应该是无线资源控制协议(Radio Resource Control), RRC应该工作在OSI参考模型中的第三层网络层, 而TCP, UDP工作在第四层传输层, 上文说的BP, 应该就是手机中的基带, 也有叫Radio的,
    Google在Optimizing Downloads for Efficient Network Access 中提到了一个叫Radio State Machine的东西

    TCP长连接是可以将AP唤醒,但是UDP数据包并不会唤醒。

    具体的原因可能是因为底层对于TCP长连接的数据过来,会产生AP中断来唤醒AP,但是UDP不会。。。这么做也是有道理的,因为TCP长链接是客户端自身验证过的服务器,也就是数据来源可靠。。。若UDP也会唤醒,那完全可以进行UDP数据包工具,这样一来,被攻击的手机至少耗电量将会大幅度上升。

    附录A——NAT超时介绍

    因为 IP v4 的 IP 量有限,运营商分配给手机终端的 IP 是运营商内网的 IP,手机要连接 Internet,就需要通过运营商的网关做一个网络地址转换(Network Address Translation,NAT)。简单的说运营商的网关需要维护一个外网 IP、端口到内网 IP、端口的对应关系,以确保内网的手机可以跟 Internet 的服务器通讯。

    大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰 NAT 表中的对应项,造成链路中断。下表列出一些已测试过的网络的NAT超时时间(更多数据由于测试条件所限没有测到):

    地区/网络 NAT超时时间
    中国移动3G和2G 5分钟
    中国联通2G 5分钟
    中国电信3G 大于28分钟
    美国3G 大于28分钟
    台湾3G 大于28分钟

    GGSN(Gateway GPRS Support Node 网关GPRS支持结点)模块就实现了NAT功能。
    因为大部分移动无线网络运营商都是为了减少网关的NAT映射表的负荷,所以如果发现链路中有一段时间没有数据通讯时,会删除其对应表,造成链路中断。

    长连接心跳间隔必须要小于NAT超时时间(aging-time),如果超过aging-time不做心跳,TCP长连接链路就会中断,Server就无法发送Push给手机,只能等到客户端下次心跳失败后,重建连接才能取到消息。

    附录B——安卓DHCP的租期(lease time)问题

    目前测试发现安卓系统对DHCP的处理有Bug:
    1、 DHCP租期到了不会主动续约并且会继续使用过期IP,详细描述见http://www.net.princeton.edu/android/android-stops-renewing-lease-keeps-using-IP-address-11236.html。这个问题导致的问题表象是,在超过租期的某个时间点(没有规律)会导致IP过期,老的TCP连接不能正常收发数据。并且系统没有网络变化事件,只有等应用判断主动建立新的TCP连接才引起安卓设备重新向DHCP Server申请IP租用。
    2、 未到租期的一半时间,安卓设备重新向DHCP Server申请IP租用。从目前测试结果来看,这种现象恢复的比较快。
    3、 移动2G/3G,联通2G没有抓到DHCP。
    4、 美国3G下抓取24小时,没有抓到DHCP。

    参考:
    Android推送技术研究
    Android实现推送方式解决方案
    Android微信智能心跳方案
    Android休眠问题探讨

    关注我的公众号,轻松了解和学习更多技术
    这里写图片描述

    展开全文
  • Android休眠机制

    2017-08-11 18:16:44
    最近修复一个遗留的bug,定时检测,超过多长时间则弹出一个Tip,在...回过神来一想,应该是掉进了Android休眠机制的坑里了。趁此机会对Android休眠机制进行一个总结。 Linux的休眠机制 Android是基于Linux的,要

           最近修复一个遗留的bug,定时检测,超过多长时间则弹出一个Tip,在debug跟进这个bug的时候,并没有发现问题,Timer和TimerTask实现的定时任务,但是在实际使用的时候,产品等很多人都遇到不弹Tip的问题。回过神来一想,应该是掉进了Android休眠机制的坑里了。趁此机会对Android的休眠机制进行一个总结。

    Linux的休眠机制


           Android是基于Linux的,要理解Android的休眠机制,那就需要先了解Linux系统的电源状态。Linux系统的电源状态可以分为四种:On,Standby,Suspend-to-RAM,Suspend-to-disk.

    • On:表示处于工作状态(working),CPU、RAM等设备都处于工作状态。

    • Standby:CPU、RAM等设备依然处于通电状态,但是并没有进行工作,此时还是需要损耗小部分电。

    • Suspend-to-RAM:挂起到内存,简称待机。计算机将目前的运行状态等数据存放在内存,关闭硬 盘、外设等设备,进入等待状态。此时内存仍然需要电力维持其数据,但整机耗电很少;恢复时计算机从内存读出数据,回到挂起前的状态,恢复速度较快。

    • Suspend-to-disk:挂起到硬盘,简称休眠。把运行状态等数据存放在硬盘上某个文件或者某个特定的区域,关闭硬盘、外设等设备,进入关机状态。此时计算机完全关闭,不耗电。恢复时计算机从休眠文件/分区中读出数据,回到休眠前的状态,恢复速度较慢。

    Linux支持的电源状态都记录在/sys/power/state中,Root的手机可以通过ADB进行查看,我的手机没有Root,只能看到目录,无法看到里面的内容。

    这里写图片描述


    AutoSleep


           Android系统包含AP和BP两个处理器,应用程序等都运行在AP处理器中,因此下面所说的Android休眠指的是AP。
           Android系统虽然是基于Linux的,但是它的AutoSleep并不支持上述所有的四种电源状态。首先,On 肯定是需要支持的,因为我们使用手机的时候正是出于On的电源状态,同时还支持Suspend-to-RAM的电源状态,Android系统休眠就是处于Suspend-to-RAM电源状态,根据上面的介绍,从Suspend-to-RAM恢复数据比Suspend-to-disk快,而耗电有点Standby少。

    early_suspend与late_resume

           当我们的手机从亮屏到灭屏时,此时我们的应用还需要处于活跃的状态,但是为了节省电量,触摸屏、LCD等设备此时可以关闭了。而当我们的手机处于休眠状态时收到网络数据,需要应用程序处理时我们不希望触摸屏、LCD等设备开启;因此Android引入了early_suspend和late_resume.

    • early_suspend:当灭屏时,LCD、触摸屏等设备就会通过对应驱动,使其进入suspend状态,减少电量的损耗。

    • late_resume:对应early_suspend关闭的设备。系统休眠时,当应用收到网络数据,进行处理时,不会执行late_resume。

    wake_lock 与 wake_unlock

           某些情况下,我们应用在后台需要处理一些数据,在处理数据的时候,不希望系统进入休眠,当处理完数据之后才能进入休眠状态。因此引入了wake_lock与wake_unlock机制。wake_lock机制一开始并不是Linux所支持的,而是由Android层实现的,后面由于Android的普及,Linux才进行支持。

    这里写图片描述

    • wake_lock:当应用有数据需要处理,不希望系统马上进入休眠时,可以通过wake_lock,当有应用持有wake_lock时,系统不会进入休眠。当应用申请一个XXX的wake_lock时,会将XXX写入wake_lock文件中,,并标记为active。

    • wake_unlock:当应用处理完数据后,需要释放其所有持有的wake_lock,不然无法使系统进入休眠状态,耗费大量的电。当应用释放一个XXX的wake_lock时,会在wake_unlock中写入XXX,并将其标记的deactive.

    AutoSleep流程

    这里写图片描述

    AlarmManager


           回到文章开头的那个bug,在系统休眠的时候,CPU已经停止工作了,应用的代码也没法被执行,如何定时弹出Tip呢。第一种方式就是在回到应用的时候再次判断时间,当超过时间就弹出Tip继续及时,采用这种方法解决了问题。但是当IM等即时通讯时,在系统休眠的情况下也需要及时通知消息,此时就需要采用另外的方式解决问题了。
           通过AlarmManager定时解决问题,前面提到在Android系统中,有两个处理器AP与BP,系统休眠中的CPU停止指的是AP处理器,而BP处理器处于正常工作的状态,当接受到网络数据等时,BP处理器会唤醒AP处理器来进行处理,而AlarmManager也是同理,定时通过BP处理器唤醒AP处理器,从而让AP处理器进行定时操作,然后AP处理器会在满足条件的情况下再次休眠。

    Doze


           在Android 6.0时,引入了Doze模式。如果用户设备未插接电源、处于静止状态一段时间且屏幕关闭,设备会进入低电耗模式。 在低电耗模式下,系统会尝试通过限制应用对网络和 CPU 密集型服务的访问来节省电量。 这还可以阻止应用访问网络并推迟其作业、同步和标准闹铃。系统会定期退出低电耗模式一会儿,好让应用完成其已推迟的 Activity。在此维护时段内,系统会运行所有待定同步、作业和闹铃并允许应用访问网络。

    这里写图片描述

    在每个维护时段结束后,系统会再次进入低电耗模式,暂停网络访问并推迟作业、同步和闹铃。 随着时间的推移,系统安排维护时段的次数越来越少,这有助于在设备未连接至充电器的情况下长期处于不活动状态时降低电池消耗。一旦用户通过移动设备、打开屏幕或连接到充电器唤醒设备,系统就会立即退出低电耗模式,并且所有应用都将返回到正常 Activity。

    在低电耗模式下,您的应用会受到以下限制:

    • 暂停访问网络

    • 系统将忽略 wake locks

    • 标准 AlarmManager 闹铃(包括 setExact() 和 setWindow())推迟到下一维护时段。如果您需要设置在低电耗模式下触发的闹铃,请使用setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle(),触发闹铃的时间间隔都不能超过 9 分钟。一般情况下,使用 setAlarmClock() 设置的闹铃将继续触发,但系统会在这些闹铃触发之前不久退出低电耗模式。

    • 系统不执行 Wi-Fi 扫描

    • 系统不允许运行同步适配器

    • 系统不允许运行 JobScheduler

    注意AlarmManager标准的闹铃也会被推迟,在定时执行任务不是均匀的执行,而是间隔时间越来越久。例如定时心跳推荐用setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()。

    总结


    1. Android包含AP和BP两个处理器,系统休眠时AP停止运行,但BP依旧执行

    2. 定时任务推荐用AlarmManager

    3. Doze模式下,标准的Alarm会被推迟,推荐使用setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()

    4. Android系统浅休眠指early_suspend,此时AP处理器并没有停止,应用可以执行;Android系统深度休眠指标准的Linux Suspend-to-RAM,系统的状态保存在RAM中,AP处理器停止工作,应用也停止执行。

    展开全文
  • 休眠 DC连接汽车12V永不掉电,熄火时ACC发出掉电信号时,行车记录装置采用不关机,深度休眠策略。关闭屏幕,停止录像,记录轨迹的同时,需要打开飞行模式(蓝牙,WiFi),关闭FM发射,关闭GPS。如果此时有音乐播放和...
  • Android设置系统休眠

    2018-06-13 13:46:12
    可以通过以下方法进行系统休眠的获取和判断:(测试环境Android5.1)/** * 设置休眠时间 * * @param millisecond * @param context */ public static void setScreenSleepTime(int millisecond, Context ...
  • 1.电源管理通过监测display的状态,当灭屏时则发起休眠的流程,调用native层的方法继续往下走。首先是在DisplayPowerController中收到MSG_UPDATE_POWER_STATE消息,随后经过一系列的回调了DisplayBlanker接口的...
  • 首先看一下Android Powermanager Class Overview,对Android的几种不同的休眠模式有个大致了解。 如果不进行特别的设置,Android会在一定时间后屏幕变暗,在屏幕变暗后一定时间内,约几分钟,CPU也会休眠,大多数的...
  • Android 进入休眠分析

    2012-08-02 14:43:19
    Android 的上层是使用 goToSleep() 这个函数让系统进入休眠的。但是这个命令为什么会让 Android 进入 Suspend Mode。   以前在做其他系统的时候, 一般都要自己手工去控制 apm_bios 这个设备的,比如使用 ...
  • android手机进入设置,在进入显示,有个休眠时间的选项。可以设置多久不操作后熄灭屏幕。android熄灭屏幕实际根据系统当前wakeLock锁的数量和类型有关,本篇文章不讨论这个问题。只是本人发现了一个奇怪的现象: ...
  • Android wifi休眠策略

    2017-10-23 14:33:09
    本文转自http://blog.csdn.net/wwwwap2008/article/details/51783138最近在项目里...W/Settings: Setting wifi_sleep_policy has moved from android.provider.Settings.System to android.provider.Settings.Global,
  • 近日接到一个比较诡异的产品需求,在我看来需要修改Android PMS。 具体需求如下:  要求在某一Activity界面在灭屏之后也能监听屏幕的手势事件,在我看来这种手势事件需求应该放在TP的驱动中来完成是最合理的,但是...
  • android 休眠

    2017-09-25 10:51:03
    首先先简单介绍下Android休眠机制,它主要是基于系统的wake_lock机制,只要系统中存在任一有效的wake_lock,系统就无法进入休眠态。wake_lock一般在关闭屏幕时,仍然需要正常运行的情况下使用,比如关闭屏幕后的听...
  • Android手机的休眠状态

    2015-07-08 14:12:13
    Android手机有两个处理器,一个叫Application Processor(AP),一个叫Baseband Processor(BP)。非通话时间,BP的能耗基本上在5mA左右,而AP只要处于非休眠状态,能耗至少在50mA以上,执行图形运算时会更高。一般...
  • Android 自动休眠唤醒

    2015-08-12 09:19:02
    **一、自动休眠唤醒的实现. 二、binder机制.(广播既然能实现进程间通信,两者区别?) 三、自定义控件的使用和原理.(benwenbutantao….) 四、动画效果的实现原理.**一、自动休眠唤醒的实现. 分析: 标准...
  • Android休眠唤醒机制简介(一) 1、背景介绍:  睡眠/唤醒是嵌入式Linux非常重要的组成部分,因为优秀的睡眠唤醒机制可以是嵌入式设备尽可能的进入休眠状态,来延长电池的续航时间(这在移动终端消费类电子设备...
  • android计时与系统休眠

    2016-04-20 15:18:38
    我们项目里面用的是Timer计时的方法,但是,当系统休眠的时候,Timer也是处于休眠状态的。后来,我改进了几个方法,一个是handle+message的方法,还有一个是handle+runnable的方法,还有handle+Thread的方法。但
1 2 3 4 5 ... 20
收藏数 6,330
精华内容 2,532