1 /* 2 * Copyright (C) 2022 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.app; 18 19 import android.Manifest; 20 import android.annotation.FlaggedApi; 21 import android.annotation.NonNull; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SystemService; 24 import android.content.Context; 25 import android.content.res.Configuration; 26 import android.os.RemoteException; 27 28 import java.util.Arrays; 29 import java.util.Collections; 30 import java.util.HashSet; 31 import java.util.Set; 32 33 /** 34 * This class allow applications to control granular grammatical inflection settings (such as 35 * per-app grammatical gender). 36 */ 37 @SystemService(Context.GRAMMATICAL_INFLECTION_SERVICE) 38 public class GrammaticalInflectionManager { 39 40 /** @hide */ 41 @NonNull 42 public static final Set<Integer> VALID_GRAMMATICAL_GENDER_VALUES = 43 Collections.unmodifiableSet(new HashSet<>(Arrays.asList( 44 Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED, 45 Configuration.GRAMMATICAL_GENDER_NEUTRAL, 46 Configuration.GRAMMATICAL_GENDER_FEMININE, 47 Configuration.GRAMMATICAL_GENDER_MASCULINE))); 48 49 private final Context mContext; 50 private final IGrammaticalInflectionManager mService; 51 52 /** @hide Instantiated by ContextImpl */ GrammaticalInflectionManager(Context context, IGrammaticalInflectionManager service)53 public GrammaticalInflectionManager(Context context, IGrammaticalInflectionManager service) { 54 mContext = context; 55 mService = service; 56 } 57 58 /** 59 * Returns the current grammatical gender for the calling app. A new value can be requested via 60 * {@link #setRequestedApplicationGrammaticalGender(int)} and will be updated with a new 61 * configuration change. The method always returns the value received with the last received 62 * configuration change. 63 * 64 * @return the value of grammatical gender 65 * @see Configuration#getGrammaticalGender 66 */ 67 @Configuration.GrammaticalGender getApplicationGrammaticalGender()68 public int getApplicationGrammaticalGender() { 69 return mContext.getApplicationContext() 70 .getResources() 71 .getConfiguration() 72 .getGrammaticalGender(); 73 } 74 75 /** 76 * Sets the current grammatical gender for the calling app (keyed by package name and user ID 77 * retrieved from the calling pid). 78 * 79 * <p><b>Note:</b> Changes to app grammatical gender will result in a configuration change (and 80 * potentially an Activity re-creation) being applied to the specified application. For more 81 * information, see the <a 82 * href="https://developer.android.com/guide/topics/resources/runtime-changes">section on 83 * handling configuration changes</a>. The set grammatical gender are persisted across 84 * application restarts; they are backed up if the user has enabled Backup & Restore.` 85 * 86 * @param grammaticalGender the terms of address the user preferred in an application. 87 * @see Configuration#getGrammaticalGender 88 */ setRequestedApplicationGrammaticalGender( @onfiguration.GrammaticalGender int grammaticalGender)89 public void setRequestedApplicationGrammaticalGender( 90 @Configuration.GrammaticalGender int grammaticalGender) { 91 if (!VALID_GRAMMATICAL_GENDER_VALUES.contains(grammaticalGender)) { 92 throw new IllegalArgumentException("Unknown grammatical gender"); 93 } 94 95 try { 96 mService.setRequestedApplicationGrammaticalGender( 97 mContext.getPackageName(), mContext.getUserId(), grammaticalGender); 98 } catch (RemoteException e) { 99 throw e.rethrowFromSystemServer(); 100 } 101 } 102 103 /** 104 * Sets the current grammatical gender for all privileged applications. The value will be 105 * stored in an encrypted file at {@link android.os.Environment#getDataSystemCeDirectory(int)} 106 * 107 * @param grammaticalGender the grammatical gender set by the user for the system. 108 * 109 * @see Configuration#getGrammaticalGender 110 * @hide 111 */ setSystemWideGrammaticalGender( @onfiguration.GrammaticalGender int grammaticalGender)112 public void setSystemWideGrammaticalGender( 113 @Configuration.GrammaticalGender int grammaticalGender) { 114 if (!VALID_GRAMMATICAL_GENDER_VALUES.contains(grammaticalGender)) { 115 throw new IllegalArgumentException("Unknown grammatical gender"); 116 } 117 118 try { 119 mService.setSystemWideGrammaticalGender(grammaticalGender, mContext.getUserId()); 120 } catch (RemoteException e) { 121 throw e.rethrowFromSystemServer(); 122 } 123 } 124 125 /** 126 * Allows privileged preloaded applications to get the system grammatical gender when set. 127 * 128 * @return The value of system grammatical gender only if the calling app has the 129 * permission, otherwise throwing an exception. 130 * 131 * @throws SecurityException If the caller does not have the required permission. 132 * 133 * @see Configuration#getGrammaticalGender 134 */ 135 @RequiresPermission(Manifest.permission.READ_SYSTEM_GRAMMATICAL_GENDER) 136 @FlaggedApi(Flags.FLAG_SYSTEM_TERMS_OF_ADDRESS_ENABLED) 137 @Configuration.GrammaticalGender getSystemGrammaticalGender()138 public int getSystemGrammaticalGender() { 139 try { 140 return mService.getSystemGrammaticalGender(mContext.getAttributionSource(), 141 mContext.getUserId()); 142 } catch (RemoteException e) { 143 throw e.rethrowFromSystemServer(); 144 } 145 } 146 147 /** 148 * Peeks the current grammatical gender of privileged application from the specific user's 149 * encrypted file. 150 * 151 * @return the value of system grammatical gender. 152 * @hide 153 * @see Configuration#getGrammaticalGender 154 */ 155 @RequiresPermission(Manifest.permission.READ_SYSTEM_GRAMMATICAL_GENDER) 156 @FlaggedApi(Flags.FLAG_SYSTEM_TERMS_OF_ADDRESS_ENABLED) 157 @Configuration.GrammaticalGender peekSystemGrammaticalGenderByUserId(int userId)158 public int peekSystemGrammaticalGenderByUserId(int userId) { 159 try { 160 return mService.peekSystemGrammaticalGenderByUserId(mContext.getAttributionSource(), 161 userId); 162 } catch (RemoteException e) { 163 throw e.rethrowFromSystemServer(); 164 } 165 } 166 } 167