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 
17 package android.util;
18 
19 import android.annotation.NonNull;
20 import android.content.res.Configuration;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 
24 import 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  */
33 public class MergedConfiguration implements Parcelable {
34 
35     private Configuration mGlobalConfig = new Configuration();
36     private Configuration mOverrideConfig = new Configuration();
37     private Configuration mMergedConfig = new Configuration();
38 
MergedConfiguration()39     public MergedConfiguration() {
40     }
41 
MergedConfiguration(Configuration globalConfig, Configuration overrideConfig)42     public MergedConfiguration(Configuration globalConfig, Configuration overrideConfig) {
43         setConfiguration(globalConfig, overrideConfig);
44     }
45 
MergedConfiguration(Configuration globalConfig)46     public MergedConfiguration(Configuration globalConfig) {
47         setGlobalConfiguration(globalConfig);
48     }
49 
MergedConfiguration(MergedConfiguration mergedConfiguration)50     public MergedConfiguration(MergedConfiguration mergedConfiguration) {
51         setConfiguration(mergedConfiguration.getGlobalConfiguration(),
52                 mergedConfiguration.getOverrideConfiguration());
53     }
54 
MergedConfiguration(Parcel in)55     private MergedConfiguration(Parcel in) {
56         readFromParcel(in);
57     }
58 
59     @Override
writeToParcel(Parcel dest, int flags)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 
readFromParcel(Parcel source)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
describeContents()73     public int describeContents() {
74         return 0;
75     }
76 
77     public static final @android.annotation.NonNull 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      */
setConfiguration(Configuration globalConfig, Configuration overrideConfig)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      */
setGlobalConfiguration(Configuration globalConfig)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      */
setOverrideConfiguration(Configuration overrideConfig)116     public void setOverrideConfiguration(Configuration overrideConfig) {
117         mOverrideConfig.setTo(overrideConfig);
118         updateMergedConfig();
119     }
120 
setTo(MergedConfiguration config)121     public void setTo(MergedConfiguration config) {
122         setConfiguration(config.mGlobalConfig, config.mOverrideConfig);
123     }
124 
unset()125     public void unset() {
126         mGlobalConfig.unset();
127         mOverrideConfig.unset();
128         updateMergedConfig();
129     }
130 
131     /**
132      * @return Stored global configuration value.
133      */
134     @NonNull
getGlobalConfiguration()135     public Configuration getGlobalConfiguration() {
136         return mGlobalConfig;
137     }
138 
139     /**
140      * @return Stored override configuration value.
141      */
getOverrideConfiguration()142     public Configuration getOverrideConfiguration() {
143         return mOverrideConfig;
144     }
145 
146     /**
147      * @return Stored merged configuration value.
148      */
getMergedConfiguration()149     public Configuration getMergedConfiguration() {
150         return mMergedConfig;
151     }
152 
153     /** Update merged config when global or override config changes. */
updateMergedConfig()154     private void updateMergedConfig() {
155         mMergedConfig.setTo(mGlobalConfig);
156         mMergedConfig.updateFrom(mOverrideConfig);
157     }
158 
159     @Override
toString()160     public String toString() {
161         return "{mGlobalConfig=" + mGlobalConfig + " mOverrideConfig=" + mOverrideConfig + "}";
162     }
163 
164     @Override
hashCode()165     public int hashCode() {
166         return mMergedConfig.hashCode();
167     }
168 
169     @Override
equals(Object that)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 
dump(PrintWriter pw, String prefix)179     public void dump(PrintWriter pw, String prefix) {
180         pw.println(prefix + "mGlobalConfig=" + mGlobalConfig);
181         pw.println(prefix + "mOverrideConfig=" + mOverrideConfig);
182     }
183 }
184