1 /*
2  * Copyright (C) 2014 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 android.service.voice;
18 
19 import android.Manifest;
20 import android.app.AppGlobals;
21 import android.content.ComponentName;
22 import android.content.pm.PackageManager;
23 import android.content.pm.ServiceInfo;
24 import android.content.res.Resources;
25 import android.content.res.TypedArray;
26 import android.content.res.XmlResourceParser;
27 import android.os.RemoteException;
28 import android.util.AttributeSet;
29 import android.util.Log;
30 import android.util.Xml;
31 import org.xmlpull.v1.XmlPullParser;
32 import org.xmlpull.v1.XmlPullParserException;
33 
34 import java.io.IOException;
35 
36 /** @hide */
37 public class VoiceInteractionServiceInfo {
38     static final String TAG = "VoiceInteractionServiceInfo";
39 
40     private String mParseError;
41 
42     private ServiceInfo mServiceInfo;
43     private String mSessionService;
44     private String mRecognitionService;
45     private String mSettingsActivity;
46     private boolean mSupportsAssist;
47     private boolean mSupportsLaunchFromKeyguard;
48     private boolean mSupportsLocalInteraction;
49 
VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)50     public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)
51             throws PackageManager.NameNotFoundException {
52         this(pm, pm.getServiceInfo(comp, PackageManager.GET_META_DATA));
53     }
54 
VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp, int userHandle)55     public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp, int userHandle)
56             throws PackageManager.NameNotFoundException {
57         this(pm, getServiceInfoOrThrow(comp, userHandle));
58     }
59 
getServiceInfoOrThrow(ComponentName comp, int userHandle)60     static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle)
61             throws PackageManager.NameNotFoundException {
62         try {
63             ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(comp,
64                     PackageManager.GET_META_DATA
65                             | PackageManager.MATCH_DIRECT_BOOT_AWARE
66                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
67                             | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
68                     userHandle);
69             if (si != null) {
70                 return si;
71             }
72         } catch (RemoteException e) {
73         }
74         throw new PackageManager.NameNotFoundException(comp.toString());
75     }
76 
VoiceInteractionServiceInfo(PackageManager pm, ServiceInfo si)77     public VoiceInteractionServiceInfo(PackageManager pm, ServiceInfo si) {
78         if (si == null) {
79             mParseError = "Service not available";
80             return;
81         }
82         if (!Manifest.permission.BIND_VOICE_INTERACTION.equals(si.permission)) {
83             mParseError = "Service does not require permission "
84                     + Manifest.permission.BIND_VOICE_INTERACTION;
85             return;
86         }
87 
88         XmlResourceParser parser = null;
89         try {
90             parser = si.loadXmlMetaData(pm, VoiceInteractionService.SERVICE_META_DATA);
91             if (parser == null) {
92                 mParseError = "No " + VoiceInteractionService.SERVICE_META_DATA
93                         + " meta-data for " + si.packageName;
94                 return;
95             }
96 
97             Resources res = pm.getResourcesForApplication(si.applicationInfo);
98 
99             AttributeSet attrs = Xml.asAttributeSet(parser);
100 
101             int type;
102             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
103                     && type != XmlPullParser.START_TAG) {
104             }
105 
106             String nodeName = parser.getName();
107             if (!"voice-interaction-service".equals(nodeName)) {
108                 mParseError = "Meta-data does not start with voice-interaction-service tag";
109                 return;
110             }
111 
112             TypedArray array = res.obtainAttributes(attrs,
113                     com.android.internal.R.styleable.VoiceInteractionService);
114             mSessionService = array.getString(
115                     com.android.internal.R.styleable.VoiceInteractionService_sessionService);
116             mRecognitionService = array.getString(
117                     com.android.internal.R.styleable.VoiceInteractionService_recognitionService);
118             mSettingsActivity = array.getString(
119                     com.android.internal.R.styleable.VoiceInteractionService_settingsActivity);
120             mSupportsAssist = array.getBoolean(
121                     com.android.internal.R.styleable.VoiceInteractionService_supportsAssist,
122                     false);
123             mSupportsLaunchFromKeyguard = array.getBoolean(com.android.internal.
124                     R.styleable.VoiceInteractionService_supportsLaunchVoiceAssistFromKeyguard,
125                     false);
126             mSupportsLocalInteraction = array.getBoolean(com.android.internal.
127                     R.styleable.VoiceInteractionService_supportsLocalInteraction, false);
128             array.recycle();
129             if (mSessionService == null) {
130                 mParseError = "No sessionService specified";
131                 return;
132             }
133             if (mRecognitionService == null) {
134                 mParseError = "No recognitionService specified";
135                 return;
136             }
137         } catch (XmlPullParserException e) {
138             mParseError = "Error parsing voice interation service meta-data: " + e;
139             Log.w(TAG, "error parsing voice interaction service meta-data", e);
140             return;
141         } catch (IOException e) {
142             mParseError = "Error parsing voice interation service meta-data: " + e;
143             Log.w(TAG, "error parsing voice interaction service meta-data", e);
144             return;
145         } catch (PackageManager.NameNotFoundException e) {
146             mParseError = "Error parsing voice interation service meta-data: " + e;
147             Log.w(TAG, "error parsing voice interaction service meta-data", e);
148             return;
149         } finally {
150             if (parser != null) parser.close();
151         }
152         mServiceInfo = si;
153     }
154 
getParseError()155     public String getParseError() {
156         return mParseError;
157     }
158 
getServiceInfo()159     public ServiceInfo getServiceInfo() {
160         return mServiceInfo;
161     }
162 
getSessionService()163     public String getSessionService() {
164         return mSessionService;
165     }
166 
getRecognitionService()167     public String getRecognitionService() {
168         return mRecognitionService;
169     }
170 
getSettingsActivity()171     public String getSettingsActivity() {
172         return mSettingsActivity;
173     }
174 
getSupportsAssist()175     public boolean getSupportsAssist() {
176         return mSupportsAssist;
177     }
178 
getSupportsLaunchFromKeyguard()179     public boolean getSupportsLaunchFromKeyguard() {
180         return mSupportsLaunchFromKeyguard;
181     }
182 
getSupportsLocalInteraction()183     public boolean getSupportsLocalInteraction() {
184         return mSupportsLocalInteraction;
185     }
186 }
187