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