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.
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 @@
 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.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 @@
     
     final Context mContext;
     final boolean mFactoryTest;
+    final boolean mNoDexOpt;
     final DisplayMetrics mMetrics;
     final int mDefParseFlags;
     final String[] mSeparateProcesses;
@@ -303,6 +302,7 @@
         
         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 @@
                     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 @@
             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 @@
                             // 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 @@
         }
         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 @@
                 }
             }
 
-            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;
                 }