19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootpackage com.android.server.pm;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageStats;
20a3cdaa5337fa573c4c61770195d6232c2e587090Jason parksimport android.net.LocalSocket;
21cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport android.net.LocalSocketAddress;
228a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28f69c812f49cb2dea296cd319984e58af026f4c3aJeff Brownpublic final class Installer {
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "Installer";
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3163ebffcb84f4e2fc55d576aed07c4559f66d97a8Joe Onorato    private static final boolean LOCAL_DEBUG = false;
32cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
33cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    InputStream mIn;
34cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
35cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    OutputStream mOut;
36cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
37cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    LocalSocket mSocket;
38cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
39cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    byte buf[] = new byte[1024];
40cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
41cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    int buflen = 0;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean connect() {
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mSocket != null) {
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
478a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.i(TAG, "connecting...");
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSocket = new LocalSocket();
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
51cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            LocalSocketAddress address = new LocalSocketAddress("installd",
52cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                    LocalSocketAddress.Namespace.RESERVED);
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSocket.connect(address);
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIn = mSocket.getInputStream();
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOut = mSocket.getOutputStream();
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException ex) {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            disconnect();
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
65cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    private void disconnect() {
66cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        Slog.i(TAG, "disconnecting...");
67cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        try {
68cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            if (mSocket != null)
69cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                mSocket.close();
70cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        } catch (IOException ex) {
71cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
72cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        try {
73cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            if (mIn != null)
74cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                mIn.close();
75cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        } catch (IOException ex) {
76cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
77cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        try {
78cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            if (mOut != null)
79cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                mOut.close();
80cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        } catch (IOException ex) {
81cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
82cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        mSocket = null;
83cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        mIn = null;
84cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        mOut = null;
85cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
86cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
87cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    private boolean readBytes(byte buffer[], int len) {
88cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        int off = 0, count;
89cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if (len < 0)
90cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return false;
91cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        while (off != len) {
92cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            try {
93cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                count = mIn.read(buffer, off, len - off);
94cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                if (count <= 0) {
958a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.e(TAG, "read error " + count);
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
98cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                off += count;
99cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            } catch (IOException ex) {
100cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                Slog.e(TAG, "read exception");
101cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                break;
102cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            }
103cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
104cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if (LOCAL_DEBUG) {
105cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            Slog.i(TAG, "read " + len + " bytes");
106cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
107cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if (off == len)
108cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return true;
109cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        disconnect();
110cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        return false;
111cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
112cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
113cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    private boolean readReply() {
114cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        int len;
115cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        buflen = 0;
116cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if (!readBytes(buf, 2))
117cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return false;
118cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8);
119cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if ((len < 1) || (len > 1024)) {
120cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            Slog.e(TAG, "invalid reply length (" + len + ")");
121cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            disconnect();
122cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return false;
123cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
124cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if (!readBytes(buf, len))
125cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return false;
126cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        buflen = len;
127cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        return true;
128cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
129cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
130cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    private boolean writeCommand(String _cmd) {
131cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        byte[] cmd = _cmd.getBytes();
132cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        int len = cmd.length;
133cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if ((len < 1) || (len > 1024))
134cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return false;
135cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        buf[0] = (byte) (len & 0xff);
136cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        buf[1] = (byte) ((len >> 8) & 0xff);
137cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        try {
138cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            mOut.write(buf, 0, 2);
139cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            mOut.write(cmd, 0, len);
140cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        } catch (IOException ex) {
141cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            Slog.e(TAG, "write error");
142cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            disconnect();
143cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return false;
144cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
145cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        return true;
146cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
147cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
148cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    private synchronized String transaction(String cmd) {
149cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if (!connect()) {
1508a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "connection failed");
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "-1";
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!writeCommand(cmd)) {
155cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            /*
156cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root             * If installd died and restarted in the background (unlikely but
157cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root             * possible) we'll fail on the next write (this one). Try to
158cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root             * reconnect and write the command one more time before giving up.
159cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root             */
1608a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "write command failed? reconnect!");
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!connect() || !writeCommand(cmd)) {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return "-1";
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
165cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if (LOCAL_DEBUG) {
166cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            Slog.i(TAG, "send: '" + cmd + "'");
167cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
168cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if (readReply()) {
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String s = new String(buf, 0, buflen);
170cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            if (LOCAL_DEBUG) {
171cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                Slog.i(TAG, "recv: '" + s + "'");
172cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            }
173cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return s;
174cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        } else {
175cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            if (LOCAL_DEBUG) {
176cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                Slog.i(TAG, "fail");
177cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            }
178cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return "-1";
179cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
180cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
181cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
182cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    private int execute(String cmd) {
183cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        String res = transaction(cmd);
184cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        try {
185cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return Integer.parseInt(res);
186cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        } catch (NumberFormatException ex) {
187cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return -1;
188cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
189cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19135ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    public int install(String name, int uid, int gid) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder builder = new StringBuilder("install");
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(name);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(uid);
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(gid);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return execute(builder.toString());
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int dexopt(String apkPath, int uid, boolean isPublic) {
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder builder = new StringBuilder("dexopt");
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(apkPath);
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(uid);
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(isPublic ? " 1" : " 0");
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return execute(builder.toString());
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int movedex(String srcPath, String dstPath) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder builder = new StringBuilder("movedex");
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(srcPath);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(dstPath);
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return execute(builder.toString());
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int rmdex(String codePath) {
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder builder = new StringBuilder("rmdex");
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(codePath);
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return execute(builder.toString());
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2280b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    public int remove(String name, int userId) {
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder builder = new StringBuilder("remove");
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(name);
2320b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(' ');
2330b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(userId);
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return execute(builder.toString());
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23735ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    public int rename(String oldname, String newname) {
238b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn        StringBuilder builder = new StringBuilder("rename");
239b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn        builder.append(' ');
240b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn        builder.append(oldname);
241b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn        builder.append(' ');
242b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn        builder.append(newname);
243b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn        return execute(builder.toString());
244b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn    }
245b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn
246383fa18b511c195cc51a96c5504442bfec998e9fDave Burke    public int fixUid(String name, int uid, int gid) {
247d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn        StringBuilder builder = new StringBuilder("fixuid");
248d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn        builder.append(' ');
249d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn        builder.append(name);
250d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn        builder.append(' ');
251d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn        builder.append(uid);
252d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn        builder.append(' ');
253383fa18b511c195cc51a96c5504442bfec998e9fDave Burke        builder.append(gid);
254d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn        return execute(builder.toString());
255d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn    }
256d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn
25754289b8b4a110cc1ae106d79785cc762a2aebd6eAmith Yamasani    public int deleteCacheFiles(String name, int userId) {
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder builder = new StringBuilder("rmcache");
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(name);
26154289b8b4a110cc1ae106d79785cc762a2aebd6eAmith Yamasani        builder.append(' ');
26254289b8b4a110cc1ae106d79785cc762a2aebd6eAmith Yamasani        builder.append(userId);
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return execute(builder.toString());
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
265cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
2660b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    public int createUserData(String name, int uid, int userId) {
2670b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        StringBuilder builder = new StringBuilder("mkuserdata");
2680b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(' ');
2690b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(name);
2700b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(' ');
2710b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(uid);
2720b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(' ');
2730b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(userId);
2740b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        return execute(builder.toString());
2750b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    }
2760b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
2770b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    public int removeUserDataDirs(int userId) {
2780b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        StringBuilder builder = new StringBuilder("rmuser");
2790b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(' ');
2800b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(userId);
2810b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        return execute(builder.toString());
2820b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    }
2830b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
2840b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    public int clearUserData(String name, int userId) {
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder builder = new StringBuilder("rmuserdata");
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(name);
2880b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(' ');
2890b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        builder.append(userId);
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return execute(builder.toString());
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
292cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
293742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    /**
294742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * Clone all the package data directories from srcUserId to targetUserId. If copyData is true,
295742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * some of the data is also copied, otherwise just empty directories are created with the
296742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * correct access rights.
297742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * @param srcUserId user to copy the data directories from
298742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * @param targetUserId user to copy the data directories to
299742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * @param copyData whether the data itself is to be copied. If false, empty directories are
300742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * created.
301742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     * @return success/error code
302742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani     */
303742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    public int cloneUserData(int srcUserId, int targetUserId, boolean copyData) {
304742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        StringBuilder builder = new StringBuilder("cloneuserdata");
305742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        builder.append(' ');
306742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        builder.append(srcUserId);
307742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        builder.append(' ');
308742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        builder.append(targetUserId);
309742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        builder.append(' ');
310742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        builder.append(copyData ? '1' : '0');
311742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return execute(builder.toString());
312742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
313742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean ping() {
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (execute("ping") < 0) {
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
321cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int freeCache(long freeStorageSize) {
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder builder = new StringBuilder("freecache");
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(String.valueOf(freeStorageSize));
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return execute(builder.toString());
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3290c3804950236fe170ebf6cc7a5f1e3e305b8f315Dianne Hackborn    public int getSizeInfo(String pkgName, int persona, String apkPath, String fwdLockApkPath,
330292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn            String asecPath, PackageStats pStats) {
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder builder = new StringBuilder("getsize");
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(pkgName);
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
3350c3804950236fe170ebf6cc7a5f1e3e305b8f315Dianne Hackborn        builder.append(persona);
3360c3804950236fe170ebf6cc7a5f1e3e305b8f315Dianne Hackborn        builder.append(' ');
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(apkPath);
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(' ');
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
340292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn        builder.append(' ');
341292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn        builder.append(asecPath != null ? asecPath : "!");
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String s = transaction(builder.toString());
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String res[] = s.split(" ");
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
346292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn        if ((res == null) || (res.length != 5)) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pStats.codeSize = Long.parseLong(res[1]);
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pStats.dataSize = Long.parseLong(res[2]);
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pStats.cacheSize = Long.parseLong(res[3]);
353292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn            pStats.externalCodeSize = Long.parseLong(res[4]);
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return Integer.parseInt(res[0]);
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (NumberFormatException e) {
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
358cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
359b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn
360b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn    public int moveFiles() {
361b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn        return execute("movefiles");
362b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn    }
3636a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root
364ddbe50df2ca70700a46e5849347989b520d1113eKenny Root    /**
365ddbe50df2ca70700a46e5849347989b520d1113eKenny Root     * Links the native library directory in an application's directory to its
366ddbe50df2ca70700a46e5849347989b520d1113eKenny Root     * real location.
367ddbe50df2ca70700a46e5849347989b520d1113eKenny Root     *
368ddbe50df2ca70700a46e5849347989b520d1113eKenny Root     * @param dataPath data directory where the application is
369ddbe50df2ca70700a46e5849347989b520d1113eKenny Root     * @param nativeLibPath target native library path
370ddbe50df2ca70700a46e5849347989b520d1113eKenny Root     * @return -1 on error
371ddbe50df2ca70700a46e5849347989b520d1113eKenny Root     */
372a3e90798b7ad3ed62e5b31842c699b2f98bd457bKenny Root    public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath, int userId) {
3736a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root        if (dataPath == null) {
3749bbd70a96397bd5f1445ad6c21977fccfb350dfaKenny Root            Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
3756a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root            return -1;
3766a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root        } else if (nativeLibPath == null) {
3779bbd70a96397bd5f1445ad6c21977fccfb350dfaKenny Root            Slog.e(TAG, "linkNativeLibraryDirectory nativeLibPath is null");
3786a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root            return -1;
3796a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root        }
3806a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root
3816a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root        StringBuilder builder = new StringBuilder("linklib ");
3826a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root        builder.append(dataPath);
3836a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root        builder.append(' ');
3846a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root        builder.append(nativeLibPath);
385a3e90798b7ad3ed62e5b31842c699b2f98bd457bKenny Root        builder.append(' ');
386a3e90798b7ad3ed62e5b31842c699b2f98bd457bKenny Root        builder.append(userId);
3876a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root
3886a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root        return execute(builder.toString());
3896a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root    }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
391