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

Commit a6ff80bf authored by Fabian Kozynski's avatar Fabian Kozynski
Browse files

"Fix" NPE in PhoneStatusBarPolicy

Callback returns a copy of the list
Makes PrivacyItemController dumpable

Test: atest
Test: adb shell dumpsys activity service com.android.systemui/.SystemUIService Dependency
Fixes: 124234367

Change-Id: I1400ee8294f34b129723bb0f0ce7745dafaf5545
parent 78e3b2da
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -62,4 +62,6 @@ data class PrivacyApplication(val packageName: String, val uid: Int, val context
            context.packageManager.getApplicationLabel(it) as String
        } ?: packageName
    }

    override fun toString() = "PrivacyApplication(packageName=$packageName, uid=$uid)"
}
+26 −2
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@ import com.android.systemui.Dependency.MAIN_HANDLER_NAME
import com.android.systemui.R
import com.android.systemui.appops.AppOpItem
import com.android.systemui.appops.AppOpsController
import com.android.systemui.Dumpable
import java.io.FileDescriptor
import java.io.PrintWriter
import java.lang.ref.WeakReference
import javax.inject.Inject
import javax.inject.Named
@@ -42,7 +45,7 @@ class PrivacyItemController @Inject constructor(
        private val appOpsController: AppOpsController,
        @Named(MAIN_HANDLER_NAME) private val uiHandler: Handler,
        @Named(BG_HANDLER_NAME) private val bgHandler: Handler
) {
) : Dumpable {

    companion object {
        val OPS = intArrayOf(AppOpsManager.OP_CAMERA,
@@ -56,7 +59,10 @@ class PrivacyItemController @Inject constructor(
        const val SYSTEM_UID = 1000
    }

    private var privacyList = emptyList<PrivacyItem>()
    @VisibleForTesting
    internal var privacyList = emptyList<PrivacyItem>()
        get() = field.toList() // Provides a shallow copy of the list

    private val userManager = context.getSystemService(UserManager::class.java)
    private var currentUserIds = emptyList<Int>()
    private var listening = false
@@ -189,4 +195,22 @@ class PrivacyItemController @Inject constructor(
            callback?.privacyChanged(list)
        }
    }

    override fun dump(fd: FileDescriptor?, pw: PrintWriter?, args: Array<out String>?) {
        pw?.println("PrivacyItemController state:")
        pw?.println("  Listening: $listening")
        pw?.println("  Current user ids: $currentUserIds")
        pw?.println("  Privacy Items:")
        privacyList.forEach {
            pw?.print("    ")
            pw?.println(it.toString())
        }
        pw?.println("  Callbacks:")
        callbacks.forEach {
            it.get()?.let {
                pw?.print("    ")
                pw?.println(it.toString())
            }
        }
    }
}
 No newline at end of file
+11 −0
Original line number Diff line number Diff line
@@ -92,6 +92,8 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.NotificationChannels;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.Locale;

@@ -793,6 +795,15 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
        boolean showMicrophone = false;
        boolean showLocation = false;
        for (PrivacyItem item : items) {
            if (item == null /* b/124234367 */) {
                if (DEBUG) {
                    Log.e(TAG, "updatePrivacyItems - null item found");
                    StringWriter out = new StringWriter();
                    mPrivacyItemController.dump(null, new PrintWriter(out), null);
                    Log.e(TAG, out.toString());
                }
                continue;
            }
            switch (item.getPrivacyType()) {
                case TYPE_CAMERA:
                    showCamera = true;
+27 −0
Original line number Diff line number Diff line
@@ -35,7 +35,12 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.appops.AppOpItem
import com.android.systemui.appops.AppOpsController
import org.hamcrest.Matchers.hasItem
import org.hamcrest.Matchers.not
import org.hamcrest.Matchers.nullValue
import org.junit.Assert.assertEquals
import org.junit.Assert.assertThat
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -240,4 +245,26 @@ class PrivacyItemControllerTest : SysuiTestCase() {
        verify(callback, never()).privacyChanged(anyList())
        verify(otherCallback).privacyChanged(anyList())
    }

    @Test
    fun testListShouldNotHaveNull() {
        doReturn(listOf(AppOpItem(AppOpsManager.OP_ACTIVATE_VPN, TEST_UID, "", 0),
                        AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0)))
                .`when`(appOpsController).getActiveAppOpsForUser(anyInt())
        privacyItemController.addCallback(callback)
        testableLooper.processAllMessages()

        verify(callback).privacyChanged(capture(argCaptor))
        assertEquals(1, argCaptor.value.size)
        assertThat(argCaptor.value, not(hasItem(nullValue())))
    }

    @Test
    fun testListShouldBeCopy() {
        val list = listOf(PrivacyItem(PrivacyType.TYPE_CAMERA,
                PrivacyApplication("", TEST_UID, mContext)))
        privacyItemController.privacyList = list
        assertEquals(list, privacyItemController.privacyList)
        assertTrue(list !== privacyItemController.privacyList)
    }
}
 No newline at end of file