The problem of alarm in Android4.4 and after sleep condition
To reduce power consumption, extend battery life. Android 4.4
and the subsequent version number adopts the non-precision alarm clock mechanism. And the wakeup
type of hibernation will alarm
not wake the device in real time, but will wait until the machine is physically awakened alarm
. Android 6.0
provides a new API: setExactAndAllowWhileIdle()
partially solves the problem, but still cannot wake up accurately in hibernation.
alarm api
for support and use please refer to:
(Image source: Https://plus.google.com/+AndroidDevelopers/posts/GdNrQciPwqo)
In addition, the application layer should not wakelock
be used instead of being held BroadcastReceiver
WakefulBroadcastReceiver
.
In order to fix this problem. In the case of version 5.0.2, the alarm-dev.c under the kernel and the Alarmmanagerservice under the framework need to be changed.
Kernel ALARM-DEV.C: The reason for this is that it uses generic static struct wakeup_source alarm_wake_lock;
rather than WAKE_LOCK_SUSPEND
categorical information and struct wake_lock
needs to use android_
a prefix- wakeup lock
related function.
That
android_wake_lock_initandroid_wake_lock_destroyandroid_wake_lockandroid_wake_lock_timeoutandroid_wake_unlock
Rather than the normal wake lock
operation function:
wake_lock_initwake_lock_destroywake_lockwake_lock_timeoutwake_unlock
Framework Alarmmanagerservice.java: wakeup
Special handling of types is required alarm
: precise alarms. setImpl
Add the following code in the example:
Public Boolean Iswakeup(intType) {return(Type & type_nonwakeup_mask) = =0;}voidSetimpl (intTypeLongTriggerattime,LongWindowlength,LongInterval, pendingintent operation,BooleanIsstandalone, WorkSource WorkSource, Alarmmanager.alarmclockinfo alarmclock) {if(Operation = =NULL) {SLOG.W (TAG,"Set/setrepeating ignored because there is no intent");return; }if(Iswakeup (type)) {windowlength = alarmmanager.window_exact; Isstandalone =true; }
And alarm
when triggered, more than a few satisfying conditions to batch
do the processing:
BooleanTriggeralarmslocked (arraylist<alarm> triggerlist,Final LongNowelapsed,Final LongNOWRTC) {BooleanHaswakeup =false;//Batches is temporally sorted, so we need //start of the list until we either empty it or hit a batch // that's not yet deliverableArraylist<alarm> repeatlist =NewArraylist<alarm> (); Listiterator<batch> it = Malarmbatches.listiterator (); while(It.hasnext ()) {Batch Batch = It.next ();if(Batch.start > nowelapsed) {//Everything else is scheduled Break; }//We'll (re) schedule some alarms now; don ' t let that interfere //With delivery of this current batchIt.remove ();Final intN = Batch.size (); for(inti =0; i < N; i++) {Alarm Alarm = Batch.get (i); Alarm.Count=1; Triggerlist.add (alarm);//Recurring alarms may has passed several alarm intervals while the //Phone is asleep or off, so pass a trigger count when sending them. if(Alarm.repeatinterval >0) {//This adjustment'll be the zero if we ' re late by //Less than one full repeat intervalAlarm.Count+ = (nowelapsed-alarm.whenelapsed)/alarm.repeatinterval;//Also schedule its next recurrenceRepeatlist.add (alarm); }if(alarm.wakeup) {haswakeup =true; Mnextwakeup =0; }//We removed an alarm clock. Let the caller recompute the next alarm clock. if(Alarm.alarmclock! =NULL) {Mnextalarmclockmaychange =true; } } }if(Repeatlist.size () >0) { for(Alarm alarm:repeatlist) {Final LongDelta = alarm.Count* ALARM.REPEATINTERVAL;Final Longnextelapsed = alarm.whenelapsed + Delta; Setimpllocked (Alarm.type, Alarm.when + Delta, nextelapsed, Alarm.windowlength, Maxtriggertime (NowELAPSE D, nextelapsed, Alarm.repeatinterval), Alarm.repeatinterval, alarm.operation, alarm.windowlength = Ala Rmmanager.window_exact,true, Alarm.worksource, Alarm.alarmclock, Alarm.userid); } }//This is a new alarm delivery set, bump the sequence number to indicate //All apps ' alarm delivery classes should is recalculated.mcurrentseq++; Calculatedeliverypriorities (triggerlist); Collections.sort (Triggerlist, malarmdispatchcomparator);returnHaswakeup;}
Application-level use WakefulBroadcastReceiver
:
ImportAndroid.support.v4.content.WakefulBroadcastReceiver; Public class autoupdatealarmreceiver extends wakefulbroadcastreceiver { @Override Public void OnReceive(context context, Intent Intent) {//Start the service, keeping the device awake while the service is //Launching. The Intent to deliver to the service.Intent Service =NewIntent (context, autoupdateintentservice.class); Service.setaction (Intent.getaction ()); Startwakefulservice (context, service); }}
The corresponding IntentService
example of the following is seen:
Public class autoupdateintentservice extends intentservice { Public Autoupdateintentservice() {Super("Autoupdateintentservice"); }@Override protected void onhandleintent(Intent Intent) {String action = intent.getaction ();//Do your work here. // ... //Release The wake Lock provided by the Wakefulbroadcastreceiver.Autoupdatealarmreceiver.completewakefulintent (Intent); }}
The problem of alarm in dormant state after Android4.4