blob: 6cc7189cbde5427f1104e8763631ed7918d63bf1 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.content_shell_apk;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.SparseArray;
import org.chromium.base.CommandLine;
import org.chromium.base.Log;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.base.process_launcher.ChildProcessService;
import org.chromium.base.process_launcher.ChildProcessServiceDelegate;
import javax.annotation.concurrent.GuardedBy;
/**
* Child service started by ChildProcessLauncherTest.
*/
public class TestChildProcessService extends ChildProcessService {
private static final String TAG = "TestProcessService";
private static final long MAIN_BLOCKING_DURATION_MS = 5000;
private static class TestChildProcessServiceDelegate implements ChildProcessServiceDelegate {
private final Object mConnectionSetupLock = new Object();
@GuardedBy("mConnectionSetupLock")
private boolean mConnectionSetup;
private boolean mServiceCreated;
private Bundle mServiceBundle;
private String[] mCommandLine;
private IChildProcessTest mIChildProcessTest;
@Override
public void onServiceCreated() {
mServiceCreated = true;
}
@Override
public void onServiceBound(Intent intent) {
mServiceBundle = intent.getExtras();
}
@Override
public void onConnectionSetup(Bundle connectionBundle, IBinder callback) {
if (callback != null) {
mIChildProcessTest = IChildProcessTest.Stub.asInterface(callback);
}
if (mIChildProcessTest != null) {
try {
mIChildProcessTest.onConnectionSetup(
mServiceCreated, mServiceBundle, connectionBundle);
} catch (RemoteException re) {
Log.e(TAG, "Failed to call IChildProcessTest.onConnectionSetup.", re);
}
}
synchronized (mConnectionSetupLock) {
mConnectionSetup = true;
mConnectionSetupLock.notifyAll();
}
}
@Override
public void onDestroy() {
if (mIChildProcessTest == null) return;
try {
mIChildProcessTest.onDestroy();
} catch (RemoteException re) {
Log.e(TAG, "Failed to call IChildProcessTest.onDestroy.", re);
}
}
@Override
public boolean loadNativeLibrary(Context hostContext) {
// Store the command line before loading the library to avoid an assert in CommandLine.
mCommandLine = CommandLine.getJavaSwitchesOrNull();
LibraryLoader libraryLoader = null;
boolean isLoaded = false;
try {
libraryLoader = LibraryLoader.get(LibraryProcessType.PROCESS_CHILD);
libraryLoader.loadNow();
libraryLoader.ensureInitialized();
isLoaded = true;
} catch (ProcessInitException e) {
Log.e(TAG, "Failed to load native library.", e);
}
// Loading the library happen on the main thread and onConnectionSetup is called from
// the client. Wait for onConnectionSetup so mIChildProcessTest is set.
synchronized (mConnectionSetupLock) {
while (!mConnectionSetup) {
try {
mConnectionSetupLock.wait();
} catch (InterruptedException e) {
// Ignore.
}
}
}
if (mIChildProcessTest != null) {
try {
mIChildProcessTest.onLoadNativeLibrary(isLoaded);
} catch (RemoteException re) {
Log.e(TAG, "Failed to call IChildProcessTest.onLoadNativeLibrary.", re);
}
}
return true;
}
@Override
public SparseArray<String> getFileDescriptorsIdsToKeys() {
return null;
}
@Override
public void onBeforeMain() {
if (mIChildProcessTest == null) return;
try {
mIChildProcessTest.onBeforeMain(mCommandLine);
} catch (RemoteException re) {
Log.e(TAG, "Failed to call IChildProcessTest.onBeforeMain.", re);
}
}
@Override
public void runMain() {
if (mIChildProcessTest != null) {
try {
mIChildProcessTest.onRunMain();
} catch (RemoteException re) {
Log.e(TAG, "Failed to call IChildProcessTest.onRunMain.", re);
}
}
// Run a message loop to keep the service from exiting.
Looper.prepare();
Looper.loop();
}
};
public TestChildProcessService() {
super(new TestChildProcessServiceDelegate());
}
}