8

Good day, situation:

I'm developing Android application that serve as sport tracker/navigation app - so it require permanent connection to GPS and also permanent awake device. Recording is done every second.

Current solution working for years is thanks to wakelocks that keep device awake.

Doze mode in Android 6.0+ complicate situation, but it is not this case.

On Huawei device is probably different type of optimization.

Here is part of log:

10-10 10:33:18.462 1014-384 D/PFW.HwPFWAppWakeLockPolicy: getUidWakeLock uid: 10097 wakelock >= 10 mins 10-10 10:33:18.543 1014-384 D/PFW.HwPFWAppWakeLockPolicy: force stop abnormal wakelock app uid: 10097 10-10 10:33:18.558 1014-384 I/ActivityManager: Force stopping menion.android.locus appid=10097 user=0: from pid 1014

So after approx. 30+ minutes, system simply decide that app use too much wakelocks and terminate it completely with all services, history, simply kill.

Any experience with this behavior and any suggestion, how to this simple task (permanent recording of GPS location when screen is off) better?

As I wrote at start, on all other devices except new Huawei, such system works correctly for many years.

EDIT: note after comment of one user (deleted?), "whitelist" app in Huawei battery manager (mark as "protected application") has no effect on this problem.

Menion Asamm
  • 984
  • 11
  • 19

2 Answers2

10

There are two Huawei system apps that may kill user apps to save battery:

  • SystemManager (com.huawei.systemmanager) kills any apps that are still running after the screen is turned off, unless they're in the "Protected Apps" list.
  • PowerGenie (com.huawei.powergenie) kills any apps that hold wake locks for a long time.

It sounds like your app is being killed by PowerGenie. You can avoid this by taking advantage of PowerGenie's hardcoded whitelist of wake lock tags. For example, if your wake lock's tag is "LocationManagerService" it will be ignored by PowerGenie, because a system service holds a wake lock with the same tag and PowerGenie has whitelisted it.

akwizgran
  • 176
  • 1
  • 8
  • I have researched a little bit and have tried with my app using this logic. I have been working on a solution for a neverending location service app. I have everything for the app to work but the only problem that I have is Huawei and Xiaomi devices (and only the 6.0 version of android ones). I gave this a try, and bingo. Force closing Power Engine and my app works on 6.0 huawei devices. So the workaround is to somehow make power engine whitelist you app (not sure how currently but at least, the problem is now clear) Thank you so much @akwizgran – Jose Jet Mar 20 '18 at 14:14
  • It works! I have specified the wake lock tag as "LocationManagerService" – Oleg A Sep 06 '18 at 04:59
  • May I ask what do you mean by specifying the wake lock tag? – rosu alin Apr 04 '19 at 07:46
  • @OlegA And you use PARTIAL_WAKE_LOCK as the wake flag? – rosu alin Apr 04 '19 at 08:05
  • @rosualin Yeah, I use PowerManager.PARTIAL_WAKE_LOCK – Oleg A Apr 05 '19 at 05:57
  • this still kills my gps after a while on a mate 10 pro :( – rosu alin Apr 05 '19 at 08:24
  • @rosualin the tag is the second argument to [newWakeLock()](https://developer.android.com/reference/android/os/PowerManager.html#newWakeLock(int,%20java.lang.String)). – akwizgran Apr 05 '19 at 16:11
  • @rosualin some power managers specifically look for apps that are using the GPS. As an experiment, you could try disabling the GPS functionality of your app but keeping the wake lock, then running it overnight on a test device. If it doesn't get killed then it's the GPS rather than the wake lock that the power manager is objecting to. – akwizgran Apr 06 '19 at 10:15
1

Have you tried setting an Alarm that regularly releases the WakeLock and then reacquires it after a couple of seconds? If the issue is that Huawei's Android does not like the abuse of Wakelocks, maybe they are fine if you release it every now and then? For example: I suppose you will have a background process running in foreground. If so, in your onStartCommand insert:

setupWakeupAlarm(context);

where the method is defined as:

private static void setupWakeupAlarm(Context context) {
    AlarmManager mWakeUpAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    PendingIntent mWakeUpAlarmIntent;
    Intent serviceIntent;
    serviceIntent = new Intent(context, SSAlarmReceiver.class);
    mWakeUpAlarmIntent = PendingIntent.getBroadcast(context, 0, serviceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    // every 5 minutes 
    mWakeUpAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
            SystemClock.elapsedRealtime() + WAKEUP_ALARM_FREQUENCY, mWakeUpAlarmIntent);
    Log.d("TAG", "wakup alarm set up or reset!");
}

and where the receiver is a local class:

static public class SSAlarmReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(final Context context, Intent intent) {
        setupWakeupAlarm(context);
        mBackgroundService.stopForeground(true);
        if (mWakeLock.isHeld())
            mWakeLock.release();
        new Timer().schedule(
                new TimerTask() {
                    @Override
                    public void run() {
                        mWakeLock.acquire();
                        mBackgroundService.startForeground(mNotificationId, mNotification.getNotification());
                        }
                },
                3000
        );
    }
}

Note that in my case I also had my background service running in foreground and I decided to stop the foreground. Not sure it is necessary.

The risk is of course that in the 3 seconds the Wakelock is not active, your process can be killed.

FabioC
  • 462
  • 5
  • 14