[AW][ComponentUpdater] Override Service#onStartCommand for testing
Override AwComponentUpdateService#onStartCommand to run the native update service. This way it's possible to deterministically force launch the service on devices running android M and below for testing purposes where it's not possible to force launch the job service via `adb shell cmd jobscheduler`. The service isn't exported so other apps can't start the service. The service can be launched using the commandline: `adb shell am startservice <webview-package-name>/org.chromium.android_webview.nonembedded.AwComponentUpdateService` Fixed: 1209275 Test: Manually launch the service via adb, run webview shell and see scheduled jobs Change-Id: I994b46e5b250e4f42498dc20b4b89c11ea452485 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2905562 Reviewed-by: Mugdha Lakhani <nator@chromium.org> Reviewed-by: Richard Coles <torne@chromium.org> Commit-Queue: Hazem Ashmawy <hazems@chromium.org> Cr-Commit-Position: refs/heads/master@{#894619}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
fdb9894661
commit
ebccaf66ab
@ -6,6 +6,7 @@ package org.chromium.android_webview.nonembedded;
|
|||||||
import android.app.job.JobParameters;
|
import android.app.job.JobParameters;
|
||||||
import android.app.job.JobService;
|
import android.app.job.JobService;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
|
||||||
@ -48,8 +49,65 @@ public class AwComponentUpdateService extends JobService {
|
|||||||
private static final String SHARED_PREFERENCES_NAME = "AwComponentUpdateServicePreferences";
|
private static final String SHARED_PREFERENCES_NAME = "AwComponentUpdateServicePreferences";
|
||||||
private static final String KEY_UNEXPECTED_EXIT = "UnexpectedExit";
|
private static final String KEY_UNEXPECTED_EXIT = "UnexpectedExit";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service can be both started by {@link android.app.job.JobScheduler} as a {@link
|
||||||
|
* JobService} and as a started service by calling {@link Context#startService}. These two
|
||||||
|
* states can apply at the same time. The service won't stop until all necessary stop
|
||||||
|
* methods are called:
|
||||||
|
* - Calling jobFinished if it's launched as a JobService.
|
||||||
|
* - Calling stopSelf if it's launched as a start service.
|
||||||
|
*/
|
||||||
|
// If it has a non zero value, then the service is running via onStartCommand.
|
||||||
|
private int mServiceStartedId;
|
||||||
|
|
||||||
|
// If not null then the service is running as a Job service.
|
||||||
|
private JobParameters mJobParameters;
|
||||||
|
|
||||||
|
private boolean isServiceRunning() {
|
||||||
|
return mJobParameters != null || mServiceStartedId != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by JobScheduler.
|
||||||
@Override
|
@Override
|
||||||
public boolean onStartJob(JobParameters params) {
|
public boolean onStartJob(JobParameters params) {
|
||||||
|
assert mJobParameters == null;
|
||||||
|
mJobParameters = params;
|
||||||
|
if (isServiceRunning()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return startNativeService();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by JobScheduler.
|
||||||
|
@Override
|
||||||
|
public boolean onStopJob(JobParameters params) {
|
||||||
|
setUnexpectedExit(false);
|
||||||
|
mJobParameters = null;
|
||||||
|
|
||||||
|
// This should only be called if the service needs to be shut down before we've called
|
||||||
|
// jobFinished. Request reschedule so we can finish downloading component updates.
|
||||||
|
return /*reschedule= */ true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For testing only. To manually start the service on Android builds <= M where force running
|
||||||
|
// the job service doesn't work. The service isn't exported, so other apps won't be able to
|
||||||
|
// force start the service.
|
||||||
|
// Note: This can be simpilified when we stop supporting Android M in WebView (no need to store
|
||||||
|
// the state of how the service is running) or when manually starting the service on M isn't
|
||||||
|
// needed.
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
if (!isServiceRunning() && !startNativeService()) {
|
||||||
|
stopSelf(startId);
|
||||||
|
} else {
|
||||||
|
// Always keep the most recent startId as this is the one that should be used to stop
|
||||||
|
// the service.
|
||||||
|
mServiceStartedId = startId;
|
||||||
|
}
|
||||||
|
return START_STICKY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean startNativeService() {
|
||||||
maybeRecordUnexpectedExit();
|
maybeRecordUnexpectedExit();
|
||||||
|
|
||||||
// TODO(http://crbug.com/1179297) look at doing this in a task on a background thread
|
// TODO(http://crbug.com/1179297) look at doing this in a task on a background thread
|
||||||
@ -62,8 +120,8 @@ public class AwComponentUpdateService extends JobService {
|
|||||||
recordJobDuration(SystemClock.uptimeMillis() - startTime);
|
recordJobDuration(SystemClock.uptimeMillis() - startTime);
|
||||||
recordFilesChanged(count);
|
recordFilesChanged(count);
|
||||||
recordDirectorySize();
|
recordDirectorySize();
|
||||||
jobFinished(params, /* needReschedule= */ false);
|
|
||||||
setUnexpectedExit(false);
|
setUnexpectedExit(false);
|
||||||
|
stopService();
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -71,13 +129,18 @@ public class AwComponentUpdateService extends JobService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Call the appropriate stop method according to how the service is launched.
|
||||||
public boolean onStopJob(JobParameters params) {
|
private void stopService() {
|
||||||
setUnexpectedExit(false);
|
// Service is launched as a started service.
|
||||||
|
if (mServiceStartedId > 0) {
|
||||||
// This should only be called if the service needs to be shut down before we've called
|
stopSelf(mServiceStartedId);
|
||||||
// jobFinished. Request reschedule so we can finish downloading component updates.
|
mServiceStartedId = 0;
|
||||||
return /*reschedule= */ true;
|
}
|
||||||
|
// Service is launched as a job service.
|
||||||
|
if (mJobParameters != null) {
|
||||||
|
jobFinished(mJobParameters, /* needReschedule= */ false);
|
||||||
|
mJobParameters = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recordDirectorySize() {
|
private void recordDirectorySize() {
|
||||||
|
Reference in New Issue
Block a user