Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5fd2169e authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Work on issue #4518815: Compatibility mode introduces compatibility regression...

...for Market App iRunner

There were a lot of serious issues with how we updated (or often didn't update)
the display and resource state when switching compatibility mode in conjunction
with restarting and updating application components.  This addresses everything
I could find.

Unfortunately it does *not* fix this particular app.  I am starting to think this
is just an issue in the app.  This change does fix a number of other problems
I could repro, such as switching the compatibility mode of an IME.

Also a few changes here and there to get rid of $#*&^!! debug logs.

Change-Id: Ib15572eac9ec93b4b9966ddcbbc830ce9dec1317
parent 4381f642
Loading
Loading
Loading
Loading
+6 −6
Original line number Original line Diff line number Diff line
@@ -213,7 +213,7 @@ int move_dex(const char *src, const char *dst)
    if (create_cache_path(src_dex, src)) return -1;
    if (create_cache_path(src_dex, src)) return -1;
    if (create_cache_path(dst_dex, dst)) return -1;
    if (create_cache_path(dst_dex, dst)) return -1;


    LOGI("move %s -> %s\n", src_dex, dst_dex);
    LOGV("move %s -> %s\n", src_dex, dst_dex);
    if (rename(src_dex, dst_dex) < 0) {
    if (rename(src_dex, dst_dex) < 0) {
        LOGE("Couldn't move %s: %s\n", src_dex, strerror(errno));
        LOGE("Couldn't move %s: %s\n", src_dex, strerror(errno));
        return -1;
        return -1;
@@ -229,7 +229,7 @@ int rm_dex(const char *path)
    if (!is_valid_apk_path(path)) return -1;
    if (!is_valid_apk_path(path)) return -1;
    if (create_cache_path(dex_path, path)) return -1;
    if (create_cache_path(dex_path, path)) return -1;


    LOGI("unlink %s\n", dex_path);
    LOGV("unlink %s\n", dex_path);
    if (unlink(dex_path) < 0) {
    if (unlink(dex_path) < 0) {
        LOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno));
        LOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno));
        return -1;
        return -1;
@@ -428,7 +428,7 @@ static int wait_dexopt(pid_t pid, const char* apk_path)
    }
    }


    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
        LOGD("DexInv: --- END '%s' (success) ---\n", apk_path);
        LOGV("DexInv: --- END '%s' (success) ---\n", apk_path);
        return 0;
        return 0;
    } else {
    } else {
        LOGW("DexInv: --- END '%s' --- status=0x%04x, process failed\n",
        LOGW("DexInv: --- END '%s' --- status=0x%04x, process failed\n",
@@ -495,7 +495,7 @@ int dexopt(const char *apk_path, uid_t uid, int is_public)
        goto fail;
        goto fail;
    }
    }


    LOGD("DexInv: --- BEGIN '%s' ---\n", apk_path);
    LOGV("DexInv: --- BEGIN '%s' ---\n", apk_path);


    pid_t pid;
    pid_t pid;
    pid = fork();
    pid = fork();
@@ -563,7 +563,7 @@ void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
        if (path[basepos] == '/') {
        if (path[basepos] == '/') {
            path[basepos] = 0;
            path[basepos] = 0;
            if (lstat(path, statbuf) < 0) {
            if (lstat(path, statbuf) < 0) {
                LOGI("Making directory: %s\n", path);
                LOGV("Making directory: %s\n", path);
                if (mkdir(path, mode) == 0) {
                if (mkdir(path, mode) == 0) {
                    chown(path, uid, gid);
                    chown(path, uid, gid);
                } else {
                } else {
@@ -595,7 +595,7 @@ int movefileordir(char* srcpath, char* dstpath, int dstbasepos,
    if ((statbuf->st_mode&S_IFDIR) == 0) {
    if ((statbuf->st_mode&S_IFDIR) == 0) {
        mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH,
        mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH,
                dstuid, dstgid, statbuf);
                dstuid, dstgid, statbuf);
        LOGI("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
        LOGV("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
        if (rename(srcpath, dstpath) >= 0) {
        if (rename(srcpath, dstpath) >= 0) {
            if (chown(dstpath, dstuid, dstgid) < 0) {
            if (chown(dstpath, dstuid, dstgid) < 0) {
                LOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
                LOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
+69 −29
Original line number Original line Diff line number Diff line
@@ -155,7 +155,9 @@ public final class ActivityThread {
            = new HashMap<IBinder, Service>();
            = new HashMap<IBinder, Service>();
    AppBindData mBoundApplication;
    AppBindData mBoundApplication;
    Configuration mConfiguration;
    Configuration mConfiguration;
    Configuration mCompatConfiguration;
    Configuration mResConfiguration;
    Configuration mResConfiguration;
    CompatibilityInfo mResCompatibilityInfo;
    Application mInitialApplication;
    Application mInitialApplication;
    final ArrayList<Application> mAllApplications
    final ArrayList<Application> mAllApplications
            = new ArrayList<Application>();
            = new ArrayList<Application>();
@@ -181,8 +183,8 @@ public final class ActivityThread {
            = new HashMap<String, WeakReference<LoadedApk>>();
            = new HashMap<String, WeakReference<LoadedApk>>();
    final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
    final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
            = new HashMap<String, WeakReference<LoadedApk>>();
            = new HashMap<String, WeakReference<LoadedApk>>();
    Display mDisplay = null;
    final HashMap<CompatibilityInfo, DisplayMetrics> mDisplayMetrics
    DisplayMetrics mDisplayMetrics = null;
            = new HashMap<CompatibilityInfo, DisplayMetrics>();
    final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
    final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
            = new HashMap<ResourcesKey, WeakReference<Resources> >();
            = new HashMap<ResourcesKey, WeakReference<Resources> >();
    final ArrayList<ActivityClientRecord> mRelaunchingActivities
    final ArrayList<ActivityClientRecord> mRelaunchingActivities
@@ -1267,20 +1269,45 @@ public final class ActivityThread {
        return sPackageManager;
        return sPackageManager;
    }
    }


    DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
    DisplayMetrics getDisplayMetricsLocked(CompatibilityInfo ci, boolean forceUpdate) {
        if (mDisplayMetrics != null && !forceUpdate) {
        DisplayMetrics dm = mDisplayMetrics.get(ci);
            return mDisplayMetrics;
        if (dm != null && !forceUpdate) {
            return dm;
        }
        }
        if (mDisplay == null) {
        if (dm == null) {
            WindowManager wm = WindowManagerImpl.getDefault();
            dm = new DisplayMetrics();
            mDisplay = wm.getDefaultDisplay();
            mDisplayMetrics.put(ci, dm);
        }
        }
        DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics();
        Display d = WindowManagerImpl.getDefault(ci).getDefaultDisplay();
        mDisplay.getMetrics(metrics);
        d.getMetrics(dm);
        //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
        //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
        //        + metrics.heightPixels + " den=" + metrics.density
        //        + metrics.heightPixels + " den=" + metrics.density
        //        + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
        //        + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
        return metrics;
        return dm;
    }

    static Configuration applyConfigCompat(Configuration config, CompatibilityInfo compat) {
        if (config == null) {
            return null;
        }
        if (compat != null && !compat.supportsScreen()) {
            config = new Configuration(config);
            compat.applyToConfiguration(config);
        }
        return config;
    }

    private final Configuration mMainThreadConfig = new Configuration();
    Configuration applyConfigCompatMainThread(Configuration config, CompatibilityInfo compat) {
        if (config == null) {
            return null;
        }
        if (compat != null && !compat.supportsScreen()) {
            mMainThreadConfig.setTo(config);
            config = mMainThreadConfig;
            compat.applyToConfiguration(config);
        }
        return config;
    }
    }


    /**
    /**
@@ -1322,7 +1349,7 @@ public final class ActivityThread {
        }
        }


        //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
        //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
        DisplayMetrics metrics = getDisplayMetricsLocked(false);
        DisplayMetrics metrics = getDisplayMetricsLocked(compInfo, false);
        r = new Resources(assets, metrics, getConfiguration(), compInfo);
        r = new Resources(assets, metrics, getConfiguration(), compInfo);
        if (false) {
        if (false) {
            Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
            Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
@@ -1350,7 +1377,7 @@ public final class ActivityThread {
     * Creates the top level resources for the given package.
     * Creates the top level resources for the given package.
     */
     */
    Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) {
    Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) {
        return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
        return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo.get());
    }
    }


    final Handler getHandler() {
    final Handler getHandler() {
@@ -1517,7 +1544,8 @@ public final class ActivityThread {
                        CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
                        CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
                context.init(info, null, this);
                context.init(info, null, this);
                context.getResources().updateConfiguration(
                context.getResources().updateConfiguration(
                        getConfiguration(), getDisplayMetricsLocked(false));
                        getConfiguration(), getDisplayMetricsLocked(
                                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, false));
                mSystemContext = context;
                mSystemContext = context;
                //Slog.i(TAG, "Created system resources " + context.getResources()
                //Slog.i(TAG, "Created system resources " + context.getResources()
                //        + ": " + context.getResources().getConfiguration());
                //        + ": " + context.getResources().getConfiguration());
@@ -1730,7 +1758,7 @@ public final class ActivityThread {
                appContext.init(r.packageInfo, r.token, this);
                appContext.init(r.packageInfo, r.token, this);
                appContext.setOuterContext(activity);
                appContext.setOuterContext(activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mConfiguration);
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                        + r.activityInfo.name + " with config " + config);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                activity.attach(appContext, this, getInstrumentation(), r.token,
@@ -2763,13 +2791,14 @@ public final class ActivityThread {
    private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
    private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
        LoadedApk apk = peekPackageInfo(data.pkg, false);
        LoadedApk apk = peekPackageInfo(data.pkg, false);
        if (apk != null) {
        if (apk != null) {
            apk.mCompatibilityInfo = data.info;
            apk.mCompatibilityInfo.set(data.info);
        }
        }
        apk = peekPackageInfo(data.pkg, true);
        apk = peekPackageInfo(data.pkg, true);
        if (apk != null) {
        if (apk != null) {
            apk.mCompatibilityInfo = data.info;
            apk.mCompatibilityInfo.set(data.info);
        }
        }
        handleConfigurationChanged(mConfiguration, data.info);
        handleConfigurationChanged(mConfiguration, data.info);
        WindowManagerImpl.getDefault().reportNewConfiguration(mConfiguration);
    }
    }


    private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
    private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
@@ -3192,20 +3221,22 @@ public final class ActivityThread {
                ActivityClientRecord ar = it.next();
                ActivityClientRecord ar = it.next();
                Activity a = ar.activity;
                Activity a = ar.activity;
                if (a != null) {
                if (a != null) {
                    Configuration thisConfig = applyConfigCompatMainThread(newConfig,
                            ar.packageInfo.mCompatibilityInfo.getIfNeeded());
                    if (!ar.activity.mFinished && (allActivities ||
                    if (!ar.activity.mFinished && (allActivities ||
                            (a != null && !ar.paused))) {
                            (a != null && !ar.paused))) {
                        // If the activity is currently resumed, its configuration
                        // If the activity is currently resumed, its configuration
                        // needs to change right now.
                        // needs to change right now.
                        callbacks.add(a);
                        callbacks.add(a);
                    } else if (newConfig != null) {
                    } else if (thisConfig != null) {
                        // Otherwise, we will tell it about the change
                        // Otherwise, we will tell it about the change
                        // the next time it is resumed or shown.  Note that
                        // the next time it is resumed or shown.  Note that
                        // the activity manager may, before then, decide the
                        // the activity manager may, before then, decide the
                        // activity needs to be destroyed to handle its new
                        // activity needs to be destroyed to handle its new
                        // configuration.
                        // configuration.
                        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Setting activity "
                        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Setting activity "
                                + ar.activityInfo.name + " newConfig=" + newConfig);
                                + ar.activityInfo.name + " newConfig=" + thisConfig);
                        ar.newConfig = newConfig;
                        ar.newConfig = thisConfig;
                    }
                    }
                }
                }
            }
            }
@@ -3252,7 +3283,6 @@ public final class ActivityThread {
            // onConfigurationChanged
            // onConfigurationChanged
            int diff = activity.mCurrentConfig.diff(config);
            int diff = activity.mCurrentConfig.diff(config);
            if (diff != 0) {
            if (diff != 0) {

                // If this activity doesn't handle any of the config changes
                // If this activity doesn't handle any of the config changes
                // then don't bother calling onConfigurationChanged as we're
                // then don't bother calling onConfigurationChanged as we're
                // going to destroy it.
                // going to destroy it.
@@ -3296,7 +3326,15 @@ public final class ActivityThread {
            return false;
            return false;
        }
        }
        int changes = mResConfiguration.updateFrom(config);
        int changes = mResConfiguration.updateFrom(config);
        DisplayMetrics dm = getDisplayMetricsLocked(true);
        DisplayMetrics dm = getDisplayMetricsLocked(compat, true);

        if (compat != null && (mResCompatibilityInfo == null ||
                !mResCompatibilityInfo.equals(compat))) {
            mResCompatibilityInfo = compat;
            changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
                    | ActivityInfo.CONFIG_SCREEN_SIZE
                    | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
        }


        // set it for java, this also affects newly created Resources
        // set it for java, this also affects newly created Resources
        if (config.locale != null) {
        if (config.locale != null) {
@@ -3358,13 +3396,14 @@ public final class ActivityThread {
                return;
                return;
            }
            }
            mConfiguration.updateFrom(config);
            mConfiguration.updateFrom(config);
            if (compat != null) {
            if (mCompatConfiguration == null) {
                // Can't do this here, because it causes us to report the
                mCompatConfiguration = new Configuration();
                // comatible config back to the am as the current config
            }
                // of the activity, and much unhappiness results.
            mCompatConfiguration.setTo(mConfiguration);
                //compat.applyToConfiguration(mConfiguration);
            if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
                mResCompatibilityInfo.applyToConfiguration(mCompatConfiguration);
                config = mCompatConfiguration;
            }
            }

            callbacks = collectComponentCallbacksLocked(false, config);
            callbacks = collectComponentCallbacksLocked(false, config);
        }
        }


@@ -3385,7 +3424,7 @@ public final class ActivityThread {
        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
                + r.activityInfo.name);
                + r.activityInfo.name);
        
        
        performConfigurationChanged(r.activity, mConfiguration);
        performConfigurationChanged(r.activity, mCompatConfiguration);
    }
    }


    final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
    final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
@@ -3480,6 +3519,7 @@ public final class ActivityThread {
    private final void handleBindApplication(AppBindData data) {
    private final void handleBindApplication(AppBindData data) {
        mBoundApplication = data;
        mBoundApplication = data;
        mConfiguration = new Configuration(data.config);
        mConfiguration = new Configuration(data.config);
        mCompatConfiguration = new Configuration(data.config);


        // send up app name; do this *before* waiting for debugger
        // send up app name; do this *before* waiting for debugger
        Process.setArgV0(data.processName);
        Process.setArgV0(data.processName);
+3 −1
Original line number Original line Diff line number Diff line
@@ -37,6 +37,8 @@ import android.content.res.Configuration;
 * when first constructing the singleton.</p>
 * when first constructing the singleton.</p>
 */
 */
public class Application extends ContextWrapper implements ComponentCallbacks {
public class Application extends ContextWrapper implements ComponentCallbacks {
    /** @hide */
    public LoadedApk mLoadedApk;
    
    
    public Application() {
    public Application() {
        super(null);
        super(null);
@@ -75,6 +77,6 @@ public class Application extends ContextWrapper implements ComponentCallbacks {
     */
     */
    /* package */ final void attach(Context context) {
    /* package */ final void attach(Context context) {
        attachBaseContext(context);
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }
    }

}
}
+10 −2
Original line number Original line Diff line number Diff line
@@ -425,11 +425,19 @@ class ContextImpl extends Context {


        registerService(WINDOW_SERVICE, new ServiceFetcher() {
        registerService(WINDOW_SERVICE, new ServiceFetcher() {
                public Object getService(ContextImpl ctx) {
                public Object getService(ContextImpl ctx) {
                    CompatibilityInfo ci = ctx.mResources.getCompatibilityInfo();
                    return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo);
                    return WindowManagerImpl.getDefault(ci);
                }});
                }});
    }
    }


    static ContextImpl getImpl(Context context) {
        Context nextContext;
        while ((context instanceof ContextWrapper) &&
                (nextContext=((ContextWrapper)context).getBaseContext()) != null) {
            context = nextContext;
        }
        return (ContextImpl)context;
    }

    // The system service cache for the system services that are
    // The system service cache for the system services that are
    // cached per-ContextImpl.  Package-scoped to avoid accessor
    // cached per-ContextImpl.  Package-scoped to avoid accessor
    // methods.
    // methods.
+6 −5
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ import android.os.RemoteException;
import android.os.StrictMode;
import android.os.StrictMode;
import android.util.AndroidRuntimeException;
import android.util.AndroidRuntimeException;
import android.util.Slog;
import android.util.Slog;
import android.view.CompatibilityInfoHolder;


import java.io.File;
import java.io.File;
import java.io.IOException;
import java.io.IOException;
@@ -64,7 +65,7 @@ final class ServiceConnectionLeaked extends AndroidRuntimeException {
 * Local state maintained about a currently loaded .apk.
 * Local state maintained about a currently loaded .apk.
 * @hide
 * @hide
 */
 */
final class LoadedApk {
public final class LoadedApk {


    private final ActivityThread mActivityThread;
    private final ActivityThread mActivityThread;
    private final ApplicationInfo mApplicationInfo;
    private final ApplicationInfo mApplicationInfo;
@@ -78,10 +79,10 @@ final class LoadedApk {
    private final ClassLoader mBaseClassLoader;
    private final ClassLoader mBaseClassLoader;
    private final boolean mSecurityViolation;
    private final boolean mSecurityViolation;
    private final boolean mIncludeCode;
    private final boolean mIncludeCode;
    public final CompatibilityInfoHolder mCompatibilityInfo = new CompatibilityInfoHolder();
    Resources mResources;
    Resources mResources;
    private ClassLoader mClassLoader;
    private ClassLoader mClassLoader;
    private Application mApplication;
    private Application mApplication;
    CompatibilityInfo mCompatibilityInfo;


    private final HashMap<Context, HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mReceivers
    private final HashMap<Context, HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mReceivers
        = new HashMap<Context, HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
        = new HashMap<Context, HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
@@ -121,7 +122,7 @@ final class LoadedApk {
        mBaseClassLoader = baseLoader;
        mBaseClassLoader = baseLoader;
        mSecurityViolation = securityViolation;
        mSecurityViolation = securityViolation;
        mIncludeCode = includeCode;
        mIncludeCode = includeCode;
        mCompatibilityInfo = compatInfo;
        mCompatibilityInfo.set(compatInfo);


        if (mAppDir == null) {
        if (mAppDir == null) {
            if (ActivityThread.mSystemContext == null) {
            if (ActivityThread.mSystemContext == null) {
@@ -129,7 +130,7 @@ final class LoadedApk {
                    ContextImpl.createSystemContext(mainThread);
                    ContextImpl.createSystemContext(mainThread);
                ActivityThread.mSystemContext.getResources().updateConfiguration(
                ActivityThread.mSystemContext.getResources().updateConfiguration(
                         mainThread.getConfiguration(),
                         mainThread.getConfiguration(),
                         mainThread.getDisplayMetricsLocked(false),
                         mainThread.getDisplayMetricsLocked(compatInfo, false),
                         compatInfo);
                         compatInfo);
                //Slog.i(TAG, "Created system resources "
                //Slog.i(TAG, "Created system resources "
                //        + mSystemContext.getResources() + ": "
                //        + mSystemContext.getResources() + ": "
@@ -157,7 +158,7 @@ final class LoadedApk {
        mIncludeCode = true;
        mIncludeCode = true;
        mClassLoader = systemContext.getClassLoader();
        mClassLoader = systemContext.getClassLoader();
        mResources = systemContext.getResources();
        mResources = systemContext.getResources();
        mCompatibilityInfo = compatInfo;
        mCompatibilityInfo.set(compatInfo);
    }
    }


    public String getPackageName() {
    public String getPackageName() {
Loading