1 /* 2 * Copyright (C) 2024 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.window; 18 19 import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; 20 21 import android.annotation.CallSuper; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.UserIdInt; 26 import android.app.ActivityThread; 27 import android.os.Parcel; 28 import android.os.Parcelable; 29 import android.view.IWindowManager; 30 31 import com.android.internal.annotations.VisibleForTesting; 32 import com.android.server.LocalServices; 33 import com.android.window.flags.Flags; 34 35 import java.lang.annotation.Retention; 36 import java.lang.annotation.RetentionPolicy; 37 import java.util.Objects; 38 39 /** 40 * Represents a setting request that can be applied as part of a batch to avoid multiple 41 * configuration updates. 42 * 43 * @hide 44 */ 45 public abstract class ConfigurationChangeSetting implements Parcelable { 46 /* The type of the setting for creating from a parcel. */ 47 public static final int SETTING_TYPE_UNKNOWN = -1; 48 public static final int SETTING_TYPE_DISPLAY_DENSITY = 0; 49 public static final int SETTING_TYPE_FONT_SCALE = 1; 50 51 @IntDef(prefix = {"SETTING_TYPE_"}, value = { 52 SETTING_TYPE_UNKNOWN, 53 SETTING_TYPE_DISPLAY_DENSITY, 54 SETTING_TYPE_FONT_SCALE 55 }) 56 @Retention(RetentionPolicy.SOURCE) 57 public @interface SettingType { 58 } 59 60 @SettingType 61 private final int mSettingType; 62 ConfigurationChangeSetting(@ettingType int settingType)63 private ConfigurationChangeSetting(@SettingType int settingType) { 64 if (!Flags.condenseConfigurationChangeForSimpleMode()) { 65 throw new IllegalStateException( 66 "ConfigurationChangeSetting cannot be instantiated because the " 67 + "condenseConfigurationChangeForSimpleMode flag is not enabled. " 68 + "Please ensure this flag is enabled."); 69 } 70 mSettingType = settingType; 71 } 72 73 @CallSuper 74 @Override writeToParcel(@onNull Parcel dest, int flags)75 public void writeToParcel(@NonNull Parcel dest, int flags) { 76 dest.writeInt(mSettingType); 77 } 78 79 public static final Creator<ConfigurationChangeSetting> CREATOR = new CreatorImpl(); 80 81 /** 82 * Implementation of the {@link Parcelable.Creator} for {@link ConfigurationChangeSetting}. 83 * 84 * <p>Creates {@link ConfigurationChangeSetting} objects from a {@link Parcel}, handling 85 * system/client processes. System process delegates creation to the server-side implementation. 86 * 87 * @hide 88 */ 89 @VisibleForTesting(visibility = PRIVATE) 90 public static class CreatorImpl implements Creator<ConfigurationChangeSetting> { 91 private final boolean mIsSystem; 92 CreatorImpl()93 private CreatorImpl() { 94 this(ActivityThread.isSystem()); 95 } 96 97 @VisibleForTesting(visibility = PRIVATE) CreatorImpl(boolean isSystem)98 public CreatorImpl(boolean isSystem) { 99 mIsSystem = isSystem; 100 } 101 102 @Override createFromParcel(@onNull Parcel in)103 public ConfigurationChangeSetting createFromParcel(@NonNull Parcel in) { 104 final int settingType = in.readInt(); 105 if (mIsSystem) { 106 return LocalServices.getService(ConfigurationChangeSettingInternal.class) 107 .createImplFromParcel(settingType, in); 108 } 109 switch (settingType) { 110 case SETTING_TYPE_DISPLAY_DENSITY: 111 return DensitySetting.CREATOR.createFromParcel(in); 112 case SETTING_TYPE_FONT_SCALE: 113 return FontScaleSetting.CREATOR.createFromParcel(in); 114 default: 115 throw new IllegalArgumentException("Unknown setting type " + settingType); 116 } 117 } 118 119 @Override newArray(int size)120 public ConfigurationChangeSetting[] newArray(int size) { 121 return new ConfigurationChangeSetting[size]; 122 } 123 } 124 125 @Override describeContents()126 public int describeContents() { 127 return 0; 128 } 129 130 /** 131 * Applies the specific setting request to the system. 132 * 133 * <p>This method should handle the logic for modifying system settings or making other 134 * adjustments to achieve the intended configuration change. It is called within the 135 * context of a batch update, where multiple {@link ConfigurationChangeSetting} instances 136 * might be applied sequentially. 137 * 138 * @param userId The user for which to apply the setting 139 * @hide Only for use within the system server. 140 * @see IWindowManager#setConfigurationChangeSettingsForUser(ConfigurationChangeSetting[], int) 141 */ apply(@serIdInt int userId)142 public void apply(@UserIdInt int userId) { 143 // no-op in client process, the apply will be executed in server side. 144 } 145 146 /** 147 * Interface for server side implementation of {@link ConfigurationChangeSetting}. 148 * 149 * @hide Only for use within the system server. 150 */ 151 public interface ConfigurationChangeSettingInternal { 152 /** 153 * Create server side {@link ConfigurationChangeSetting} implementation from parcel. 154 * 155 * @param settingType the type of {@link ConfigurationChangeSetting}. 156 * @param in the {@link Parcel} to read data from. 157 * @return server side {@link ConfigurationChangeSetting} implementation. 158 */ 159 @NonNull createImplFromParcel(@ettingType int settingType, @NonNull Parcel in)160 ConfigurationChangeSetting createImplFromParcel(@SettingType int settingType, 161 @NonNull Parcel in); 162 } 163 164 /** 165 * Represents a request to change the display density. 166 * 167 * @hide 168 */ 169 public static class DensitySetting extends ConfigurationChangeSetting { 170 protected final int mDisplayId; 171 protected final int mDensity; 172 173 /** 174 * Constructs a {@link DensitySetting}. 175 * 176 * @param density The new display density. 177 * @hide 178 */ DensitySetting(int displayId, int density)179 public DensitySetting(int displayId, int density) { 180 super(SETTING_TYPE_DISPLAY_DENSITY); 181 mDisplayId = displayId; 182 mDensity = density; 183 } 184 DensitySetting(@onNull Parcel in)185 protected DensitySetting(@NonNull Parcel in) { 186 this(in.readInt(), in.readInt()); 187 } 188 189 @Override writeToParcel(@onNull Parcel dest, int flags)190 public void writeToParcel(@NonNull Parcel dest, int flags) { 191 super.writeToParcel(dest, flags); 192 dest.writeInt(mDisplayId); 193 dest.writeInt(mDensity); 194 } 195 196 public static final Creator<DensitySetting> CREATOR = new Creator<>() { 197 @Override 198 public DensitySetting createFromParcel(@NonNull Parcel in) { 199 return new DensitySetting(in); 200 } 201 202 @Override 203 public DensitySetting[] newArray(int size) { 204 return new DensitySetting[size]; 205 } 206 }; 207 208 @Override equals(@ullable Object obj)209 public boolean equals(@Nullable Object obj) { 210 if (!(obj instanceof DensitySetting other)) { 211 return false; 212 } 213 return mDisplayId == other.mDisplayId && mDensity == other.mDensity; 214 } 215 216 @Override hashCode()217 public int hashCode() { 218 return Objects.hash(mDisplayId, mDensity); 219 } 220 } 221 222 /** 223 * Represents a request to change the font scale. 224 * 225 * @hide 226 */ 227 public static class FontScaleSetting extends ConfigurationChangeSetting { 228 protected final float mFontScaleFactor; 229 230 /** 231 * Constructs a {@code FontScaleSetting}. 232 * 233 * @param fontScaleFactor The new font scale factor. 234 * @hide 235 */ FontScaleSetting(float fontScaleFactor)236 public FontScaleSetting(float fontScaleFactor) { 237 super(SETTING_TYPE_FONT_SCALE); 238 mFontScaleFactor = fontScaleFactor; 239 } 240 FontScaleSetting(@onNull Parcel in)241 protected FontScaleSetting(@NonNull Parcel in) { 242 this(in.readFloat()); 243 } 244 245 @Override writeToParcel(@onNull Parcel dest, int flags)246 public void writeToParcel(@NonNull Parcel dest, int flags) { 247 super.writeToParcel(dest, flags); 248 dest.writeFloat(mFontScaleFactor); 249 } 250 251 public static final Creator<FontScaleSetting> CREATOR = new Creator<>() { 252 @Override 253 public FontScaleSetting createFromParcel(@NonNull Parcel in) { 254 return new FontScaleSetting(in); 255 } 256 257 @Override 258 public FontScaleSetting[] newArray(int size) { 259 return new FontScaleSetting[size]; 260 } 261 }; 262 263 @Override equals(@ullable Object obj)264 public boolean equals(@Nullable Object obj) { 265 if (!(obj instanceof FontScaleSetting other)) { 266 return false; 267 } 268 return Float.compare(mFontScaleFactor, other.mFontScaleFactor) == 0; 269 } 270 271 @Override hashCode()272 public int hashCode() { 273 return Objects.hash(mFontScaleFactor); 274 } 275 } 276 } 277