Fixes multi-user support
The controller is probably not recreated on user changed, so it listens to intent broadcasts to update its current profiles list. Test: atest Fixes: 120028217 Change-Id: I8139827065fc61bc215870631f0215dd1bebe697
This commit is contained in:
@@ -18,10 +18,14 @@ package com.android.systemui.privacy
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.app.AppOpsManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Handler
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import com.android.internal.annotations.VisibleForTesting
|
||||
import com.android.systemui.Dependency
|
||||
import com.android.systemui.appops.AppOpItem
|
||||
import com.android.systemui.appops.AppOpsController
|
||||
@@ -33,25 +37,29 @@ class PrivacyItemController(val context: Context, val callback: Callback) {
|
||||
AppOpsManager.OP_RECORD_AUDIO,
|
||||
AppOpsManager.OP_COARSE_LOCATION,
|
||||
AppOpsManager.OP_FINE_LOCATION)
|
||||
val intents = listOf(Intent.ACTION_USER_FOREGROUND,
|
||||
Intent.ACTION_MANAGED_PROFILE_ADDED,
|
||||
Intent.ACTION_MANAGED_PROFILE_REMOVED)
|
||||
const val TAG = "PrivacyItemController"
|
||||
}
|
||||
|
||||
private var privacyList = emptyList<PrivacyItem>()
|
||||
private val appOpsController = Dependency.get(AppOpsController::class.java)
|
||||
private val userManager = context.getSystemService(UserManager::class.java)
|
||||
private val currentUser = ActivityManager.getCurrentUser()
|
||||
private val currentUserIds = userManager.getProfiles(currentUser).map { it.id }
|
||||
private var currentUserIds = emptyList<Int>()
|
||||
private val bgHandler = Handler(Dependency.get(Dependency.BG_LOOPER))
|
||||
private val uiHandler = Dependency.get(Dependency.MAIN_HANDLER)
|
||||
private var listening = false
|
||||
|
||||
private val notifyChanges = Runnable {
|
||||
callback.privacyChanged(privacyList)
|
||||
}
|
||||
|
||||
private val updateListAndNotifyChanges = Runnable {
|
||||
updatePrivacyList()
|
||||
uiHandler.post(notifyChanges)
|
||||
}
|
||||
|
||||
private var listening = false
|
||||
|
||||
private val cb = object : AppOpsController.Callback {
|
||||
override fun onActiveStateChanged(
|
||||
code: Int,
|
||||
@@ -61,12 +69,36 @@ class PrivacyItemController(val context: Context, val callback: Callback) {
|
||||
) {
|
||||
val userId = UserHandle.getUserId(uid)
|
||||
if (userId in currentUserIds) {
|
||||
update()
|
||||
update(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun update() {
|
||||
@VisibleForTesting
|
||||
internal var userSwitcherReceiver = Receiver()
|
||||
set(value) {
|
||||
context.unregisterReceiver(field)
|
||||
field = value
|
||||
registerReceiver()
|
||||
}
|
||||
|
||||
init {
|
||||
registerReceiver()
|
||||
}
|
||||
|
||||
private fun registerReceiver() {
|
||||
context.registerReceiverAsUser(userSwitcherReceiver, UserHandle.ALL, IntentFilter().apply {
|
||||
intents.forEach {
|
||||
addAction(it)
|
||||
}
|
||||
}, null, null)
|
||||
}
|
||||
|
||||
private fun update(updateUsers: Boolean) {
|
||||
if (updateUsers) {
|
||||
val currentUser = ActivityManager.getCurrentUser()
|
||||
currentUserIds = userManager.getProfiles(currentUser).map { it.id }
|
||||
}
|
||||
bgHandler.post(updateListAndNotifyChanges)
|
||||
}
|
||||
|
||||
@@ -75,7 +107,7 @@ class PrivacyItemController(val context: Context, val callback: Callback) {
|
||||
listening = listen
|
||||
if (listening) {
|
||||
appOpsController.addCallback(OPS, cb)
|
||||
update()
|
||||
update(true)
|
||||
} else {
|
||||
appOpsController.removeCallback(OPS, cb)
|
||||
}
|
||||
@@ -102,4 +134,12 @@ class PrivacyItemController(val context: Context, val callback: Callback) {
|
||||
interface Callback {
|
||||
fun privacyChanged(privacyItems: List<PrivacyItem>)
|
||||
}
|
||||
|
||||
internal inner class Receiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
if (intent?.action in intents) {
|
||||
update(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,12 @@
|
||||
|
||||
package com.android.systemui.privacy
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.app.AppOpsManager
|
||||
import android.content.Intent
|
||||
import android.os.Handler
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import android.support.test.filters.SmallTest
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
@@ -34,9 +38,11 @@ import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.ArgumentMatchers.anyList
|
||||
import org.mockito.ArgumentMatchers.eq
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.atLeastOnce
|
||||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.verify
|
||||
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@@ -44,10 +50,18 @@ import org.mockito.MockitoAnnotations
|
||||
@RunWithLooper
|
||||
class PrivacyItemControllerTest : SysuiTestCase() {
|
||||
|
||||
companion object {
|
||||
val CURRENT_USER_ID = ActivityManager.getCurrentUser()
|
||||
val OTHER_USER = UserHandle(CURRENT_USER_ID + 1)
|
||||
const val TAG = "PrivacyItemControllerTest"
|
||||
}
|
||||
|
||||
@Mock
|
||||
private lateinit var appOpsController: AppOpsController
|
||||
@Mock
|
||||
private lateinit var callback: PrivacyItemController.Callback
|
||||
@Mock
|
||||
private lateinit var userManager: UserManager
|
||||
|
||||
private lateinit var testableLooper: TestableLooper
|
||||
private lateinit var privacyItemController: PrivacyItemController
|
||||
@@ -57,15 +71,17 @@ class PrivacyItemControllerTest : SysuiTestCase() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
testableLooper = TestableLooper.get(this)
|
||||
|
||||
appOpsController = mDependency.injectMockDependency(AppOpsController:: class.java)
|
||||
appOpsController = mDependency.injectMockDependency(AppOpsController::class.java)
|
||||
mDependency.injectTestDependency(Dependency.BG_LOOPER, testableLooper.looper)
|
||||
mDependency.injectTestDependency(Dependency.MAIN_HANDLER, Handler(testableLooper.looper))
|
||||
mContext.addMockSystemService(UserManager::class.java, userManager)
|
||||
|
||||
doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, 0, "", 0)))
|
||||
.`when`(appOpsController).getActiveAppOpsForUser(anyInt())
|
||||
|
||||
privacyItemController = PrivacyItemController(mContext, callback)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetListeningTrue() {
|
||||
privacyItemController.setListening(true)
|
||||
@@ -80,6 +96,38 @@ class PrivacyItemControllerTest : SysuiTestCase() {
|
||||
privacyItemController.setListening(true)
|
||||
privacyItemController.setListening(false)
|
||||
verify(appOpsController).removeCallback(eq(PrivacyItemController.OPS),
|
||||
any(AppOpsController.Callback:: class.java))
|
||||
any(AppOpsController.Callback::class.java))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRegisterReceiver_allUsers() {
|
||||
val spiedContext = spy(mContext)
|
||||
val itemController = PrivacyItemController(spiedContext, callback)
|
||||
|
||||
verify(spiedContext, atLeastOnce()).registerReceiverAsUser(
|
||||
eq(itemController.userSwitcherReceiver), eq(UserHandle.ALL), any(), eq(null),
|
||||
eq(null))
|
||||
verify(spiedContext, never()).unregisterReceiver(eq(itemController.userSwitcherReceiver))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testReceiver_ACTION_USER_FOREGROUND() {
|
||||
privacyItemController.userSwitcherReceiver.onReceive(context,
|
||||
Intent(Intent.ACTION_USER_FOREGROUND))
|
||||
verify(userManager).getProfiles(anyInt())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testReceiver_ACTION_MANAGED_PROFILE_ADDED() {
|
||||
privacyItemController.userSwitcherReceiver.onReceive(context,
|
||||
Intent(Intent.ACTION_MANAGED_PROFILE_ADDED))
|
||||
verify(userManager).getProfiles(anyInt())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testReceiver_ACTION_MANAGED_PROFILE_REMOVED() {
|
||||
privacyItemController.userSwitcherReceiver.onReceive(context,
|
||||
Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED))
|
||||
verify(userManager).getProfiles(anyInt())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user