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

Commit 97a457c0 authored by Vitor Carvalho's avatar Vitor Carvalho Committed by Android (Google) Code Review
Browse files

Merge "Introduce an utility class in SettingsLib to create an intent to the...

Merge "Introduce an utility class in SettingsLib to create an intent to the supervision settings page." into main
parents 1e17cbab 29c4c58b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
file:platform/frameworks/base:/core/java/android/app/supervision/OWNERS
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settingslib.supervision

import android.app.supervision.SupervisionManager
import android.content.Context
import android.content.Intent

/** Helper class meant to provide an intent to launch the supervision settings page. */
object SupervisionIntentProvider {
    private const val ACTION_SHOW_PARENTAL_CONTROLS = "android.settings.SHOW_PARENTAL_CONTROLS"

    /**
     * Returns an [Intent] to the supervision settings page or null if supervision is disabled or
     * the intent is not resolvable.
     */
    @JvmStatic
    fun getSettingsIntent(context: Context): Intent? {
        val supervisionManager = context.getSystemService(SupervisionManager::class.java)
        val supervisionAppPackage = supervisionManager?.activeSupervisionAppPackage ?: return null

        val intent =
            Intent(ACTION_SHOW_PARENTAL_CONTROLS)
                .setPackage(supervisionAppPackage)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        val activities =
            context.packageManager.queryIntentActivitiesAsUser(intent, 0, context.userId)
        return if (activities.isNotEmpty()) intent else null
    }
}
+8 −7
Original line number Diff line number Diff line
@@ -46,16 +46,17 @@ android_robolectric_test {
        "src/**/*.kt",
    ],
    static_libs: [
        "Settings_robolectric_meta_service_file",
        "Robolectric_shadows_androidx_fragment_upstream",
        "SettingsLib-robo-testutils",
        "Settings_robolectric_meta_service_file",
        "androidx.core_core",
        "androidx.fragment_fragment",
        "androidx.test.core",
        "androidx.core_core",
        "kotlinx_coroutines_test",
        "androidx.test.ext.junit",
        "flag-junit",
        "settingslib_media_flags_lib",
        "kotlinx_coroutines_test",
        "settingslib_illustrationpreference_flags_lib",
        "settingslib_media_flags_lib",
        "settingslib_selectorwithwidgetpreference_flags_lib",
        "testng", // TODO: remove once JUnit on Android provides assertThrows
    ],
@@ -87,8 +88,8 @@ java_library {
        "testutils/com/android/settingslib/testutils/**/*.java",
    ],
    javacflags: [
        "-Aorg.robolectric.annotation.processing.shadowPackage=com.android.settingslib.testutils.shadow",
        "-Aorg.robolectric.annotation.processing.sdkCheckMode=ERROR",
        "-Aorg.robolectric.annotation.processing.shadowPackage=com.android.settingslib.testutils.shadow",
        // Uncomment the below to debug annotation processors not firing.
        //"-verbose",
        //"-XprintRounds",
@@ -97,9 +98,9 @@ java_library {
        //"-J-verbose",
    ],
    plugins: [
        "auto_value_plugin_1.9",
        "auto_value_builder_plugin_1.9",
        "Robolectric_processor",
        "auto_value_builder_plugin_1.9",
        "auto_value_plugin_1.9",
    ],
    libs: [
        "Robolectric_all-target",
+105 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settingslib.supervision

import android.app.supervision.SupervisionManager
import android.content.Context
import android.content.ContextWrapper
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule

/**
 * Unit tests for [SupervisionIntentProvider].
 *
 * Run with `atest SupervisionIntentProviderTest`.
 */
@RunWith(AndroidJUnit4::class)
class SupervisionIntentProviderTest {
    @get:Rule val mocks: MockitoRule = MockitoJUnit.rule()

    @Mock private lateinit var mockPackageManager: PackageManager

    @Mock private lateinit var mockSupervisionManager: SupervisionManager

    private lateinit var context: Context

    @Before
    fun setUp() {
        context =
            object : ContextWrapper(InstrumentationRegistry.getInstrumentation().context) {
                override fun getPackageManager() = mockPackageManager

                override fun getSystemService(name: String) =
                    when (name) {
                        Context.SUPERVISION_SERVICE -> mockSupervisionManager
                        else -> super.getSystemService(name)
                    }
            }
    }

    @Test
    fun getSettingsIntent_nullSupervisionPackage() {
        `when`(mockSupervisionManager.activeSupervisionAppPackage).thenReturn(null)

        val intent = SupervisionIntentProvider.getSettingsIntent(context)

        assertThat(intent).isNull()
    }

    @Test
    fun getSettingsIntent_unresolvedIntent() {
        `when`(mockSupervisionManager.activeSupervisionAppPackage)
            .thenReturn(SUPERVISION_APP_PACKAGE)
        `when`(mockPackageManager.queryIntentActivitiesAsUser(any(), anyInt(), anyInt()))
            .thenReturn(emptyList())

        val intent = SupervisionIntentProvider.getSettingsIntent(context)

        assertThat(intent).isNull()
    }

    @Test
    fun getSettingsIntent_resolvedIntent() {
        `when`(mockSupervisionManager.activeSupervisionAppPackage)
            .thenReturn(SUPERVISION_APP_PACKAGE)
        `when`(mockPackageManager.queryIntentActivitiesAsUser(any(), anyInt(), anyInt()))
            .thenReturn(listOf(ResolveInfo()))

        val intent = SupervisionIntentProvider.getSettingsIntent(context)

        assertThat(intent).isNotNull()
        assertThat(intent?.action).isEqualTo("android.settings.SHOW_PARENTAL_CONTROLS")
        assertThat(intent?.`package`).isEqualTo(SUPERVISION_APP_PACKAGE)
    }

    private companion object {
        const val SUPERVISION_APP_PACKAGE = "app.supervision"
    }
}