141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills/*
241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * Copyright (C) 2015 The Android Open Source Project
341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills *
441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * Licensed under the Apache License, Version 2.0 (the "License");
541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * you may not use this file except in compliance with the License.
641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * You may obtain a copy of the License at
741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills *
841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills *      http://www.apache.org/licenses/LICENSE-2.0
941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills *
1041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * Unless required by applicable law or agreed to in writing, software
1141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * distributed under the License is distributed on an "AS IS" BASIS,
1241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * See the License for the specific language governing permissions and
1441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * limitations under the License.
1541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills */
1641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
1741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Willspackage com.android.server.wifi;
1841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
1972c639e8b97067e948eca8be50dfea3173121090Mitchell Willsimport static org.mockito.Mockito.any;
2072c639e8b97067e948eca8be50dfea3173121090Mitchell Willsimport static org.mockito.Mockito.anyInt;
2172c639e8b97067e948eca8be50dfea3173121090Mitchell Willsimport static org.mockito.Mockito.anyLong;
2272c639e8b97067e948eca8be50dfea3173121090Mitchell Willsimport static org.mockito.Mockito.anyString;
2372c639e8b97067e948eca8be50dfea3173121090Mitchell Willsimport static org.mockito.Mockito.doAnswer;
2472c639e8b97067e948eca8be50dfea3173121090Mitchell Willsimport static org.mockito.Mockito.mock;
2541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
2641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Willsimport android.app.AlarmManager;
2741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Willsimport android.os.Handler;
2841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
2994bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Willsimport com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
3041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
3141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Willsimport java.util.ArrayList;
3241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Willsimport java.util.Iterator;
3341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Willsimport java.util.List;
349d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Willsimport java.util.Objects;
3541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
3641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills/**
3741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * Creates an AlarmManager whose alarm dispatch can be controlled
3841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * Currently only supports alarm listeners
3941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills *
4041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * Alarm listeners will be dispatched to the handler provided or will
4141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * be dispatched imediatly if they would have been sent to the main
4241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills * looper (handler was null).
4341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills */
4441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Willspublic class MockAlarmManager {
4541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    private final AlarmManager mAlarmManager;
4641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    private final List<PendingAlarm> mPendingAlarms;
4741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
4841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    public MockAlarmManager() throws Exception {
4941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        mPendingAlarms = new ArrayList<>();
5041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
5141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        mAlarmManager = mock(AlarmManager.class);
5211d58263dc941e2ec644ea89de83725d3e1256e1Etan Cohen        doAnswer(new SetListenerAnswer()).when(mAlarmManager).set(anyInt(), anyLong(), anyString(),
5311d58263dc941e2ec644ea89de83725d3e1256e1Etan Cohen                any(AlarmManager.OnAlarmListener.class), any(Handler.class));
5411d58263dc941e2ec644ea89de83725d3e1256e1Etan Cohen        doAnswer(new SetListenerAnswer()).when(mAlarmManager).setExact(anyInt(), anyLong(),
5511d58263dc941e2ec644ea89de83725d3e1256e1Etan Cohen                anyString(), any(AlarmManager.OnAlarmListener.class), any(Handler.class));
5641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        doAnswer(new CancelListenerAnswer())
5741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                .when(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
5841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    }
5941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
6041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    public AlarmManager getAlarmManager() {
6141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        return mAlarmManager;
6241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    }
6341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
6441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    /**
659d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills     * Dispatch a pending alarm with the given tag
669d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills     * @return if any alarm was dispatched
6741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills     */
689d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills    public boolean dispatch(String tag) {
699d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills        for (int i = 0; i < mPendingAlarms.size(); ++i) {
709d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills            PendingAlarm alarm = mPendingAlarms.get(i);
719d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills            if (Objects.equals(tag, alarm.getTag())) {
729d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills                mPendingAlarms.remove(i);
739d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills                alarm.dispatch();
749d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills                return true;
759d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills            }
7641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        }
779d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills        return false;
7841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    }
7941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
8041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    /**
819d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills     * @return if an alarm with the given tag is pending
8241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills     */
839d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills    public boolean isPending(String tag) {
849d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills        for (int i = 0; i < mPendingAlarms.size(); ++i) {
859d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills            PendingAlarm alarm = mPendingAlarms.get(i);
869d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills            if (Objects.equals(tag, alarm.getTag())) {
879d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills                return true;
889d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills            }
899d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills        }
909d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills        return false;
9141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    }
9241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
93b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    /**
94b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     * @return trigger time of an pending alarm with the given tag
95b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     *         -1 if no pending alram with the given tag
96b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     */
97b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    public long getTriggerTimeMillis(String tag) {
98b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        for (int i = 0; i < mPendingAlarms.size(); ++i) {
99b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan            PendingAlarm alarm = mPendingAlarms.get(i);
100b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan            if (Objects.equals(tag, alarm.getTag())) {
101b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan                return alarm.getTriggerTimeMillis();
102b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan            }
103b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        }
104b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        return -1;
105b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    }
106b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
10741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    private static class PendingAlarm {
10841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        private final int mType;
10941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        private final long mTriggerAtMillis;
11041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        private final String mTag;
11141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        private final Runnable mCallback;
11241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
11341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        public PendingAlarm(int type, long triggerAtMillis, String tag, Runnable callback) {
11441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            mType = type;
11541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            mTriggerAtMillis = triggerAtMillis;
11641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            mTag = tag;
11741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            mCallback = callback;
11841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        }
11941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
12041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        public void dispatch() {
12141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            if (mCallback != null) {
12241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                mCallback.run();
12341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            }
12441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        }
12541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
12641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        public Runnable getCallback() {
12741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            return mCallback;
12841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        }
1299d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills
1309d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills        public String getTag() {
1319d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills            return mTag;
1329d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills        }
133b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
134b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        public long getTriggerTimeMillis() {
135b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan            return mTriggerAtMillis;
136b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        }
13741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    }
13841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
13979d691a718a3b8980f99940cbeae8d434c469858Mitchell Wills    private class SetListenerAnswer extends AnswerWithArguments {
14094bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills        public void answer(int type, long triggerAtMillis, String tag,
14194bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills                AlarmManager.OnAlarmListener listener, Handler handler) {
14241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            mPendingAlarms.add(new PendingAlarm(type, triggerAtMillis, tag,
14341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                            new AlarmListenerRunnable(listener, handler)));
14441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        }
14541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    }
14641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
14779d691a718a3b8980f99940cbeae8d434c469858Mitchell Wills    private class CancelListenerAnswer extends AnswerWithArguments {
14894bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills        public void answer(AlarmManager.OnAlarmListener listener) {
14941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            Iterator<PendingAlarm> alarmItr = mPendingAlarms.iterator();
15041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            while (alarmItr.hasNext()) {
15141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                PendingAlarm alarm = alarmItr.next();
15241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                if (alarm.getCallback() instanceof AlarmListenerRunnable) {
15341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                    AlarmListenerRunnable alarmCallback =
15441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                            (AlarmListenerRunnable) alarm.getCallback();
15541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                    if (alarmCallback.getListener() == listener) {
15641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                        alarmItr.remove();
15741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                    }
15841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                }
15941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            }
16041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        }
16141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    }
16241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
16341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    private static class AlarmListenerRunnable implements Runnable {
16441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        private final AlarmManager.OnAlarmListener mListener;
16541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        private final Handler mHandler;
16641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        public AlarmListenerRunnable(AlarmManager.OnAlarmListener listener, Handler handler) {
16741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            mListener = listener;
16841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            mHandler = handler;
16941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        }
17041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
17141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        public Handler getHandler() {
17241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            return mHandler;
17341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        }
17441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
17541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        public AlarmManager.OnAlarmListener getListener() {
17641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            return mListener;
17741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        }
17841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills
17941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        public void run() {
18041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            if (mHandler != null) {
18141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                mHandler.post(new Runnable() {
18241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                        public void run() {
18341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                            mListener.onAlarm();
18441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                        }
18541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                    });
18672c639e8b97067e948eca8be50dfea3173121090Mitchell Wills            } else { // normally gets dispatched in main looper
18741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills                mListener.onAlarm();
18841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills            }
18941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills        }
19041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills    }
19141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills}
192