在应用程序中可以通过此工具类与android系统native服务通信
这些native服务是指在init.rc中定义的随机启动的服务,如zygote
但是如需要通过此工具类来启动和停止系统服务,需要具有system权限
即需要设置sharedUId=system
这些native服务是指在init.rc中定义的随机启动的服务,如zygote
但是如需要通过此工具类来启动和停止系统服务,需要具有system权限
即需要设置sharedUId=system
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.net.vpn.VpnManager;
import android.os.SystemProperties;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
class Command implements Serializable {
private static final long serialVersionUID = 1L;
private static final boolean DBG = true;
private static final int WAITING_TIME = 15; // sec
private static final String SVC_STATE_CMD_PREFIX = "init.svc.";
private static final String SVC_START_CMD = "ctl.start";
private static final String SVC_STOP_CMD = "ctl.stop";
private static final String SVC_STATE_RUNNING = "running";
private static final String SVC_STATE_STOPPED = "stopped";
private static final int END_OF_ARGUMENTS = 255;
private String mName;
private String mTag;
private transient LocalSocket mControlSocket;
/**
* Creates a proxy of the specified daemon.
* @param daemonName name of the daemon
*/
UsbMacCommand(String daemonName) {
mName = daemonName;
mTag = "UsbMacCommand";
}
void start() throws IOException {
String svc = mName;
if (DBG) Log.i(mTag, "Start usbmac native server " + svc);
SystemProperties.set(SVC_START_CMD, svc);
if (!blockUntil(SVC_STATE_RUNNING, WAITING_TIME)) { //if running
if (DBG) Log.i(mTag, "cannot start service: " + svc);
throw new IOException("cannot start service: " + svc);
} else {
mControlSocket = createServiceSocket();
}
}
int sendCommand(String ...args) throws IOException {
if (DBG) Log.i(mTag,"sendCommand begin");
OutputStream out = getControlSocketOutput();
for (String arg : args) outputString(out, arg);
out.write(END_OF_ARGUMENTS);
out.flush();
int result = getResultFromSocket(true);
if (DBG) Log.i(mTag,"sendCommand return:" + (char)result + "," + result);
return result;
}
// returns 0 if nothing is in the receive buffer
int getResultFromSocket() throws IOException {
return getResultFromSocket(false);
}
void closeControlSocket() {
if (mControlSocket == null) return;
try {
mControlSocket.close();
} catch (IOException e) {
if (DBG) Log.w(mTag, "close control socket", e);
} finally {
mControlSocket = null;
}
}
boolean stop() {
String svc = mName;
if (DBG) Log.i(mTag, "stop usbmac server: " + svc);
SystemProperties.set(SVC_STOP_CMD, svc);
boolean success = blockUntil(SVC_STATE_STOPPED, 5);
if (DBG) Log.i(mTag, "stopping " + svc + " success = " + success);
return success;
}
boolean isStopped() {
String cmd = SVC_STATE_CMD_PREFIX + mName;
return SVC_STATE_STOPPED.equals(SystemProperties.get(cmd));
}
private int getResultFromSocket(boolean blocking) throws IOException {
LocalSocket s = mControlSocket;
if (s == null) return 0;
InputStream in = s.getInputStream();
if (!blocking && in.available() == 0) return 0;
int data = in.read();
return data;
}
private LocalSocket createServiceSocket() throws IOException {
LocalSocket s = new LocalSocket();
LocalSocketAddress a = new LocalSocketAddress(mName,
LocalSocketAddress.Namespace.RESERVED);
// try a few times in case the service has not listen()ed
IOException excp = null;
for (int i = 0; i < 10; i++) {
try {
s.connect(a);
return s;
} catch (IOException e) {
if (DBG) Log.w(mTag, "service not yet listen()ing; try again");
excp = e;
sleep(500);
}
}
throw excp;
}
private OutputStream getControlSocketOutput() throws IOException {
if (mControlSocket != null) {
return mControlSocket.getOutputStream();
} else {
throw new IOException("no control socket available");
}
}
/**
* Waits for the process to be in the expected state. The method returns
* false if after the specified duration (in seconds), the process is still
* not in the expected state.
*/
private boolean blockUntil(String expectedState, int waitTime) {
String cmd = SVC_STATE_CMD_PREFIX + mName;
int sleepTime = 200; // ms
int n = waitTime * 1000 / sleepTime;
for (int i = 0; i < n; i++) {
if (expectedState.equals(SystemProperties.get(cmd))) {
if (DBG) {
Log.i(mTag, mName + " is " + expectedState + " after "
+ (i * sleepTime) + " msec");
}
break;
}
sleep(sleepTime);
}
return expectedState.equals(SystemProperties.get(cmd));
}
private void outputString(OutputStream out, String s) throws IOException {
byte[] bytes = s.getBytes();
out.write(bytes.length);
out.write(bytes);
out.flush();
}
private void sleep(int msec) {
try {
Thread.currentThread().sleep(msec);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}