1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.test.wakeuploop;
18
19import android.app.AlarmManager;
20import android.app.PendingIntent;
21import android.content.BroadcastReceiver;
22import android.content.Context;
23import android.content.Intent;
24import android.os.Environment;
25import android.os.Message;
26import android.os.Messenger;
27import android.os.PowerManager;
28import android.os.PowerManager.WakeLock;
29import android.os.RemoteException;
30import android.os.SystemClock;
31import android.util.Log;
32
33import java.io.File;
34
35/**
36 * The receiver for the alarm we set
37 *
38 */
39public class WakeUpCall extends BroadcastReceiver {
40    private static final String LOG_TAG = WakeUpCall.class.getSimpleName();
41    static final String WAKEUP_CALL = "android.test.wakeuploop.WAKEUP";
42    static final String CANCEL = "CANCEL";
43
44    @Override
45    public void onReceive(Context context, Intent intent) {
46        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
47        boolean cancel = intent.hasExtra(CANCEL);
48        if (!cancel) {
49            long maxLoop = intent.getLongExtra(WakeLoopService.MAX_LOOP, 0);
50            long wakeupInterval = intent.getLongExtra(WakeLoopService.WAKEUP_INTERNAL, 0);
51            long thisLoop = intent.getLongExtra(WakeLoopService.THIS_LOOP, -1);
52            Log.d(LOG_TAG, String.format("incoming: interval = %d, max loop = %d, this loop = %d",
53                    wakeupInterval, maxLoop, thisLoop));
54            if (thisLoop == -1) {
55                Log.e(LOG_TAG, "no valid loop count received, trying to stop service");
56                stopService(intent);
57                return;
58            }
59            if (wakeupInterval == 0) {
60                Log.e(LOG_TAG, "no valid wakeup interval received, trying to stop service");
61                stopService(intent);
62                return;
63            }
64            thisLoop++;
65            Log.d(LOG_TAG, String.format("WakeLoop - iteration %d of %d", thisLoop, maxLoop));
66            if (thisLoop == maxLoop) {
67                // when maxLoop is 0, we loop forever, so not checking that case
68                // here
69                Log.d(LOG_TAG, "reached max loop count, stopping service");
70                stopService(intent);
71                return;
72            }
73            screenOn(context);
74            FileUtil.get().writeDateToFile(
75                    new File(Environment.getExternalStorageDirectory(), "wakeup-loop.txt"));
76            // calculate when device should be waken up
77            long atTime = SystemClock.elapsedRealtime() + wakeupInterval;
78            intent.putExtra(WakeLoopService.THIS_LOOP, thisLoop);
79            PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent,
80                    PendingIntent.FLAG_UPDATE_CURRENT);
81            // set alarm, which will be delivered in form of the wakeupIntent
82            am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, atTime, pi);
83        } else {
84            // cancel alarms
85            Log.d(LOG_TAG, "cancelling future alarms on request");
86            am.cancel(PendingIntent.getBroadcast(context, 0, intent, 0));
87        }
88    }
89
90    private void stopService(Intent i) {
91        Messenger msgr = i.getParcelableExtra(WakeLoopService.STOP_CALLBACK);
92        if (msgr == null) {
93            Log.e(LOG_TAG, "no stop service callback found, cannot stop");
94        } else {
95            Message msg = new Message();
96            msg.what = WakeLoopService.MSG_STOP_SERVICE;
97            try {
98                msgr.send(msg);
99            } catch (RemoteException e) {
100                Log.e(LOG_TAG, "ignored remoted exception while attempting to stop service", e);
101            }
102        }
103    }
104
105    private void screenOn(Context context) {
106        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
107        @SuppressWarnings("deprecation")
108        WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK |
109                PowerManager.ACQUIRE_CAUSES_WAKEUP, LOG_TAG);
110        wl.acquire(500);
111    }
112}
113