/*
 * Copyright (C) 2016 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.cts;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import java.io.IOException;
import java.nio.channels.FileLock;

/**
 * A Service that listens for commands from the FileChannelInterProcessLockTest to acquire locks of
 * different types. It exists to test the behavior when file locks are acquired/released across
 * multiple processes.
 */
public class LockHoldingService extends Service {

    /**
     *  The key of the Bundle extra used to record a time after a lock is released by the service.
     */
    static final String LOCK_DEFINITELY_RELEASED_TIMESTAMP = "lockReleasedTimestamp";

    /**
     * The key of the Bundle extra used to record just before the lock is released by the service.
     */
    static final String LOCK_NOT_YET_RELEASED_TIMESTAMP = "lockNotReleasedTimestamp";

    /**
     * The key of the Bundle extra used to send general notifications to the test.
     */
    static final String NOTIFICATION_KEY = "notification";

    /**
     * The value for the notification sent to the test after the service starts.
     */
    static final String NOTIFICATION_START = "onStart";

    /**
     * The value for the notification sent to the test just before the service stops.
     */
    static final String NOTIFICATION_STOP = "onStop";

    /**
     * The value for the notification sent to the test after the lock is acquired.
     */
    static final String NOTIFICATION_LOCK_HELD = "lockHeld";

    /**
     * The value for the notification sent to the test after the lock is released
     */
    static final String NOTIFICATION_LOCK_RELEASED = "lockReleased";

    /**
     * The key of the Bundle extra used to send time for which the service should wait before
     * releasing the lock.
     */
    static final String TIME_TO_HOLD_LOCK_KEY = "timeToHoldLock";

    /**
     * The key of the Bundle extra used for the type of lock to be held.
     */
    static final String LOCK_TYPE_KEY = "lockType";

    /**
     * The key of the Bundle extra used to let he service know whether to release the lock after
     * some time.
     */
    static final String LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY = "releaseAndNotify";

    static final String ACTION_TYPE_FOR_INTENT_COMMUNICATION
            = "android.cts.CtsLibcoreFileIOTestCases";

    final String LOG_MESSAGE_TAG = "CtsLibcoreFileIOTestCases";

    private FileLock fileLock = null;

    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startID) {
        try {
            if (intent.getBooleanExtra(LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY, false)) {
                acquireLockAndThenWaitThenRelease(intent);
            } else {
                acquireLock(intent);
            }
        } catch (Exception e) {
            Log.e(LOG_MESSAGE_TAG, e.getMessage());
        }
        return START_STICKY;
    }

    /**
     * Acquires the lock asked by the test indefinitely.
     */
    private void acquireLock(Intent intent) throws IOException {
        FileChannelInterProcessLockTest.LockType lockType =
                (FileChannelInterProcessLockTest.LockType)intent.getSerializableExtra(
                        LOCK_TYPE_KEY);

        // Acquire the lock based on the information contained in the intent received.
        this.fileLock = FileChannelInterProcessLockTest.acquire(lockType);
        Intent responseIntent = new Intent().putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_HELD)
                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
        sendBroadcast(responseIntent);
    }

    /**
     * Acquires and holds the lock for a time specified by the test. Sends a broadcast message after
     * releasing the lock.
     */
    private void acquireLockAndThenWaitThenRelease(Intent intent)
            throws IOException, InterruptedException {
        long lockHoldTimeMillis = intent.getLongExtra(TIME_TO_HOLD_LOCK_KEY, 0);

        // Acquire the lock.
        FileChannelInterProcessLockTest.LockType lockType =
                (FileChannelInterProcessLockTest.LockType)intent.getSerializableExtra(
                        LOCK_TYPE_KEY);
        this.fileLock = FileChannelInterProcessLockTest.acquire(lockType);

        // Signal the lock is now held.
        Intent heldIntent = new Intent()
                .putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_HELD)
                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
        sendBroadcast(heldIntent);

        Thread.sleep(lockHoldTimeMillis);

        long lockNotReleasedTimestamp = System.currentTimeMillis();

        // Release the lock
        fileLock.release();

        long lockReleasedTimestamp = System.currentTimeMillis();

        // Signal the lock is released and some information about timing.
        Intent releaseIntent = new Intent()
                .putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_RELEASED)
                .putExtra(LOCK_NOT_YET_RELEASED_TIMESTAMP, lockNotReleasedTimestamp)
                .putExtra(LOCK_DEFINITELY_RELEASED_TIMESTAMP, lockReleasedTimestamp)
                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
        sendBroadcast(releaseIntent);
    }

    @Override
    public void onDestroy() {
        try {
            if (fileLock != null) {
                fileLock.release();
            }
        } catch (IOException e) {
            Log.e(LOG_MESSAGE_TAG, e.getMessage());
        }
        Intent intent = new Intent().putExtra(NOTIFICATION_KEY, NOTIFICATION_STOP)
                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
        sendBroadcast(intent);
    }
}
