标签:inf comm views 技术分享 dev ati int ble adc
为了减轻功耗,延长电池使用时间,Android 4.4
及之后的版本采用非精准闹钟机制,以及休眠状态下的wakeup
类型的alarm
不会实时唤醒设备,而会等到机器被物理唤醒时才触发alarm
。Android 6.0
提供了新的api:setExactAndAllowWhileIdle()
部分解决这个问题,但依然不能在休眠状态下精准唤醒。
关于alarm api
的支持与使用请参考下图:
(图片来源:https://plus.google.com/+AndroidDevelopers/posts/GdNrQciPwqo)
此外,应用层面不要使用不持有wakelock
的BroadcastReceiver
,而要使用WakefulBroadcastReceiver
。
为了修复这个问题,以5.0.2版本为例,需要修改内核下的alarm-dev.c以及framework下的AlarmManagerService。
内核 alarm-dev.c:其原因是使用普通的static struct wakeup_source alarm_wake_lock;
,而非带有WAKE_LOCK_SUSPEND
类别信息的struct wake_lock
,并且需要使用带有android_
前缀的wakeup lock
相关函数。即:
android_wake_lock_init
android_wake_lock_destroy
android_wake_lock
android_wake_lock_timeout
android_wake_unlock
而非普通的wake lock
操作函数:
wake_lock_init
wake_lock_destroy
wake_lock
wake_lock_timeout
wake_unlock
framework AlarmManagerService.java:需要将wakeup
类型的alarm
特殊处理:即精准闹铃。在setImpl
中添加如下代码:
public boolean isWakeup(int type)
{
return (type & TYPE_NONWAKEUP_MASK) == 0;
}
void setImpl(int type, long triggerAtTime, long windowLength, long interval,
PendingIntent operation, boolean isStandalone, 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;
}
并在alarm
被触发时多取几个满足条件的batch
做处理:
boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
final long nowRTC) {
boolean hasWakeup = false;
// batches are temporally sorted, so we need only pull from the
// start of the list until we either empty it or hit a batch
// that is not yet deliverable
ArrayList<Alarm> repeatList = new ArrayList<Alarm>();
ListIterator<Batch> it = mAlarmBatches.listIterator();
while (it.hasNext()) {
Batch batch = it.next();
if (batch.start > nowELAPSED) {
// Everything else is scheduled for the future
break;
}
// We will (re)schedule some alarms now; don‘t let that interfere
// with delivery of this current batch
it.remove();
final int N = batch.size();
for (int i = 0; i < N; i++) {
Alarm alarm = batch.get(i);
alarm.count = 1;
triggerList.add(alarm);
// Recurring alarms may have passed several alarm intervals while the
// phone was asleep or off, so pass a trigger count when sending them.
if (alarm.repeatInterval > 0) {
// this adjustment will be zero if we‘re late by
// less than one full repeat interval
alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval;
// Also schedule its next recurrence
repeatList.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 long delta = alarm.count * alarm.repeatInterval;
final long nextElapsed = alarm.whenElapsed + delta;
setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
alarm.repeatInterval, alarm.operation, alarm.windowLength == AlarmManager.WINDOW_EXACT, true,
alarm.workSource, alarm.alarmClock, alarm.userId);
}
}
// This is a new alarm delivery set; bump the sequence number to indicate that
// all apps‘ alarm delivery classes should be recalculated.
mCurrentSeq++;
calculateDeliveryPriorities(triggerList);
Collections.sort(triggerList, mAlarmDispatchComparator);
return hasWakeup;
}
应用层面使用WakefulBroadcastReceiver
:
import android.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. This is the Intent to deliver to the service.
Intent service = new Intent(context, AutoUpdateIntentService.class);
service.setAction(intent.getAction());
startWakefulService(context, service);
}
}
相应的IntentService
如下所示:
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);
}
}
标签:inf comm views 技术分享 dev ati int ble adc
原文地址:http://blog.csdn.net/kesalin/article/details/70211621