diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 75c92e000c4dc..b4612daa4d383 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -907,7 +907,7 @@ android:excludeFromRecents="true" android:theme="@android:style/Theme.NoDisplay" android:label="@string/note_task_button_label" - android:icon="@drawable/ic_note_task_button"> + android:icon="@drawable/ic_note_task_shortcut_widget"> diff --git a/packages/SystemUI/res/drawable/ic_note_task_shortcut_keyguard.xml b/packages/SystemUI/res/drawable/ic_note_task_shortcut_keyguard.xml new file mode 100644 index 0000000000000..ee8d488343c49 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_note_task_shortcut_keyguard.xml @@ -0,0 +1,31 @@ + + + + + diff --git a/packages/SystemUI/res/drawable/ic_note_task_button.xml b/packages/SystemUI/res/drawable/ic_note_task_shortcut_widget.xml similarity index 95% rename from packages/SystemUI/res/drawable/ic_note_task_button.xml rename to packages/SystemUI/res/drawable/ic_note_task_shortcut_widget.xml index bb5e224ea3150..7590182895629 100644 --- a/packages/SystemUI/res/drawable/ic_note_task_button.xml +++ b/packages/SystemUI/res/drawable/ic_note_task_shortcut_widget.xml @@ -19,10 +19,13 @@ android:viewportHeight="24" android:viewportWidth="24"> diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml index f4434e8d00440..ea3c012afc431 100644 --- a/packages/SystemUI/res/values-sw600dp/config.xml +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -36,4 +36,15 @@ 1 true + + + + bottom_start:home + bottom_end:create_note + diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt index ea5b4f43cc75f..d3bb22ccd8632 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt @@ -25,6 +25,7 @@ package com.android.systemui.keyguard.data.quickaffordance object BuiltInKeyguardQuickAffordanceKeys { // Please keep alphabetical order of const names to simplify future maintenance. const val CAMERA = "camera" + const val CREATE_NOTE = "create_note" const val DO_NOT_DISTURB = "do_not_disturb" const val FLASHLIGHT = "flashlight" const val HOME_CONTROLS = "home" diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt index 26e3f49828c75..4b10d69a2b800 100644 --- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt +++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt @@ -72,6 +72,9 @@ constructor( companion object { // TODO(b/254606432): Use Intent.ACTION_CREATE_NOTE instead. const val ACTION_CREATE_NOTE = "android.intent.action.CREATE_NOTE" + + // TODO(b/265912743): Use RoleManager.NOTES_ROLE instead. + const val NOTE_ROLE = "android.app.role.NOTES" } } diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt index 8bdf3195d53b5..22ce121321247 100644 --- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt +++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt @@ -18,11 +18,13 @@ package com.android.systemui.notetask import android.app.Activity import android.app.KeyguardManager +import android.app.role.RoleManager import android.content.Context import android.os.UserManager import androidx.core.content.getSystemService import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceModule import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity import dagger.Binds @@ -33,20 +35,25 @@ import dagger.multibindings.IntoMap import java.util.Optional /** Compose all dependencies required by Note Task feature. */ -@Module +@Module(includes = [NoteTaskQuickAffordanceModule::class]) internal interface NoteTaskModule { @[Binds IntoMap ClassKey(LaunchNoteTaskActivity::class)] - fun bindNoteTaskLauncherActivity(activity: LaunchNoteTaskActivity): Activity? + fun LaunchNoteTaskActivity.bindNoteTaskLauncherActivity(): Activity @[Binds IntoMap ClassKey(CreateNoteTaskShortcutActivity::class)] - fun bindNoteTaskShortcutActivity(activity: CreateNoteTaskShortcutActivity): Activity? + fun CreateNoteTaskShortcutActivity.bindNoteTaskShortcutActivity(): Activity companion object { @[Provides NoteTaskEnabledKey] - fun provideIsNoteTaskEnabled(featureFlags: FeatureFlags): Boolean { - return featureFlags.isEnabled(Flags.NOTE_TASKS) + fun provideIsNoteTaskEnabled( + featureFlags: FeatureFlags, + roleManager: RoleManager, + ): Boolean { + val isRoleAvailable = roleManager.isRoleAvailable(NoteTaskIntentResolver.NOTE_ROLE) + val isFeatureEnabled = featureFlags.isEnabled(Flags.NOTE_TASKS) + return isRoleAvailable && isFeatureEnabled } @Provides diff --git a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt new file mode 100644 index 0000000000000..cfbaa48a4fa46 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2023 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.notetask.quickaffordance + +import android.content.Context +import com.android.systemui.R +import com.android.systemui.animation.Expandable +import com.android.systemui.common.shared.model.ContentDescription +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys +import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig +import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState +import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult +import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.PickerScreenState +import com.android.systemui.notetask.NoteTaskController +import com.android.systemui.notetask.NoteTaskEnabledKey +import javax.inject.Inject +import kotlinx.coroutines.flow.flowOf + +internal class NoteTaskQuickAffordanceConfig +@Inject +constructor( + context: Context, + private val noteTaskController: NoteTaskController, + @NoteTaskEnabledKey private val isEnabled: Boolean, +) : KeyguardQuickAffordanceConfig { + + override val key = BuiltInKeyguardQuickAffordanceKeys.CREATE_NOTE + + override val pickerName: String = context.getString(R.string.note_task_button_label) + + override val pickerIconResourceId = R.drawable.ic_note_task_shortcut_keyguard + + override val lockScreenState = flowOf(getLockScreenState()) + + // TODO(b/265949213) + private fun getLockScreenState() = + if (isEnabled) { + val icon = Icon.Resource(pickerIconResourceId, ContentDescription.Loaded(pickerName)) + LockScreenState.Visible(icon) + } else { + LockScreenState.Hidden + } + + override suspend fun getPickerScreenState() = + if (isEnabled) { + PickerScreenState.Default() + } else { + PickerScreenState.UnavailableOnDevice + } + + override fun onTriggered(expandable: Expandable?): OnTriggeredResult { + noteTaskController.showNoteTask() + return OnTriggeredResult.Handled + } +} diff --git a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt new file mode 100644 index 0000000000000..7cb932aa19163 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2023 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.notetask.quickaffordance + +import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoSet + +@Module +internal interface NoteTaskQuickAffordanceModule { + + @[Binds IntoSet] + fun NoteTaskQuickAffordanceConfig.bindNoteTaskQuickAffordance(): KeyguardQuickAffordanceConfig +} diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt index f6a623e4f0013..6ab0da6fe3b3c 100644 --- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt @@ -46,7 +46,7 @@ internal class CreateNoteTaskShortcutActivity @Inject constructor() : ComponentA id = SHORTCUT_ID, shortLabel = getString(R.string.note_task_button_label), intent = LaunchNoteTaskActivity.newIntent(context = this), - iconResource = R.drawable.ic_note_task_button, + iconResource = R.drawable.ic_note_task_shortcut_widget, ) setResult(Activity.RESULT_OK, intent) diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt new file mode 100644 index 0000000000000..a1d42a0ce5056 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2023 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. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.android.systemui.notetask.quickaffordance + +import android.test.suitebuilder.annotation.SmallTest +import androidx.test.runner.AndroidJUnit4 +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.common.shared.model.ContentDescription +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState +import com.android.systemui.notetask.NoteTaskController +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +/** + * Tests for [NoteTaskQuickAffordanceConfig]. + * + * Build/Install/Run: + * - atest SystemUITests:NoteTaskQuickAffordanceConfigTest + */ +@SmallTest +@RunWith(AndroidJUnit4::class) +internal class NoteTaskQuickAffordanceConfigTest : SysuiTestCase() { + + @Mock lateinit var noteTaskController: NoteTaskController + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + whenever(noteTaskController.showNoteTask()).then {} + } + + private fun createUnderTest(isEnabled: Boolean) = + NoteTaskQuickAffordanceConfig( + context = context, + noteTaskController = noteTaskController, + isEnabled = isEnabled, + ) + + @Test + fun lockScreenState_isNotEnabled_shouldEmitHidden() = runTest { + val underTest = createUnderTest(isEnabled = false) + + val actual = collectLastValue(underTest.lockScreenState) + + assertThat(actual()).isEqualTo(LockScreenState.Hidden) + } + + @Test + fun lockScreenState_isEnabled_shouldEmitVisible() = runTest { + val stringResult = "Notetaking" + val underTest = createUnderTest(isEnabled = true) + + val actual = collectLastValue(underTest.lockScreenState) + + val expected = + LockScreenState.Visible( + icon = + Icon.Resource( + res = R.drawable.ic_note_task_shortcut_keyguard, + contentDescription = ContentDescription.Loaded(stringResult), + ) + ) + assertThat(actual()).isEqualTo(expected) + } + + @Test + fun onTriggered_shouldLaunchNoteTask() { + val underTest = createUnderTest(isEnabled = false) + + underTest.onTriggered(expandable = null) + + verify(noteTaskController).showNoteTask() + } +}