diff --git a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinService.java b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinService.java index c265c2aa..beb7f56b 100755 --- a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinService.java +++ b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinService.java @@ -29,6 +29,7 @@ import androidx.legacy.content.WakefulBroadcastReceiver; import com.google.android.gms.checkin.internal.ICheckinService; import org.microg.gms.auth.AuthConstants; +import org.microg.gms.common.ForegroundServiceContext; import org.microg.gms.gcm.McsService; import org.microg.gms.people.PeopleManager; @@ -53,6 +54,7 @@ public class CheckinService extends IntentService { @Override protected void onHandleIntent(Intent intent) { try { + ForegroundServiceContext.completeForegroundService(this, intent, TAG); if (CheckinPrefs.get(this).isEnabled()) { LastCheckinInfo info = CheckinManager.checkin(this, intent.getBooleanExtra(EXTRA_FORCE_CHECKIN, false)); if (info != null) { diff --git a/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java b/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java index 91a00358..b531928b 100755 --- a/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java +++ b/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java @@ -24,6 +24,8 @@ import android.util.Log; import androidx.legacy.content.WakefulBroadcastReceiver; +import org.microg.gms.common.ForegroundServiceContext; + import static org.microg.gms.checkin.CheckinService.EXTRA_FORCE_CHECKIN; public class TriggerReceiver extends WakefulBroadcastReceiver { @@ -46,6 +48,7 @@ public class TriggerReceiver extends WakefulBroadcastReceiver { if (networkInfo != null && networkInfo.isConnected() || force) { Intent subIntent = new Intent(context, CheckinService.class); subIntent.putExtra(EXTRA_FORCE_CHECKIN, force); + startWakefulService(new ForegroundServiceContext(context), subIntent); } } else { Log.d(TAG, "Ignoring " + intent + ": checkin is disabled"); diff --git a/play-services-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java b/play-services-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java new file mode 100644 index 00000000..bf83ce46 --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java @@ -0,0 +1,61 @@ +package org.microg.gms.common; + +import android.app.ActivityManager; +import android.app.Service; +import android.content.ComponentName; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.os.Build; +import android.os.PowerManager; +import android.util.Log; + +import androidx.annotation.RequiresApi; + +import java.util.List; + +public class ForegroundServiceContext extends ContextWrapper { + private static final String TAG = "ForegroundService"; + public static final String EXTRA_FOREGROUND = "foreground"; + + public ForegroundServiceContext(Context base) { + super(base); + } + + @Override + public ComponentName startService(Intent service) { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isIgnoringBatteryOptimizations() && !isAppOnForeground()) { + Log.d(TAG, "Starting in foreground mode."); + service.putExtra(EXTRA_FOREGROUND, true); + return super.startForegroundService(service); + } + return super.startService(service); + } + + @RequiresApi(api = Build.VERSION_CODES.M) + private boolean isIgnoringBatteryOptimizations() { + PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); + return powerManager.isIgnoringBatteryOptimizations(getPackageName()); + } + + private boolean isAppOnForeground() { + ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); + List appProcesses = activityManager.getRunningAppProcesses(); + if (appProcesses == null) { + return false; + } + final String packageName = getPackageName(); + for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { + if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) { + return true; + } + } + return false; + } + + public static void completeForegroundService(Service service, Intent intent, String tag) { + if (intent != null && intent.getBooleanExtra(EXTRA_FOREGROUND, false) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Log.d(tag, "Started in foreground mode."); + } + } +} diff --git a/play-services-core/src/main/java/org/microg/gms/gcm/McsService.java b/play-services-core/src/main/java/org/microg/gms/gcm/McsService.java index bb29c29d..acbc1de3 100644 --- a/play-services-core/src/main/java/org/microg/gms/gcm/McsService.java +++ b/play-services-core/src/main/java/org/microg/gms/gcm/McsService.java @@ -47,6 +47,7 @@ import com.mgoogle.android.gms.R; import com.squareup.wire.Message; import org.microg.gms.checkin.LastCheckinInfo; +import org.microg.gms.common.ForegroundServiceContext; import org.microg.gms.common.PackageUtils; import org.microg.gms.gcm.mcs.AppData; import org.microg.gms.gcm.mcs.Close; @@ -294,6 +295,7 @@ public class McsService extends Service implements Handler.Callback { @Override public int onStartCommand(Intent intent, int flags, int startId) { + ForegroundServiceContext.completeForegroundService(this, intent, TAG); synchronized (McsService.class) { if (rootHandler != null) { if (intent == null) return START_REDELIVER_INTENT; diff --git a/play-services-core/src/main/java/org/microg/gms/gcm/TriggerReceiver.java b/play-services-core/src/main/java/org/microg/gms/gcm/TriggerReceiver.java index d7de7259..2d12deee 100644 --- a/play-services-core/src/main/java/org/microg/gms/gcm/TriggerReceiver.java +++ b/play-services-core/src/main/java/org/microg/gms/gcm/TriggerReceiver.java @@ -26,6 +26,7 @@ import android.util.Log; import androidx.legacy.content.WakefulBroadcastReceiver; import org.microg.gms.checkin.LastCheckinInfo; +import org.microg.gms.common.ForegroundServiceContext; import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION_CODES.N; @@ -84,6 +85,21 @@ public class TriggerReceiver extends WakefulBroadcastReceiver { return; } } + + if (!McsService.isConnected() || force) { + Log.d(TAG, "Not connected to GCM but should be, asking the service to start up. Triggered by: " + intent); + startWakefulService(new ForegroundServiceContext(context), new Intent(ACTION_CONNECT, null, context, McsService.class) + .putExtra(EXTRA_REASON, intent)); + } else { + if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { + Log.d(TAG, "Ignoring " + intent + ": service is running. schedule reconnect instead."); + McsService.scheduleReconnect(context); + } else { + Log.d(TAG, "Ignoring " + intent + ": service is running. heartbeat instead."); + startWakefulService(new ForegroundServiceContext(context), new Intent(ACTION_HEARTBEAT, null, context, McsService.class) + .putExtra(EXTRA_REASON, intent)); + } + } } catch (Exception e) { Log.w(TAG, e); }