diff --git a/play-services-core/src/main/AndroidManifest.xml b/play-services-core/src/main/AndroidManifest.xml
index 82308568..fa15b346 100644
--- a/play-services-core/src/main/AndroidManifest.xml
+++ b/play-services-core/src/main/AndroidManifest.xml
@@ -93,6 +93,7 @@
+
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 9fc69307..009d9d44 100644
--- 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 android.util.Log;
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;
@@ -55,6 +56,7 @@ public class CheckinService extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
try {
+ ForegroundServiceContext.completeForegroundService(this, intent, TAG);
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(PREF_ENABLE_CHECKIN, false)) {
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 fbb8aaca..08df8cdb 100644
--- 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,10 @@ import android.preference.PreferenceManager;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
+import org.microg.gms.common.ForegroundServiceContext;
+
+import static org.microg.gms.checkin.CheckinService.EXTRA_FORCE_CHECKIN;
+
public class TriggerReceiver extends WakefulBroadcastReceiver {
private static final String TAG = "GmsCheckinTrigger";
public static final String PREF_ENABLE_CHECKIN = "checkin_enable_service";
@@ -31,23 +35,27 @@ public class TriggerReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- boolean force = "android.provider.Telephony.SECRET_CODE".equals(intent.getAction());
- ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ try {
+ boolean force = "android.provider.Telephony.SECRET_CODE".equals(intent.getAction());
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(PREF_ENABLE_CHECKIN, false) || force) {
- if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()) &&
- LastCheckinInfo.read(context).lastCheckin > System.currentTimeMillis() - REGULAR_CHECKIN_INTERVAL) {
- return;
- }
+ if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(PREF_ENABLE_CHECKIN, false) || force) {
+ if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()) &&
+ LastCheckinInfo.read(context).lastCheckin > System.currentTimeMillis() - REGULAR_CHECKIN_INTERVAL) {
+ return;
+ }
- NetworkInfo networkInfo = cm.getActiveNetworkInfo();
- if (networkInfo != null && networkInfo.isConnected() || force) {
- Intent subIntent = new Intent(context, CheckinService.class);
- subIntent.putExtra(CheckinService.EXTRA_FORCE_CHECKIN, force);
- startWakefulService(context, subIntent);
+ NetworkInfo networkInfo = cm.getActiveNetworkInfo();
+ 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");
}
- } else {
- Log.d(TAG, "Ignoring " + intent + ": checkin is disabled");
+ } catch (Exception e) {
+ Log.w(TAG, e);
}
}
}
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..f2fc2026
--- /dev/null
+++ b/play-services-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java
@@ -0,0 +1,80 @@
+package org.microg.gms.common;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+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.support.annotation.RequiresApi;
+import android.util.Log;
+
+import com.google.android.gms.R;
+
+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.getBooleanExtra(EXTRA_FOREGROUND, false) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ Log.d(tag, "Started in foreground mode.");
+ service.startForeground(tag.hashCode(), buildForegroundNotification(service));
+ }
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ private static Notification buildForegroundNotification(Context context) {
+ NotificationChannel channel = new NotificationChannel("foreground-service", "Foreground Service", NotificationManager.IMPORTANCE_NONE);
+ channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+ channel.setShowBadge(false);
+ channel.setVibrationPattern(new long[0]);
+ context.getSystemService(NotificationManager.class).createNotificationChannel(channel);
+ return new Notification.Builder(context, channel.getId())
+ .setOngoing(true)
+ .setContentTitle("Running in background")
+ .setSmallIcon(R.drawable.gcm_bell)
+ .build();
+ }
+}
diff --git a/play-services-core/src/main/java/org/microg/gms/common/PackageUtils.java b/play-services-core/src/main/java/org/microg/gms/common/PackageUtils.java
index a2b65de1..6ca24440 100644
--- a/play-services-core/src/main/java/org/microg/gms/common/PackageUtils.java
+++ b/play-services-core/src/main/java/org/microg/gms/common/PackageUtils.java
@@ -31,6 +31,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import static android.os.Build.VERSION.SDK_INT;
@@ -198,8 +199,11 @@ public class PackageUtils {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (manager == null) return null;
if (pid <= 0) return null;
- for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
- if (processInfo.pid == pid) return processInfo.processName;
+ List runningAppProcesses = manager.getRunningAppProcesses();
+ if (runningAppProcesses != null) {
+ for (ActivityManager.RunningAppProcessInfo processInfo : runningAppProcesses) {
+ if (processInfo.pid == pid) return processInfo.processName;
+ }
}
return null;
}
diff --git a/play-services-core/src/main/java/org/microg/gms/gcm/GcmPrefs.java b/play-services-core/src/main/java/org/microg/gms/gcm/GcmPrefs.java
index d0cc000f..30a95703 100644
--- a/play-services-core/src/main/java/org/microg/gms/gcm/GcmPrefs.java
+++ b/play-services-core/src/main/java/org/microg/gms/gcm/GcmPrefs.java
@@ -28,7 +28,6 @@ import java.util.Collections;
import java.util.List;
public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListener {
- public static final String PREF_HEARTBEAT = "gcm_heartbeat_interval";
public static final String PREF_FULL_LOG = "gcm_full_log";
public static final String PREF_LAST_PERSISTENT_ID = "gcm_last_persistent_id";
public static final String PREF_CONFIRM_NEW_APPS = "gcm_confirm_new_apps";
@@ -43,6 +42,9 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
public static final String PREF_LEARNT_WIFI = "gcm_learnt_wifi";
public static final String PREF_LEARNT_OTHER = "gcm_learnt_other";
+ private static final int MIN_INTERVAL = 5 * 60 * 1000; // 5 minutes
+ private static final int MAX_INTERVAL = 30 * 60 * 1000; // 30 minutes
+
private static GcmPrefs INSTANCE;
public static GcmPrefs get(Context context) {
@@ -53,7 +55,6 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
return INSTANCE;
}
- private int heartbeatMs = 300000;
private boolean gcmLogEnabled = true;
private String lastPersistedId = "";
private boolean confirmNewApps = false;
@@ -79,7 +80,6 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
}
public void update() {
- heartbeatMs = Integer.parseInt(defaultPreferences.getString(PREF_HEARTBEAT, "300")) * 1000;
gcmLogEnabled = defaultPreferences.getBoolean(PREF_FULL_LOG, true);
lastPersistedId = defaultPreferences.getString(PREF_LAST_PERSISTENT_ID, "");
confirmNewApps = defaultPreferences.getBoolean(PREF_CONFIRM_NEW_APPS, false);
@@ -95,10 +95,6 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
learntOther = defaultPreferences.getInt(PREF_LEARNT_OTHER, 300000);
}
- public int getHeartbeatMs() {
- return heartbeatMs;
- }
-
public String getNetworkPrefForInfo(NetworkInfo info) {
if (info == null) return PREF_NETWORK_OTHER;
if (info.isRoaming()) return PREF_NETWORK_ROAMING;
@@ -158,7 +154,7 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
learntOther *= 0.95;
break;
}
- defaultPreferences.edit().putInt(PREF_LEARNT_MOBILE, learntMobile).putInt(PREF_LEARNT_WIFI, learntWifi).putInt(PREF_LEARNT_OTHER, learntOther).apply();
+ updateLearntValues();
}
public void learnReached(String pref, long time) {
@@ -178,6 +174,13 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
learntOther *= 1.02;
break;
}
+ updateLearntValues();
+ }
+
+ private void updateLearntValues() {
+ learntMobile = Math.max(MIN_INTERVAL, Math.min(learntMobile, MAX_INTERVAL));
+ learntWifi = Math.max(MIN_INTERVAL, Math.min(learntWifi, MAX_INTERVAL));
+ learntOther = Math.max(MIN_INTERVAL, Math.min(learntOther, MAX_INTERVAL));
defaultPreferences.edit().putInt(PREF_LEARNT_MOBILE, learntMobile).putInt(PREF_LEARNT_WIFI, learntWifi).putInt(PREF_LEARNT_OTHER, learntOther).apply();
}
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 66679e5c..8766055b 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
@@ -17,13 +17,15 @@
package org.microg.gms.gcm;
import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.content.pm.PermissionInfo;
import android.content.pm.ResolveInfo;
import android.net.ConnectivityManager;
import android.os.Build;
@@ -36,12 +38,14 @@ import android.os.Parcelable;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.support.annotation.RequiresApi;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
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;
@@ -66,6 +70,7 @@ import okio.ByteString;
import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
import static android.os.Build.VERSION.SDK_INT;
+import static org.microg.gms.common.ForegroundServiceContext.EXTRA_FOREGROUND;
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_RECEIVE;
import static org.microg.gms.gcm.GcmConstants.EXTRA_APP;
import static org.microg.gms.gcm.GcmConstants.EXTRA_COLLAPSE_KEY;
@@ -173,11 +178,16 @@ public class McsService extends Service implements Handler.Callback {
heartbeatIntent = PendingIntent.getService(this, 0, new Intent(ACTION_HEARTBEAT, null, this, McsService.class), 0);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
powerManager = (PowerManager) getSystemService(POWER_SERVICE);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission("android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST") == PackageManager.PERMISSION_GRANTED) {
try {
- Field field = Context.class.getField("DEVICE_IDLE_CONTROLLER");
+ String deviceIdleControllerName = "deviceidle";
+ try {
+ Field field = Context.class.getField("DEVICE_IDLE_CONTROLLER");
+ deviceIdleControllerName = (String) field.get(null);
+ } catch (Exception ignored) {
+ }
IBinder binder = (IBinder) Class.forName("android.os.ServiceManager")
- .getMethod("getService", String.class).invoke(null, field.get(null));
+ .getMethod("getService", String.class).invoke(null, deviceIdleControllerName);
if (binder != null) {
deviceIdleController = Class.forName("android.os.IDeviceIdleController$Stub")
.getMethod("asInterface", IBinder.class).invoke(null, binder);
@@ -240,8 +250,12 @@ public class McsService extends Service implements Handler.Callback {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
long delay = getCurrentDelay();
logd("Scheduling reconnect in " + delay / 1000 + " seconds...");
- alarmManager.set(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay,
- PendingIntent.getBroadcast(context, 1, new Intent(ACTION_RECONNECT, null, context, TriggerReceiver.class), 0));
+ PendingIntent pi = PendingIntent.getBroadcast(context, 1, new Intent(ACTION_RECONNECT, null, context, TriggerReceiver.class), 0);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ alarmManager.setExactAndAllowWhileIdle(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pi);
+ } else {
+ alarmManager.set(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pi);
+ }
}
public void scheduleHeartbeat(Context context) {
@@ -252,13 +266,16 @@ public class McsService extends Service implements Handler.Callback {
closeAll();
}
logd("Scheduling heartbeat in " + heartbeatMs / 1000 + " seconds...");
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- alarmManager.set(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + heartbeatMs, heartbeatIntent);
- } else {
- // with KitKat, the alarms become inexact by default, but with the newly available setWindow we can get inexact alarms with guarantees.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ // This is supposed to work even when running in idle and without battery optimization disabled
+ alarmManager.setExactAndAllowWhileIdle(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + heartbeatMs, heartbeatIntent);
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ // With KitKat, the alarms become inexact by default, but with the newly available setWindow we can get inexact alarms with guarantees.
// Schedule the alarm to fire within the interval [heartbeatMs/3*4, heartbeatMs]
alarmManager.setWindow(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + heartbeatMs / 4 * 3, heartbeatMs / 4,
heartbeatIntent);
+ } else {
+ alarmManager.set(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + heartbeatMs, heartbeatIntent);
}
}
@@ -277,6 +294,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;
@@ -299,6 +317,19 @@ public class McsService extends Service implements Handler.Callback {
return START_REDELIVER_INTENT;
}
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ private Notification buildForegroundNotification() {
+ NotificationChannel channel = new NotificationChannel("foreground-service", "Foreground Service", NotificationManager.IMPORTANCE_LOW);
+ channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+ channel.setShowBadge(false);
+ getSystemService(NotificationManager.class).createNotificationChannel(channel);
+ return new Notification.Builder(this, channel.getId())
+ .setOngoing(true)
+ .setContentTitle("Running in background")
+ .setSmallIcon(android.R.drawable.stat_notify_sync)
+ .build();
+ }
+
private void handleSendMessage(Intent intent) {
String messageId = intent.getStringExtra(EXTRA_MESSAGE_ID);
String collapseKey = intent.getStringExtra(EXTRA_COLLAPSE_KEY);
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 1a7bdb8b..50a7a03b 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
@@ -25,6 +25,7 @@ import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
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;
@@ -51,51 +52,55 @@ public class TriggerReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- boolean force = "android.provider.Telephony.SECRET_CODE".equals(intent.getAction()) || FORCE_TRY_RECONNECT.equals(intent.getAction());
- ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ try {
+ boolean force = "android.provider.Telephony.SECRET_CODE".equals(intent.getAction()) || FORCE_TRY_RECONNECT.equals(intent.getAction());
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- if (!GcmPrefs.get(context).isEnabled() && !force) {
- Log.d(TAG, "Ignoring " + intent + ": gcm is disabled");
- return;
- }
-
- if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
- McsService.resetCurrentDelay();
- }
-
- if (LastCheckinInfo.read(context).androidId == 0) {
- Log.d(TAG, "Ignoring " + intent + ": need to checkin first.");
- return;
- }
-
- force |= "android.intent.action.BOOT_COMPLETED".equals(intent.getAction());
-
- NetworkInfo networkInfo = cm.getActiveNetworkInfo();
-
- if (!force) {
- if (networkInfo == null || !networkInfo.isConnected()) {
- Log.d(TAG, "Ignoring " + intent + ": network is offline, scheduling new attempt.");
- McsService.scheduleReconnect(context);
- return;
- } else if (!GcmPrefs.get(context).isEnabledFor(networkInfo)) {
- Log.d(TAG, "Ignoring " + intent + ": gcm is disabled for " + networkInfo.getTypeName());
+ if (!GcmPrefs.get(context).isEnabled() && !force) {
+ Log.d(TAG, "Ignoring " + intent + ": gcm is disabled");
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(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(context, new Intent(ACTION_HEARTBEAT, null, context, McsService.class)
- .putExtra(EXTRA_REASON, intent));
+ McsService.resetCurrentDelay();
}
+
+ if (LastCheckinInfo.read(context).androidId == 0) {
+ Log.d(TAG, "Ignoring " + intent + ": need to checkin first.");
+ return;
+ }
+
+ force |= "android.intent.action.BOOT_COMPLETED".equals(intent.getAction());
+
+ NetworkInfo networkInfo = cm.getActiveNetworkInfo();
+
+ if (!force) {
+ if (networkInfo == null || !networkInfo.isConnected()) {
+ Log.d(TAG, "Ignoring " + intent + ": network is offline, scheduling new attempt.");
+ McsService.scheduleReconnect(context);
+ return;
+ } else if (!GcmPrefs.get(context).isEnabledFor(networkInfo)) {
+ Log.d(TAG, "Ignoring " + intent + ": gcm is disabled for " + networkInfo.getTypeName());
+ 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);
}
}