事例紹介

WHOOP が過度の部分的な wake lock セッションを 90% 以上削減した方法

4 分で読了
Breana Tate
デベロッパー リレーション エンジニア

ウェアラブル向けの Android アプリを構築する場合、実際の作業は画面がオフになったときに始まります。WHOOP は、トレーニング、リカバリー、睡眠、ストレスに対する体の反応を把握するのに役立ちます。Android を使用している多くの WHOOP メンバーにとって、信頼性の高いバックグラウンドでの同期と接続は、分析情報を得るために不可欠です。

今年初め、Google Play は Android Vitals に新しい指標「過度の部分的な wake lock」をリリースしました。この指標は、24 時間以内に累積で 2 時間を超える wake lock の使用(免除を除く)があったユーザー セッションの割合を測定します。この指標の目的は、バッテリーの消耗の原因を特定して対処できるようにすることです。これは、優れたユーザー エクスペリエンスを提供するために不可欠です。

2026 年 3 月 1 日以降、品質のしきい値を満たしていないアプリは、Google Play の検出面から除外される可能性があります。また、Google Play ストアの掲載情報に警告が表示され、アプリが想定よりも多くのバッテリーを使用する可能性があることが示される場合があります。

WHOOP のシニア Android エンジニアである Mayank Saini 氏によると、Android Vitals でアプリの過度の部分的な wake lock の割合が 15%(推奨される 5% のしきい値を超えている)と報告された後、「チームは Android の効率性を高める機会を得ました」。

mayank.png

チームは、Android Vitals の指標を、バックグラウンド処理によって CPU が不必要に長く起動していることを示す明確なシグナルと捉えました。この問題を解決することで、優れたユーザー エクスペリエンスを提供しながら、バックグラウンドでの無駄な時間を減らし、信頼性の高いタイムリーな Bluetooth 接続と同期を維持できるようになります。

問題の特定

チームは、まず Android Vitals を使用して、どの wake lock が指標に影響しているかについての詳細な分析情報を取得しました。Android Vitals の過度の部分的な wake lock ダッシュボードを確認することで、過度の部分的な wake lock の最大の原因が WorkManager ワーカーの 1 つ(ダッシュボードでは androidx.work.impl.background.systemjob.SystemJobService として識別)であることを特定できました。WHOOP の「常時オン」のエクスペリエンスをサポートするため、アプリは WorkManager を使用して、定期的な同期やウェアラブルへの定期的な更新の配信などのバックグラウンド タスクを実行しています。

チームは、バックグラウンドでタスクを実行する際に WorkManager が wake lock を取得することを認識していましたが、Android Vitals に過度の部分的な wake lock 指標が導入されるまで、WorkManager 以外のすべてのバックグラウンド処理がどのように分散されているかを把握できませんでした

ダッシュボードで WorkManager が主な原因であることが特定できたため、チームはどのワーカーが最も貢献しているかを特定し、問題の解決に取り組むことができました。

内部の指標とデータを使用して原因を絞り込む

WHOOP には、WorkManager の指標をモニタリングするための内部インフラストラクチャがすでに設定されていました。定期的にモニタリングしている内容は次のとおりです。

  1. 平均実行時間: ワーカーの実行時間。
  2. タイムアウト: ワーカーが完了せずにタイムアウトする頻度。
  3. 再試行: 処理がタイムアウトまたは失敗した場合にワーカーが再試行する頻度。
  4. キャンセル: 処理がキャンセルされた頻度。

ワーカーの成功と失敗だけでなく、より多くの情報を追跡することで、チームは処理の効率性を把握できます。

内部の指標では、一部のワーカーで平均実行時間が長い ことが示されたため、調査範囲をさらに絞り込むことができました。

内部の指標に加えて、チームはAndroid Studio の_Background Task Inspector_を使用して、対象のワーカーを検査してデバッグしました。Android Vitals でフラグが設定された指標に合わせて、関連する wake lock に特に重点を置きました。

調査: ワーカーのバリエーションを区別する

WHOOP では、一部のワーカーに 1 回限りのスケジュール定期的なスケジュールの両方を使用しています。これにより、アプリは同じ成功基準を持つ同一のタスクに同じ Worker ロジックを再利用できます。タイミングのみが異なります。

内部の指標を使用すると、検索範囲を特定のワーカーに絞り込むことができましたが、バグがワーカーの 1 回限りのバリエーションで発生したのか、定期的なバリエーションで発生したのか、両方で発生したのかを判断できませんでした。そこで、WorkManager の setTraceTag メソッド を使用して、同じ Worker の 1 回限りのバリエーションと定期的なバリエーションを区別する更新をリリースしました。

この追加情報により、過度の部分的な wake lock が発生するセッションに最も貢献しているワーカーのバリエーション(定期的なバリエーションまたは 1 回限りのバリエーション)を明確に特定できるようになりました。しかし、データから、どちらのバリエーションも他方よりも貢献していないことが明らかになったため、チームは驚きました。

WHOOP の Android エンジニア II である Manmeet Tuteja 氏は、「この分割により、両方のバリエーションで問題が発生していることを確認できました。これにより、スケジューリング構成ではなく、ワーカー実装内の共有ビジネスロジックの問題が示されました」と述べています。

manmeet.png

ワーカーの動作を詳しく調べ、根本原因を修正する

ワーカー内のロジックを確認する必要があることを把握したチームは、調査中にフラグが設定されたワーカーのワーカーの動作を再確認しました。具体的には、処理が停止して完了しないインスタンスを探していました。

これらすべてが、過度の wake lock の根本原因の発見につながりました。

続行する前に WHOOP センサーへの接続を待機するように設計された CoroutineWorker。 

センサーが接続されていない状態で処理が開始された場合、センサーが接続されているかどうかを示す whoopSensorFlownull でした。SensorWorker はこれを早期終了条件として扱わず、実行を継続し、接続を無期限に待機していました。その結果、WorkManager は処理がタイムアウトするまで部分的な wake lock を保持し、バックグラウンドでの wake lock の使用量が増加し、SensorWorker の不要な再スケジュールが頻繁に行われるようになりました。

この問題を解決するため、WHOOP チームは、コア ビジネス ロジックの実行を試みる前に接続ステータスを確認するように Worker のロジックを更新しました。

センサーが使用できない場合、ワーカーは終了し、タイムアウト シナリオを回避して wake lock を解放します。次のコード スニペットは、解決策を示しています。

class SensorWorker(appContext: Context, params: WorkerParameters): CoroutineWorker(appContext, params) {
   override suspend fun doWork(): Result {
      ...
      // Check the sensor state and perform work or return failure
       return whoopSensorFlow.replayCache
            .firstOrNull()
            ?.let { cachedData ->
                processSensorData(cachedData)
                Result.success()
            } ?: run {
                Result.failure()
            }
}

過度の部分的な wake lock が発生するセッションを 90% 削減

修正をリリースした後も、チームは Android Vitals のダッシュボードで変更の影響を確認しました。

最終的に、WHOOP は Worker の変更を実装してから 30 日後に、過度の部分的な wake lock の割合が 15% から 1%未満に減少 しました。 

partialWake.png

変更の結果、処理が完了せずにタイムアウトするインスタンスが減少し、平均実行時間が短縮されました。

バックグラウンド処理の効率性を向上させたい他のデベロッパーへの WHOOP チームからのアドバイスは次のとおりです。

sarthak.png

使ってみる

アプリの過度の部分的な wake lock を減らしたり、ワーカーの効率性を向上させたりする場合は、Android Vitals でアプリの過度の部分的な wake lock 指標を確認し、wake lock のドキュメントでベスト プラクティスとデバッグ戦略をご確認ください。

執筆者:

続きを読む