Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2015 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.internal.app;
     18 
     19 import com.android.internal.R;
     20 
     21 import android.app.SearchManager;
     22 import android.content.ComponentName;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.content.pm.ApplicationInfo;
     26 import android.content.pm.PackageManager;
     27 import android.content.pm.ResolveInfo;
     28 import android.os.Bundle;
     29 import android.os.IBinder;
     30 import android.os.RemoteException;
     31 import android.os.ServiceManager;
     32 import android.provider.Settings;
     33 import android.util.Log;
     34 
     35 /**
     36  * Utility method for dealing with the assistant aspects of
     37  * {@link com.android.internal.app.IVoiceInteractionManagerService IVoiceInteractionManagerService}.
     38  */
     39 public class AssistUtils {
     40 
     41     private static final String TAG = "AssistUtils";
     42 
     43     private final Context mContext;
     44     private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
     45 
     46     public AssistUtils(Context context) {
     47         mContext = context;
     48         mVoiceInteractionManagerService = IVoiceInteractionManagerService.Stub.asInterface(
     49                 ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
     50     }
     51 
     52     public boolean showSessionForActiveService(Bundle args, int sourceFlags,
     53             IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
     54         try {
     55             if (mVoiceInteractionManagerService != null) {
     56                 return mVoiceInteractionManagerService.showSessionForActiveService(args,
     57                         sourceFlags, showCallback, activityToken);
     58             }
     59         } catch (RemoteException e) {
     60             Log.w(TAG, "Failed to call showSessionForActiveService", e);
     61         }
     62         return false;
     63     }
     64 
     65     public void launchVoiceAssistFromKeyguard() {
     66         try {
     67             if (mVoiceInteractionManagerService != null) {
     68                 mVoiceInteractionManagerService.launchVoiceAssistFromKeyguard();
     69             }
     70         } catch (RemoteException e) {
     71             Log.w(TAG, "Failed to call launchVoiceAssistFromKeyguard", e);
     72         }
     73     }
     74 
     75     public boolean activeServiceSupportsAssistGesture() {
     76         try {
     77             return mVoiceInteractionManagerService != null
     78                     && mVoiceInteractionManagerService.activeServiceSupportsAssist();
     79         } catch (RemoteException e) {
     80             Log.w(TAG, "Failed to call activeServiceSupportsAssistGesture", e);
     81             return false;
     82         }
     83     }
     84 
     85     public boolean activeServiceSupportsLaunchFromKeyguard() {
     86         try {
     87             return mVoiceInteractionManagerService != null
     88                     && mVoiceInteractionManagerService.activeServiceSupportsLaunchFromKeyguard();
     89         } catch (RemoteException e) {
     90             Log.w(TAG, "Failed to call activeServiceSupportsLaunchFromKeyguard", e);
     91             return false;
     92         }
     93     }
     94 
     95     public ComponentName getActiveServiceComponentName() {
     96         try {
     97             if (mVoiceInteractionManagerService != null) {
     98                 return mVoiceInteractionManagerService.getActiveServiceComponentName();
     99             } else {
    100                 return null;
    101             }
    102         } catch (RemoteException e) {
    103             Log.w(TAG, "Failed to call getActiveServiceComponentName", e);
    104             return null;
    105         }
    106     }
    107 
    108     public boolean isSessionRunning() {
    109         try {
    110             return mVoiceInteractionManagerService != null
    111                     && mVoiceInteractionManagerService.isSessionRunning();
    112         } catch (RemoteException e) {
    113             Log.w(TAG, "Failed to call isSessionRunning", e);
    114             return false;
    115         }
    116     }
    117 
    118     public void hideCurrentSession() {
    119         try {
    120             if (mVoiceInteractionManagerService != null) {
    121                 mVoiceInteractionManagerService.hideCurrentSession();
    122             }
    123         } catch (RemoteException e) {
    124             Log.w(TAG, "Failed to call hideCurrentSession", e);
    125         }
    126     }
    127 
    128     public void onLockscreenShown() {
    129         try {
    130             if (mVoiceInteractionManagerService != null) {
    131                 mVoiceInteractionManagerService.onLockscreenShown();
    132             }
    133         } catch (RemoteException e) {
    134             Log.w(TAG, "Failed to call onLockscreenShown", e);
    135         }
    136     }
    137 
    138     public void registerVoiceInteractionSessionListener(IVoiceInteractionSessionListener listener) {
    139         try {
    140             if (mVoiceInteractionManagerService != null) {
    141                 mVoiceInteractionManagerService.registerVoiceInteractionSessionListener(listener);
    142             }
    143         } catch (RemoteException e) {
    144             Log.w(TAG, "Failed to register voice interaction listener", e);
    145         }
    146     }
    147 
    148     public ComponentName getAssistComponentForUser(int userId) {
    149         final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
    150                 Settings.Secure.ASSISTANT, userId);
    151         if (setting != null) {
    152             return ComponentName.unflattenFromString(setting);
    153         }
    154 
    155         // Fallback to keep backward compatible behavior when there is no user setting.
    156         if (activeServiceSupportsAssistGesture()) {
    157             return getActiveServiceComponentName();
    158         }
    159         final SearchManager searchManager =
    160             (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
    161         if (searchManager == null) {
    162             return null;
    163         }
    164         final Intent intent = searchManager.getAssistIntent(false);
    165         PackageManager pm = mContext.getPackageManager();
    166         ResolveInfo info = pm.resolveActivityAsUser(intent, PackageManager.MATCH_DEFAULT_ONLY,
    167                 userId);
    168         if (info != null) {
    169             return new ComponentName(info.activityInfo.applicationInfo.packageName,
    170                     info.activityInfo.name);
    171         }
    172         return null;
    173     }
    174 
    175     public static boolean isPreinstalledAssistant(Context context, ComponentName assistant) {
    176         if (assistant == null) {
    177             return false;
    178         }
    179         ApplicationInfo applicationInfo;
    180         try {
    181             applicationInfo = context.getPackageManager().getApplicationInfo(
    182                     assistant.getPackageName(), 0);
    183         } catch (PackageManager.NameNotFoundException e) {
    184             return false;
    185         }
    186         return applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp();
    187     }
    188 
    189     private static boolean isDisclosureEnabled(Context context) {
    190         return Settings.Secure.getInt(context.getContentResolver(),
    191                 Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 0) != 0;
    192     }
    193 
    194     /**
    195      * @return if the disclosure animation should trigger for the given assistant.
    196      *
    197      * Third-party assistants will always need to disclose, while the user can configure this for
    198      * pre-installed assistants.
    199      */
    200     public static boolean shouldDisclose(Context context, ComponentName assistant) {
    201         if (!allowDisablingAssistDisclosure(context)) {
    202             return true;
    203         }
    204 
    205         return isDisclosureEnabled(context) || !isPreinstalledAssistant(context, assistant);
    206     }
    207 
    208     public static boolean allowDisablingAssistDisclosure(Context context) {
    209         return context.getResources().getBoolean(
    210                 com.android.internal.R.bool.config_allowDisablingAssistDisclosure);
    211     }
    212 }
    213