Merge "Communicate flags from systemui async" into sc-v2-dev am: c3ef628c75

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16200718

Change-Id: Ib5a429f951a65f3f277baed4e21a8c18ed55ba69
This commit is contained in:
Dave Mankoff
2021-11-08 18:32:17 +00:00
committed by Automerger Merge Worker
4 changed files with 171 additions and 21 deletions

View File

@@ -62,6 +62,7 @@ java_library {
srcs: [ srcs: [
"src/com/android/systemui/flags/Flag.kt", "src/com/android/systemui/flags/Flag.kt",
], ],
include_srcs: true,
static_kotlin_stdlib: false, static_kotlin_stdlib: false,
java_version: "1.8", java_version: "1.8",
min_sdk_version: "current", min_sdk_version: "current",
@@ -74,11 +75,11 @@ java_library {
], ],
static_kotlin_stdlib: false, static_kotlin_stdlib: false,
libs: [ libs: [
"SystemUI-flags",
"androidx.concurrent_concurrent-futures", "androidx.concurrent_concurrent-futures",
], ],
static_libs: [ static_libs: [
"SystemUI-flag-types", "SystemUI-flag-types",
"SystemUI-flags",
], ],
java_version: "1.8", java_version: "1.8",
min_sdk_version: "current", min_sdk_version: "current",

View File

@@ -16,37 +16,157 @@
package com.android.systemui.flags package com.android.systemui.flags
interface Flag<T> { import android.os.Parcel
import android.os.Parcelable
interface Flag<T> : Parcelable {
val id: Int val id: Int
val default: T val default: T
override fun describeContents() = 0
} }
// Consider using the "parcelize" kotlin library.
data class BooleanFlag @JvmOverloads constructor( data class BooleanFlag @JvmOverloads constructor(
override val id: Int, override val id: Int,
override val default: Boolean = false override val default: Boolean = false
) : Flag<Boolean> ) : Flag<Boolean> {
companion object {
@JvmField
val CREATOR = object : Parcelable.Creator<BooleanFlag> {
override fun createFromParcel(parcel: Parcel) = BooleanFlag(parcel)
override fun newArray(size: Int) = arrayOfNulls<BooleanFlag>(size)
}
}
private constructor(parcel: Parcel) : this(
id = parcel.readInt(),
default = parcel.readBoolean()
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id)
parcel.writeBoolean(default)
}
}
data class StringFlag @JvmOverloads constructor( data class StringFlag @JvmOverloads constructor(
override val id: Int, override val id: Int,
override val default: String = "" override val default: String = ""
) : Flag<String> ) : Flag<String> {
companion object {
@JvmField
val CREATOR = object : Parcelable.Creator<StringFlag> {
override fun createFromParcel(parcel: Parcel) = StringFlag(parcel)
override fun newArray(size: Int) = arrayOfNulls<StringFlag>(size)
}
}
private constructor(parcel: Parcel) : this(
id = parcel.readInt(),
default = parcel.readString() ?: ""
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id)
parcel.writeString(default)
}
}
data class IntFlag @JvmOverloads constructor( data class IntFlag @JvmOverloads constructor(
override val id: Int, override val id: Int,
override val default: Int = 0 override val default: Int = 0
) : Flag<Int> ) : Flag<Int> {
companion object {
@JvmField
val CREATOR = object : Parcelable.Creator<IntFlag> {
override fun createFromParcel(parcel: Parcel) = IntFlag(parcel)
override fun newArray(size: Int) = arrayOfNulls<IntFlag>(size)
}
}
private constructor(parcel: Parcel) : this(
id = parcel.readInt(),
default = parcel.readInt()
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id)
parcel.writeInt(default)
}
}
data class LongFlag @JvmOverloads constructor( data class LongFlag @JvmOverloads constructor(
override val id: Int, override val id: Int,
override val default: Long = 0 override val default: Long = 0
) : Flag<Long> ) : Flag<Long> {
companion object {
@JvmField
val CREATOR = object : Parcelable.Creator<LongFlag> {
override fun createFromParcel(parcel: Parcel) = LongFlag(parcel)
override fun newArray(size: Int) = arrayOfNulls<LongFlag>(size)
}
}
private constructor(parcel: Parcel) : this(
id = parcel.readInt(),
default = parcel.readLong()
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id)
parcel.writeLong(default)
}
}
data class FloatFlag @JvmOverloads constructor( data class FloatFlag @JvmOverloads constructor(
override val id: Int, override val id: Int,
override val default: Float = 0f override val default: Float = 0f
) : Flag<Float> ) : Flag<Float> {
companion object {
@JvmField
val CREATOR = object : Parcelable.Creator<FloatFlag> {
override fun createFromParcel(parcel: Parcel) = FloatFlag(parcel)
override fun newArray(size: Int) = arrayOfNulls<FloatFlag>(size)
}
}
private constructor(parcel: Parcel) : this(
id = parcel.readInt(),
default = parcel.readFloat()
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id)
parcel.writeFloat(default)
}
}
data class DoubleFlag @JvmOverloads constructor( data class DoubleFlag @JvmOverloads constructor(
override val id: Int, override val id: Int,
override val default: Double = 0.0 override val default: Double = 0.0
) : Flag<Double> ) : Flag<Double> {
companion object {
@JvmField
val CREATOR = object : Parcelable.Creator<DoubleFlag> {
override fun createFromParcel(parcel: Parcel) = DoubleFlag(parcel)
override fun newArray(size: Int) = arrayOfNulls<DoubleFlag>(size)
}
}
private constructor(parcel: Parcel) : this(
id = parcel.readInt(),
default = parcel.readDouble()
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id)
parcel.writeDouble(default)
}
}

View File

@@ -16,10 +16,13 @@
package com.android.systemui.flags package com.android.systemui.flags
import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.database.ContentObserver import android.database.ContentObserver
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.provider.Settings import android.provider.Settings
import androidx.concurrent.futures.CallbackToFutureAdapter import androidx.concurrent.futures.CallbackToFutureAdapter
@@ -34,10 +37,12 @@ class FlagManager constructor(
companion object { companion object {
const val RECEIVING_PACKAGE = "com.android.systemui" const val RECEIVING_PACKAGE = "com.android.systemui"
const val ACTION_SET_FLAG = "com.android.systemui.action.SET_FLAG" const val ACTION_SET_FLAG = "com.android.systemui.action.SET_FLAG"
const val ACTION_GET_FLAGS = "com.android.systemui.action.GET_FLAGS"
const val FLAGS_PERMISSION = "com.android.systemui.permission.FLAGS" const val FLAGS_PERMISSION = "com.android.systemui.permission.FLAGS"
const val FIELD_ID = "id" const val FIELD_ID = "id"
const val FIELD_VALUE = "value" const val FIELD_VALUE = "value"
const val FIELD_TYPE = "type" const val FIELD_TYPE = "type"
const val FIELD_FLAGS = "flags"
const val TYPE_BOOLEAN = "boolean" const val TYPE_BOOLEAN = "boolean"
private const val SETTINGS_PREFIX = "systemui/flags" private const val SETTINGS_PREFIX = "systemui/flags"
} }
@@ -46,14 +51,26 @@ class FlagManager constructor(
private val settingsObserver: ContentObserver = SettingsObserver() private val settingsObserver: ContentObserver = SettingsObserver()
fun getFlagsFuture(): ListenableFuture<Collection<Flag<*>>> { fun getFlagsFuture(): ListenableFuture<Collection<Flag<*>>> {
val knownFlagMap = Flags.collectFlags() val intent = Intent(ACTION_GET_FLAGS)
// Possible todo in the future: query systemui async to actually get the known flag ids. intent.setPackage(RECEIVING_PACKAGE)
return CallbackToFutureAdapter.getFuture(
CallbackToFutureAdapter.Resolver { return CallbackToFutureAdapter.getFuture {
completer: CallbackToFutureAdapter.Completer<Collection<Flag<*>>> -> completer: CallbackToFutureAdapter.Completer<Any?> ->
completer.set(knownFlagMap.values as Collection<Flag<*>>) context.sendOrderedBroadcast(intent, null,
"Retrieving Flags" object : BroadcastReceiver() {
}) override fun onReceive(context: Context, intent: Intent) {
val extras: Bundle? = getResultExtras(false)
val listOfFlags: java.util.ArrayList<Flag<*>>? =
extras?.getParcelableArrayList(FIELD_FLAGS)
if (listOfFlags != null) {
completer.set(listOfFlags)
} else {
completer.setException(NoFlagResultsException())
}
}
}, null, Activity.RESULT_OK, "extra data", null)
"QueryingFlags"
} as ListenableFuture<Collection<Flag<*>>>
} }
fun setFlagValue(id: Int, enabled: Boolean) { fun setFlagValue(id: Int, enabled: Boolean) {
@@ -149,4 +166,7 @@ class FlagManager constructor(
} }
} }
class InvalidFlagStorageException : Exception("Data found but is invalid") class InvalidFlagStorageException : Exception("Data found but is invalid")
class NoFlagResultsException : Exception(
"SystemUI failed to communicate its flags back successfully")

View File

@@ -16,10 +16,11 @@
package com.android.systemui.flags; package com.android.systemui.flags;
import static com.android.systemui.flags.FlagManager.ACTION_GET_FLAGS;
import static com.android.systemui.flags.FlagManager.ACTION_SET_FLAG; import static com.android.systemui.flags.FlagManager.ACTION_SET_FLAG;
import static com.android.systemui.flags.FlagManager.FIELD_FLAGS;
import static com.android.systemui.flags.FlagManager.FIELD_ID; import static com.android.systemui.flags.FlagManager.FIELD_ID;
import static com.android.systemui.flags.FlagManager.FIELD_VALUE; import static com.android.systemui.flags.FlagManager.FIELD_VALUE;
import static com.android.systemui.flags.FlagManager.FLAGS_PERMISSION;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@@ -69,8 +70,10 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
DumpManager dumpManager) { DumpManager dumpManager) {
mFlagManager = flagManager; mFlagManager = flagManager;
mSecureSettings = secureSettings; mSecureSettings = secureSettings;
IntentFilter filter = new IntentFilter(ACTION_SET_FLAG); IntentFilter filter = new IntentFilter();
context.registerReceiver(mReceiver, filter, FLAGS_PERMISSION, null); filter.addAction(ACTION_SET_FLAG);
filter.addAction(ACTION_GET_FLAGS);
context.registerReceiver(mReceiver, filter, null, null);
dumpManager.registerDumpable(TAG, this); dumpManager.registerDumpable(TAG, this);
} }
@@ -151,9 +154,15 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
if (action == null) { if (action == null) {
return; return;
} }
if (ACTION_SET_FLAG.equals(action)) { if (ACTION_SET_FLAG.equals(action)) {
handleSetFlag(intent.getExtras()); handleSetFlag(intent.getExtras());
} else if (ACTION_GET_FLAGS.equals(action)) {
Map<Integer, Flag<?>> knownFlagMap = Flags.collectFlags();
ArrayList<Flag<?>> flags = new ArrayList<>(knownFlagMap.values());
Bundle extras = getResultExtras(true);
if (extras != null) {
extras.putParcelableArrayList(FIELD_FLAGS, flags);
}
} }
} }