1 /* 2 * Copyright (C) 2016 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 com.android.server.am; 18 19 import android.content.res.Configuration; 20 21 /** 22 * Contains common logic for classes that have override configurations and are organized in a 23 * hierarchy. 24 */ 25 // TODO(b/36505427): Move to wm package and have WindowContainer use this instead of having its own 26 // implementation for merging configuration. 27 abstract class ConfigurationContainer<E extends ConfigurationContainer> { 28 29 /** Contains override configuration settings applied to this configuration container. */ 30 private Configuration mOverrideConfiguration = new Configuration(); 31 32 /** 33 * Contains full configuration applied to this configuration container. Corresponds to full 34 * parent's config with applied {@link #mOverrideConfiguration}. 35 */ 36 private Configuration mFullConfiguration = new Configuration(); 37 38 /** 39 * Contains merged override configuration settings from the top of the hierarchy down to this 40 * particular instance. It is different from {@link #mFullConfiguration} because it starts from 41 * topmost container's override config instead of global config. 42 */ 43 private Configuration mMergedOverrideConfiguration = new Configuration(); 44 45 /** 46 * Returns full configuration applied to this configuration container. 47 * This method should be used for getting settings applied in each particular level of the 48 * hierarchy. 49 */ getConfiguration()50 Configuration getConfiguration() { 51 return mFullConfiguration; 52 } 53 54 /** 55 * Notify that parent config changed and we need to update full configuration. 56 * @see #mFullConfiguration 57 */ onConfigurationChanged(Configuration newParentConfig)58 void onConfigurationChanged(Configuration newParentConfig) { 59 mFullConfiguration.setTo(newParentConfig); 60 mFullConfiguration.updateFrom(mOverrideConfiguration); 61 for (int i = getChildCount() - 1; i >= 0; --i) { 62 final ConfigurationContainer child = getChildAt(i); 63 child.onConfigurationChanged(mFullConfiguration); 64 } 65 } 66 67 /** Returns override configuration applied to this configuration container. */ getOverrideConfiguration()68 Configuration getOverrideConfiguration() { 69 return mOverrideConfiguration; 70 } 71 72 /** 73 * Update override configuration and recalculate full config. 74 * @see #mOverrideConfiguration 75 * @see #mFullConfiguration 76 */ onOverrideConfigurationChanged(Configuration overrideConfiguration)77 void onOverrideConfigurationChanged(Configuration overrideConfiguration) { 78 mOverrideConfiguration.setTo(overrideConfiguration); 79 // Update full configuration of this container and all its children. 80 final ConfigurationContainer parent = getParent(); 81 onConfigurationChanged(parent != null ? parent.getConfiguration() : Configuration.EMPTY); 82 // Update merged override config of this container and all its children. 83 onMergedOverrideConfigurationChanged(); 84 } 85 86 /** 87 * Get merged override configuration from the top of the hierarchy down to this particular 88 * instance. This should be reported to client as override config. 89 */ getMergedOverrideConfiguration()90 Configuration getMergedOverrideConfiguration() { 91 return mMergedOverrideConfiguration; 92 } 93 94 /** 95 * Update merged override configuration based on corresponding parent's config and notify all 96 * its children. If there is no parent, merged override configuration will set equal to current 97 * override config. 98 * @see #mMergedOverrideConfiguration 99 */ onMergedOverrideConfigurationChanged()100 private void onMergedOverrideConfigurationChanged() { 101 final ConfigurationContainer parent = getParent(); 102 if (parent != null) { 103 mMergedOverrideConfiguration.setTo(parent.getMergedOverrideConfiguration()); 104 mMergedOverrideConfiguration.updateFrom(mOverrideConfiguration); 105 } else { 106 mMergedOverrideConfiguration.setTo(mOverrideConfiguration); 107 } 108 for (int i = getChildCount() - 1; i >= 0; --i) { 109 final ConfigurationContainer child = getChildAt(i); 110 child.onMergedOverrideConfigurationChanged(); 111 } 112 } 113 114 /** 115 * Must be called when new parent for the container was set. 116 */ onParentChanged()117 void onParentChanged() { 118 final ConfigurationContainer parent = getParent(); 119 // Removing parent usually means that we've detached this entity to destroy it or to attach 120 // to another parent. In both cases we don't need to update the configuration now. 121 if (parent != null) { 122 // Update full configuration of this container and all its children. 123 onConfigurationChanged(parent.mFullConfiguration); 124 // Update merged override configuration of this container and all its children. 125 onMergedOverrideConfigurationChanged(); 126 } 127 } 128 getChildCount()129 abstract protected int getChildCount(); 130 getChildAt(int index)131 abstract protected E getChildAt(int index); 132 getParent()133 abstract protected ConfigurationContainer getParent(); 134 } 135