Commit c7474520 authored by Sylvain Berfini's avatar Sylvain Berfini 🎩
Browse files

Handle vibration for incoming call for Android in CoreService

parent ea322217
......@@ -10,6 +10,9 @@ This changelog file was started on October 2019. Previous changes were more or l
## [5.0.0] Unreleased
### Added
- CoreService class for Android can make the device vibrate while incoming call is ringing.
### Changed
- Java wrapper now creates a separated managed object for const native pointers and print an error log when trying to use a non-const method on it.
- Java & C# wrapper now takes a strong reference on listeners, allowing to use inner classes & lambda expressions even without keeping parent object around.
......
......@@ -2729,6 +2729,15 @@ bool_t linphone_core_is_auto_iterate_enabled(LinphoneCore *core) {
return core->auto_iterate_enabled;
}
void linphone_core_set_vibration_on_incoming_call_enabled(LinphoneCore *core, bool_t enable) {
linphone_config_set_int(core->config, "misc", "vibrate_on_incoming_call", enable);
core->vibrate_on_incoming_call = enable;
}
bool_t linphone_core_is_vibration_on_incoming_call_enabled(LinphoneCore *core) {
return core->vibrate_on_incoming_call;
}
static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig *config, void * userdata, void *system_context, bool_t automatically_start) {
LinphoneFactory *lfactory = linphone_factory_get();
LinphoneCoreCbs *internal_cbs = _linphone_core_cbs_new();
......@@ -2756,12 +2765,17 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig
bool_t push_notification_default = FALSE;
bool_t auto_iterate_default = FALSE;
bool_t vibration_incoming_call_default = FALSE;
#if __ANDROID__ || TARGET_OS_IPHONE
push_notification_default = TRUE;
auto_iterate_default = TRUE;
#endif
#if __ANDROID__
vibration_incoming_call_default = TRUE;
#endif
lc->push_notification_enabled = !!linphone_config_get_int(lc->config, "net", "push_notification", push_notification_default);
lc->auto_iterate_enabled = !!linphone_config_get_int(lc->config, "misc", "auto_iterate", auto_iterate_default);
lc->vibrate_on_incoming_call = !!linphone_config_get_int(lc->config, "misc", "vibrate_on_incoming_call", vibration_incoming_call_default);
lc->push_config = linphone_push_notification_config_new();
......
......@@ -812,7 +812,8 @@ namespace LinphonePrivate {
bool_t is_unreffing; \
bool_t push_notification_enabled; \
bool_t auto_iterate_enabled; \
bool_t native_ringing_enabled;\
bool_t native_ringing_enabled; \
bool_t vibrate_on_incoming_call; \
......
......@@ -5499,6 +5499,22 @@ LINPHONE_PUBLIC void linphone_core_set_auto_iterate_enabled(LinphoneCore *core,
*/
LINPHONE_PUBLIC bool_t linphone_core_is_auto_iterate_enabled(LinphoneCore *core);
/**
* Enable vibration will incoming call is ringing (Android only).
* @param core The #LinphoneCore @notnil
* @return TRUE if the device should vibrate while an incoming call is ringing, FALSE otherwise
* @ingroup misc
*/
LINPHONE_PUBLIC void linphone_core_set_vibration_on_incoming_call_enabled(LinphoneCore *core, bool_t enable);
/**
* Gets whether the device will vibrate while an incoming call is ringing (Android only).
* @param core The #LinphoneCore @notnil
* @return TRUE if the device will vibrate (if possible), FALSE otherwise
* @ingroup misc
*/
LINPHONE_PUBLIC bool_t linphone_core_is_vibration_on_incoming_call_enabled(LinphoneCore *core);
/**
* Returns a list of audio devices, with only the first device for each type
* To have the list of all audio devices, use #linphone_core_get_extended_audio_devices()
......
......@@ -21,6 +21,7 @@ package org.linphone.core.tools.compatibility;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.os.Vibrator;
import org.linphone.mediastream.Version;
......@@ -65,4 +66,12 @@ public class DeviceUtils {
DeviceUtils30.logPreviousCrashesIfAny(context);
}
}
public static void vibrate(Vibrator vibrator) {
if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
DeviceUtils26.vibrate(vibrator);
} else {
DeviceUtils23.vibrate(vibrator);
}
}
}
......@@ -21,6 +21,7 @@ package org.linphone.core.tools.compatibility;
import android.content.Context;
import android.os.PowerManager;
import android.os.Vibrator;
import org.linphone.core.tools.Log;
......@@ -31,4 +32,9 @@ public class DeviceUtils23 {
Log.i("[Platform Helper] Is app in device battery optimization whitelist: " + ignoringBatteryOptimizations);
return !ignoringBatteryOptimizations;
}
public static void vibrate(Vibrator vibrator) {
long[] pattern = {0, 1000, 1000};
vibrator.vibrate(pattern, 1);
}
}
......@@ -20,9 +20,23 @@
package org.linphone.core.tools.compatibility;
import android.graphics.SurfaceTexture;
import android.media.AudioAttributes;
import android.os.Vibrator;
import android.os.VibrationEffect;
public class DeviceUtils26 {
public static boolean isSurfaceTextureReleased(SurfaceTexture surfaceTexture) {
return surfaceTexture.isReleased();
}
public static void vibrate(Vibrator vibrator) {
long[] timings = {0, 1000, 1000};
int[] amplitudes = {0, VibrationEffect.DEFAULT_AMPLITUDE, 0};
VibrationEffect effect = VibrationEffect.createWaveform(timings, amplitudes, 1);
AudioAttributes audioAttrs =
new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.build();
vibrator.vibrate(effect, audioAttrs);
}
}
......@@ -23,18 +23,22 @@ import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.os.Vibrator;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import org.linphone.core.Call;
import org.linphone.core.Core;
import org.linphone.core.CoreListenerStub;
import org.linphone.core.Factory;
import org.linphone.core.tools.Log;
import org.linphone.core.tools.compatibility.DeviceUtils;
import org.linphone.mediastream.Version;
/**
......@@ -54,6 +58,8 @@ public class CoreService extends Service {
protected Notification mServiceNotification = null;
private CoreListenerStub mListener;
private Vibrator mVibrator;
private boolean mIsVibrating;
@Override
public void onCreate() {
......@@ -67,6 +73,8 @@ public class CoreService extends Service {
createServiceNotificationChannel();
}
mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mListener = new CoreListenerStub() {
@Override
public void onFirstCallStarted(Core core) {
......@@ -75,6 +83,28 @@ public class CoreService extends Service {
if (!mIsInForegroundMode) {
startForeground();
}
// Starting Android 10 foreground service is a requirement to be able to vibrate if app is in background
if (core.getCurrentCall().getDir() == Call.Dir.Incoming && core.isVibrationOnIncomingCallEnabled()) {
if (mVibrator.hasVibrator()) {
Log.i("[Core Service] Starting vibrator");
DeviceUtils.vibrate(mVibrator);
mIsVibrating = true;
} else {
Log.e("[Core Service] Device doesn't have a vibrator");
}
}
}
@Override
public void onCallStateChanged(Core core, Call call, Call.State state, String message) {
if (state == Call.State.End || state == Call.State.Error || state == Call.State.Connected) {
if (mIsVibrating) {
Log.i("[Core Service] Stopping vibrator");
mVibrator.cancel();
mIsVibrating = false;
}
}
}
@Override
......@@ -95,6 +125,18 @@ public class CoreService extends Service {
if (core.getCallsNb() > 0) {
Log.w("[Core Service] Service started while at least one call active !");
startForeground();
Call call = core.getCurrentCall();
// Starting Android 10 foreground service is a requirement to be able to vibrate if app is in background
if (call.getDir() == Call.Dir.Incoming && call.getState() == Call.State.IncomingReceived && core.isVibrationOnIncomingCallEnabled()) {
if (mVibrator.hasVibrator()) {
Log.i("[Core Service] Starting vibrator");
DeviceUtils.vibrate(mVibrator);
mIsVibrating = true;
} else {
Log.e("[Core Service] Device doesn't have a vibrator");
}
}
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment