1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package android.util;
18
19import android.annotation.NonNull;
20import android.content.res.Configuration;
21import android.os.Parcel;
22import android.os.Parcelable;
23
24import java.io.PrintWriter;
25
26/**
27 * Container that holds global and override config and their merge product.
28 * Merged configuration updates automatically whenever global or override configs are updated via
29 * setters.
30 *
31 * {@hide}
32 */
33public class MergedConfiguration implements Parcelable {
34
35    private Configuration mGlobalConfig = new Configuration();
36    private Configuration mOverrideConfig = new Configuration();
37    private Configuration mMergedConfig = new Configuration();
38
39    public MergedConfiguration() {
40    }
41
42    public MergedConfiguration(Configuration globalConfig, Configuration overrideConfig) {
43        setConfiguration(globalConfig, overrideConfig);
44    }
45
46    public MergedConfiguration(Configuration globalConfig) {
47        setGlobalConfiguration(globalConfig);
48    }
49
50    public MergedConfiguration(MergedConfiguration mergedConfiguration) {
51        setConfiguration(mergedConfiguration.getGlobalConfiguration(),
52                mergedConfiguration.getOverrideConfiguration());
53    }
54
55    private MergedConfiguration(Parcel in) {
56        readFromParcel(in);
57    }
58
59    @Override
60    public void writeToParcel(Parcel dest, int flags) {
61        dest.writeParcelable(mGlobalConfig, flags);
62        dest.writeParcelable(mOverrideConfig, flags);
63        dest.writeParcelable(mMergedConfig, flags);
64    }
65
66    public void readFromParcel(Parcel source) {
67        mGlobalConfig = source.readParcelable(Configuration.class.getClassLoader());
68        mOverrideConfig = source.readParcelable(Configuration.class.getClassLoader());
69        mMergedConfig = source.readParcelable(Configuration.class.getClassLoader());
70    }
71
72    @Override
73    public int describeContents() {
74        return 0;
75    }
76
77    public static final Creator<MergedConfiguration> CREATOR = new Creator<MergedConfiguration>() {
78        @Override
79        public MergedConfiguration createFromParcel(Parcel in) {
80            return new MergedConfiguration(in);
81        }
82
83        @Override
84        public MergedConfiguration[] newArray(int size) {
85            return new MergedConfiguration[size];
86        }
87    };
88
89    /**
90     * Update global and override configurations.
91     * Merged configuration will automatically be updated.
92     * @param globalConfig New global configuration.
93     * @param overrideConfig New override configuration.
94     */
95    public void setConfiguration(Configuration globalConfig, Configuration overrideConfig) {
96        mGlobalConfig.setTo(globalConfig);
97        mOverrideConfig.setTo(overrideConfig);
98        updateMergedConfig();
99    }
100
101    /**
102     * Update global configurations.
103     * Merged configuration will automatically be updated.
104     * @param globalConfig New global configuration.
105     */
106    public void setGlobalConfiguration(Configuration globalConfig) {
107        mGlobalConfig.setTo(globalConfig);
108        updateMergedConfig();
109    }
110
111    /**
112     * Update override configurations.
113     * Merged configuration will automatically be updated.
114     * @param overrideConfig New override configuration.
115     */
116    public void setOverrideConfiguration(Configuration overrideConfig) {
117        mOverrideConfig.setTo(overrideConfig);
118        updateMergedConfig();
119    }
120
121    public void setTo(MergedConfiguration config) {
122        setConfiguration(config.mGlobalConfig, config.mOverrideConfig);
123    }
124
125    public void unset() {
126        mGlobalConfig.unset();
127        mOverrideConfig.unset();
128        updateMergedConfig();
129    }
130
131    /**
132     * @return Stored global configuration value.
133     */
134    @NonNull
135    public Configuration getGlobalConfiguration() {
136        return mGlobalConfig;
137    }
138
139    /**
140     * @return Stored override configuration value.
141     */
142    public Configuration getOverrideConfiguration() {
143        return mOverrideConfig;
144    }
145
146    /**
147     * @return Stored merged configuration value.
148     */
149    public Configuration getMergedConfiguration() {
150        return mMergedConfig;
151    }
152
153    /** Update merged config when global or override config changes. */
154    private void updateMergedConfig() {
155        mMergedConfig.setTo(mGlobalConfig);
156        mMergedConfig.updateFrom(mOverrideConfig);
157    }
158
159    @Override
160    public String toString() {
161        return "{mGlobalConfig=" + mGlobalConfig + " mOverrideConfig=" + mOverrideConfig + "}";
162    }
163
164    @Override
165    public int hashCode() {
166        return mMergedConfig.hashCode();
167    }
168
169    @Override
170    public boolean equals(Object that) {
171        if (!(that instanceof MergedConfiguration)) {
172            return false;
173        }
174
175        if (that == this) return true;
176        return mMergedConfig.equals(((MergedConfiguration) that).mMergedConfig);
177    }
178
179    public void dump(PrintWriter pw, String prefix) {
180        pw.println(prefix + "mGlobalConfig=" + mGlobalConfig);
181        pw.println(prefix + "mOverrideConfig=" + mOverrideConfig);
182    }
183}
184