summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2009-06-18 17:10:57 -0700
committerDianne Hackborn <hackbod@google.com>2009-06-18 17:10:57 -0700
commit5c1e00b14d2ef10ec76abf3e951fa8003a67f558 (patch)
treefa723a6f96f5b977dfdfdc08b5b8aab98c20d500
parente748161ca89867e8c57d4e71c780486d4de8039c (diff)
downloadframeworks_base-5c1e00b14d2ef10ec76abf3e951fa8003a67f558.zip
frameworks_base-5c1e00b14d2ef10ec76abf3e951fa8003a67f558.tar.gz
frameworks_base-5c1e00b14d2ef10ec76abf3e951fa8003a67f558.tar.bz2
Fix targetSdkVersion, make resize mode a flag, delayed dexopt, easy ApplicationInfo.
- Fix a bug where targetSdkVersion could not be set if minSdkVersion. Stupid, stupid. Also make sure to fail if minSdkVersion is for a code name. Really stupid. - Change the API for resize compatibility mode to be a bit in the flags field, instead of a separate boolean. - Implement delayed dexopting, to avoid the looong full dexopt during boot. This is only enabled for "eng" builds. When in this mode, the activity manager will make sure that a dexopt has been done before loading an .apk into a process, and will try to avoid displaying ANRs if they are due to the dexopt causing some operation to take longer than it normally would (though I make no guarantees about this totally working). - Add API to Context to get the ApplicationInfo for its package, for easy access to things like targetSdkVersion.
-rw-r--r--api/current.xml65
-rw-r--r--core/java/android/app/ActivityThread.java6
-rw-r--r--core/java/android/app/ApplicationContext.java8
-rw-r--r--core/java/android/content/Context.java4
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java19
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl7
-rw-r--r--core/java/android/content/pm/PackageManager.java6
-rw-r--r--core/java/android/content/pm/PackageParser.java50
-rw-r--r--core/java/android/content/res/CompatibilityInfo.java3
-rw-r--r--services/java/com/android/server/PackageManagerService.java92
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java62
-rw-r--r--services/java/com/android/server/am/HistoryRecord.java6
-rw-r--r--test-runner/android/test/mock/MockContext.java6
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java7
15 files changed, 263 insertions, 84 deletions
diff --git a/api/current.xml b/api/current.xml
index 4efc71f..95c396f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -27473,6 +27473,17 @@
visibility="public"
>
</method>
+<method name="getApplicationInfo"
+ return="android.content.pm.ApplicationInfo"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getAssets"
return="android.content.res.AssetManager"
abstract="true"
@@ -28825,6 +28836,17 @@
visibility="public"
>
</method>
+<method name="getApplicationInfo"
+ return="android.content.pm.ApplicationInfo"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getAssets"
return="android.content.res.AssetManager"
abstract="false"
@@ -35185,6 +35207,17 @@
visibility="public"
>
</field>
+<field name="FLAG_SUPPORTS_LARGE_SCREENS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="512"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="FLAG_SYSTEM"
type="int"
transient="false"
@@ -35258,16 +35291,6 @@
visibility="public"
>
</field>
-<field name="expandable"
- type="boolean"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="flags"
type="int"
transient="false"
@@ -37127,17 +37150,6 @@
visibility="public"
>
</field>
-<field name="GET_EXPANDABLE"
- type="int"
- transient="false"
- volatile="false"
- value="131072"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="GET_GIDS"
type="int"
transient="false"
@@ -114387,6 +114399,17 @@
visibility="public"
>
</method>
+<method name="getApplicationInfo"
+ return="android.content.pm.ApplicationInfo"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getAssets"
return="android.content.res.AssetManager"
abstract="false"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 477badb..6873379 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -187,7 +187,7 @@ public final class ActivityThread {
try {
appInfo = getPackageManager().getApplicationInfo(
pkgInfo.getPackageName(),
- PackageManager.GET_SUPPORTS_DENSITIES | PackageManager.GET_EXPANDABLE);
+ PackageManager.GET_SUPPORTS_DENSITIES);
} catch (RemoteException e) {
throw new AssertionError(e);
}
@@ -287,6 +287,10 @@ public final class ActivityThread {
return mPackageName;
}
+ public ApplicationInfo getApplicationInfo() {
+ return mApplicationInfo;
+ }
+
public boolean isSecurityViolation() {
return mSecurityViolation;
}
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 23daf12..bbad8f4 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -283,6 +283,14 @@ class ApplicationContext extends Context {
}
@Override
+ public ApplicationInfo getApplicationInfo() {
+ if (mPackageInfo != null) {
+ return mPackageInfo.getApplicationInfo();
+ }
+ throw new RuntimeException("Not supported in system context");
+ }
+
+ @Override
public String getPackageResourcePath() {
if (mPackageInfo != null) {
return mPackageInfo.getResDir();
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 925249e..b0396f6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -16,6 +16,7 @@
package android.content;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
@@ -233,6 +234,9 @@ public abstract class Context {
/** Return the name of this application's package. */
public abstract String getPackageName();
+ /** Return the full application info for this context's package. */
+ public abstract ApplicationInfo getApplicationInfo();
+
/**
* {@hide}
* Return the full path to this context's resource files. This is the ZIP files
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 262204e..7513b3b 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -16,6 +16,7 @@
package android.content;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
@@ -120,6 +121,11 @@ public class ContextWrapper extends Context {
}
@Override
+ public ApplicationInfo getApplicationInfo() {
+ return mBase.getApplicationInfo();
+ }
+
+ @Override
public String getPackageResourcePath() {
return mBase.getPackageResourcePath();
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index f10dd53..2a2cf93 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -137,6 +137,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public static final int FLAG_TEST_ONLY = 1<<8;
/**
+ * Value for {@link #flags}: true when the application's window can be
+ * expanded over default window size in target density (320x480 for
+ * 1.0 density, 480x720 for 1.5 density etc)
+ */
+ public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<9;
+
+ /**
* Value for {@link #flags}: this is false if the application has set
* its android:allowBackup to false, true otherwise.
*
@@ -201,12 +208,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public int[] supportsDensities;
/**
- * True when the application's window can be expanded over default window
- * size in target density (320x480 for 1.0 density, 480x720 for 1.5 density etc)
- */
- public boolean expandable = false;
-
- /**
* The minimum SDK version this application targets. It may run on earilier
* versions, but it knows how to work with any new behavior added at this
* version. Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
@@ -240,7 +241,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));
pw.println(prefix + "supportsDensities=" + supportsDensities);
- pw.println(prefix + "expandable=" + expandable);
super.dumpBack(pw, prefix);
}
@@ -288,7 +288,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
manageSpaceActivityName = orig.manageSpaceActivityName;
descriptionRes = orig.descriptionRes;
supportsDensities = orig.supportsDensities;
- expandable = orig.expandable;
}
@@ -321,7 +320,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
dest.writeString(backupAgentName);
dest.writeInt(descriptionRes);
dest.writeIntArray(supportsDensities);
- dest.writeInt(expandable ? 1 : 0);
}
public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -353,7 +351,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
backupAgentName = source.readString();
descriptionRes = source.readInt();
supportsDensities = source.createIntArray();
- expandable = source.readInt() != 0;
}
/**
@@ -383,7 +380,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
public void disableCompatibilityMode() {
- expandable = true;
+ flags |= FLAG_SUPPORTS_LARGE_SCREENS;
supportsDensities = ANY_DENSITIES_ARRAY;
}
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 5656b6b..b33a85b 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -301,4 +301,11 @@ interface IPackageManager {
boolean isSafeMode();
void systemReady();
boolean hasSystemUidErrors();
+
+ /**
+ * Ask the package manager to perform dex-opt (if needed) on the given
+ * package, if it already hasn't done mode. Only does this if running
+ * in the special development "no pre-dexopt" mode.
+ */
+ boolean performDexOpt(String packageName);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f746a40..e0cad39 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -181,12 +181,6 @@ public abstract class PackageManager {
public static final int MATCH_DEFAULT_ONLY = 0x00010000;
/**
- * {@link ApplicationInfo} flag: return the
- * {link ApplicationInfo#expandable} boolean flag of the package.
- */
- public static final int GET_EXPANDABLE = 0x00020000;
-
- /**
* Permission check result: this is returned by {@link #checkPermission}
* if the permission has been granted to the given package.
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ab8559c..ab9518e 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -777,7 +777,7 @@ public class PackageParser {
targetCode = minCode = val.string.toString();
} else {
// If it's not a string, it's an integer.
- minVers = val.data;
+ targetVers = minVers = val.data;
}
}
@@ -798,6 +798,25 @@ public class PackageParser {
sa.recycle();
+ if (minCode != null) {
+ if (!minCode.equals(mSdkCodename)) {
+ if (mSdkCodename != null) {
+ outError[0] = "Requires development platform " + minCode
+ + " (current platform is " + mSdkCodename + ")";
+ } else {
+ outError[0] = "Requires development platform " + minCode
+ + " but this is a release platform.";
+ }
+ mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
+ return null;
+ }
+ } else if (minVers > mSdkVersion) {
+ outError[0] = "Requires newer sdk version #" + minVers
+ + " (current version is #" + mSdkVersion + ")";
+ mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
+ return null;
+ }
+
if (targetCode != null) {
if (!targetCode.equals(mSdkCodename)) {
if (mSdkCodename != null) {
@@ -817,13 +836,6 @@ public class PackageParser {
pkg.applicationInfo.targetSdkVersion = targetVers;
}
- if (minVers > mSdkVersion) {
- outError[0] = "Requires newer sdk version #" + minVers
- + " (current version is #" + mSdkVersion + ")";
- mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
- return null;
- }
-
if (maxVers < mSdkVersion) {
outError[0] = "Requires older sdk version #" + maxVers
+ " (current version is #" + mSdkVersion + ")";
@@ -865,7 +877,7 @@ public class PackageParser {
XmlUtils.skipCurrentTag(parser);
} else if (tagName.equals("expandable")) {
- pkg.expandable = true;
+ pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
XmlUtils.skipCurrentTag(parser);
} else {
Log.w(TAG, "Bad element under <manifest>: "
@@ -2262,9 +2274,6 @@ public class PackageParser {
public final ArrayList<Integer> supportsDensityList = new ArrayList<Integer>();
public int[] supportsDensities = null;
- // If the application's window is expandable.
- public boolean expandable;
-
// If this is a 3rd party app, this is the path of the zip file.
public String mPath;
@@ -2287,6 +2296,17 @@ public class PackageParser {
// preferred up order.
public int mPreferredOrder = 0;
+ // For use by package manager service to keep track of which apps
+ // have been installed with forward locking.
+ public boolean mForwardLocked;
+
+ // For use by the package manager to keep track of the path to the
+ // file an app came from.
+ public String mScanPath;
+
+ // For use by package manager to keep track of where it has done dexopt.
+ public boolean mDidDexOpt;
+
// Additional data supplied by callers.
public Object mExtras;
@@ -2439,9 +2459,6 @@ public class PackageParser {
&& p.supportsDensities != null) {
return true;
}
- if ((flags & PackageManager.GET_EXPANDABLE) != 0) {
- return true;
- }
return false;
}
@@ -2462,9 +2479,6 @@ public class PackageParser {
if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0) {
ai.supportsDensities = p.supportsDensities;
}
- if ((flags & PackageManager.GET_EXPANDABLE) != 0) {
- ai.expandable = p.expandable;
- }
return ai;
}
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 836de39..680fef8 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -69,7 +69,8 @@ public class CompatibilityInfo {
public final boolean mScalingRequired;
public CompatibilityInfo(ApplicationInfo appInfo) {
- mExpandable = mConfiguredExpandable = appInfo.expandable;
+ mExpandable = mConfiguredExpandable =
+ (appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0;
float packageDensityScale = -1.0f;
if (appInfo.supportsDensities != null) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index f51f3d0..f18d6e0 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -19,7 +19,6 @@ package com.android.server;
import com.android.internal.app.ResolverActivity;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
-import com.android.server.PackageManagerService.PreferredActivity;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -30,7 +29,6 @@ import android.app.IActivityManager;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -152,6 +150,7 @@ class PackageManagerService extends IPackageManager.Stub {
final Context mContext;
final boolean mFactoryTest;
+ final boolean mNoDexOpt;
final DisplayMetrics mMetrics;
final int mDefParseFlags;
final String[] mSeparateProcesses;
@@ -303,6 +302,7 @@ class PackageManagerService extends IPackageManager.Stub {
mContext = context;
mFactoryTest = factoryTest;
+ mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
mMetrics = new DisplayMetrics();
mSettings = new Settings();
mSettings.addSharedUserLP("android.uid.system",
@@ -372,6 +372,10 @@ class PackageManagerService extends IPackageManager.Stub {
startTime);
int scanMode = SCAN_MONITOR;
+ if (mNoDexOpt) {
+ Log.w(TAG, "Running ENG build: no pre-dexopt!");
+ scanMode |= SCAN_NO_DEX;
+ }
final HashSet<String> libFiles = new HashSet<String>();
@@ -993,10 +997,11 @@ class PackageManagerService extends IPackageManager.Stub {
if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
if (a != null && mSettings.isEnabledLP(a.info, flags)) {
ActivityInfo ainfo = PackageParser.generateActivityInfo(a, flags);
- if (ainfo != null && (flags & PackageManager.GET_EXPANDABLE) != 0) {
+ if (ainfo != null) {
ApplicationInfo appInfo = getApplicationInfo(component.getPackageName(),
- PackageManager.GET_EXPANDABLE | PackageManager.GET_SUPPORTS_DENSITIES);
- if (appInfo != null && !appInfo.expandable) {
+ PackageManager.GET_SUPPORTS_DENSITIES);
+ if (appInfo != null &&
+ (appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) == 0) {
// Check if the screen size is same as what the application expect.
CompatibilityInfo info = new CompatibilityInfo(appInfo);
DisplayMetrics metrics = new DisplayMetrics();
@@ -1009,11 +1014,13 @@ class PackageManagerService extends IPackageManager.Stub {
// Don't allow an app that cannot expand to handle rotation.
ainfo.configChanges &= ~ ActivityInfo.CONFIG_ORIENTATION;
} else {
- appInfo.expandable = true;
+ appInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
}
if (DEBUG_SETTINGS) {
Log.d(TAG, "component=" + component +
- ", expandable:" + appInfo.expandable);
+ ", expandable:" +
+ ((appInfo.flags &
+ ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0));
}
}
}
@@ -1943,7 +1950,56 @@ class PackageManagerService extends IPackageManager.Stub {
}
return true;
}
+
+ public boolean performDexOpt(String packageName) {
+ if (!mNoDexOpt) {
+ return false;
+ }
+
+ PackageParser.Package p;
+ synchronized (mPackages) {
+ p = mPackages.get(packageName);
+ if (p == null || p.mDidDexOpt) {
+ return false;
+ }
+ }
+ synchronized (mInstallLock) {
+ return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
+ }
+ }
+
+ static final int DEX_OPT_SKIPPED = 0;
+ static final int DEX_OPT_PERFORMED = 1;
+ static final int DEX_OPT_FAILED = -1;
+
+ private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
+ boolean performed = false;
+ if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
+ String path = pkg.mScanPath;
+ int ret = 0;
+ try {
+ if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
+ ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
+ !pkg.mForwardLocked);
+ pkg.mDidDexOpt = true;
+ performed = true;
+ }
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Apk not found for dexopt: " + path);
+ ret = -1;
+ } catch (IOException e) {
+ Log.w(TAG, "Exception reading apk: " + path, e);
+ ret = -1;
+ }
+ if (ret < 0) {
+ //error from installer
+ return DEX_OPT_FAILED;
+ }
+ }
+ return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
+ }
+
private PackageParser.Package scanPackageLI(
File scanFile, File destCodeFile, File destResourceFile,
PackageParser.Package pkg, int parseFlags, int scanMode) {
@@ -2239,23 +2295,11 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
- if ((scanMode&SCAN_NO_DEX) == 0
- && (pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
- int ret = 0;
- try {
- if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
- ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
- (scanMode&SCAN_FORWARD_LOCKED) == 0);
- }
- } catch (FileNotFoundException e) {
- Log.w(TAG, "Apk not found for dexopt: " + path);
- ret = -1;
- } catch (IOException e) {
- Log.w(TAG, "Exception reading apk: " + path, e);
- ret = -1;
- }
- if (ret < 0) {
- //error from installer
+ pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
+ pkg.mScanPath = path;
+
+ if ((scanMode&SCAN_NO_DEX) == 0) {
+ if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
return null;
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 045e636..8cf1cc2 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -181,7 +181,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// The flags that are set for all calls we make to the package manager.
static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES
- | PackageManager.GET_SUPPORTS_DENSITIES | PackageManager.GET_EXPANDABLE;
+ | PackageManager.GET_SUPPORTS_DENSITIES;
private static final String SYSTEM_SECURE = "ro.secure";
@@ -809,6 +809,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
*/
int[] mProcDeaths = new int[20];
+ /**
+ * This is set if we had to do a delayed dexopt of an app before launching
+ * it, to increasing the ANR timeouts in that case.
+ */
+ boolean mDidDexOpt;
+
String mDebugApp = null;
boolean mWaitForDebugger = false;
boolean mDebugTransient = false;
@@ -1007,6 +1013,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
+ if (mDidDexOpt) {
+ mDidDexOpt = false;
+ Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
+ mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
+ return;
+ }
broadcastTimeout();
} break;
case PAUSE_TIMEOUT_MSG: {
@@ -1017,9 +1029,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
activityPaused(token, null, true);
} break;
case IDLE_TIMEOUT_MSG: {
- IBinder token = (IBinder)msg.obj;
+ if (mDidDexOpt) {
+ mDidDexOpt = false;
+ Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
+ nmsg.obj = msg.obj;
+ mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
+ return;
+ }
// We don't at this point know if the activity is fullscreen,
// so we need to be conservative and assume it isn't.
+ IBinder token = (IBinder)msg.obj;
Log.w(TAG, "Activity idle timeout for " + token);
activityIdleInternal(token, true);
} break;
@@ -1035,6 +1054,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
activityIdle(token);
} break;
case SERVICE_TIMEOUT_MSG: {
+ if (mDidDexOpt) {
+ mDidDexOpt = false;
+ Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
+ nmsg.obj = msg.obj;
+ mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
+ return;
+ }
serviceTimeout((ProcessRecord)msg.obj);
} break;
case UPDATE_TIME_ZONE: {
@@ -1071,6 +1097,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
} break;
case LAUNCH_TIMEOUT_MSG: {
+ if (mDidDexOpt) {
+ mDidDexOpt = false;
+ Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
+ mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
+ return;
+ }
synchronized (ActivityManagerService.this) {
if (mLaunchingActivity.isHeld()) {
Log.w(TAG, "Launch timeout has expired, giving up wake lock!");
@@ -1091,6 +1123,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
case PROC_START_TIMEOUT_MSG: {
+ if (mDidDexOpt) {
+ mDidDexOpt = false;
+ Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
+ nmsg.obj = msg.obj;
+ mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
+ return;
+ }
ProcessRecord app = (ProcessRecord)msg.obj;
synchronized (ActivityManagerService.this) {
processStartTimedOutLocked(app);
@@ -1607,6 +1646,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
return proc;
}
+ private void ensurePackageDexOpt(String packageName) {
+ IPackageManager pm = ActivityThread.getPackageManager();
+ try {
+ if (pm.performDexOpt(packageName)) {
+ mDidDexOpt = true;
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
private boolean isNextTransitionForward() {
int transit = mWindowManager.getPendingAppTransition();
return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
@@ -1666,6 +1715,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (r.isHomeActivity) {
mHomeProcess = app;
}
+ ensurePackageDexOpt(r.intent.getComponent().getPackageName());
app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
r.info, r.icicle, results, newIntents, !andResume,
isNextTransitionForward());
@@ -4819,6 +4869,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
|| (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
}
+ ensurePackageDexOpt(app.info.packageName);
+ if (app.instrumentationInfo != null) {
+ ensurePackageDexOpt(app.instrumentationInfo.packageName);
+ }
thread.bindApplication(processName, app.instrumentationInfo != null
? app.instrumentationInfo : app.info, providers,
app.instrumentationClass, app.instrumentationProfileFile,
@@ -4907,6 +4961,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// Check whether the next backup agent is in this process...
if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
if (DEBUG_BACKUP) Log.v(TAG, "New app is backup target, launching agent for " + app);
+ ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
try {
thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
} catch (Exception e) {
@@ -6918,6 +6973,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
app.pubProviders.put(cpi.name, cpr);
app.addPackage(cpi.applicationInfo.packageName);
+ ensurePackageDexOpt(cpi.applicationInfo.packageName);
}
}
return providers;
@@ -9542,6 +9598,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
+ ensurePackageDexOpt(r.serviceInfo.packageName);
app.thread.scheduleCreateService(r, r.serviceInfo);
created = true;
} finally {
@@ -11098,6 +11155,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (DEBUG_BROADCAST_LIGHT) Log.v(TAG,
"Delivering to component " + r.curComponent
+ ": " + r);
+ ensurePackageDexOpt(r.intent.getComponent().getPackageName());
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
r.resultCode, r.resultData, r.resultExtras, r.ordered);
started = true;
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index 944ea02..b3fc313 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -463,6 +463,12 @@ class HistoryRecord extends IApplicationToken.Stub {
return false;
}
+ if (service.mDidDexOpt) {
+ // Give more time since we were dexopting.
+ service.mDidDexOpt = false;
+ return false;
+ }
+
if (r.app.instrumentationClass == null) {
service.appNotRespondingLocked(r.app, r, "keyDispatchingTimedOut");
} else {
diff --git a/test-runner/android/test/mock/MockContext.java b/test-runner/android/test/mock/MockContext.java
index 9e0cf2c..efc4880 100644
--- a/test-runner/android/test/mock/MockContext.java
+++ b/test-runner/android/test/mock/MockContext.java
@@ -24,6 +24,7 @@ import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
@@ -100,6 +101,11 @@ public class MockContext extends Context {
}
@Override
+ public ApplicationInfo getApplicationInfo() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public String getPackageResourcePath() {
throw new UnsupportedOperationException();
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
index d0896b5..69f3d9c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
@@ -29,6 +29,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
@@ -960,6 +961,12 @@ public final class BridgeContext extends Context {
}
@Override
+ public ApplicationInfo getApplicationInfo() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
public String getPackageResourcePath() {
// TODO Auto-generated method stub
return null;