diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index d7da25ccc..56b7865c9 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -3,8 +3,13 @@
xmlns:tools="http://schemas.android.com/tools">
-
-
+
+
+
+
+
+
+
+
+
@@ -77,32 +92,40 @@
-
+
+
+
-
@@ -150,7 +173,6 @@
+ android:exported="true">
@@ -265,7 +286,6 @@
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 5a072e9c6..6c87fd94a 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -19,6 +19,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.media.AudioManager;
@@ -487,6 +488,7 @@ public class XmppConnectionService extends Service {
private WakeLock wakeLock;
private LruCache mBitmapCache;
private final BroadcastReceiver mInternalEventReceiver = new InternalEventReceiver();
+ private final BroadcastReceiver mInternalRestrictedEventReceiver = new RestrictedEventReceiver(Arrays.asList(TorServiceUtils.ACTION_STATUS));
private final BroadcastReceiver mInternalScreenEventReceiver = new InternalEventReceiver();
private static String generateFetchKey(Account account, final Avatar avatar) {
@@ -1236,16 +1238,26 @@ public class XmppConnectionService extends Service {
toggleForegroundService();
updateUnreadCountBadge();
toggleScreenEventReceiver();
- final IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(TorServiceUtils.ACTION_STATUS);
+ final IntentFilter systemBroadcastFilter = new IntentFilter();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
scheduleNextIdlePing();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ systemBroadcastFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
}
- intentFilter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
+ systemBroadcastFilter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
}
- registerReceiver(this.mInternalEventReceiver, intentFilter);
+ ContextCompat.registerReceiver(
+ this,
+ this.mInternalEventReceiver,
+ systemBroadcastFilter,
+ ContextCompat.RECEIVER_NOT_EXPORTED);
+ final IntentFilter exportedBroadcastFilter = new IntentFilter();
+ exportedBroadcastFilter.addAction(TorServiceUtils.ACTION_STATUS);
+ ContextCompat.registerReceiver(
+ this,
+ this.mInternalRestrictedEventReceiver,
+ exportedBroadcastFilter,
+ ContextCompat.RECEIVER_EXPORTED);
mForceDuringOnCreate.set(false);
toggleForegroundService();
setupPhoneStateListener();
@@ -1315,6 +1327,7 @@ public class XmppConnectionService extends Service {
public void onDestroy() {
try {
unregisterReceiver(this.mInternalEventReceiver);
+ unregisterReceiver(this.mInternalRestrictedEventReceiver);
unregisterReceiver(this.mInternalScreenEventReceiver);
} catch (final IllegalArgumentException e) {
//ignored
@@ -1396,9 +1409,26 @@ public class XmppConnectionService extends Service {
private void startForegroundOrCatch(final int id, final Notification notification) {
try {
- startForeground(id, notification);
- } catch (final IllegalStateException e) {
- Log.e(Config.LOGTAG,"Could not start foreground service", e);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ final int foregroundServiceType;
+ if (getSystemService(PowerManager.class)
+ .isIgnoringBatteryOptimizations(getPackageName())) {
+ foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED;
+ } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
+ == PackageManager.PERMISSION_GRANTED) {
+ foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
+ } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
+ == PackageManager.PERMISSION_GRANTED) {
+ foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
+ } else {
+ foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
+ }
+ startForeground(id, notification, foregroundServiceType);
+ } else {
+ startForeground(id, notification);
+ }
+ } catch (final IllegalStateException | SecurityException e) {
+ Log.e(Config.LOGTAG, "Could not start foreground service", e);
}
}
@@ -5027,11 +5057,30 @@ public class XmppConnectionService extends Service {
private class InternalEventReceiver extends BroadcastReceiver {
@Override
- public void onReceive(Context context, Intent intent) {
+ public void onReceive(final Context context, final Intent intent) {
onStartCommand(intent, 0, 0);
}
}
+ private class RestrictedEventReceiver extends BroadcastReceiver {
+
+ private final Collection allowedActions;
+
+ private RestrictedEventReceiver(final Collection allowedActions) {
+ this.allowedActions = allowedActions;
+ }
+
+ @Override
+ public void onReceive(final Context context, final Intent intent) {
+ final String action = intent == null ? null : intent.getAction();
+ if (allowedActions.contains(action)) {
+ onStartCommand(intent,0,0);
+ } else {
+ Log.e(Config.LOGTAG,"restricting broadcast of event "+action);
+ }
+ }
+ }
+
public static class OngoingCall {
public final AbstractJingleConnection.Id id;
public final Set media;