Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0aeb0847 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Import SettingsLib/Graph library" into main

parents 1a912c79 659b6963
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ package {

filegroup {
    name: "SettingsLibGraph-srcs",
    srcs: ["src/**/*"],
    srcs: ["src/**/*.kt"],
}

android_library {
@@ -14,8 +14,24 @@ android_library {
    ],
    srcs: [":SettingsLibGraph-srcs"],
    static_libs: [
        "SettingsLibGraph-proto-lite",
        "SettingsLibIpc",
        "SettingsLibMetadata",
        "SettingsLibPreference",
        "androidx.annotation_annotation",
        "androidx.fragment_fragment",
        "androidx.preference_preference",
    ],
    kotlincflags: ["-Xjvm-default=all"],
}

java_library {
    name: "SettingsLibGraph-proto-lite",
    srcs: ["graph.proto"],
    proto: {
        type: "lite",
        canonical_path_from_root: false,
    },
    sdk_version: "core_current",
    static_libs: ["libprotobuf-java-lite"],
}
+156 −0
Original line number Diff line number Diff line
syntax = "proto3";

package com.android.settingslib.graph;

option java_package = "com.android.settingslib.graph.proto";
option java_multiple_files = true;

// Proto represents preference graph.
message PreferenceGraphProto {
  // Preference screens appear in the graph.
  // Key: preference key of the PreferenceScreen. Value: PreferenceScreen.
  map<string, PreferenceScreenProto> screens = 1;
  // Roots of the graph.
  // Each element is a preference key of the PreferenceScreen.
  repeated string roots = 2;
  // Activities appear in the graph.
  // Key: activity class. Value: preference key of associated PreferenceScreen.
  map<string, string> activity_screens = 3;
}

// Proto of PreferenceScreen.
message PreferenceScreenProto {
  // Intent to show the PreferenceScreen.
  optional IntentProto intent = 1;
  // Root of the PreferenceScreen hierarchy.
  optional PreferenceGroupProto root = 2;
  // If the preference screen provides complete hierarchy by source code.
  optional bool complete_hierarchy = 3;
}

// Proto of PreferenceGroup.
message PreferenceGroupProto {
  // Self information of PreferenceGroup.
  optional PreferenceProto preference = 1;
  // A list of children.
  repeated PreferenceOrGroupProto preferences = 2;
}

// Proto represents either PreferenceProto or PreferenceGroupProto.
message PreferenceOrGroupProto {
  oneof kind {
    // It is a Preference.
    PreferenceProto preference = 1;
    // It is a PreferenceGroup.
    PreferenceGroupProto group = 2;
  }
}

// Proto of Preference.
message PreferenceProto {
  // Key of the preference.
  optional string key = 1;
  // Title of the preference.
  optional TextProto title = 2;
  // Summary of the preference.
  optional TextProto summary = 3;
  // Icon of the preference.
  optional int32 icon = 4;
  // Additional keywords for indexing.
  optional int32 keywords = 5;
  // Extras of the preference.
  optional BundleProto extras = 6;
  // Whether the preference is indexable.
  optional bool indexable = 7;
  // Whether the preference is enabled.
  optional bool enabled = 8;
  // Whether the preference is available/visible.
  optional bool available = 9;
  // Whether the preference is persistent.
  optional bool persistent = 10;
  // Whether the preference is restricted by managed configurations.
  optional bool restricted = 11;
  // Target of the preference action.
  optional ActionTarget action_target = 12;
  // Preference value (if present, it means `persistent` is true).
  optional PreferenceValueProto value = 13;

  // Target of an Intent
  message ActionTarget {
    oneof kind {
      // Resolved key of the preference screen located in current app.
      // This is resolved from android:fragment or activity of current app.
      string key = 1;
      // Unresolvable Intent that is either an unrecognized activity of current
      // app or activity belongs to other app.
      IntentProto intent = 2;
    }
  }
}

// Proto of string or string resource id.
message TextProto {
  oneof text {
    int32 resource_id = 1;
    string string = 2;
  }
}

// Proto of preference value.
message PreferenceValueProto {
  oneof value {
    bool boolean_value = 1;
  }
}

// Proto of android.content.Intent
message IntentProto {
  // The action of the Intent.
  optional string action = 1;

  // The data attribute of the Intent, expressed as a URI.
  optional string data = 2;

  // The package attribute of the Intent, which may be set to force the
  // detection of a particular application package that can handle the event.
  optional string pkg = 3;

  // The component attribute of the Intent, which may be set to force the
  // detection of a particular component (app). If present, this must be a
  // package name followed by a '/' and then followed by the class name.
  optional string component = 4;

  // Flags controlling how intent is handled. The value must be bitwise OR of
  // intent flag constants defined by Android.
  // http://developer.android.com/reference/android/content/Intent.html#setFlags(int)
  optional int32 flags = 5;

  // Extended data from the intent.
  optional BundleProto extras = 6;

  // The MIME type of the Intent (e.g. "text/plain").
  //
  // For more information, see
  // https://developer.android.com/reference/android/content/Intent#setType(java.lang.String).
  optional string mime_type = 7;
}

// Proto of android.os.Bundle
message BundleProto {
  // Bundle data.
  map<string, BundleValue> values = 1;

  message BundleValue {
    // Bundle data value for the associated key name.
    // Can be extended to support other types of bundled data.
    oneof value {
      string string_value = 1;
      bytes bytes_value = 2;
      int32 int_value = 3;
      int64 long_value = 4;
      bool boolean_value = 5;
      double double_value = 6;
      BundleProto bundle_value = 7;
    }
  }
}
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.settingslib.graph

import android.app.Application
import android.os.Bundle
import com.android.settingslib.graph.proto.PreferenceGraphProto
import com.android.settingslib.ipc.ApiHandler
import com.android.settingslib.ipc.MessageCodec
import java.util.Locale

/** API to get preference graph. */
abstract class GetPreferenceGraphApiHandler(private val activityClasses: Set<String>) :
    ApiHandler<GetPreferenceGraphRequest, PreferenceGraphProto> {

    override val requestCodec: MessageCodec<GetPreferenceGraphRequest>
        get() = GetPreferenceGraphRequestCodec

    override val responseCodec: MessageCodec<PreferenceGraphProto>
        get() = PreferenceGraphProtoCodec

    override suspend fun invoke(
        application: Application,
        myUid: Int,
        callingUid: Int,
        request: GetPreferenceGraphRequest,
    ): PreferenceGraphProto {
        val builderRequest =
            if (request.activityClasses.isEmpty()) {
                GetPreferenceGraphRequest(activityClasses, request.visitedScreens, request.locale)
            } else {
                request
            }
        return PreferenceGraphBuilder.of(application, builderRequest).build()
    }
}

/**
 * Request of [GetPreferenceGraphApiHandler].
 *
 * @param activityClasses activities of the preference graph
 * @param visitedScreens keys of the visited preference screen
 * @param locale locale of the preference graph
 */
data class GetPreferenceGraphRequest
@JvmOverloads
constructor(
    val activityClasses: Set<String> = setOf(),
    val visitedScreens: Set<String> = setOf(),
    val locale: Locale? = null,
    val includeValue: Boolean = true,
)

object GetPreferenceGraphRequestCodec : MessageCodec<GetPreferenceGraphRequest> {
    override fun encode(data: GetPreferenceGraphRequest): Bundle =
        Bundle(3).apply {
            putStringArray(KEY_ACTIVITIES, data.activityClasses.toTypedArray())
            putStringArray(KEY_PREF_KEYS, data.visitedScreens.toTypedArray())
            putString(KEY_LOCALE, data.locale?.toLanguageTag())
        }

    override fun decode(data: Bundle): GetPreferenceGraphRequest {
        val activities = data.getStringArray(KEY_ACTIVITIES) ?: arrayOf()
        val visitedScreens = data.getStringArray(KEY_PREF_KEYS) ?: arrayOf()
        fun String?.toLocale() = if (this != null) Locale.forLanguageTag(this) else null
        return GetPreferenceGraphRequest(
            activities.toSet(),
            visitedScreens.toSet(),
            data.getString(KEY_LOCALE).toLocale(),
        )
    }

    private const val KEY_ACTIVITIES = "activities"
    private const val KEY_PREF_KEYS = "keys"
    private const val KEY_LOCALE = "locale"
}

object PreferenceGraphProtoCodec : MessageCodec<PreferenceGraphProto> {
    override fun encode(data: PreferenceGraphProto): Bundle =
        Bundle(1).apply { putByteArray(KEY_GRAPH, data.toByteArray()) }

    override fun decode(data: Bundle): PreferenceGraphProto =
        PreferenceGraphProto.parseFrom(data.getByteArray(KEY_GRAPH)!!)

    private const val KEY_GRAPH = "graph"
}
+445 −0

File added.

Preview size limit exceeded, changes collapsed.

+0 −70
Original line number Diff line number Diff line
package com.android.settingslib.graph

import androidx.annotation.StringRes
import androidx.annotation.XmlRes
import androidx.preference.Preference
import androidx.preference.PreferenceManager
import androidx.preference.PreferenceScreen

/** Manager to create and initialize preference screen. */
class PreferenceScreenManager(private val preferenceManager: PreferenceManager) {
    private val context = preferenceManager.context
    // the map will preserve order
    private val updaters = mutableMapOf<String, PreferenceUpdater>()
    private val screenUpdaters = mutableListOf<PreferenceScreenUpdater>()

    /** Creates an empty [PreferenceScreen]. */
    fun createPreferenceScreen(): PreferenceScreen =
        preferenceManager.createPreferenceScreen(context)

    /** Creates [PreferenceScreen] from resource. */
    fun createPreferenceScreen(@XmlRes xmlRes: Int): PreferenceScreen =
        preferenceManager.inflateFromResource(context, xmlRes, null)

    /** Adds updater for given preference. */
    fun addPreferenceUpdater(@StringRes key: Int, updater: PreferenceUpdater) =
        addPreferenceUpdater(context.getString(key), updater)

    /** Adds updater for given preference. */
    fun addPreferenceUpdater(
        key: String,
        updater: PreferenceUpdater,
    ): PreferenceScreenManager {
        updaters.put(key, updater)?.let { if (it != updater) throw IllegalArgumentException() }
        return this
    }

    /** Adds updater for preference screen. */
    fun addPreferenceScreenUpdater(updater: PreferenceScreenUpdater): PreferenceScreenManager {
        screenUpdaters.add(updater)
        return this
    }

    /** Adds a list of updaters for preference screen. */
    fun addPreferenceScreenUpdater(
        vararg updaters: PreferenceScreenUpdater,
    ): PreferenceScreenManager {
        screenUpdaters.addAll(updaters)
        return this
    }

    /** Updates preference screen with registered updaters. */
    fun updatePreferenceScreen(preferenceScreen: PreferenceScreen) {
        for ((key, updater) in updaters) {
            preferenceScreen.findPreference<Preference>(key)?.let { updater.updatePreference(it) }
        }
        for (updater in screenUpdaters) {
            updater.updatePreferenceScreen(preferenceScreen)
        }
    }
}

/** Updater of [Preference]. */
interface PreferenceUpdater {
    fun updatePreference(preference: Preference)
}

/** Updater of [PreferenceScreen]. */
interface PreferenceScreenUpdater {
    fun updatePreferenceScreen(preferenceScreen: PreferenceScreen)
}
Loading