What kind of app optimizations do newer Android versions do at the first reboot? I received from my phone carrier, Vodafone IT, the official OTA Google update to Android Ice Cream Sandwich 4.0.4 on my Nexus S. When automatically rebooting for the first time after the update, the system displayed a notice stating that it was optimizing the installed apps. What kind of optimization does Android 4.0+ do at the first reboot?
Digging into the PackageManagerService class on grepCode (warning: this class file is huge, your browser may chug a fair bit when rendering it), the optimizing message is displayed in the following context:

public void performBootDexOpt() {
    ArrayList&lt;PackageParser.Package&gt; pkgs = null;
    synchronized (mPackages) {
        if (mDeferredDexOpt.size() &gt; 0) {
            pkgs = new ArrayList&lt;PackageParser.Package&gt;(mDeferredDexOpt);
            mDeferredDexOpt.clear();
        }
    }
    if (pkgs != null) {
        for (int i=0; i&lt;pkgs.size(); i++) {
            if (!isFirstBoot()) {
                try {
                    ActivityManagerNative.getDefault().showBootMessage(
                            mContext.getResources().getString(
                                    com.android.internal.R.string.android_upgrading_apk,
                                    i+1, pkgs.size()), true);
                } catch (RemoteException e) {
                }
            }
            PackageParser.Package p = pkgs.get(i);
            synchronized (mInstallLock) {
                if (!p.mDidDexOpt) {
                    performDexOptLI(p, false, false);
                }
            }
        }
    }
}



Here the value of com.android.internal.R.string.android_upgrading_apk is the string "Optimizing application". In layman's terms, it loops through each application on the device, updates the message on the screen by calling showBootMessage() and then calls performDexOptLI() on the application. So naturally, the next question is "What does performDexOptLI() do?" Well here's what that looks like:

private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer) {
    boolean performed = false;
    if ((pkg.applicationInfo.flags&amp;ApplicationInfo.FLAG_HAS_CODE) != 0) {
        String path = pkg.mScanPath;
        int ret = 0;
        try {
            if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
                if (!forceDex &amp;&amp; defer) {
                    mDeferredDexOpt.add(pkg);
                    return DEX_OPT_DEFERRED;
                } else {
                    Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
                    ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
                            !isForwardLocked(pkg));
                    pkg.mDidDexOpt = true;
                    performed = true;
                }
            }
        } catch (...) {
           //I've trimmed out a bunch of exception handling here, it basically just writes to
           //the log and sets the return value
        }
    }

    return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
}


So this invokes the dexopt utility on all of the applications that need it. It's difficult to find any simple documentation regarding dexopt, but there's a high-level overview here. Suffice it to say, it's being used by the Just In Time (JIT) compiler to create optimized .dex files that help improve the performance of the apps on your device and it outputs them into the VM cache. The reason it stores the .dex files in the cache is because otherwise it would have to re-extract them any time you want to run the app (the .apk is just an archive, it is not an executable file!). Thus, it makes sense to just keep them in the /data/dalvik-cache directory to reuse them, and dexopt performs some optimizations during the initial extraction while it's at it.



TL;DR (or non-programmer summary, I guess): It's rebuilding the Dalvik cache.