129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath/* 229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * Copyright (C) 2008 The Android Open Source Project 329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * 429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * Licensed under the Apache License, Version 2.0 (the "License"); 529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * you may not use this file except in compliance with the License. 629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * You may obtain a copy of the License at 729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * 829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * http://www.apache.org/licenses/LICENSE-2.0 929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * 1029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * Unless required by applicable law or agreed to in writing, software 1129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * distributed under the License is distributed on an "AS IS" BASIS, 1229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * See the License for the specific language governing permissions and 1429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * limitations under the License 1529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath */ 1629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 1729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamathpackage com.android.internal.os; 1829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 1929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamathimport android.net.LocalSocket; 2029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamathimport android.net.LocalSocketAddress; 21c8a2cfed0192afc6a408f4bdb77e8a0bdd5d752bMakoto Onukiimport android.os.SystemClock; 22fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkeyimport android.text.TextUtils; 2329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamathimport android.util.Slog; 24fa54ab7950b7ad7605cb842b47826b71a685bc28Todd Kennedy 258948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkeyimport com.android.internal.util.Preconditions; 268948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey 2729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamathimport libcore.io.IoUtils; 2829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamathimport libcore.io.Streams; 2929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 3029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamathimport java.io.IOException; 3129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamathimport java.io.InputStream; 3229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamathimport java.io.OutputStream; 33fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkeyimport java.util.Arrays; 3429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 3529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath/** 3629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * Represents a connection to {@code installd}. Allows multiple connect and 3729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * disconnect cycles. 3829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * 3929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * @hide for internal use only 4029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath */ 4129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamathpublic class InstallerConnection { 4229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath private static final String TAG = "InstallerConnection"; 4329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath private static final boolean LOCAL_DEBUG = false; 4429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 4529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath private InputStream mIn; 4629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath private OutputStream mOut; 4729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath private LocalSocket mSocket; 4829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 498948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey private volatile Object mWarnIfHeld; 508948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey 5129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath private final byte buf[] = new byte[1024]; 5229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 5329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath public InstallerConnection() { 5429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 5529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 568948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey /** 578948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey * Yell loudly if someone tries making future calls while holding a lock on 588948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey * the given object. 598948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey */ 608948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey public void setWarnIfHeld(Object warnIfHeld) { 618948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey Preconditions.checkState(mWarnIfHeld == null); 628948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld); 638948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey } 648948c01eb726ec79983472e5597ddac8004f9f44Jeff Sharkey 6529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath public synchronized String transact(String cmd) { 66fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) { 67fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x" 68fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable()); 69fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey } 70fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey 7129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (!connect()) { 7229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.e(TAG, "connection failed"); 7329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return "-1"; 7429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 7529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 7629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (!writeCommand(cmd)) { 7729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath /* 7829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * If installd died and restarted in the background (unlikely but 7929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * possible) we'll fail on the next write (this one). Try to 8029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath * reconnect and write the command one more time before giving up. 8129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath */ 8229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.e(TAG, "write command failed? reconnect!"); 8329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (!connect() || !writeCommand(cmd)) { 8429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return "-1"; 8529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 8629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 8729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (LOCAL_DEBUG) { 8829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.i(TAG, "send: '" + cmd + "'"); 8929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 9029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 9129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath final int replyLength = readReply(); 9229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (replyLength > 0) { 9329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath String s = new String(buf, 0, replyLength); 9429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (LOCAL_DEBUG) { 9529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.i(TAG, "recv: '" + s + "'"); 9629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 9729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return s; 9829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } else { 9929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (LOCAL_DEBUG) { 10029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.i(TAG, "fail"); 10129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 10229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return "-1"; 10329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 10429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 10529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 1064288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey public String[] execute(String cmd, Object... args) throws InstallerException { 107fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey final StringBuilder builder = new StringBuilder(cmd); 108fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey for (Object arg : args) { 109fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey String escaped; 110fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey if (arg == null) { 111fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey escaped = ""; 112fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey } else { 113fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey escaped = String.valueOf(arg); 114fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey } 115fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey if (escaped.indexOf('\0') != -1 || escaped.indexOf(' ') != -1 || "!".equals(escaped)) { 116fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey throw new InstallerException( 117fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey "Invalid argument while executing " + cmd + " " + Arrays.toString(args)); 118fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey } 119fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey if (TextUtils.isEmpty(escaped)) { 120fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey escaped = "!"; 121fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey } 122fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey builder.append(' ').append(escaped); 12329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 1244288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey final String[] resRaw = transact(builder.toString()).split(" "); 1254288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey int res = -1; 1264288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey try { 1274288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey res = Integer.parseInt(resRaw[0]); 1284288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey } catch (ArrayIndexOutOfBoundsException | NumberFormatException ignored) { 1294288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey } 1304288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey if (res != 0) { 1314288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey throw new InstallerException( 1324288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey "Failed to execute " + cmd + " " + Arrays.toString(args) + ": " + res); 1334288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey } 1344288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey return resRaw; 13529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 13629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 137fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded, 138c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries) 139c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao throws InstallerException { 140c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded, null /*outputPath*/, dexFlags, 141c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao compilerFilter, volumeUuid, sharedLibraries); 142feb193085adbdc379ee70dbb7dc6ae4c9f2971ddCalin Juravle } 143feb193085adbdc379ee70dbb7dc6ae4c9f2971ddCalin Juravle 144fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey public void dexopt(String apkPath, int uid, String pkgName, String instructionSet, 145bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe int dexoptNeeded, String outputPath, int dexFlags, String compilerFilter, 146c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao String volumeUuid, String sharedLibraries) throws InstallerException { 147db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle execute("dexopt", 148db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle apkPath, 149db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle uid, 150db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle pkgName, 151db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle instructionSet, 152db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle dexoptNeeded, 153db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle outputPath, 154db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle dexFlags, 155bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe compilerFilter, 156c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao volumeUuid, 157c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao sharedLibraries); 158bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe } 159bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe 160a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr private boolean safeParseBooleanResult(String[] res) throws InstallerException { 161bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe if ((res == null) || (res.length != 2)) { 1624288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey throw new InstallerException("Invalid size result: " + Arrays.toString(res)); 163bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe } 164bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe 165bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe // Just as a sanity check. Anything != "true" will be interpreted as false by parseBoolean. 166bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe if (!res[1].equals("true") && !res[1].equals("false")) { 1674288419787120ce85a241a4b315d7d2123aa2d4aJeff Sharkey throw new InstallerException("Invalid boolean result: " + Arrays.toString(res)); 168bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe } 169bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe 170bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe return Boolean.parseBoolean(res[1]); 17129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 17229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 173a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr public boolean mergeProfiles(int uid, String pkgName) throws InstallerException { 174a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr final String[] res = execute("merge_profiles", uid, pkgName); 175a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr 176a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr return safeParseBooleanResult(res); 177a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr } 178a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr 179a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr public boolean dumpProfiles(String gid, String packageName, String codePaths) 180a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr throws InstallerException { 181a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr final String[] res = execute("dump_profiles", gid, packageName, codePaths); 182a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr 183a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr return safeParseBooleanResult(res); 184a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr } 185a87770828637813dacd176ba3c8d3810f7ed6ab8David Sehr 18629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath private boolean connect() { 18729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (mSocket != null) { 18829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return true; 18929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 19029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.i(TAG, "connecting..."); 19129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath try { 19229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath mSocket = new LocalSocket(); 19329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 19429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath LocalSocketAddress address = new LocalSocketAddress("installd", 19529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath LocalSocketAddress.Namespace.RESERVED); 19629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 19729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath mSocket.connect(address); 19829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 19929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath mIn = mSocket.getInputStream(); 20029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath mOut = mSocket.getOutputStream(); 20129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } catch (IOException ex) { 20229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath disconnect(); 20329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return false; 20429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 20529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return true; 20629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 20729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 20829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath public void disconnect() { 20929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.i(TAG, "disconnecting..."); 21029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath IoUtils.closeQuietly(mSocket); 21129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath IoUtils.closeQuietly(mIn); 21229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath IoUtils.closeQuietly(mOut); 21329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 21429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath mSocket = null; 21529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath mIn = null; 21629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath mOut = null; 21729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 21829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 21929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 22029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath private boolean readFully(byte[] buffer, int len) { 22129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath try { 22229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Streams.readFully(mIn, buffer, 0, len); 22329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } catch (IOException ioe) { 22429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.e(TAG, "read exception"); 22529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath disconnect(); 22629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return false; 22729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 22829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 22929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (LOCAL_DEBUG) { 23029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.i(TAG, "read " + len + " bytes"); 23129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 23229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 23329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return true; 23429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 23529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 23629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath private int readReply() { 23729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (!readFully(buf, 2)) { 23829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return -1; 23929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 24029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 24129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath final int len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8); 24229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if ((len < 1) || (len > buf.length)) { 24329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.e(TAG, "invalid reply length (" + len + ")"); 24429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath disconnect(); 24529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return -1; 24629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 24729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 24829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if (!readFully(buf, len)) { 24929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return -1; 25029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 25129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 25229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return len; 25329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 25429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 25529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath private boolean writeCommand(String cmdString) { 25629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath final byte[] cmd = cmdString.getBytes(); 25729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath final int len = cmd.length; 25829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath if ((len < 1) || (len > buf.length)) { 25929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return false; 26029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 26129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath 26229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath buf[0] = (byte) (len & 0xff); 26329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath buf[1] = (byte) ((len >> 8) & 0xff); 26429564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath try { 26529564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath mOut.write(buf, 0, 2); 26629564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath mOut.write(cmd, 0, len); 26729564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } catch (IOException ex) { 26829564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath Slog.e(TAG, "write error"); 26929564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath disconnect(); 27029564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return false; 27129564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 27229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath return true; 27329564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath } 274c8a2cfed0192afc6a408f4bdb77e8a0bdd5d752bMakoto Onuki 275c8a2cfed0192afc6a408f4bdb77e8a0bdd5d752bMakoto Onuki public void waitForConnection() { 276c8a2cfed0192afc6a408f4bdb77e8a0bdd5d752bMakoto Onuki for (;;) { 277fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey try { 278fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey execute("ping"); 279c8a2cfed0192afc6a408f4bdb77e8a0bdd5d752bMakoto Onuki return; 280fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey } catch (InstallerException ignored) { 281c8a2cfed0192afc6a408f4bdb77e8a0bdd5d752bMakoto Onuki } 282c8a2cfed0192afc6a408f4bdb77e8a0bdd5d752bMakoto Onuki Slog.w(TAG, "installd not ready"); 283c8a2cfed0192afc6a408f4bdb77e8a0bdd5d752bMakoto Onuki SystemClock.sleep(1000); 284c8a2cfed0192afc6a408f4bdb77e8a0bdd5d752bMakoto Onuki } 285c8a2cfed0192afc6a408f4bdb77e8a0bdd5d752bMakoto Onuki } 286fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey 287fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey public static class InstallerException extends Exception { 288fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey public InstallerException(String detailMessage) { 289fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey super(detailMessage); 290fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey } 291fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey } 29229564cd24589867f653cd22cabbaac6493cfc530Narayan Kamath} 293