/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app.cts;


import android.app.AlarmManager;
import android.app.AlarmManager.AlarmClockInfo;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.cts.util.PollingCheck;
import android.os.Build;
import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.util.Log;
import android.test.MoreAsserts;

public class AlarmManagerTest extends AndroidTestCase {
    public static final String MOCKACTION = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER";
    public static final String MOCKACTION2 = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER2";

    private AlarmManager mAm;
    private Intent mIntent;
    private PendingIntent mSender;
    private Intent mIntent2;
    private PendingIntent mSender2;

    /*
     *  The default snooze delay: 5 seconds
     */
    private static final long SNOOZE_DELAY = 5 * 1000L;
    private long mWakeupTime;
    private MockAlarmReceiver mMockAlarmReceiver;
    private MockAlarmReceiver mMockAlarmReceiver2;

    private static final int TIME_DELTA = 1000;
    private static final int TIME_DELAY = 10000;
    private static final int REPEAT_PERIOD = 60000;

    // Receiver registration/unregistration between tests races with the system process, so
    // we add a little buffer time here to allow the system to process before we proceed.
    // This value is in milliseconds.
    private static final long REGISTER_PAUSE = 250;

    // Constants used for validating exact vs inexact alarm batching immunity.  We run a few
    // trials of an exact alarm that is placed within an inexact alarm's window of opportunity,
    // and mandate that the average observed delivery skew between the two be statistically
    // significant -- i.e. that the two alarms are not being coalesced.  We also place an
    // additional exact alarm only a short time after the inexact alarm's nominal trigger time.
    // If exact alarms are allowed to batch with inexact ones this will tend to have no effect,
    // but in the correct behavior -- inexact alarms not permitted to batch with exact ones --
    // this additional exact alarm will have the effect of guaranteeing that the inexact alarm
    // must fire no later than it -- i.e. a considerable time before the significant, later
    // exact alarm.
    //
    // The test essentially amounts to requiring that the inexact MOCKACTION alarm and
    // the much later exact MOCKACTION2 alarm fire far apart, always; with an implicit
    // insistence that alarm batches are delivered at the head of their window.
    private static final long TEST_WINDOW_LENGTH = 5 * 1000L;
    private static final long TEST_ALARM_FUTURITY = 6 * 1000L;
    private static final long FAIL_DELTA = 50;
    private static final long NUM_TRIALS = 5;
    private static final long MAX_NEAR_DELIVERIES = 2;

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        mAm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

        mIntent = new Intent(MOCKACTION)
                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        mSender = PendingIntent.getBroadcast(mContext, 0, mIntent, 0);
        mMockAlarmReceiver = new MockAlarmReceiver(mIntent.getAction());

        mIntent2 = new Intent(MOCKACTION2)
                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        mSender2 = PendingIntent.getBroadcast(mContext, 0, mIntent2, 0);
        mMockAlarmReceiver2 = new MockAlarmReceiver(mIntent2.getAction());

        IntentFilter filter = new IntentFilter(mIntent.getAction());
        mContext.registerReceiver(mMockAlarmReceiver, filter);

        IntentFilter filter2 = new IntentFilter(mIntent2.getAction());
        mContext.registerReceiver(mMockAlarmReceiver2, filter2);

        Thread.sleep(REGISTER_PAUSE);
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        mContext.unregisterReceiver(mMockAlarmReceiver);
        mContext.unregisterReceiver(mMockAlarmReceiver2);

        Thread.sleep(REGISTER_PAUSE);
    }

    public void testSetTypes() throws Exception {
        // TODO: try to find a way to make device sleep then test whether
        // AlarmManager perform the expected way

        // test parameter type is RTC_WAKEUP
        mMockAlarmReceiver.setAlarmedFalse();
        mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
        mAm.setExact(AlarmManager.RTC_WAKEUP, mWakeupTime, mSender);
        new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
            @Override
            protected boolean check() {
                return mMockAlarmReceiver.alarmed;
            }
        }.run();
        assertEquals(mMockAlarmReceiver.rtcTime, mWakeupTime, TIME_DELTA);

        // test parameter type is RTC
        mMockAlarmReceiver.setAlarmedFalse();
        mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
        mAm.setExact(AlarmManager.RTC, mWakeupTime, mSender);
        new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
            @Override
            protected boolean check() {
                return mMockAlarmReceiver.alarmed;
            }
        }.run();
        assertEquals(mMockAlarmReceiver.rtcTime, mWakeupTime, TIME_DELTA);

        // test parameter type is ELAPSED_REALTIME
        mMockAlarmReceiver.setAlarmedFalse();
        mWakeupTime = SystemClock.elapsedRealtime() + SNOOZE_DELAY;
        mAm.setExact(AlarmManager.ELAPSED_REALTIME, mWakeupTime, mSender);
        new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
            @Override
            protected boolean check() {
                return mMockAlarmReceiver.alarmed;
            }
        }.run();
        assertEquals(mMockAlarmReceiver.elapsedTime, mWakeupTime, TIME_DELTA);

        // test parameter type is ELAPSED_REALTIME_WAKEUP
        mMockAlarmReceiver.setAlarmedFalse();
        mWakeupTime = SystemClock.elapsedRealtime() + SNOOZE_DELAY;
        mAm.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, mWakeupTime, mSender);
        new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
            @Override
            protected boolean check() {
                return mMockAlarmReceiver.alarmed;
            }
        }.run();
        assertEquals(mMockAlarmReceiver.elapsedTime, mWakeupTime, TIME_DELTA);
    }

    public void testAlarmTriggersImmediatelyIfSetTimeIsNegative() throws Exception {
        // An alarm with a negative wakeup time should be triggered immediately.
        // This exercises a workaround for a limitation of the /dev/alarm driver
        // that would instead cause such alarms to never be triggered.
        mMockAlarmReceiver.setAlarmedFalse();
        mWakeupTime = -1000;
        mAm.set(AlarmManager.RTC, mWakeupTime, mSender);
        new PollingCheck(TIME_DELAY) {
            @Override
            protected boolean check() {
                return mMockAlarmReceiver.alarmed;
            }
        }.run();
    }

    public void testExactAlarmBatching() throws Exception {
        int deliveriesTogether = 0;
        for (int i = 0; i < NUM_TRIALS; i++) {
            final long now = System.currentTimeMillis();
            final long windowStart = now + TEST_ALARM_FUTURITY;
            final long exactStart = windowStart + TEST_WINDOW_LENGTH - 1;

            mMockAlarmReceiver.setAlarmedFalse();
            mMockAlarmReceiver2.setAlarmedFalse();
            mAm.setWindow(AlarmManager.RTC_WAKEUP, windowStart, TEST_WINDOW_LENGTH, mSender);
            mAm.setExact(AlarmManager.RTC_WAKEUP, exactStart, mSender2);

            // Wait until a half-second beyond its target window, just to provide a
            // little safety slop.
            new PollingCheck(TEST_WINDOW_LENGTH + (windowStart - now) + 500) {
                @Override
                protected boolean check() {
                    return mMockAlarmReceiver.alarmed;
                }
            }.run();

            // Now wait until 1 sec beyond the expected exact alarm fire time, or for at
            // least one second if we're already past the nominal exact alarm fire time
            long timeToExact = Math.max(exactStart - System.currentTimeMillis() + 1000, 1000);
            new PollingCheck(timeToExact) {
                @Override
                protected boolean check() {
                    return mMockAlarmReceiver2.alarmed;
                }
            }.run();

            // Success when we observe that the exact and windowed alarm are not being often
            // delivered close together -- that is, when we can be confident that they are not
            // being coalesced.
            final long delta = Math.abs(mMockAlarmReceiver2.rtcTime - mMockAlarmReceiver.rtcTime);
            Log.i("TEST", "[" + i + "]  delta = " + delta);
            if (delta < FAIL_DELTA) {
                deliveriesTogether++;
                assertTrue("Exact alarms appear to be coalescing with inexact alarms",
                        deliveriesTogether <= MAX_NEAR_DELIVERIES);
            }
        }
    }

    public void testSetRepeating() throws Exception {
        mMockAlarmReceiver.setAlarmedFalse();
        mWakeupTime = System.currentTimeMillis() + TEST_ALARM_FUTURITY;
        mAm.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, REPEAT_PERIOD, mSender);

        // wait beyond the initial alarm's possible delivery window to verify that it fires the first time
        new PollingCheck(TEST_ALARM_FUTURITY + REPEAT_PERIOD) {
            @Override
            protected boolean check() {
                return mMockAlarmReceiver.alarmed;
            }
        }.run();
        assertTrue(mMockAlarmReceiver.alarmed);

        // Now reset the receiver and wait for the intended repeat alarm to fire as expected
        mMockAlarmReceiver.setAlarmedFalse();
        new PollingCheck(REPEAT_PERIOD*2) {
            @Override
            protected boolean check() {
                return mMockAlarmReceiver.alarmed;
            }
        }.run();
        assertTrue(mMockAlarmReceiver.alarmed);

        mAm.cancel(mSender);
    }

    public void testCancel() throws Exception {
        mMockAlarmReceiver.setAlarmedFalse();
        mMockAlarmReceiver2.setAlarmedFalse();

        // set two alarms
        final long when1 = System.currentTimeMillis() + TEST_ALARM_FUTURITY;
        mAm.setExact(AlarmManager.RTC_WAKEUP, when1, mSender);
        final long when2 = when1 + TIME_DELTA; // will fire after when1's target time
        mAm.setExact(AlarmManager.RTC_WAKEUP, when2, mSender2);

        // cancel the earlier one
        mAm.cancel(mSender);

        // and verify that only the later one fired
        new PollingCheck(TIME_DELAY) {
            @Override
            protected boolean check() {
                return mMockAlarmReceiver2.alarmed;
            }
        }.run();

        assertFalse(mMockAlarmReceiver.alarmed);
        assertTrue(mMockAlarmReceiver2.alarmed);
    }

    public void testSetInexactRepeating() throws Exception {
        mAm.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
                AlarmManager.INTERVAL_FIFTEEN_MINUTES, mSender);
        SystemClock.setCurrentTimeMillis(System.currentTimeMillis()
                + AlarmManager.INTERVAL_FIFTEEN_MINUTES);
        // currently there is no way to write Android system clock. When try to
        // write the system time, there will be log as
        // " Unable to open alarm driver: Permission denied". But still fail
        // after tried many permission.
    }

    public void testSetAlarmClock() throws Exception {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mMockAlarmReceiver.setAlarmedFalse();
            mMockAlarmReceiver2.setAlarmedFalse();

            // Set first alarm clock.
            final long wakeupTimeFirst = System.currentTimeMillis()
                    + 2 * TEST_ALARM_FUTURITY;
            mAm.setAlarmClock(new AlarmClockInfo(wakeupTimeFirst, null), mSender);

            // Verify getNextAlarmClock returns first alarm clock.
            AlarmClockInfo nextAlarmClock = mAm.getNextAlarmClock();
            assertEquals(wakeupTimeFirst, nextAlarmClock.getTriggerTime());
            assertNull(nextAlarmClock.getShowIntent());

            // Set second alarm clock, earlier than first.
            final long wakeupTimeSecond = System.currentTimeMillis()
                    + TEST_ALARM_FUTURITY;
            PendingIntent showIntentSecond = PendingIntent.getBroadcast(getContext(), 0,
                    new Intent(getContext(), AlarmManagerTest.class).setAction("SHOW_INTENT"), 0);
            mAm.setAlarmClock(new AlarmClockInfo(wakeupTimeSecond, showIntentSecond),
                    mSender2);

            // Verify getNextAlarmClock returns second alarm clock now.
            nextAlarmClock = mAm.getNextAlarmClock();
            assertEquals(wakeupTimeSecond, nextAlarmClock.getTriggerTime());
            assertEquals(showIntentSecond, nextAlarmClock.getShowIntent());

            // Cancel second alarm.
            mAm.cancel(mSender2);

            // Verify getNextAlarmClock returns first alarm clock again.
            nextAlarmClock = mAm.getNextAlarmClock();
            assertEquals(wakeupTimeFirst, nextAlarmClock.getTriggerTime());
            assertNull(nextAlarmClock.getShowIntent());

            // Wait for first alarm to trigger.
            assertFalse(mMockAlarmReceiver.alarmed);
            new PollingCheck(2 * TEST_ALARM_FUTURITY + TIME_DELAY) {
                @Override
                protected boolean check() {
                    return mMockAlarmReceiver.alarmed;
                }
            }.run();

            // Verify first alarm fired at the right time.
            assertEquals(mMockAlarmReceiver.rtcTime, wakeupTimeFirst, TIME_DELTA);

            // Verify second alarm didn't fire.
            assertFalse(mMockAlarmReceiver2.alarmed);

            // Verify the next alarm is not returning neither the first nor the second alarm.
            nextAlarmClock = mAm.getNextAlarmClock();
            MoreAsserts.assertNotEqual(wakeupTimeFirst, nextAlarmClock != null
                    ? nextAlarmClock.getTriggerTime()
                    : null);
            MoreAsserts.assertNotEqual(wakeupTimeSecond, nextAlarmClock != null
                    ? nextAlarmClock.getTriggerTime()
                    : null);
        }
    }
}
