explicitly declare foreground service type
This commit is contained in:
parent
7e5bf623ae
commit
418d6b09a0
|
@ -3,8 +3,13 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="32"
|
||||||
|
tools:ignore="ScopedStorage" />
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="32" />
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
<uses-permission android:name="android.permission.READ_PROFILE" />
|
<uses-permission android:name="android.permission.READ_PROFILE" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
|
@ -40,6 +45,16 @@
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
|
<!-- New permissions required to run as foreground service on Android 14.
|
||||||
|
SYSTEM_EXEMPTED is used when the app is on the doze allow list. This is normal
|
||||||
|
and the expected default behaviour. The other two hijack RECORD_AUDIO and CAMERA if they
|
||||||
|
happen to be granted. -->
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
|
||||||
|
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.camera"
|
android:name="android.hardware.camera"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
|
@ -77,32 +92,40 @@
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:appCategory="social"
|
android:appCategory="social"
|
||||||
android:fullBackupContent="@xml/backup_content"
|
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
android:fullBackupContent="@xml/backup_content"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:icon="@mipmap/new_launcher"
|
android:icon="@mipmap/new_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
|
android:localeConfig="@xml/locales_config"
|
||||||
android:networkSecurityConfig="@xml/network_security_configuration"
|
android:networkSecurityConfig="@xml/network_security_configuration"
|
||||||
android:preserveLegacyExternalStorage="true"
|
android:preserveLegacyExternalStorage="true"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:theme="@style/ConversationsTheme"
|
android:theme="@style/ConversationsTheme"
|
||||||
tools:replace="android:label"
|
tools:replace="android:label"
|
||||||
android:localeConfig="@xml/locales_config"
|
|
||||||
tools:targetApi="tiramisu">
|
tools:targetApi="tiramisu">
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.gms.car.application"
|
android:name="com.google.android.gms.car.application"
|
||||||
android:resource="@xml/automotive_app_desc" />
|
android:resource="@xml/automotive_app_desc" />
|
||||||
|
|
||||||
<service android:name=".services.XmppConnectionService" />
|
<service
|
||||||
|
android:name=".services.XmppConnectionService"
|
||||||
|
android:exported="false"
|
||||||
|
android:foregroundServiceType="specialUse|systemExempted|microphone|camera">
|
||||||
|
<property
|
||||||
|
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
|
||||||
|
android:value="im" />
|
||||||
|
</service>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".services.EventReceiver"
|
android:name=".services.EventReceiver"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"
|
<action
|
||||||
|
android:name="android.net.conn.CONNECTIVITY_CHANGE"
|
||||||
tools:ignore="BatteryLife" />
|
tools:ignore="BatteryLife" />
|
||||||
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
|
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
|
||||||
<action android:name="android.media.RINGER_MODE_CHANGED" />
|
<action android:name="android.media.RINGER_MODE_CHANGED" />
|
||||||
|
@ -150,7 +173,6 @@
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.ConversationsActivity"
|
android:name=".ui.ConversationsActivity"
|
||||||
android:label="@string/app_name"
|
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:minWidth="300dp"
|
android:minWidth="300dp"
|
||||||
android:minHeight="300dp"
|
android:minHeight="300dp"
|
||||||
|
@ -162,8 +184,7 @@
|
||||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.UriHandlerActivity"
|
android:name=".ui.UriHandlerActivity"
|
||||||
android:exported="true"
|
android:exported="true">
|
||||||
android:label="@string/app_name">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
@ -265,7 +286,6 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.ShareWithActivity"
|
android:name=".ui.ShareWithActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/app_name"
|
|
||||||
android:launchMode="singleTop">
|
android:launchMode="singleTop">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
|
@ -19,6 +19,7 @@ import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ServiceInfo;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
@ -487,6 +488,7 @@ public class XmppConnectionService extends Service {
|
||||||
private WakeLock wakeLock;
|
private WakeLock wakeLock;
|
||||||
private LruCache<String, Bitmap> mBitmapCache;
|
private LruCache<String, Bitmap> mBitmapCache;
|
||||||
private final BroadcastReceiver mInternalEventReceiver = new InternalEventReceiver();
|
private final BroadcastReceiver mInternalEventReceiver = new InternalEventReceiver();
|
||||||
|
private final BroadcastReceiver mInternalRestrictedEventReceiver = new RestrictedEventReceiver(Arrays.asList(TorServiceUtils.ACTION_STATUS));
|
||||||
private final BroadcastReceiver mInternalScreenEventReceiver = new InternalEventReceiver();
|
private final BroadcastReceiver mInternalScreenEventReceiver = new InternalEventReceiver();
|
||||||
|
|
||||||
private static String generateFetchKey(Account account, final Avatar avatar) {
|
private static String generateFetchKey(Account account, final Avatar avatar) {
|
||||||
|
@ -1236,16 +1238,26 @@ public class XmppConnectionService extends Service {
|
||||||
toggleForegroundService();
|
toggleForegroundService();
|
||||||
updateUnreadCountBadge();
|
updateUnreadCountBadge();
|
||||||
toggleScreenEventReceiver();
|
toggleScreenEventReceiver();
|
||||||
final IntentFilter intentFilter = new IntentFilter();
|
final IntentFilter systemBroadcastFilter = new IntentFilter();
|
||||||
intentFilter.addAction(TorServiceUtils.ACTION_STATUS);
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
scheduleNextIdlePing();
|
scheduleNextIdlePing();
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
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);
|
mForceDuringOnCreate.set(false);
|
||||||
toggleForegroundService();
|
toggleForegroundService();
|
||||||
setupPhoneStateListener();
|
setupPhoneStateListener();
|
||||||
|
@ -1315,6 +1327,7 @@ public class XmppConnectionService extends Service {
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
try {
|
try {
|
||||||
unregisterReceiver(this.mInternalEventReceiver);
|
unregisterReceiver(this.mInternalEventReceiver);
|
||||||
|
unregisterReceiver(this.mInternalRestrictedEventReceiver);
|
||||||
unregisterReceiver(this.mInternalScreenEventReceiver);
|
unregisterReceiver(this.mInternalScreenEventReceiver);
|
||||||
} catch (final IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
//ignored
|
//ignored
|
||||||
|
@ -1396,9 +1409,26 @@ public class XmppConnectionService extends Service {
|
||||||
|
|
||||||
private void startForegroundOrCatch(final int id, final Notification notification) {
|
private void startForegroundOrCatch(final int id, final Notification notification) {
|
||||||
try {
|
try {
|
||||||
startForeground(id, notification);
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||||
} catch (final IllegalStateException e) {
|
final int foregroundServiceType;
|
||||||
Log.e(Config.LOGTAG,"Could not start foreground service", e);
|
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 {
|
private class InternalEventReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
onStartCommand(intent, 0, 0);
|
onStartCommand(intent, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class RestrictedEventReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
private final Collection<String> allowedActions;
|
||||||
|
|
||||||
|
private RestrictedEventReceiver(final Collection<String> 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 static class OngoingCall {
|
||||||
public final AbstractJingleConnection.Id id;
|
public final AbstractJingleConnection.Id id;
|
||||||
public final Set<Media> media;
|
public final Set<Media> media;
|
||||||
|
|
Loading…
Reference in a new issue