[go: nahoru, domu]

1/*
2 * Copyright (C) 2015 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 com.android.server.wifi;
18
19import static org.mockito.Mockito.any;
20import static org.mockito.Mockito.anyInt;
21import static org.mockito.Mockito.anyLong;
22import static org.mockito.Mockito.anyString;
23import static org.mockito.Mockito.doAnswer;
24import static org.mockito.Mockito.mock;
25
26import android.app.AlarmManager;
27import android.os.Handler;
28
29import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
30
31import java.util.ArrayList;
32import java.util.Iterator;
33import java.util.List;
34import java.util.Objects;
35
36/**
37 * Creates an AlarmManager whose alarm dispatch can be controlled
38 * Currently only supports alarm listeners
39 *
40 * Alarm listeners will be dispatched to the handler provided or will
41 * be dispatched imediatly if they would have been sent to the main
42 * looper (handler was null).
43 */
44public class MockAlarmManager {
45    private final AlarmManager mAlarmManager;
46    private final List<PendingAlarm> mPendingAlarms;
47
48    public MockAlarmManager() throws Exception {
49        mPendingAlarms = new ArrayList<>();
50
51        mAlarmManager = mock(AlarmManager.class);
52        doAnswer(new SetListenerAnswer()).when(mAlarmManager).set(anyInt(), anyLong(), anyString(),
53                any(AlarmManager.OnAlarmListener.class), any(Handler.class));
54        doAnswer(new SetListenerAnswer()).when(mAlarmManager).setExact(anyInt(), anyLong(),
55                anyString(), any(AlarmManager.OnAlarmListener.class), any(Handler.class));
56        doAnswer(new CancelListenerAnswer())
57                .when(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
58    }
59
60    public AlarmManager getAlarmManager() {
61        return mAlarmManager;
62    }
63
64    /**
65     * Dispatch a pending alarm with the given tag
66     * @return if any alarm was dispatched
67     */
68    public boolean dispatch(String tag) {
69        for (int i = 0; i < mPendingAlarms.size(); ++i) {
70            PendingAlarm alarm = mPendingAlarms.get(i);
71            if (Objects.equals(tag, alarm.getTag())) {
72                mPendingAlarms.remove(i);
73                alarm.dispatch();
74                return true;
75            }
76        }
77        return false;
78    }
79
80    /**
81     * @return if an alarm with the given tag is pending
82     */
83    public boolean isPending(String tag) {
84        for (int i = 0; i < mPendingAlarms.size(); ++i) {
85            PendingAlarm alarm = mPendingAlarms.get(i);
86            if (Objects.equals(tag, alarm.getTag())) {
87                return true;
88            }
89        }
90        return false;
91    }
92
93    /**
94     * @return trigger time of an pending alarm with the given tag
95     *         -1 if no pending alram with the given tag
96     */
97    public long getTriggerTimeMillis(String tag) {
98        for (int i = 0; i < mPendingAlarms.size(); ++i) {
99            PendingAlarm alarm = mPendingAlarms.get(i);
100            if (Objects.equals(tag, alarm.getTag())) {
101                return alarm.getTriggerTimeMillis();
102            }
103        }
104        return -1;
105    }
106
107    private static class PendingAlarm {
108        private final int mType;
109        private final long mTriggerAtMillis;
110        private final String mTag;
111        private final Runnable mCallback;
112
113        public PendingAlarm(int type, long triggerAtMillis, String tag, Runnable callback) {
114            mType = type;
115            mTriggerAtMillis = triggerAtMillis;
116            mTag = tag;
117            mCallback = callback;
118        }
119
120        public void dispatch() {
121            if (mCallback != null) {
122                mCallback.run();
123            }
124        }
125
126        public Runnable getCallback() {
127            return mCallback;
128        }
129
130        public String getTag() {
131            return mTag;
132        }
133
134        public long getTriggerTimeMillis() {
135            return mTriggerAtMillis;
136        }
137    }
138
139    private class SetListenerAnswer extends AnswerWithArguments {
140        public void answer(int type, long triggerAtMillis, String tag,
141                AlarmManager.OnAlarmListener listener, Handler handler) {
142            mPendingAlarms.add(new PendingAlarm(type, triggerAtMillis, tag,
143                            new AlarmListenerRunnable(listener, handler)));
144        }
145    }
146
147    private class CancelListenerAnswer extends AnswerWithArguments {
148        public void answer(AlarmManager.OnAlarmListener listener) {
149            Iterator<PendingAlarm> alarmItr = mPendingAlarms.iterator();
150            while (alarmItr.hasNext()) {
151                PendingAlarm alarm = alarmItr.next();
152                if (alarm.getCallback() instanceof AlarmListenerRunnable) {
153                    AlarmListenerRunnable alarmCallback =
154                            (AlarmListenerRunnable) alarm.getCallback();
155                    if (alarmCallback.getListener() == listener) {
156                        alarmItr.remove();
157                    }
158                }
159            }
160        }
161    }
162
163    private static class AlarmListenerRunnable implements Runnable {
164        private final AlarmManager.OnAlarmListener mListener;
165        private final Handler mHandler;
166        public AlarmListenerRunnable(AlarmManager.OnAlarmListener listener, Handler handler) {
167            mListener = listener;
168            mHandler = handler;
169        }
170
171        public Handler getHandler() {
172            return mHandler;
173        }
174
175        public AlarmManager.OnAlarmListener getListener() {
176            return mListener;
177        }
178
179        public void run() {
180            if (mHandler != null) {
181                mHandler.post(new Runnable() {
182                        public void run() {
183                            mListener.onAlarm();
184                        }
185                    });
186            } else { // normally gets dispatched in main looper
187                mListener.onAlarm();
188            }
189        }
190    }
191}
192