1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.settings.applications.assist;
18 
19 import android.car.drivingstate.CarUxRestrictions;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.database.ContentObserver;
24 import android.net.Uri;
25 import android.os.Handler;
26 import android.os.Looper;
27 import android.provider.Settings;
28 
29 import androidx.annotation.Nullable;
30 import androidx.annotation.VisibleForTesting;
31 
32 import com.android.car.settings.applications.defaultapps.DefaultAppsPickerEntryBasePreferenceController;
33 import com.android.car.settings.common.FragmentController;
34 import com.android.internal.app.AssistUtils;
35 import com.android.settingslib.applications.DefaultAppInfo;
36 
37 import java.util.Objects;
38 
39 /**
40  * Business logic to show the currently selected default voice input service and also link to the
41  * service settings, if it exists.
42  */
43 public class DefaultVoiceInputPickerEntryPreferenceController extends
44         DefaultAppsPickerEntryBasePreferenceController {
45 
46     private static final Uri ASSIST_URI = Settings.Secure.getUriFor(Settings.Secure.ASSISTANT);
47 
48     @VisibleForTesting
49     final ContentObserver mSettingObserver = new ContentObserver(
50             new Handler(Looper.getMainLooper())) {
51         @Override
52         public void onChange(boolean selfChange, Uri uri) {
53             super.onChange(selfChange, uri);
54 
55             if (ASSIST_URI.equals(uri)) {
56                 refreshUi();
57             }
58         }
59     };
60 
61     private final VoiceInputInfoProvider mVoiceInputInfoProvider;
62     private final AssistUtils mAssistUtils;
63 
DefaultVoiceInputPickerEntryPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)64     public DefaultVoiceInputPickerEntryPreferenceController(Context context, String preferenceKey,
65             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
66         this(context, preferenceKey, fragmentController, uxRestrictions,
67                 new VoiceInputInfoProvider(context), new AssistUtils(context));
68     }
69 
70     @VisibleForTesting
DefaultVoiceInputPickerEntryPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions, VoiceInputInfoProvider voiceInputInfoProvider, AssistUtils assistUtils)71     DefaultVoiceInputPickerEntryPreferenceController(Context context, String preferenceKey,
72             FragmentController fragmentController, CarUxRestrictions uxRestrictions,
73             VoiceInputInfoProvider voiceInputInfoProvider, AssistUtils assistUtils) {
74         super(context, preferenceKey, fragmentController, uxRestrictions);
75         mVoiceInputInfoProvider = voiceInputInfoProvider;
76         mAssistUtils = assistUtils;
77     }
78 
79     @Override
getAvailabilityStatus()80     protected int getAvailabilityStatus() {
81         ComponentName currentVoiceService = VoiceInputUtils.getCurrentService(getContext());
82         ComponentName currentAssist = mAssistUtils.getAssistComponentForUser(
83                 getCurrentProcessUserId());
84 
85         return Objects.equals(currentAssist, currentVoiceService) ? CONDITIONALLY_UNAVAILABLE
86                 : AVAILABLE;
87     }
88 
89     @Override
onStartInternal()90     protected void onStartInternal() {
91         getContext().getContentResolver().registerContentObserver(ASSIST_URI,
92                 /* notifyForDescendants= */ false, mSettingObserver);
93     }
94 
95     @Override
onStopInternal()96     protected void onStopInternal() {
97         getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
98     }
99 
100     @Nullable
101     @Override
getCurrentDefaultAppInfo()102     protected DefaultAppInfo getCurrentDefaultAppInfo() {
103         VoiceInputInfoProvider.VoiceInputInfo info = mVoiceInputInfoProvider.getInfoForComponent(
104                 VoiceInputUtils.getCurrentService(getContext()));
105         return (info == null) ? null : new DefaultVoiceInputServiceInfo(getContext(),
106                 getContext().getPackageManager(), getCurrentProcessUserId(), info,
107                 /* enabled= */ true);
108     }
109 
110     @Nullable
111     @Override
getSettingIntent(@ullable DefaultAppInfo info)112     protected Intent getSettingIntent(@Nullable DefaultAppInfo info) {
113         if (info instanceof DefaultVoiceInputServiceInfo) {
114             return ((DefaultVoiceInputServiceInfo) info).getSettingIntent();
115         }
116         return null;
117     }
118 }
119