Mark resource-only splits as hasCode=false.

PackageManagerService now skips dexopt for split APKs that don't
declare they have code.  Also surface more detailed error messages
in logs.

Bug: 14975160
Change-Id: Ie6078dba724815020cee59b7fc52317e88ca097a
This commit is contained in:
Jeff Sharkey
2014-07-15 20:18:34 -07:00
parent da96e137bc
commit 78a130144b
4 changed files with 48 additions and 11 deletions

View File

@@ -846,7 +846,7 @@ public class PackageParser {
throw e;
} catch (Exception e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Unable to read AndroidManifest.xml of " + apkPath);
"Failed to read manifest from " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
IoUtils.closeQuietly(assets);
@@ -895,7 +895,7 @@ public class PackageParser {
throw e;
} catch (Exception e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Unable to read AndroidManifest.xml of " + apkPath);
"Failed to read manifest from " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
IoUtils.closeQuietly(assets);
@@ -910,9 +910,13 @@ public class PackageParser {
* omitted here.
*/
private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
int splitIndex, String[] outError) throws XmlPullParserException, IOException {
int splitIndex, String[] outError) throws XmlPullParserException, IOException,
PackageParserException {
AttributeSet attrs = parser;
// We parsed manifest tag earlier; just skip past it
parsePackageSplitNames(parser, attrs, flags);
mParseInstrumentationArgs = null;
mParseActivityArgs = null;
mParseServiceArgs = null;

View File

@@ -39,4 +39,20 @@ public class ExceptionUtils {
throw new IOException(e.getMessage().substring(PREFIX_IO.length()));
}
}
public static String getCompleteMessage(String msg, Throwable t) {
final StringBuilder builder = new StringBuilder();
if (msg != null) {
builder.append(msg).append(": ");
}
builder.append(t.getMessage());
while ((t = t.getCause()) != null) {
builder.append(": ").append(t.getMessage());
}
return builder.toString();
}
public static String getCompleteMessage(Throwable t) {
return getCompleteMessage(null, t);
}
}

View File

@@ -165,6 +165,7 @@ import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.ExceptionUtils;
import android.util.Log;
import android.util.LogPrinter;
import android.util.PrintStreamPrinter;
@@ -9855,6 +9856,18 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, msg);
}
public void setError(String msg, PackageParserException e) {
returnCode = e.error;
returnMsg = ExceptionUtils.getCompleteMessage(msg, e);
Slog.w(TAG, msg, e);
}
public void setError(String msg, PackageManagerException e) {
returnCode = e.error;
returnMsg = ExceptionUtils.getCompleteMessage(msg, e);
Slog.w(TAG, msg, e);
}
// In some error cases we want to convey more info back to the observer
String origPackage;
String origPermission;
@@ -9908,8 +9921,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
} catch (PackageManagerException e) {
res.setError(e.error,
"Package couldn't be installed in " + pkg.codePath + ": " + e.getMessage());
res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
}
@@ -10007,8 +10019,7 @@ public class PackageManagerService extends IPackageManager.Stub {
updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
updatedSettings = true;
} catch (PackageManagerException e) {
res.setError(e.error,
"Package couldn't be installed in " + pkg.codePath + ": " + e.getMessage());
res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
}
@@ -10139,8 +10150,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
} catch (PackageManagerException e) {
res.setError(e.error,
"Package couldn't be installed in " + pkg.codePath + ": " + e.getMessage());
res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
@@ -10278,7 +10288,7 @@ public class PackageManagerService extends IPackageManager.Stub {
try {
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
} catch (PackageParserException e) {
res.setError(e.error, "Failed parse during installPackageLI: " + e.getMessage());
res.setError("Failed parse during installPackageLI", e);
return;
}
@@ -10294,7 +10304,7 @@ public class PackageManagerService extends IPackageManager.Stub {
pp.collectCertificates(pkg, parseFlags);
pp.collectManifestDigest(pkg);
} catch (PackageParserException e) {
res.setError(e.error, "Failed collect during installPackageLI: " + e.getMessage());
res.setError("Failed collect during installPackageLI", e);
return;
}

View File

@@ -931,6 +931,13 @@ status_t generateAndroidManifestForSplit(Bundle* bundle, const sp<AaptAssets>& a
// Build an empty <application> tag (required).
sp<XMLNode> app = XMLNode::newElement(filename, String16(), String16("application"));
// Add the 'hasCode' attribute which is never true for resource splits.
if (!addTagAttribute(app, RESOURCES_ANDROID_NAMESPACE, "hasCode",
"false", true, true)) {
return UNKNOWN_ERROR;
}
manifest->addChild(app);
root->addChild(manifest);