`
月下独酌
  • 浏览: 128543 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

app socket native

 
阅读更多
在应用程序中可以通过此工具类与android系统native服务通信
这些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);
        }
    }
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics