1 /* 2 * Copyright (C) 2021 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.alarmmanager.util; 18 19 import static com.android.compatibility.common.util.TestUtils.waitUntil; 20 21 import static org.junit.Assert.assertTrue; 22 23 import android.provider.DeviceConfig; 24 import android.util.Log; 25 26 import com.android.compatibility.common.util.SystemUtil; 27 28 import java.util.Collections; 29 import java.util.HashMap; 30 import java.util.Map; 31 32 public class AlarmManagerDeviceConfigHelper { 33 private static final String TAG = AlarmManagerDeviceConfigHelper.class.getSimpleName(); 34 35 private static final int UPDATE_TIMEOUT_SECONDS = 60; 36 37 private volatile Map<String, String> mCommittedMap; 38 private final Map<String, String> mInitialPropertiesMap; 39 private final Map<String, String> mPropertiesToSetMap; 40 AlarmManagerDeviceConfigHelper()41 public AlarmManagerDeviceConfigHelper() { 42 mPropertiesToSetMap = new HashMap<>(); 43 DeviceConfig.Properties initialProperties = null; 44 try { 45 initialProperties = SystemUtil.callWithShellPermissionIdentity( 46 () -> DeviceConfig.getProperties(DeviceConfig.NAMESPACE_ALARM_MANAGER)); 47 } catch (Exception e) { 48 Log.e(TAG, "Unexpected exception while fetching device_config properties", e); 49 } 50 if (initialProperties != null) { 51 for (String key : initialProperties.getKeyset()) { 52 mPropertiesToSetMap.put(key, initialProperties.getString(key, null)); 53 } 54 mCommittedMap = mInitialPropertiesMap = Collections.unmodifiableMap( 55 new HashMap<>(mPropertiesToSetMap)); 56 } else { 57 mCommittedMap = mInitialPropertiesMap = Collections.emptyMap(); 58 } 59 } 60 with(String key, long value)61 public AlarmManagerDeviceConfigHelper with(String key, long value) { 62 return with(key, Long.toString(value)); 63 } 64 with(String key, int value)65 public AlarmManagerDeviceConfigHelper with(String key, int value) { 66 return with(key, Integer.toString(value)); 67 } 68 with(String key, boolean value)69 public AlarmManagerDeviceConfigHelper with(String key, boolean value) { 70 return with(key, Boolean.toString(value)); 71 } 72 with(String key, String value)73 public AlarmManagerDeviceConfigHelper with(String key, String value) { 74 mPropertiesToSetMap.put(key, value); 75 return this; 76 } 77 without(String key)78 public AlarmManagerDeviceConfigHelper without(String key) { 79 mPropertiesToSetMap.remove(key); 80 return this; 81 } 82 getCurrentConfigVersion()83 private static int getCurrentConfigVersion() { 84 final String output = SystemUtil.runShellCommand("cmd alarm get-config-version").trim(); 85 return Integer.parseInt(output); 86 } 87 commitAndAwaitPropagation(DeviceConfig.Properties propertiesToSet)88 public static void commitAndAwaitPropagation(DeviceConfig.Properties propertiesToSet) { 89 final int currentVersion = getCurrentConfigVersion(); 90 try { 91 assertTrue("setProperties returned false", SystemUtil.callWithShellPermissionIdentity( 92 () -> DeviceConfig.setProperties(propertiesToSet))); 93 } catch (Exception e) { 94 throw new RuntimeException(e); 95 } 96 try { 97 waitUntil("Could not update config within " + UPDATE_TIMEOUT_SECONDS 98 + "s. Current version: " + currentVersion, UPDATE_TIMEOUT_SECONDS, 99 () -> (getCurrentConfigVersion() > currentVersion)); 100 } catch (Exception e) { 101 throw new RuntimeException("Unexpected exception while updating config", e); 102 } 103 } 104 commitAndAwaitPropagation()105 public void commitAndAwaitPropagation() { 106 if (mPropertiesToSetMap.equals(mCommittedMap)) { 107 // This will not cause any change, and will not bump up the config version. 108 return; 109 } 110 commitAndAwaitPropagation( 111 new DeviceConfig.Properties(DeviceConfig.NAMESPACE_ALARM_MANAGER, 112 mPropertiesToSetMap)); 113 mCommittedMap = Collections.unmodifiableMap(new HashMap<>(mPropertiesToSetMap)); 114 } 115 restoreAll()116 public void restoreAll() { 117 if (mCommittedMap.equals(mInitialPropertiesMap)) { 118 // This will not cause any change, and will not bump up the config version. 119 return; 120 } 121 commitAndAwaitPropagation(new DeviceConfig.Properties(DeviceConfig.NAMESPACE_ALARM_MANAGER, 122 mInitialPropertiesMap)); 123 mCommittedMap = Collections.emptyMap(); 124 } 125 } 126