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

Commit df259d30 authored by Robert Carr's avatar Robert Carr
Browse files

Correct error in Configuration.updateFrom

When updating the non direction members of screenLayout
we check that they are not in total undefined, before
accepting the new value in full. This was enough for LONG/SIZE
which are always undefined or set together. It seems we have paths
now where SCREENLAYOUT_ROUND however can be undefined and the others
will be set. In this case if we pass a configuration with
SCREENLAYOUT_ROUND_UNDEFINED but LONG/SIZE set to updateFrom then
we will overwrite our previous SCREENLAYOUT_ROUND value.
This triggers extra configuration changes. We take extra care with
SCREENLAYOUT_COMPAT_NEEDED as it doesn't have an undefined value.

Bug: 33098677
Test: bit FrameworksCoreTests:android.content.res.ConfigurationTest
Change-Id: I6e7d123d5444f93c511aeb6e0f3adfea2a480352
parent cac1d6a0
Loading
Loading
Loading
Loading
+28 −10
Original line number Diff line number Diff line
@@ -1047,18 +1047,36 @@ public final class Configuration implements Parcelable, Comparable<Configuration
            changed |= ActivityInfo.CONFIG_ORIENTATION;
            orientation = delta.orientation;
        }
        if (getScreenLayoutNoDirection(delta.screenLayout) !=
                    (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
                && (getScreenLayoutNoDirection(screenLayout) !=
                    getScreenLayoutNoDirection(delta.screenLayout))) {

        if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED)
                && (delta.screenLayout & SCREENLAYOUT_SIZE_MASK)
                != (screenLayout & SCREENLAYOUT_SIZE_MASK)) {
            changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
            // We need to preserve the previous layout dir bits if they were defined
            if ((delta.screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == 0) {
                screenLayout = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK)|delta.screenLayout;
            } else {
                screenLayout = delta.screenLayout;
            screenLayout = (screenLayout & ~SCREENLAYOUT_SIZE_MASK)
                    | (delta.screenLayout & SCREENLAYOUT_SIZE_MASK);
        }
        if (((delta.screenLayout & SCREENLAYOUT_LONG_MASK) != SCREENLAYOUT_LONG_UNDEFINED)
                && (delta.screenLayout & SCREENLAYOUT_LONG_MASK)
                != (screenLayout & SCREENLAYOUT_LONG_MASK)) {
            changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
            screenLayout = (screenLayout & ~SCREENLAYOUT_LONG_MASK)
                    | (delta.screenLayout & SCREENLAYOUT_LONG_MASK);
        }
        if (((delta.screenLayout & SCREENLAYOUT_ROUND_MASK) != SCREENLAYOUT_ROUND_UNDEFINED)
                && (delta.screenLayout & SCREENLAYOUT_ROUND_MASK)
                != (screenLayout & SCREENLAYOUT_ROUND_MASK)) {
            changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
            screenLayout = (screenLayout & ~SCREENLAYOUT_ROUND_MASK)
                    | (delta.screenLayout & SCREENLAYOUT_ROUND_MASK);
        }
        if ((delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
                != (screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
                && delta.screenLayout != 0) {
            changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
            screenLayout = (screenLayout & ~SCREENLAYOUT_COMPAT_NEEDED)
                | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED);
        }

        if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
                && uiMode != delta.uiMode) {
            changed |= ActivityInfo.CONFIG_UI_MODE;
+58 −0
Original line number Diff line number Diff line
/*
1;3409;0c * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package android.content.res;

import org.junit.runner.RunWith;
import org.junit.Test;
import org.junit.runners.JUnit4;

import android.content.res.Configuration;
import android.support.test.filters.SmallTest;
import android.platform.test.annotations.Presubmit;

import junit.framework.TestCase;

import static org.junit.Assert.assertEquals;

/**
 * Build/install/run: bit FrameworksCoreTests:android.content.res.ConfigurationTest
 */
@RunWith(JUnit4.class)
@SmallTest
@Presubmit
public class ConfigurationTest extends TestCase {
    @Test
    public void testUpdateFromPreservesRoundBit() {
        Configuration config = new Configuration();
        config.screenLayout = Configuration.SCREENLAYOUT_ROUND_YES;
        Configuration config2 = new Configuration();

        config.updateFrom(config2);
        assertEquals(config.screenLayout, Configuration.SCREENLAYOUT_ROUND_YES);
    }

    @Test
    public void testUpdateFromPreservesCompatNeededBit() {
        Configuration config = new Configuration();
        config.screenLayout = Configuration.SCREENLAYOUT_COMPAT_NEEDED;
        Configuration config2 = new Configuration();
        config.updateFrom(config2);
        assertEquals(config.screenLayout, Configuration.SCREENLAYOUT_COMPAT_NEEDED);

        config2.updateFrom(config);
        assertEquals(config2.screenLayout, Configuration.SCREENLAYOUT_COMPAT_NEEDED);
    }
}