/* * Copyright (c) 2010-2019 Belledonne Communications SARL. * * This file is part of linphone-android * (see https://www.linphone.org). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package org.linphone.service; import android.app.Application; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.view.WindowManager; import org.linphone.LinphoneContext; import org.linphone.LinphoneManager; import org.linphone.R; import org.linphone.call.views.LinphoneGL2JNIViewOverlay; import org.linphone.call.views.LinphoneOverlay; import org.linphone.call.views.LinphoneTextureViewOverlay; import org.linphone.core.Call; import org.linphone.core.Core; import org.linphone.core.tools.Log; import org.linphone.mediastream.Version; import org.linphone.settings.LinphonePreferences; public final class LinphoneService extends Service { private static LinphoneService sInstance; private LinphoneOverlay mOverlay; private WindowManager mWindowManager; private Application.ActivityLifecycleCallbacks mActivityCallbacks; private boolean misLinphoneContextOwned; @SuppressWarnings("unchecked") @Override public void onCreate() { super.onCreate(); setupActivityMonitor(); misLinphoneContextOwned = false; if (!LinphoneContext.isReady()) { new LinphoneContext(getApplicationContext()); misLinphoneContextOwned = true; } Log.i("[Service] Created"); mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); } @Override public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); boolean isPush = false; if (intent != null && intent.getBooleanExtra("PushNotification", false)) { Log.i("[Service] [Push Notification] LinphoneService started because of a push"); isPush = true; } if (sInstance != null) { Log.w("[Service] Attempt to start the LinphoneService but it is already running !"); return START_STICKY; } sInstance = this; if (LinphonePreferences.instance().getServiceNotificationVisibility() || (Version.sdkAboveOrEqual(Version.API26_O_80) && intent != null && intent.getBooleanExtra("ForceStartForeground", false))) { Log.i("[Service] Background service mode enabled, displaying notification"); // We need to call this asap after the Service can be accessed through it's singleton LinphoneContext.instance().getNotificationManager().startForeground(); } if (misLinphoneContextOwned) { LinphoneContext.instance().start(isPush); } else { LinphoneContext.instance().updateContext(this); } Log.i("[Service] Started"); return START_STICKY; } @Override public void onTaskRemoved(Intent rootIntent) { boolean serviceNotif = LinphonePreferences.instance().getServiceNotificationVisibility(); if (serviceNotif) { Log.i("[Service] Service is running in foreground, don't stop it"); } else if (getResources().getBoolean(R.bool.kill_service_with_task_manager)) { Log.i("[Service] Task removed, stop service"); Core core = LinphoneManager.getCore(); if (core != null) { core.terminateAllCalls(); } // If push is enabled, don't unregister account, otherwise do unregister if (LinphonePreferences.instance().isPushNotificationEnabled()) { if (core != null) core.setNetworkReachable(false); } stopSelf(); } super.onTaskRemoved(rootIntent); } @SuppressWarnings("UnusedAssignment") @Override public synchronized void onDestroy() { Log.i("[Service] Destroying"); if (mActivityCallbacks != null) { getApplication().unregisterActivityLifecycleCallbacks(mActivityCallbacks); mActivityCallbacks = null; } destroyOverlay(); LinphoneContext.instance().destroy(); sInstance = null; super.onDestroy(); } @Override public IBinder onBind(Intent intent) { return null; } public static boolean isReady() { return sInstance != null; } public static LinphoneService instance() { if (isReady()) return sInstance; throw new RuntimeException("LinphoneService not instantiated yet"); } /* Managers accessors */ public void createOverlay() { Log.i("[Service] Creating video overlay"); if (mOverlay != null) destroyOverlay(); Core core = LinphoneManager.getCore(); Call call = core.getCurrentCall(); if (call == null || !call.getCurrentParams().videoEnabled()) return; if ("MSAndroidOpenGLDisplay".equals(core.getVideoDisplayFilter())) { mOverlay = new LinphoneGL2JNIViewOverlay(this); } else { mOverlay = new LinphoneTextureViewOverlay(this); } WindowManager.LayoutParams params = mOverlay.getWindowManagerLayoutParams(); params.x = 0; params.y = 0; mOverlay.addToWindowManager(mWindowManager, params); } public void destroyOverlay() { Log.i("[Service] Destroying video overlay"); if (mOverlay != null) { mOverlay.removeFromWindowManager(mWindowManager); mOverlay.destroy(); } mOverlay = null; } private void setupActivityMonitor() { if (mActivityCallbacks != null) return; getApplication() .registerActivityLifecycleCallbacks(mActivityCallbacks = new ActivityMonitor()); } }