LoginSignup
11
15

More than 5 years have passed since last update.

Android 8.0調査メモ:もう裏でこっそりサービスを動かせない件(後編)

Posted at

後編?

startForegroundServiceしたあと5秒以内にstartForegroundしないと落ちるカラクリを説明します。
「なんのこと?」っていう人は前編から見て下さい。(まえおき、まとめ、だけ見れば多分イメージ湧きます)

実際にアプリを動かすとどんな感じになっているか?(再掲)

  • JobScheduler(とか、それをラップしているGcmNetworkManager)から起動されるジョブサービスはちゃんと裏でも動ける
    • でもそこからstartServiceやるとクラッシュ
  • Activityから立ち上げたサービスはちゃんと起動できる
    • でもActivityを閉じてしばらく経つと、サービスが勝手に終了する
  • startForegroundServiceすれば、バックグラウンドからの起動でも死なない。でも
    • 5秒以内にstartForegroundを呼ばないとクラッシュ
    • startForegroundを呼ばずにstopSelf()してもクラッシュ
      • IntentServiceの場合は、どこかでstartForeground呼ばないとクラッシュ

参考:Android Oからのバックグラウンド・サービスの制限事項を実演する。

ソースを読むぞ

startForegroundServiceしたあと5秒以内にstartForegroundしないと落ちるカラクリ

落ちるときのエラーログを手がかりに見ていきます。

E/AndroidRuntime: FATAL EXCEPTION: main
                  android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
3358    void serviceForegroundTimeout(ServiceRecord r) {
3359        ProcessRecord app;
3360        synchronized (mAm) {
3361            if (!r.fgRequired || r.destroying) {
3362                return;
3363            }
3364
3365            if (DEBUG_BACKGROUND_CHECK) {
3366                Slog.i(TAG, "Service foreground-required timeout for " + r);
3367            }
3368            app = r.app;
3369            r.fgWaiting = false;
3370            stopServiceLocked(r);
3371        }
3372
3373        if (app != null) {
3374            mAm.mAppErrors.appNotResponding(app, null, null, false,
3375                    "Context.startForegroundService() did not then call Service.startForeground()");
3376        }
3377    }
3378
3379    void serviceForegroundCrash(ProcessRecord app) {
3380        mAm.crashApplication(app.uid, app.pid, app.info.packageName, app.userId,
3381                "Context.startForegroundService() did not then call Service.startForeground()");
3382    }

2ヶ所ありますが、たぶん serviceForegroundTimeout のほうでしょう。

タイムアウトを設定しているのは誰?

/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
 107    // How long the startForegroundService() grace period is to get  around to
 108    // calling startForeground() before we ANR + stop it.
 109    static final int SERVICE_START_FOREGROUND_TIMEOUT = 5*1000;

    ...

3395    void scheduleServiceForegroundTransitionTimeoutLocked(ServiceRecord r) {
3396        if (r.app.executingServices.size() == 0 || r.app.thread == null) {
3397            return;
3398        }
3399        Message msg = mAm.mHandler.obtainMessage(
3400                ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG);
3401        msg.obj = r;
3402        r.fgWaiting = true;
3403        mAm.mHandler.sendMessageDelayed(msg, SERVICE_START_FOREGROUND_TIMEOUT);
3404    }

  ↑
sendServiceArgsLocked
  ↑
bingUpServiceLocked
  ↑
startServiceInnerLocked
  ↑・・・ここで前編に書いたForeground起動してるかチェックされてる
startServiceLocked
 

まとめ

Android 8.0対応、きついです・・・(まとまってないw

11
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
15