/*
 * 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.externalservice.cts;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.externalservice.common.RunningServiceInfo;
import android.externalservice.common.ServiceMessages;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.Process;
import android.os.RemoteException;
import android.test.AndroidTestCase;
import android.util.Log;

public class ExternalServiceTest extends AndroidTestCase {
    private static final String TAG = "ExternalServiceTest";

    static final String sServicePackage = "android.externalservice.service";

    private Connection mConnection = new Connection();

    private ConditionVariable mCondition = new ConditionVariable(false);

    static final int CONDITION_TIMEOUT = 10 * 1000 /* 10 seconds */;

    public void tearDown() {
        if (mConnection.service != null)
            getContext().unbindService(mConnection);
    }

    /** Tests that an isolatedProcess service cannot be bound to by an external package. */
    public void testFailBindIsolated() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".IsolatedService"));
        try {
            getContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
            fail("Should not be able to bind to non-exported, non-external service");
        } catch (SecurityException e) {
        }
    }

    /** Tests that BIND_EXTERNAL_SERVICE does not work with plain isolatedProcess services. */
    public void testFailBindExternalIsolated() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".IsolatedService"));
        try {
            getContext().bindService(intent, mConnection,
                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE);
            fail("Should not be able to BIND_EXTERNAL_SERVICE to non-exported, non-external service");
        } catch (SecurityException e) {
        }
    }

    /** Tests that BIND_EXTERNAL_SERVICE does not work with exported, isolatedProcess services (
     * requires externalService as well). */
    public void testFailBindExternalExported() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExportedService"));
        try {
            getContext().bindService(intent, mConnection,
                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE);
            fail("Should not be able to BIND_EXTERNAL_SERVICE to non-external service");
        } catch (SecurityException e) {
        }
    }

    /** Tests that BIND_EXTERNAL_SERVICE requires that an externalService be exported. */
    public void testFailBindExternalNonExported() {
        Intent intent = new Intent();
        intent.setComponent(
                new ComponentName(sServicePackage, sServicePackage+".ExternalNonExportedService"));
        try {
            getContext().bindService(intent, mConnection,
                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE);
            fail("Should not be able to BIND_EXTERNAL_SERVICE to non-exported service");
        } catch (SecurityException e) {
        }
    }

    /** Tests that BIND_EXTERNAL_SERVICE requires the service be an isolatedProcess. */
    public void testFailBindExternalNonIsolated() {
        Intent intent = new Intent();
        intent.setComponent(
                new ComponentName(sServicePackage, sServicePackage+".ExternalNonIsolatedService"));
        try {
            getContext().bindService(intent, mConnection,
                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE);
            fail("Should not be able to BIND_EXTERNAL_SERVICE to non-isolated service");
        } catch (SecurityException e) {
        }
    }

    /** Tests that an externalService can only be bound with BIND_EXTERNAL_SERVICE. */
    public void testFailBindWithoutBindExternal() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExternalService"));
        try {
            getContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
            fail("Should not be able to bind to an external service without BIND_EXTERNAL_SERVICE");
        } catch (SecurityException e) {
        }
    }

    /** Tests that an external service can be bound, and that it runs as a different principal. */
    public void testBindExternalService() {
        // Start the service and wait for connection.
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExternalService"));

        mCondition.close();
        assertTrue(getContext().bindService(intent, mConnection,
                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE));

        assertTrue(mCondition.block(CONDITION_TIMEOUT));
        assertEquals(getContext().getPackageName(), mConnection.name.getPackageName());
        assertNotSame(sServicePackage, mConnection.name.getPackageName());

        // Check the identity of the service.
        Messenger remote = new Messenger(mConnection.service);
        RunningServiceInfo id = identifyService(remote);
        assertNotNull(id);

        assertFalse(id.uid == 0 || id.pid == 0);
        assertNotEquals(Process.myUid(), id.uid);
        assertNotEquals(Process.myPid(), id.pid);
        assertEquals(getContext().getPackageName(), id.packageName);
        assertEquals(-1, id.zygotePid);
    }

    /** Tests that the APK providing the externalService can bind the service itself, and that
     * other APKs bind to a different instance of it. */
    public void testBindExternalServiceWithRunningOwn() {
        // Start the service that will create the externalService.
        final Connection creatorConnection = new Connection();
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ServiceCreator"));

        mCondition.close();
        assertTrue(getContext().bindService(intent, creatorConnection, Context.BIND_AUTO_CREATE));
        assertTrue(mCondition.block(CONDITION_TIMEOUT));

        // Get the identity of the creator.
        Messenger remoteCreator = new Messenger(creatorConnection.service);
        RunningServiceInfo creatorId = identifyService(remoteCreator);
        assertNotNull(creatorId);
        assertFalse(creatorId.uid == 0 || creatorId.pid == 0);

        // Have the creator actually start its service.
        final Message creatorMsg =
                Message.obtain(null, ServiceMessages.MSG_CREATE_EXTERNAL_SERVICE);
        Handler creatorHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                Log.d(TAG, "Received message: " + msg);
                switch (msg.what) {
                    case ServiceMessages.MSG_CREATE_EXTERNAL_SERVICE_RESPONSE:
                        creatorMsg.copyFrom(msg);
                        mCondition.open();
                        break;
                }
                super.handleMessage(msg);
            }
        };
        Messenger localCreator = new Messenger(creatorHandler);
        creatorMsg.replyTo = localCreator;
        try {
            mCondition.close();
            remoteCreator.send(creatorMsg);
        } catch (RemoteException e) {
            fail("Unexpected remote exception" + e);
            return;
        }
        assertTrue(mCondition.block(CONDITION_TIMEOUT));

        // Get the connection to the creator's service.
        assertNotNull(creatorMsg.obj);
        Messenger remoteCreatorService = (Messenger) creatorMsg.obj;
        RunningServiceInfo creatorServiceId = identifyService(remoteCreatorService);
        assertNotNull(creatorServiceId);
        assertFalse(creatorServiceId.uid == 0 || creatorId.pid == 0);

        // Create an external service from this (the test) process.
        intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExternalService"));

        mCondition.close();
        assertTrue(getContext().bindService(intent, mConnection,
                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE));
        assertTrue(mCondition.block(CONDITION_TIMEOUT));
        RunningServiceInfo serviceId = identifyService(new Messenger(mConnection.service));
        assertNotNull(serviceId);
        assertFalse(serviceId.uid == 0 || serviceId.pid == 0);

        // Make sure that all the processes are unique.
        int myUid = Process.myUid();
        int myPid = Process.myPid();
        String myPkg = getContext().getPackageName();

        assertNotEquals(myUid, creatorId.uid);
        assertNotEquals(myUid, creatorServiceId.uid);
        assertNotEquals(myUid, serviceId.uid);
        assertNotEquals(myPid, creatorId.pid);
        assertNotEquals(myPid, creatorServiceId.pid);
        assertNotEquals(myPid, serviceId.pid);

        assertNotEquals(creatorId.uid, creatorServiceId.uid);
        assertNotEquals(creatorId.uid, serviceId.uid);
        assertNotEquals(creatorId.pid, creatorServiceId.pid);
        assertNotEquals(creatorId.pid, serviceId.pid);

        assertNotEquals(creatorServiceId.uid, serviceId.uid);
        assertNotEquals(creatorServiceId.pid, serviceId.pid);

        assertEquals(-1, creatorServiceId.zygotePid);
        assertEquals(-1, serviceId.zygotePid);
        assertNull(creatorServiceId.zygotePackage);
        assertNull(serviceId.zygotePackage);

        assertNotEquals(myPkg, creatorId.packageName);
        assertNotEquals(myPkg, creatorServiceId.packageName);
        assertEquals(creatorId.packageName, creatorServiceId.packageName);
        assertEquals(myPkg, serviceId.packageName);

        getContext().unbindService(creatorConnection);
    }

    /** Tests that the binding to an externalService can be changed. */
    public void testBindExternalAboveClient() {
        // Start the service and wait for connection.
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExternalService"));

        mCondition.close();
        Connection initialConn = new Connection();
        assertTrue(getContext().bindService(intent, initialConn,
                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE));

        assertTrue(mCondition.block(CONDITION_TIMEOUT));

        RunningServiceInfo idOne = identifyService(new Messenger(initialConn.service));
        assertNotNull(idOne);
        assertFalse(idOne.uid == 0 || idOne.pid == 0);

        // Bind the service with a different priority.
        mCondition.close();
        Connection prioConn = new Connection();
        assertTrue(getContext().bindService(intent, prioConn,
                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE |
                            Context.BIND_ABOVE_CLIENT));

        assertTrue(mCondition.block(CONDITION_TIMEOUT));

        RunningServiceInfo idTwo = identifyService(new Messenger(prioConn.service));
        assertNotNull(idTwo);
        assertFalse(idTwo.uid == 0 || idTwo.pid == 0);

        assertEquals(idOne.uid, idTwo.uid);
        assertEquals(idOne.pid, idTwo.pid);
        assertEquals(idOne.packageName, idTwo.packageName);
        assertNotEquals(Process.myUid(), idOne.uid);
        assertNotEquals(Process.myPid(), idOne.pid);
        assertEquals(getContext().getPackageName(), idOne.packageName);

        getContext().unbindService(prioConn);
        getContext().unbindService(initialConn);
    }

    /** Tests binding an externalService that is started by an app zygote. */
    public void testBindExternalServiceWithZygote() {
        // Start the service and wait for connection.
        Intent intent = new Intent();
        intent.setComponent(
                new ComponentName(sServicePackage, sServicePackage+".ExternalServiceWithZygote"));

        mCondition.close();
        assertTrue(getContext().bindService(intent, mConnection,
                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE));

        assertTrue(mCondition.block(CONDITION_TIMEOUT));
        assertEquals(getContext().getPackageName(), mConnection.name.getPackageName());
        assertNotSame(sServicePackage, mConnection.name.getPackageName());

        // Check the identity of the service.
        Messenger remote = new Messenger(mConnection.service);
        RunningServiceInfo id = identifyService(remote);
        assertNotNull(id);

        assertFalse(id.uid == 0 || id.pid == 0);
        assertNotEquals(Process.myUid(), id.uid);
        assertNotEquals(Process.myPid(), id.pid);
        assertEquals(getContext().getPackageName(), id.packageName);
        assertNotEquals(id.pid, id.zygotePid);
        assertNotEquals(Process.myPid(), id.zygotePid);
        assertNotEquals(-1, id.zygotePid);
        assertEquals(sServicePackage, id.zygotePackage);
    }

    /** Tests that an externalService that also is also useAppZygote=true shares the same
     * zygote, even when bound by different packages.. */
    public void testBindExternalServiceWithZygoteWithRunningOwn() {
        // Start the service that will create the externalService.
        final Connection creatorConnection = new Connection();
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ServiceCreator"));

        mCondition.close();
        assertTrue(getContext().bindService(intent, creatorConnection, Context.BIND_AUTO_CREATE));
        assertTrue(mCondition.block(CONDITION_TIMEOUT));

        // Have the creator actually start its service.
        Messenger remoteCreator = new Messenger(creatorConnection.service);
        final Message creatorMsg = Message.obtain(null, ServiceMessages.MSG_CREATE_EXTERNAL_SERVICE,
                        /* use zygote */ 1, 0);
        Handler creatorHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                Log.d(TAG, "Received message: " + msg);
                switch (msg.what) {
                    case ServiceMessages.MSG_CREATE_EXTERNAL_SERVICE_RESPONSE:
                        creatorMsg.copyFrom(msg);
                        mCondition.open();
                        break;
                }
                super.handleMessage(msg);
            }
        };
        Messenger localCreator = new Messenger(creatorHandler);
        creatorMsg.replyTo = localCreator;
        try {
            mCondition.close();
            remoteCreator.send(creatorMsg);
        } catch (RemoteException e) {
            fail("Unexpected remote exception" + e);
            return;
        }
        assertTrue(mCondition.block(CONDITION_TIMEOUT));

        // Get the connection to the creator's service.
        assertNotNull(creatorMsg.obj);
        Messenger remoteCreatorService = (Messenger) creatorMsg.obj;
        RunningServiceInfo creatorServiceId = identifyService(remoteCreatorService);
        assertNotNull(creatorServiceId);
        assertFalse(creatorServiceId.uid == 0);

        // Create an external service from this (the test) process.
        intent = new Intent();
        intent.setComponent(
                new ComponentName(sServicePackage, sServicePackage+".ExternalServiceWithZygote"));

        mCondition.close();
        assertTrue(getContext().bindService(intent, mConnection,
                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE));
        assertTrue(mCondition.block(CONDITION_TIMEOUT));
        RunningServiceInfo serviceId = identifyService(new Messenger(mConnection.service));
        assertNotNull(serviceId);
        assertFalse(serviceId.uid == 0 || serviceId.pid == 0);

        // Make sure that both services were started by the same zygote.
        assertNotEquals(-1, creatorServiceId.zygotePid);
        assertNotEquals(-1, serviceId.zygotePid);
        assertNotEquals(creatorServiceId.pid, creatorServiceId.zygotePid);
        assertNotEquals(serviceId.pid, serviceId.zygotePid);
        assertEquals(sServicePackage, creatorServiceId.zygotePackage);
        assertEquals(sServicePackage, serviceId.zygotePackage);
        assertEquals(creatorServiceId.zygotePid, serviceId.zygotePid);

        int myUid = Process.myUid();
        int myPid = Process.myPid();
        String myPkg = getContext().getPackageName();

        assertNotEquals(myUid, creatorServiceId.uid);
        assertNotEquals(myUid, serviceId.uid);
        assertNotEquals(myPid, creatorServiceId.pid);
        assertNotEquals(myPid, serviceId.pid);

        assertNotEquals(creatorServiceId.uid, serviceId.uid);
        assertNotEquals(creatorServiceId.pid, serviceId.pid);

        assertNotEquals(myPkg, creatorServiceId.packageName);
        assertEquals(myPkg, serviceId.packageName);

        getContext().unbindService(creatorConnection);
    }

    /**
     * Test when the flag BIND_EXTERNAL_SERVICE(0x80000000) is set in 64 bits long flags,
     * an IllegalArgumentException is thrown. The reason is that integer 0x80000000 is
     * automatically converted to long 0xffff_ffff_8000_000, it is not a correct flag any more.
     * In 64 bits long flags, use BIND_EXTERNAL_SERVICE_LONG(0x4000_0000_0000_0000L) instead.
     */
    public void testFailBindExternalServiceLongFlags() {
        // Start the service and wait for connection.
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExternalService"));

        mCondition.close();

        long longFlags = Context.BIND_EXTERNAL_SERVICE | Context.BIND_AUTO_CREATE;
        try {
            getContext().bindService(intent, mConnection,
                    Context.BindServiceFlags.of(longFlags)/* 64 bits long flag */);
            fail("Context.BIND_EXTERNAL_SERVICE can not be used in 64 bits bindService() flags");
        } catch (IllegalArgumentException e) {
            // expect an IllegalArgumentException when BIND_EXTERNAL_SERVICE is used in 64 bits
            // flags.
        }
    }

    /**
     * Test 64 bits long flag BIND_EXTERNAL_SERVICE_LONG(0x4000_0000_0000_0000L), it deprecates
     * 32 bits flag BIND_EXTERNAL_SERVICE(0x80000000) when 64 bits long flags is used.
     */
    public void testBindExternalServiceLongFlags() {
        // Start the service and wait for connection.
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExternalService"));

        mCondition.close();

        long longFlags = Context.BIND_EXTERNAL_SERVICE_LONG | Context.BIND_AUTO_CREATE;

        assertTrue(getContext().bindService(intent, mConnection,
                Context.BindServiceFlags.of(longFlags)/* 64 bits long flag */));
        assertTrue(mCondition.block(CONDITION_TIMEOUT));
        assertEquals(getContext().getPackageName(), mConnection.name.getPackageName());
        assertNotSame(sServicePackage, mConnection.name.getPackageName());
    }

    /** Given a Messenger, this will message the service to retrieve its UID, PID, and package name.
     * On success, returns a RunningServiceInfo. On failure, returns null. */
    private RunningServiceInfo identifyService(Messenger service) {
        try {
            return RunningServiceInfo.identifyService(service, TAG, mCondition);
        } catch (RemoteException e) {
            fail("Unexpected remote exception: " + e);
            return null;
        }
    }

    private class Connection implements ServiceConnection {
        IBinder service = null;
        ComponentName name = null;
        boolean disconnected = false;

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected " + name);
            this.service = service;
            this.name = name;
            mCondition.open();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected " + name);
        }
    }

    private <T> void assertNotEquals(T expected, T actual) {
        assertFalse("Expected <" + expected + "> should not be equal to actual <" + actual + ">",
                expected.equals(actual));
    }
}
