blob: 040641c86d8ec66a2f307e4f127b6599f9704447 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.compatibility.common.util;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import android.content.Context;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.common.base.Preconditions;
import java.util.concurrent.atomic.AtomicReference;
/**
* Manages the state of a preference backed by {@link DeviceConfig}.
*/
public final class DeviceConfigStateManager implements StateManager<String> {
private static final String TAG = DeviceConfigStateManager.class.getSimpleName();
private final Context mContext;
private final String mNamespace;
private final String mKey;
/**
* Default constructor.
*
* @param context context used to retrieve the {@link Settings} provider.
* @param namespace settings namespace.
* @param key prefence key.
*/
public DeviceConfigStateManager(@NonNull Context context, @NonNull String namespace,
@NonNull String key) {
debug("DeviceConfigStateManager", "namespace=%s, key=%s", namespace, key);
mContext = Preconditions.checkNotNull(context);
mNamespace = Preconditions.checkNotNull(namespace);
mKey = Preconditions.checkNotNull(key);
}
@Override
public void set(@Nullable String value) {
debug("set", "new value is %s", value);
runWithShellPermissionIdentity(() -> setWithPermissionsGranted(value),
"android.permission.READ_DEVICE_CONFIG", "android.permission.WRITE_DEVICE_CONFIG");
}
private void setWithPermissionsGranted(@Nullable String value) {
final OneTimeDeviceConfigListener listener = new OneTimeDeviceConfigListener(mNamespace,
mKey);
DeviceConfig.addOnPropertiesChangedListener(mNamespace, mContext.getMainExecutor(),
listener);
DeviceConfig.setProperty(mNamespace, mKey, value, /* makeDefault= */ false);
listener.assertCalled();
}
@Override
@Nullable
public String get() {
final AtomicReference<String> reference = new AtomicReference<>();
runWithShellPermissionIdentity(()
-> reference.set(DeviceConfig.getProperty(mNamespace, mKey)),
"android.permission.READ_DEVICE_CONFIG");
debug("get", "returning %s", reference.get());
return reference.get();
}
private void debug(@NonNull String methodName, @NonNull String msg, Object...args) {
if (!Log.isLoggable(TAG, Log.DEBUG)) return;
final String prefix = String.format("%s(%s:%s): ", methodName, mNamespace, mKey);
Log.d(TAG, prefix + String.format(msg, args));
}
@Override
public String toString() {
return "DeviceConfigStateManager[namespace=" + mNamespace + ", key=" + mKey + "]";
}
}