All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.joynr.android.binder.BinderService Maven / Gradle / Ivy

/*-
 * #%L
 * %%
 * Copyright (C) 2019 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */
package io.joynr.android.binder;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;

import com.google.inject.Injector;
import com.google.inject.Key;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import io.joynr.android.AndroidBinderRuntime;
import io.joynr.android.messaging.binder.JoynrBinder;
import io.joynr.messaging.JoynrMessageProcessor;
import io.joynr.messaging.routing.MessageRouter;
import joynr.ImmutableMessage;

/**
 * Android service used by {@link AndroidBinderRuntime} to communicate between instances using joynr
 * on Android.
 */
public class BinderService extends Service {
    private static final Logger logger = LoggerFactory.getLogger(BinderService.class);
    private static final long DELAY_MILLISECOND_FOR_RETRY_CHECK_CC = 1000L;
    private static final int MESSAGE_WHAT = 0;

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    private List messagesWaitingProcessing = new ArrayList();

    private final JoynrBinder.Stub binder = new JoynrBinder.Stub() {
        @Override
        public void transmit(byte[] serializedMessage) {

            try {
                ImmutableMessage message = new ImmutableMessage(serializedMessage);

                logger.debug("BinderService <<< INCOMING <<<< {}", message);
                Injector injector = AndroidBinderRuntime.getInjector();
                if (injector != null) {
                    processMessage(injector, message);
                } else {
                    messagesWaitingProcessing.add(message);
                    removeAndSendMessageDelayedToHandler();
                }

            } catch (Exception error) {
                logger.error("BinderService transmit message not processed: {}", error.getMessage());
            }
        }
    };

    /**
     * Process's a message passed as parameter sending it to the message processors
     * available in the guice injector.
     * @param injector the guice injector being used
     * @param message the message that you want to process
     */
    private void processMessage(Injector injector, ImmutableMessage message) {

        Set messageProcessors = injector.getInstance(new Key>() {
        });
        if (messageProcessors != null) {
            for (JoynrMessageProcessor processor : messageProcessors) {
                message = processor.processIncoming(message);
            }
        }

        message.setReceivedFromGlobal(true);

        MessageRouter messageRouter = AndroidBinderRuntime.getInjector().getInstance(MessageRouter.class);

        messageRouter.routeIn(message);
    }

    /**
     * Handler responsible for checking if the guice injector used by the joynr runtime
     * gets available so that messages received before the runtime gets initialized are processed.
     */
    private Handler checkInjectorRuntimeAvailabilityHandler = new Handler(Looper.getMainLooper()) {

        @Override
        public void handleMessage(android.os.Message msg) {

            try {
                Injector injector = AndroidBinderRuntime.getInjector();
                if (injector != null) {
                    messagesWaitingProcessing.forEach(immutableMessage -> {
                        processMessage(injector, immutableMessage);
                    });
                    messagesWaitingProcessing.clear();
                    logger.debug("BinderService Runtime available. Processing {} messages", messagesWaitingProcessing.size());
                } else {
                    logger.debug("BinderService Runtime not available. Checking again in 1 second...");
                    removeAndSendMessageDelayedToHandler();
                }
            } catch (Exception error) {
                logger.error("BinderService handleMessage message not processed: {}", error.getMessage());
            }
        }
    };

    /**
     * Helper function that removes possible messages waiting to be processed in the handler
     * and send a new fresh message delayed so that we can have only one message to be processed
     * in the queue.
     */
    private void removeAndSendMessageDelayedToHandler() {
        checkInjectorRuntimeAvailabilityHandler.removeMessages(MESSAGE_WHAT);
        checkInjectorRuntimeAvailabilityHandler.sendEmptyMessageDelayed(MESSAGE_WHAT, DELAY_MILLISECOND_FOR_RETRY_CHECK_CC);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy