1 /* 2 * Copyright (C) 2023 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 com.android.systemui.qs.pipeline.shared 18 19 import android.content.ComponentName 20 import android.text.TextUtils 21 import com.android.systemui.qs.external.CustomTile 22 23 /** 24 * Container for the spec that identifies a tile. 25 * 26 * A tile's [spec] is one of two options: 27 * * `custom(<componentName>)`: A [ComponentName] surrounded by [CustomTile.PREFIX] and terminated 28 * by `)`, represents a tile provided by an app, corresponding to a `TileService`. 29 * * a string not starting with [CustomTile.PREFIX], representing a tile provided by SystemUI. 30 */ 31 sealed class TileSpec private constructor(open val spec: String) { 32 33 /** Represents a spec that couldn't be parsed into a valid type of tile. */ 34 object Invalid : TileSpec("") { 35 override fun toString(): String { 36 return "TileSpec.INVALID" 37 } 38 } 39 40 /** Container for the spec of a tile provided by SystemUI. */ 41 data class PlatformTileSpec 42 internal constructor( 43 override val spec: String, 44 ) : TileSpec(spec) 45 46 /** 47 * Container for the spec of a tile provided by an app. 48 * 49 * [componentName] indicates the associated `TileService`. 50 */ 51 data class CustomTileSpec 52 internal constructor( 53 override val spec: String, 54 val componentName: ComponentName, 55 ) : TileSpec(spec) { 56 override fun toString(): String { 57 return "CustomTileSpec(${componentName.toShortString()})" 58 } 59 } 60 61 companion object { 62 /** Create a [TileSpec] from the string [spec]. */ 63 fun create(spec: String): TileSpec { 64 return if (TextUtils.isEmpty(spec)) { 65 Invalid 66 } else if (!spec.isCustomTileSpec) { 67 PlatformTileSpec(spec) 68 } else { 69 spec.componentName?.let { CustomTileSpec(spec, it) } ?: Invalid 70 } 71 } 72 73 fun create(component: ComponentName): CustomTileSpec { 74 return CustomTileSpec(CustomTile.toSpec(component), component) 75 } 76 77 private val String.isCustomTileSpec: Boolean 78 get() = startsWith(CustomTile.PREFIX) 79 80 private val String.componentName: ComponentName? 81 get() = 82 if (!isCustomTileSpec) { 83 null 84 } else { 85 if (endsWith(")")) { 86 val extracted = substring(CustomTile.PREFIX.length, length - 1) 87 ComponentName.unflattenFromString(extracted) 88 } else { 89 null 90 } 91 } 92 } 93 } 94