diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | 54b6cfa9a9e5b861a9930af873580d6dc20f773c (patch) | |
tree | 35051494d2af230dce54d6b31c6af8fc24091316 /services/java/com/android/server/Installer.java | |
download | frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.zip frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.gz frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.bz2 |
Initial Contribution
Diffstat (limited to 'services/java/com/android/server/Installer.java')
-rw-r--r-- | services/java/com/android/server/Installer.java | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/services/java/com/android/server/Installer.java b/services/java/com/android/server/Installer.java new file mode 100644 index 0000000..fe3ad15 --- /dev/null +++ b/services/java/com/android/server/Installer.java @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.content.pm.PackageStats; +import android.net.LocalSocketAddress; +import android.net.LocalSocket; +import android.util.Config; +import android.util.Log; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + + +class Installer { + private static final String TAG = "Installer"; + InputStream mIn; + OutputStream mOut; + LocalSocket mSocket; + + byte buf[] = new byte[1024]; + int buflen = 0; + + private boolean connect() { + if (mSocket != null) { + return true; + } + Log.i(TAG, "connecting..."); + try { + mSocket = new LocalSocket(); + + LocalSocketAddress address = new LocalSocketAddress( + "installd", LocalSocketAddress.Namespace.RESERVED); + + mSocket.connect(address); + + mIn = mSocket.getInputStream(); + mOut = mSocket.getOutputStream(); + } catch (IOException ex) { + disconnect(); + return false; + } + return true; + } + + private void disconnect() { + Log.i(TAG,"disconnecting..."); + try { + if (mSocket != null) mSocket.close(); + } catch (IOException ex) { } + try { + if (mIn != null) mIn.close(); + } catch (IOException ex) { } + try { + if (mOut != null) mOut.close(); + } catch (IOException ex) { } + mSocket = null; + mIn = null; + mOut = null; + } + + private boolean readBytes(byte buffer[], int len) { + int off = 0, count; + if (len < 0) return false; + while (off != len) { + try { + count = mIn.read(buffer, off, len - off); + if (count <= 0) { + Log.e(TAG, "read error " + count); + break; + } + off += count; + } catch (IOException ex) { + Log.e(TAG,"read exception"); + break; + } + } +// Log.i(TAG, "read "+len+" bytes"); + if (off == len) return true; + disconnect(); + return false; + } + + private boolean readReply() { + int len; + buflen = 0; + if (!readBytes(buf, 2)) return false; + len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8); + if ((len < 1) || (len > 1024)) { + Log.e(TAG,"invalid reply length ("+len+")"); + disconnect(); + return false; + } + if (!readBytes(buf, len)) return false; + buflen = len; + return true; + } + + private boolean writeCommand(String _cmd) { + byte[] cmd = _cmd.getBytes(); + int len = cmd.length; + if ((len < 1) || (len > 1024)) return false; + buf[0] = (byte) (len & 0xff); + buf[1] = (byte) ((len >> 8) & 0xff); + try { + mOut.write(buf, 0, 2); + mOut.write(cmd, 0, len); + } catch (IOException ex) { + Log.e(TAG,"write error"); + disconnect(); + return false; + } + return true; + } + + private synchronized String transaction(String cmd) { + if (!connect()) { + Log.e(TAG, "connection failed"); + return "-1"; + } + + if (!writeCommand(cmd)) { + /* If installd died and restarted in the background + * (unlikely but possible) we'll fail on the next + * write (this one). Try to reconnect and write + * the command one more time before giving up. + */ + Log.e(TAG, "write command failed? reconnect!"); + if (!connect() || !writeCommand(cmd)) { + return "-1"; + } + } +// Log.i(TAG,"send: '"+cmd+"'"); + if (readReply()) { + String s = new String(buf, 0, buflen); +// Log.i(TAG,"recv: '"+s+"'"); + return s; + } else { +// Log.i(TAG,"fail"); + return "-1"; + } + } + + private int execute(String cmd) { + String res = transaction(cmd); + try { + return Integer.parseInt(res); + } catch (NumberFormatException ex) { + return -1; + } + } + + public int install(String name, int uid, int gid) { + StringBuilder builder = new StringBuilder("install"); + builder.append(' '); + builder.append(name); + builder.append(' '); + builder.append(uid); + builder.append(' '); + builder.append(gid); + return execute(builder.toString()); + } + + public int dexopt(String apkPath, int uid, boolean isPublic) { + StringBuilder builder = new StringBuilder("dexopt"); + builder.append(' '); + builder.append(apkPath); + builder.append(' '); + builder.append(uid); + builder.append(isPublic ? " 1" : " 0"); + return execute(builder.toString()); + } + + public int movedex(String srcPath, String dstPath) { + StringBuilder builder = new StringBuilder("movedex"); + builder.append(' '); + builder.append(srcPath); + builder.append(' '); + builder.append(dstPath); + return execute(builder.toString()); + } + + public int rmdex(String codePath) { + StringBuilder builder = new StringBuilder("rmdex"); + builder.append(' '); + builder.append(codePath); + return execute(builder.toString()); + } + + public int remove(String name) { + StringBuilder builder = new StringBuilder("remove"); + builder.append(' '); + builder.append(name); + return execute(builder.toString()); + } + + public int deleteCacheFiles(String name) { + StringBuilder builder = new StringBuilder("rmcache"); + builder.append(' '); + builder.append(name); + return execute(builder.toString()); + } + + public int clearUserData(String name) { + StringBuilder builder = new StringBuilder("rmuserdata"); + builder.append(' '); + builder.append(name); + return execute(builder.toString()); + } + + public boolean ping() { + if (execute("ping") < 0) { + return false; + } else { + return true; + } + } + + public int freeCache(long freeStorageSize) { + StringBuilder builder = new StringBuilder("freecache"); + builder.append(' '); + builder.append(String.valueOf(freeStorageSize)); + return execute(builder.toString()); + } + + public int setForwardLockPerm(String packageName, int gid) { + StringBuilder builder = new StringBuilder("protect"); + builder.append(' '); + builder.append(packageName); + builder.append(' '); + builder.append(gid); + return execute(builder.toString()); + } + + public int getSizeInfo(String pkgName, String apkPath, + String fwdLockApkPath, PackageStats pStats) { + StringBuilder builder = new StringBuilder("getsize"); + builder.append(' '); + builder.append(pkgName); + builder.append(' '); + builder.append(apkPath); + builder.append(' '); + builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!"); + + String s = transaction(builder.toString()); + String res[] = s.split(" "); + + if((res == null) || (res.length != 4)) { + return -1; + } + try { + pStats.codeSize = Long.parseLong(res[1]); + pStats.dataSize = Long.parseLong(res[2]); + pStats.cacheSize = Long.parseLong(res[3]); + return Integer.parseInt(res[0]); + } catch (NumberFormatException e) { + return -1; + } + } +} |