Merge "Gate controls controllers with system feature flag" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0711557c68
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.controls.controller.ControlsController
|
||||
import com.android.systemui.controls.management.ControlsListingController
|
||||
import com.android.systemui.controls.ui.ControlsUiController
|
||||
import dagger.Lazy
|
||||
import java.util.Optional
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Pseudo-component to inject into classes outside `com.android.systemui.controls`.
|
||||
*
|
||||
* If `featureEnabled` is false, all the optionals should be empty. The controllers will only be
|
||||
* instantiated if `featureEnabled` is true.
|
||||
*/
|
||||
@Singleton
|
||||
class ControlsComponent @Inject constructor(
|
||||
@ControlsFeatureEnabled private val featureEnabled: Boolean,
|
||||
private val lazyControlsController: Lazy<ControlsController>,
|
||||
private val lazyControlsUiController: Lazy<ControlsUiController>,
|
||||
private val lazyControlsListingController: Lazy<ControlsListingController>
|
||||
) {
|
||||
fun getControlsController(): Optional<ControlsController> {
|
||||
return if (featureEnabled) Optional.of(lazyControlsController.get()) else Optional.empty()
|
||||
}
|
||||
|
||||
fun getControlsUiController(): Optional<ControlsUiController> {
|
||||
return if (featureEnabled) Optional.of(lazyControlsUiController.get()) else Optional.empty()
|
||||
}
|
||||
|
||||
fun getControlsListingController(): Optional<ControlsListingController> {
|
||||
return if (featureEnabled) {
|
||||
Optional.of(lazyControlsListingController.get())
|
||||
} else {
|
||||
Optional.empty()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 javax.inject.Qualifier
|
||||
|
||||
@Qualifier
|
||||
@MustBeDocumented
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class ControlsFeatureEnabled
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.controls.dagger
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.pm.PackageManager
|
||||
import com.android.systemui.controls.controller.ControlsBindingController
|
||||
import com.android.systemui.controls.controller.ControlsBindingControllerImpl
|
||||
import com.android.systemui.controls.controller.ControlsController
|
||||
@@ -28,19 +29,39 @@ import com.android.systemui.controls.management.ControlsListingController
|
||||
import com.android.systemui.controls.management.ControlsListingControllerImpl
|
||||
import com.android.systemui.controls.management.ControlsProviderSelectorActivity
|
||||
import com.android.systemui.controls.management.ControlsRequestDialog
|
||||
import com.android.systemui.controls.ui.ControlsUiController
|
||||
import com.android.systemui.controls.ui.ControlsUiControllerImpl
|
||||
import com.android.systemui.controls.ui.ControlActionCoordinator
|
||||
import com.android.systemui.controls.ui.ControlActionCoordinatorImpl
|
||||
import com.android.systemui.controls.ui.ControlsUiController
|
||||
import com.android.systemui.controls.ui.ControlsUiControllerImpl
|
||||
import dagger.Binds
|
||||
import dagger.BindsOptionalOf
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.multibindings.ClassKey
|
||||
import dagger.multibindings.IntoMap
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Module for injecting classes in `com.android.systemui.controls`-
|
||||
*
|
||||
* Classes provided by this module should only be injected directly into other classes in this
|
||||
* module. For injecting outside of this module (for example, [GlobalActionsDialog], inject
|
||||
* [ControlsComponent] and obtain the corresponding optionals from it.
|
||||
*/
|
||||
@Module
|
||||
abstract class ControlsModule {
|
||||
|
||||
@Module
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
@ControlsFeatureEnabled
|
||||
fun providesControlsFeatureEnabled(pm: PackageManager): Boolean {
|
||||
return pm.hasSystemFeature(PackageManager.FEATURE_CONTROLS)
|
||||
}
|
||||
}
|
||||
|
||||
@Binds
|
||||
abstract fun provideControlsListingController(
|
||||
controller: ControlsListingControllerImpl
|
||||
|
||||
@@ -55,6 +55,9 @@ class ControlsRequestReceiver : BroadcastReceiver() {
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_CONTROLS)) {
|
||||
return
|
||||
}
|
||||
|
||||
val packageName = intent.getParcelableExtra<ComponentName>(Intent.EXTRA_COMPONENT_NAME)
|
||||
?.packageName
|
||||
|
||||
@@ -60,7 +60,6 @@ import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.globalactions.GlobalActionsPopupMenu
|
||||
import com.android.systemui.plugins.ActivityStarter
|
||||
import com.android.systemui.statusbar.phone.ShadeController
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import dagger.Lazy
|
||||
import java.text.Collator
|
||||
@@ -80,7 +79,6 @@ class ControlsUiControllerImpl @Inject constructor (
|
||||
@Main val sharedPreferences: SharedPreferences,
|
||||
val controlActionCoordinator: ControlActionCoordinator,
|
||||
private val activityStarter: ActivityStarter,
|
||||
private val keyguardStateController: KeyguardStateController,
|
||||
private val shadeController: ShadeController
|
||||
) : ControlsUiController {
|
||||
|
||||
|
||||
@@ -120,8 +120,8 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
||||
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.ControlsAnimations;
|
||||
import com.android.systemui.controls.management.ControlsListingController;
|
||||
import com.android.systemui.controls.ui.ControlsUiController;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
@@ -140,6 +140,7 @@ import com.android.systemui.util.leak.RotationUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -234,11 +235,12 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
private final IStatusBarService mStatusBarService;
|
||||
private final NotificationShadeWindowController mNotificationShadeWindowController;
|
||||
private GlobalActionsPanelPlugin mWalletPlugin;
|
||||
private ControlsUiController mControlsUiController;
|
||||
private Optional<ControlsUiController> mControlsUiControllerOptional;
|
||||
private final IWindowManager mIWindowManager;
|
||||
private final Executor mBackgroundExecutor;
|
||||
private List<ControlsServiceInfo> mControlsServiceInfos = new ArrayList<>();
|
||||
private ControlsController mControlsController;
|
||||
private Optional<ControlsController> mControlsControllerOptional;
|
||||
private SharedPreferences mControlsPreferences;
|
||||
private final RingerModeTracker mRingerModeTracker;
|
||||
private int mDialogPressDelay = DIALOG_PRESS_DELAY; // ms
|
||||
private Handler mMainHandler;
|
||||
@@ -298,11 +300,11 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
NotificationShadeDepthController depthController, SysuiColorExtractor colorExtractor,
|
||||
IStatusBarService statusBarService,
|
||||
NotificationShadeWindowController notificationShadeWindowController,
|
||||
ControlsUiController controlsUiController, IWindowManager iWindowManager,
|
||||
IWindowManager iWindowManager,
|
||||
@Background Executor backgroundExecutor,
|
||||
ControlsListingController controlsListingController,
|
||||
ControlsController controlsController, UiEventLogger uiEventLogger,
|
||||
UiEventLogger uiEventLogger,
|
||||
RingerModeTracker ringerModeTracker, SysUiState sysUiState, @Main Handler handler,
|
||||
ControlsComponent controlsComponent,
|
||||
CurrentUserContextTracker currentUserContextTracker) {
|
||||
mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
|
||||
mWindowManagerFuncs = windowManagerFuncs;
|
||||
@@ -325,11 +327,11 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
mSysuiColorExtractor = colorExtractor;
|
||||
mStatusBarService = statusBarService;
|
||||
mNotificationShadeWindowController = notificationShadeWindowController;
|
||||
mControlsUiController = controlsUiController;
|
||||
mControlsUiControllerOptional = controlsComponent.getControlsUiController();
|
||||
mIWindowManager = iWindowManager;
|
||||
mBackgroundExecutor = backgroundExecutor;
|
||||
mRingerModeTracker = ringerModeTracker;
|
||||
mControlsController = controlsController;
|
||||
mControlsControllerOptional = controlsComponent.getControlsController();
|
||||
mSysUiState = sysUiState;
|
||||
mMainHandler = handler;
|
||||
mCurrentUserContextTracker = currentUserContextTracker;
|
||||
@@ -374,7 +376,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
mDialog.mWalletViewController.onDeviceLockStateChanged(!unlocked);
|
||||
}
|
||||
if (!mDialog.isShowingControls() && shouldShowControls()) {
|
||||
mDialog.showControls(mControlsUiController);
|
||||
mDialog.showControls(mControlsUiControllerOptional.get());
|
||||
}
|
||||
if (unlocked) {
|
||||
mDialog.hideLockMessage();
|
||||
@@ -383,7 +385,16 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
}
|
||||
});
|
||||
|
||||
controlsListingController.addCallback(list -> mControlsServiceInfos = list);
|
||||
if (controlsComponent.getControlsListingController().isPresent()) {
|
||||
controlsComponent.getControlsListingController().get()
|
||||
.addCallback(list -> mControlsServiceInfos = list);
|
||||
}
|
||||
|
||||
// Need to be user-specific with the context to make sure we read the correct prefs
|
||||
Context userContext = context.createContextAsUser(
|
||||
new UserHandle(mUserManager.getUserHandle()), 0);
|
||||
mControlsPreferences = userContext.getSharedPreferences(PREFS_CONTROLS_FILE,
|
||||
Context.MODE_PRIVATE);
|
||||
|
||||
// Listen for changes to show controls on the power menu while locked
|
||||
onPowerMenuLockScreenSettingsChanged();
|
||||
@@ -399,8 +410,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
}
|
||||
|
||||
private void seedFavorites() {
|
||||
if (!mControlsControllerOptional.isPresent()) return;
|
||||
if (mControlsServiceInfos.isEmpty()
|
||||
|| mControlsController.getFavorites().size() > 0) {
|
||||
|| mControlsControllerOptional.get().getFavorites().size() > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -433,7 +445,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
return;
|
||||
}
|
||||
|
||||
mControlsController.seedFavoritesForComponent(
|
||||
mControlsControllerOptional.get().seedFavoritesForComponent(
|
||||
preferredComponent,
|
||||
(accepted) -> {
|
||||
Log.i(TAG, "Controls seeded: " + accepted);
|
||||
@@ -636,10 +648,14 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
mDepthController.setShowingHomeControls(true);
|
||||
GlobalActionsPanelPlugin.PanelViewController walletViewController =
|
||||
getWalletViewController();
|
||||
ControlsUiController uiController = null;
|
||||
if (mControlsUiControllerOptional.isPresent() && shouldShowControls()) {
|
||||
uiController = mControlsUiControllerOptional.get();
|
||||
}
|
||||
ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, mOverflowAdapter,
|
||||
walletViewController, mDepthController, mSysuiColorExtractor,
|
||||
mStatusBarService, mNotificationShadeWindowController,
|
||||
controlsAvailable(), shouldShowControls() ? mControlsUiController : null,
|
||||
controlsAvailable(), uiController,
|
||||
mSysUiState, this::onRotate, mKeyguardShowing);
|
||||
boolean walletViewAvailable = walletViewController != null
|
||||
&& walletViewController.getPanelContent() != null;
|
||||
@@ -2403,7 +2419,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
|
||||
private boolean controlsAvailable() {
|
||||
return mDeviceProvisioned
|
||||
&& mControlsUiController.getAvailable()
|
||||
&& mControlsUiControllerOptional.isPresent()
|
||||
&& mControlsUiControllerOptional.get().getAvailable()
|
||||
&& !mControlsServiceInfos.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.controls.controller.ControlsController
|
||||
import com.android.systemui.controls.management.ControlsListingController
|
||||
import com.android.systemui.controls.ui.ControlsUiController
|
||||
import dagger.Lazy
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class ControlsComponentTest : SysuiTestCase() {
|
||||
|
||||
@Mock
|
||||
private lateinit var controller: ControlsController
|
||||
@Mock
|
||||
private lateinit var uiController: ControlsUiController
|
||||
@Mock
|
||||
private lateinit var listingController: ControlsListingController
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFeatureEnabled() {
|
||||
val component = ControlsComponent(
|
||||
true,
|
||||
Lazy { controller },
|
||||
Lazy { uiController },
|
||||
Lazy { listingController }
|
||||
)
|
||||
|
||||
assertTrue(component.getControlsController().isPresent)
|
||||
assertEquals(controller, component.getControlsController().get())
|
||||
assertTrue(component.getControlsUiController().isPresent)
|
||||
assertEquals(uiController, component.getControlsUiController().get())
|
||||
assertTrue(component.getControlsListingController().isPresent)
|
||||
assertEquals(listingController, component.getControlsListingController().get())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFeatureDisabled() {
|
||||
val component = ControlsComponent(
|
||||
false,
|
||||
Lazy { controller },
|
||||
Lazy { uiController },
|
||||
Lazy { listingController }
|
||||
)
|
||||
|
||||
assertFalse(component.getControlsController().isPresent)
|
||||
assertFalse(component.getControlsUiController().isPresent)
|
||||
assertFalse(component.getControlsListingController().isPresent)
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@ class ControlsRequestReceiverTest : SysuiTestCase() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
mContext.setMockPackageManager(packageManager)
|
||||
`when`(packageManager.hasSystemFeature(PackageManager.FEATURE_CONTROLS)).thenReturn(true)
|
||||
mContext.addMockSystemService(ActivityManager::class.java, activityManager)
|
||||
|
||||
receiver = ControlsRequestReceiver()
|
||||
@@ -145,6 +146,14 @@ class ControlsRequestReceiverTest : SysuiTestCase() {
|
||||
} ?: run { fail("Null start intent") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFeatureDisabled_activityNotStarted() {
|
||||
`when`(packageManager.hasSystemFeature(PackageManager.FEATURE_CONTROLS)).thenReturn(false)
|
||||
receiver.onReceive(wrapper, intent)
|
||||
|
||||
assertNull(wrapper.intent)
|
||||
}
|
||||
|
||||
class MyWrapper(context: Context) : ContextWrapper(context) {
|
||||
var intent: Intent? = null
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
||||
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.ControlsUiController;
|
||||
import com.android.systemui.model.SysUiState;
|
||||
@@ -121,6 +122,7 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
|
||||
@Mock GlobalActionsPanelPlugin.PanelViewController mWalletController;
|
||||
@Mock private Handler mHandler;
|
||||
@Mock private CurrentUserContextTracker mCurrentUserContextTracker;
|
||||
private ControlsComponent mControlsComponent;
|
||||
|
||||
private TestableLooper mTestableLooper;
|
||||
|
||||
@@ -132,6 +134,13 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
|
||||
|
||||
when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);
|
||||
when(mCurrentUserContextTracker.getCurrentUserContext()).thenReturn(mContext);
|
||||
mControlsComponent = new ControlsComponent(
|
||||
true,
|
||||
() -> mControlsController,
|
||||
() -> mControlsUiController,
|
||||
() -> mControlsListingController
|
||||
);
|
||||
|
||||
mGlobalActionsDialog = new GlobalActionsDialog(mContext,
|
||||
mWindowManagerFuncs,
|
||||
mAudioManager,
|
||||
@@ -156,15 +165,13 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
|
||||
mColorExtractor,
|
||||
mStatusBarService,
|
||||
mNotificationShadeWindowController,
|
||||
mControlsUiController,
|
||||
mWindowManager,
|
||||
mBackgroundExecutor,
|
||||
mControlsListingController,
|
||||
mControlsController,
|
||||
mUiEventLogger,
|
||||
mRingerModeTracker,
|
||||
mSysUiState,
|
||||
mHandler,
|
||||
mControlsComponent,
|
||||
mCurrentUserContextTracker
|
||||
);
|
||||
mGlobalActionsDialog.setZeroDialogPressDelayForTesting();
|
||||
|
||||
Reference in New Issue
Block a user