Merge "Added core startable" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
063b05fe0a
@@ -28,12 +28,13 @@ import android.content.pm.ResolveInfo
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.UserHandle
|
||||
import android.service.controls.ControlsProviderService
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.android.settingslib.applications.DefaultAppInfo
|
||||
import com.android.systemui.R
|
||||
import java.util.Objects
|
||||
|
||||
class ControlsServiceInfo(
|
||||
open class ControlsServiceInfo(
|
||||
private val context: Context,
|
||||
val serviceInfo: ServiceInfo
|
||||
) : DefaultAppInfo(
|
||||
@@ -64,7 +65,7 @@ class ControlsServiceInfo(
|
||||
* [R.array.config_controlsPreferredPackages] can declare activities for use as a panel.
|
||||
*/
|
||||
var panelActivity: ComponentName? = null
|
||||
private set
|
||||
protected set
|
||||
|
||||
private var resolved: Boolean = false
|
||||
|
||||
|
||||
@@ -121,16 +121,13 @@ class ControlsControllerImpl @Inject constructor (
|
||||
userChanging = false
|
||||
}
|
||||
|
||||
private val userTrackerCallback = object : UserTracker.Callback {
|
||||
override fun onUserChanged(newUser: Int, userContext: Context) {
|
||||
userChanging = true
|
||||
val newUserHandle = UserHandle.of(newUser)
|
||||
if (currentUser == newUserHandle) {
|
||||
userChanging = false
|
||||
return
|
||||
}
|
||||
setValuesForUser(newUserHandle)
|
||||
override fun changeUser(newUser: UserHandle) {
|
||||
userChanging = true
|
||||
if (currentUser == newUser) {
|
||||
userChanging = false
|
||||
return
|
||||
}
|
||||
setValuesForUser(newUser)
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -231,7 +228,6 @@ class ControlsControllerImpl @Inject constructor (
|
||||
dumpManager.registerDumpable(javaClass.name, this)
|
||||
resetFavorites()
|
||||
userChanging = false
|
||||
userTracker.addCallback(userTrackerCallback, executor)
|
||||
context.registerReceiver(
|
||||
restoreFinishedReceiver,
|
||||
IntentFilter(BackupHelper.ACTION_RESTORE_FINISHED),
|
||||
@@ -243,7 +239,6 @@ class ControlsControllerImpl @Inject constructor (
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
userTracker.removeCallback(userTrackerCallback)
|
||||
context.unregisterReceiver(restoreFinishedReceiver)
|
||||
listingController.removeCallback(listingCallback)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.systemui.controls.dagger
|
||||
|
||||
import com.android.systemui.CoreStartable
|
||||
import com.android.systemui.controls.start.ControlsStartable
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.multibindings.ClassKey
|
||||
import dagger.multibindings.IntoMap
|
||||
|
||||
@Module
|
||||
abstract class StartControlsStartableModule {
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(ControlsStartable::class)
|
||||
abstract fun bindFeature(impl: ControlsStartable): CoreStartable
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.systemui.controls.start
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.os.UserHandle
|
||||
import com.android.systemui.CoreStartable
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.controls.controller.ControlsController
|
||||
import com.android.systemui.controls.dagger.ControlsComponent
|
||||
import com.android.systemui.controls.management.ControlsListingController
|
||||
import com.android.systemui.controls.ui.SelectedItem
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import java.util.concurrent.Executor
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Started with SystemUI to perform early operations for device controls subsystem (only if enabled)
|
||||
*
|
||||
* In particular, it will perform the following:
|
||||
* * If there is no preferred selection for provider and at least one of the preferred packages
|
||||
* provides a panel, it will select the first one that does.
|
||||
* * If the preferred selection provides a panel, it will bind to that service (to reduce latency on
|
||||
* displaying the panel).
|
||||
*
|
||||
* It will also perform those operations on user change.
|
||||
*/
|
||||
@SysUISingleton
|
||||
class ControlsStartable
|
||||
@Inject
|
||||
constructor(
|
||||
@Main private val resources: Resources,
|
||||
@Background private val executor: Executor,
|
||||
private val controlsComponent: ControlsComponent,
|
||||
private val userTracker: UserTracker
|
||||
) : CoreStartable {
|
||||
|
||||
// These two controllers can only be accessed after `start` method once we've checked if the
|
||||
// feature is enabled
|
||||
private val controlsController: ControlsController
|
||||
get() = controlsComponent.getControlsController().get()
|
||||
|
||||
private val controlsListingController: ControlsListingController
|
||||
get() = controlsComponent.getControlsListingController().get()
|
||||
|
||||
private val userTrackerCallback =
|
||||
object : UserTracker.Callback {
|
||||
override fun onUserChanged(newUser: Int, userContext: Context) {
|
||||
controlsController.changeUser(UserHandle.of(newUser))
|
||||
startForUser()
|
||||
}
|
||||
}
|
||||
|
||||
override fun start() {
|
||||
if (!controlsComponent.isEnabled()) {
|
||||
// Controls is disabled, we don't need this anymore
|
||||
return
|
||||
}
|
||||
startForUser()
|
||||
userTracker.addCallback(userTrackerCallback, executor)
|
||||
}
|
||||
|
||||
private fun startForUser() {
|
||||
selectDefaultPanelIfNecessary()
|
||||
bindToPanel()
|
||||
}
|
||||
|
||||
private fun selectDefaultPanelIfNecessary() {
|
||||
val currentSelection = controlsController.getPreferredSelection()
|
||||
if (currentSelection == SelectedItem.EMPTY_SELECTION) {
|
||||
val availableServices = controlsListingController.getCurrentServices()
|
||||
val panels = availableServices.filter { it.panelActivity != null }
|
||||
resources
|
||||
.getStringArray(R.array.config_controlsPreferredPackages)
|
||||
// Looking for the first element in the string array such that there is one package
|
||||
// that has a panel. It will return null if there are no packages in the array,
|
||||
// or if no packages in the array have a panel associated with it.
|
||||
.firstNotNullOfOrNull { name ->
|
||||
panels.firstOrNull { it.componentName.packageName == name }
|
||||
}
|
||||
?.let { info ->
|
||||
controlsController.setPreferredSelection(
|
||||
SelectedItem.PanelItem(info.loadLabel(), info.componentName)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindToPanel() {
|
||||
val currentSelection = controlsController.getPreferredSelection()
|
||||
val panels =
|
||||
controlsListingController.getCurrentServices().filter { it.panelActivity != null }
|
||||
if (
|
||||
currentSelection is SelectedItem.PanelItem &&
|
||||
panels.firstOrNull { it.componentName == currentSelection.componentName } != null
|
||||
) {
|
||||
controlsController.bindComponentForPanel(currentSelection.componentName)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import com.android.systemui.accessibility.SystemActions
|
||||
import com.android.systemui.accessibility.WindowMagnification
|
||||
import com.android.systemui.biometrics.AuthController
|
||||
import com.android.systemui.clipboardoverlay.ClipboardListener
|
||||
import com.android.systemui.controls.dagger.StartControlsStartableModule
|
||||
import com.android.systemui.dagger.qualifiers.PerUser
|
||||
import com.android.systemui.dreams.DreamMonitor
|
||||
import com.android.systemui.globalactions.GlobalActionsComponent
|
||||
@@ -65,7 +66,10 @@ import dagger.multibindings.IntoMap
|
||||
/**
|
||||
* Collection of {@link CoreStartable}s that should be run on AOSP.
|
||||
*/
|
||||
@Module(includes = [MultiUserUtilsModule::class])
|
||||
@Module(includes = [
|
||||
MultiUserUtilsModule::class,
|
||||
StartControlsStartableModule::class
|
||||
])
|
||||
abstract class SystemUICoreStartableModule {
|
||||
/** Inject into AuthController. */
|
||||
@Binds
|
||||
|
||||
@@ -103,8 +103,6 @@ class ControlsControllerImplTest : SysuiTestCase() {
|
||||
private lateinit var controlLoadCallbackCaptor2:
|
||||
ArgumentCaptor<ControlsBindingController.LoadCallback>
|
||||
|
||||
@Captor
|
||||
private lateinit var userTrackerCallbackCaptor: ArgumentCaptor<UserTracker.Callback>
|
||||
@Captor
|
||||
private lateinit var listingCallbackCaptor:
|
||||
ArgumentCaptor<ControlsListingController.ControlsListingCallback>
|
||||
@@ -178,10 +176,6 @@ class ControlsControllerImplTest : SysuiTestCase() {
|
||||
)
|
||||
controller.auxiliaryPersistenceWrapper = auxiliaryPersistenceWrapper
|
||||
|
||||
verify(userTracker).addCallback(
|
||||
capture(userTrackerCallbackCaptor), any()
|
||||
)
|
||||
|
||||
verify(listingController).addCallback(capture(listingCallbackCaptor))
|
||||
}
|
||||
|
||||
@@ -539,7 +533,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
|
||||
|
||||
reset(persistenceWrapper)
|
||||
|
||||
userTrackerCallbackCaptor.value.onUserChanged(otherUser, mContext)
|
||||
controller.changeUser(UserHandle.of(otherUser))
|
||||
|
||||
verify(persistenceWrapper).changeFileAndBackupManager(any(), any())
|
||||
verify(persistenceWrapper).readFavorites()
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.systemui.controls.start
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.controls.ControlsServiceInfo
|
||||
import com.android.systemui.controls.controller.ControlsController
|
||||
import com.android.systemui.controls.dagger.ControlsComponent
|
||||
import com.android.systemui.controls.management.ControlsListingController
|
||||
import com.android.systemui.controls.ui.SelectedItem
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import java.util.Optional
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.verifyZeroInteractions
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class ControlsStartableTest : SysuiTestCase() {
|
||||
|
||||
@Mock private lateinit var controlsController: ControlsController
|
||||
@Mock private lateinit var controlsListingController: ControlsListingController
|
||||
@Mock private lateinit var userTracker: UserTracker
|
||||
|
||||
private lateinit var fakeExecutor: FakeExecutor
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
context.orCreateTestableResources.addOverride(
|
||||
R.array.config_controlsPreferredPackages,
|
||||
arrayOf<String>()
|
||||
)
|
||||
|
||||
fakeExecutor = FakeExecutor(FakeSystemClock())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDisabledNothingIsCalled() {
|
||||
createStartable(enabled = false).start()
|
||||
|
||||
verifyZeroInteractions(controlsController, controlsListingController, userTracker)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNoPreferredPackagesNoDefaultSelected_noNewSelection() {
|
||||
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
|
||||
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
|
||||
`when`(controlsListingController.getCurrentServices()).thenReturn(listings)
|
||||
|
||||
createStartable(enabled = true).start()
|
||||
|
||||
verify(controlsController, never()).setPreferredSelection(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPreferredPackagesNotInstalled_noNewSelection() {
|
||||
context.orCreateTestableResources.addOverride(
|
||||
R.array.config_controlsPreferredPackages,
|
||||
arrayOf(TEST_PACKAGE_PANEL)
|
||||
)
|
||||
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
|
||||
`when`(controlsListingController.getCurrentServices()).thenReturn(emptyList())
|
||||
|
||||
createStartable(enabled = true).start()
|
||||
|
||||
verify(controlsController, never()).setPreferredSelection(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPreferredPackageNotPanel_noNewSelection() {
|
||||
context.orCreateTestableResources.addOverride(
|
||||
R.array.config_controlsPreferredPackages,
|
||||
arrayOf(TEST_PACKAGE_PANEL)
|
||||
)
|
||||
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
|
||||
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT, "not panel", hasPanel = false))
|
||||
`when`(controlsListingController.getCurrentServices()).thenReturn(listings)
|
||||
|
||||
createStartable(enabled = true).start()
|
||||
|
||||
verify(controlsController, never()).setPreferredSelection(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExistingSelection_noNewSelection() {
|
||||
context.orCreateTestableResources.addOverride(
|
||||
R.array.config_controlsPreferredPackages,
|
||||
arrayOf(TEST_PACKAGE_PANEL)
|
||||
)
|
||||
`when`(controlsController.getPreferredSelection())
|
||||
.thenReturn(mock<SelectedItem.PanelItem>())
|
||||
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
|
||||
`when`(controlsListingController.getCurrentServices()).thenReturn(listings)
|
||||
|
||||
createStartable(enabled = true).start()
|
||||
|
||||
verify(controlsController, never()).setPreferredSelection(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPanelAdded() {
|
||||
context.orCreateTestableResources.addOverride(
|
||||
R.array.config_controlsPreferredPackages,
|
||||
arrayOf(TEST_PACKAGE_PANEL)
|
||||
)
|
||||
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
|
||||
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
|
||||
`when`(controlsListingController.getCurrentServices()).thenReturn(listings)
|
||||
|
||||
createStartable(enabled = true).start()
|
||||
|
||||
verify(controlsController).setPreferredSelection(listings[0].toPanelItem())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMultiplePreferredOnlyOnePanel_panelAdded() {
|
||||
context.orCreateTestableResources.addOverride(
|
||||
R.array.config_controlsPreferredPackages,
|
||||
arrayOf("other_package", TEST_PACKAGE_PANEL)
|
||||
)
|
||||
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
|
||||
val listings =
|
||||
listOf(
|
||||
ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true),
|
||||
ControlsServiceInfo(ComponentName("other_package", "cls"), "non panel", false)
|
||||
)
|
||||
`when`(controlsListingController.getCurrentServices()).thenReturn(listings)
|
||||
|
||||
createStartable(enabled = true).start()
|
||||
|
||||
verify(controlsController).setPreferredSelection(listings[0].toPanelItem())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMultiplePreferredMultiplePanels_firstPreferredAdded() {
|
||||
context.orCreateTestableResources.addOverride(
|
||||
R.array.config_controlsPreferredPackages,
|
||||
arrayOf(TEST_PACKAGE_PANEL, "other_package")
|
||||
)
|
||||
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
|
||||
val listings =
|
||||
listOf(
|
||||
ControlsServiceInfo(ComponentName("other_package", "cls"), "panel", true),
|
||||
ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true)
|
||||
)
|
||||
`when`(controlsListingController.getCurrentServices()).thenReturn(listings)
|
||||
|
||||
createStartable(enabled = true).start()
|
||||
|
||||
verify(controlsController).setPreferredSelection(listings[1].toPanelItem())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPreferredSelectionIsPanel_bindOnStart() {
|
||||
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
|
||||
`when`(controlsListingController.getCurrentServices()).thenReturn(listings)
|
||||
`when`(controlsController.getPreferredSelection()).thenReturn(listings[0].toPanelItem())
|
||||
|
||||
createStartable(enabled = true).start()
|
||||
|
||||
verify(controlsController).bindComponentForPanel(TEST_COMPONENT_PANEL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPreferredSelectionPanel_listingNoPanel_notBind() {
|
||||
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = false))
|
||||
`when`(controlsListingController.getCurrentServices()).thenReturn(listings)
|
||||
`when`(controlsController.getPreferredSelection())
|
||||
.thenReturn(SelectedItem.PanelItem("panel", TEST_COMPONENT_PANEL))
|
||||
|
||||
createStartable(enabled = true).start()
|
||||
|
||||
verify(controlsController, never()).bindComponentForPanel(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNotPanelSelection_noBind() {
|
||||
val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = false))
|
||||
`when`(controlsListingController.getCurrentServices()).thenReturn(listings)
|
||||
`when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
|
||||
|
||||
createStartable(enabled = true).start()
|
||||
|
||||
verify(controlsController, never()).bindComponentForPanel(any())
|
||||
}
|
||||
|
||||
private fun createStartable(enabled: Boolean): ControlsStartable {
|
||||
val component: ControlsComponent =
|
||||
mock() {
|
||||
`when`(isEnabled()).thenReturn(enabled)
|
||||
if (enabled) {
|
||||
`when`(getControlsController()).thenReturn(Optional.of(controlsController))
|
||||
`when`(getControlsListingController())
|
||||
.thenReturn(Optional.of(controlsListingController))
|
||||
} else {
|
||||
`when`(getControlsController()).thenReturn(Optional.empty())
|
||||
`when`(getControlsListingController()).thenReturn(Optional.empty())
|
||||
}
|
||||
}
|
||||
return ControlsStartable(context.resources, fakeExecutor, component, userTracker)
|
||||
}
|
||||
|
||||
private fun ControlsServiceInfo(
|
||||
componentName: ComponentName,
|
||||
label: CharSequence,
|
||||
hasPanel: Boolean
|
||||
): ControlsServiceInfo {
|
||||
val serviceInfo =
|
||||
ServiceInfo().apply {
|
||||
applicationInfo = ApplicationInfo()
|
||||
packageName = componentName.packageName
|
||||
name = componentName.className
|
||||
}
|
||||
return FakeControlsServiceInfo(context, serviceInfo, label, hasPanel)
|
||||
}
|
||||
|
||||
private class FakeControlsServiceInfo(
|
||||
context: Context,
|
||||
serviceInfo: ServiceInfo,
|
||||
private val label: CharSequence,
|
||||
hasPanel: Boolean
|
||||
) : ControlsServiceInfo(context, serviceInfo) {
|
||||
|
||||
init {
|
||||
if (hasPanel) {
|
||||
panelActivity = serviceInfo.componentName
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadLabel(): CharSequence {
|
||||
return label
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun ControlsServiceInfo.toPanelItem(): SelectedItem.PanelItem {
|
||||
if (panelActivity == null) {
|
||||
throw IllegalArgumentException("$this is not a panel")
|
||||
}
|
||||
return SelectedItem.PanelItem(loadLabel(), componentName)
|
||||
}
|
||||
|
||||
private const val TEST_PACKAGE = "pkg"
|
||||
private val TEST_COMPONENT = ComponentName(TEST_PACKAGE, "service")
|
||||
private const val TEST_PACKAGE_PANEL = "pkg.panel"
|
||||
private val TEST_COMPONENT_PANEL = ComponentName(TEST_PACKAGE_PANEL, "service")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user