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

Commit f2ada528 authored by Fabian Kozynski's avatar Fabian Kozynski Committed by Android (Google) Code Review
Browse files

Merge "Fixes multi-user support"

parents 20dbbf22 b5625ac6
Loading
Loading
Loading
Loading
+47 −7
Original line number Diff line number Diff line
@@ -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)
            }
        }
    }
}
 No newline at end of file
+51 −3
Original line number Diff line number Diff line
@@ -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
@@ -60,12 +74,14 @@ class PrivacyItemControllerTest : SysuiTestCase() {
        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)
@@ -82,4 +98,36 @@ class PrivacyItemControllerTest : SysuiTestCase() {
        verify(appOpsController).removeCallback(eq(PrivacyItemController.OPS),
                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())
    }
}
 No newline at end of file