Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 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 android.nfc.cardemulation; |
| 18 | |
| 19 | import android.content.ComponentName; |
| 20 | import android.content.pm.PackageManager; |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 21 | import android.content.pm.PackageManager.NameNotFoundException; |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 22 | import android.content.pm.ResolveInfo; |
| 23 | import android.content.pm.ServiceInfo; |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 24 | import android.content.res.Resources; |
| 25 | import android.content.res.TypedArray; |
| 26 | import android.content.res.XmlResourceParser; |
| 27 | import android.graphics.drawable.Drawable; |
| 28 | import android.os.Parcel; |
| 29 | import android.os.Parcelable; |
| 30 | import android.util.AttributeSet; |
| 31 | import android.util.Log; |
| 32 | import android.util.Xml; |
| 33 | |
| 34 | import org.xmlpull.v1.XmlPullParser; |
| 35 | import org.xmlpull.v1.XmlPullParserException; |
| 36 | |
| 37 | import java.io.FileDescriptor; |
| 38 | import java.io.IOException; |
| 39 | import java.io.PrintWriter; |
| 40 | |
| 41 | /** |
| 42 | * @hide |
| 43 | */ |
| 44 | public final class NfcFServiceInfo implements Parcelable { |
| 45 | static final String TAG = "NfcFServiceInfo"; |
| 46 | |
Love Khanna | f5d6d5c | 2017-08-01 18:32:59 +0530 | [diff] [blame] | 47 | private static final String DEFAULT_T3T_PMM = "FFFFFFFFFFFFFFFF"; |
| 48 | |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 49 | /** |
| 50 | * The service that implements this |
| 51 | */ |
| 52 | final ResolveInfo mService; |
| 53 | |
| 54 | /** |
| 55 | * Description of the service |
| 56 | */ |
| 57 | final String mDescription; |
| 58 | |
| 59 | /** |
| 60 | * System Code of the service |
| 61 | */ |
| 62 | final String mSystemCode; |
| 63 | |
| 64 | /** |
| 65 | * System Code of the service registered by API |
| 66 | */ |
| 67 | String mDynamicSystemCode; |
| 68 | |
| 69 | /** |
| 70 | * NFCID2 of the service |
| 71 | */ |
| 72 | final String mNfcid2; |
| 73 | |
| 74 | /** |
| 75 | * NFCID2 of the service registered by API |
| 76 | */ |
| 77 | String mDynamicNfcid2; |
| 78 | |
| 79 | /** |
| 80 | * The uid of the package the service belongs to |
| 81 | */ |
| 82 | final int mUid; |
| 83 | |
| 84 | /** |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 85 | * LF_T3T_PMM of the service |
| 86 | */ |
| 87 | final String mT3tPmm; |
| 88 | |
| 89 | /** |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 90 | * @hide |
| 91 | */ |
| 92 | public NfcFServiceInfo(ResolveInfo info, String description, |
| 93 | String systemCode, String dynamicSystemCode, String nfcid2, String dynamicNfcid2, |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 94 | int uid, String t3tPmm) { |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 95 | this.mService = info; |
| 96 | this.mDescription = description; |
| 97 | this.mSystemCode = systemCode; |
| 98 | this.mDynamicSystemCode = dynamicSystemCode; |
| 99 | this.mNfcid2 = nfcid2; |
| 100 | this.mDynamicNfcid2 = dynamicNfcid2; |
| 101 | this.mUid = uid; |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 102 | this.mT3tPmm = t3tPmm; |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | public NfcFServiceInfo(PackageManager pm, ResolveInfo info) |
| 106 | throws XmlPullParserException, IOException { |
| 107 | ServiceInfo si = info.serviceInfo; |
| 108 | XmlResourceParser parser = null; |
| 109 | try { |
| 110 | parser = si.loadXmlMetaData(pm, HostNfcFService.SERVICE_META_DATA); |
| 111 | if (parser == null) { |
| 112 | throw new XmlPullParserException("No " + HostNfcFService.SERVICE_META_DATA + |
| 113 | " meta-data"); |
| 114 | } |
| 115 | |
| 116 | int eventType = parser.getEventType(); |
| 117 | while (eventType != XmlPullParser.START_TAG && |
| 118 | eventType != XmlPullParser.END_DOCUMENT) { |
| 119 | eventType = parser.next(); |
| 120 | } |
| 121 | |
| 122 | String tagName = parser.getName(); |
| 123 | if (!"host-nfcf-service".equals(tagName)) { |
| 124 | throw new XmlPullParserException( |
| 125 | "Meta-data does not start with <host-nfcf-service> tag"); |
| 126 | } |
| 127 | |
| 128 | Resources res = pm.getResourcesForApplication(si.applicationInfo); |
| 129 | AttributeSet attrs = Xml.asAttributeSet(parser); |
| 130 | TypedArray sa = res.obtainAttributes(attrs, |
| 131 | com.android.internal.R.styleable.HostNfcFService); |
| 132 | mService = info; |
| 133 | mDescription = sa.getString( |
| 134 | com.android.internal.R.styleable.HostNfcFService_description); |
| 135 | mDynamicSystemCode = null; |
| 136 | mDynamicNfcid2 = null; |
| 137 | sa.recycle(); |
| 138 | |
| 139 | String systemCode = null; |
| 140 | String nfcid2 = null; |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 141 | String t3tPmm = null; |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 142 | final int depth = parser.getDepth(); |
| 143 | |
| 144 | while (((eventType = parser.next()) != XmlPullParser.END_TAG || |
| 145 | parser.getDepth() > depth) && eventType != XmlPullParser.END_DOCUMENT) { |
| 146 | tagName = parser.getName(); |
| 147 | if (eventType == XmlPullParser.START_TAG && |
| 148 | "system-code-filter".equals(tagName) && systemCode == null) { |
| 149 | final TypedArray a = res.obtainAttributes(attrs, |
| 150 | com.android.internal.R.styleable.SystemCodeFilter); |
| 151 | systemCode = a.getString( |
| 152 | com.android.internal.R.styleable.SystemCodeFilter_name).toUpperCase(); |
| 153 | if (!NfcFCardEmulation.isValidSystemCode(systemCode) && |
| 154 | !systemCode.equalsIgnoreCase("NULL")) { |
| 155 | Log.e(TAG, "Invalid System Code: " + systemCode); |
| 156 | systemCode = null; |
| 157 | } |
| 158 | a.recycle(); |
| 159 | } else if (eventType == XmlPullParser.START_TAG && |
| 160 | "nfcid2-filter".equals(tagName) && nfcid2 == null) { |
| 161 | final TypedArray a = res.obtainAttributes(attrs, |
| 162 | com.android.internal.R.styleable.Nfcid2Filter); |
| 163 | nfcid2 = a.getString( |
| 164 | com.android.internal.R.styleable.Nfcid2Filter_name).toUpperCase(); |
| 165 | if (!nfcid2.equalsIgnoreCase("RANDOM") && |
| 166 | !nfcid2.equalsIgnoreCase("NULL") && |
| 167 | !NfcFCardEmulation.isValidNfcid2(nfcid2)) { |
| 168 | Log.e(TAG, "Invalid NFCID2: " + nfcid2); |
| 169 | nfcid2 = null; |
| 170 | } |
| 171 | a.recycle(); |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 172 | } else if (eventType == XmlPullParser.START_TAG && tagName.equals("t3tPmm-filter") |
| 173 | && t3tPmm == null) { |
| 174 | final TypedArray a = res.obtainAttributes(attrs, |
| 175 | com.android.internal.R.styleable.T3tPmmFilter); |
| 176 | t3tPmm = a.getString( |
| 177 | com.android.internal.R.styleable.T3tPmmFilter_name).toUpperCase(); |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 178 | a.recycle(); |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 179 | } |
| 180 | } |
| 181 | mSystemCode = (systemCode == null ? "NULL" : systemCode); |
| 182 | mNfcid2 = (nfcid2 == null ? "NULL" : nfcid2); |
Love Khanna | f5d6d5c | 2017-08-01 18:32:59 +0530 | [diff] [blame] | 183 | mT3tPmm = (t3tPmm == null ? DEFAULT_T3T_PMM : t3tPmm); |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 184 | } catch (NameNotFoundException e) { |
| 185 | throw new XmlPullParserException("Unable to create context for: " + si.packageName); |
| 186 | } finally { |
| 187 | if (parser != null) parser.close(); |
| 188 | } |
| 189 | // Set uid |
| 190 | mUid = si.applicationInfo.uid; |
| 191 | } |
| 192 | |
| 193 | public ComponentName getComponent() { |
| 194 | return new ComponentName(mService.serviceInfo.packageName, |
| 195 | mService.serviceInfo.name); |
| 196 | } |
| 197 | |
| 198 | public String getSystemCode() { |
| 199 | return (mDynamicSystemCode == null ? mSystemCode : mDynamicSystemCode); |
| 200 | } |
| 201 | |
| 202 | public void setOrReplaceDynamicSystemCode(String systemCode) { |
| 203 | mDynamicSystemCode = systemCode; |
| 204 | } |
| 205 | |
| 206 | public String getNfcid2() { |
| 207 | return (mDynamicNfcid2 == null ? mNfcid2 : mDynamicNfcid2); |
| 208 | } |
| 209 | |
| 210 | public void setOrReplaceDynamicNfcid2(String nfcid2) { |
| 211 | mDynamicNfcid2 = nfcid2; |
| 212 | } |
| 213 | |
| 214 | public String getDescription() { |
| 215 | return mDescription; |
| 216 | } |
| 217 | |
| 218 | public int getUid() { |
| 219 | return mUid; |
| 220 | } |
| 221 | |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 222 | public String getT3tPmm() { |
| 223 | return mT3tPmm; |
| 224 | } |
| 225 | |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 226 | public CharSequence loadLabel(PackageManager pm) { |
| 227 | return mService.loadLabel(pm); |
| 228 | } |
| 229 | |
| 230 | public Drawable loadIcon(PackageManager pm) { |
| 231 | return mService.loadIcon(pm); |
| 232 | } |
| 233 | |
| 234 | @Override |
| 235 | public String toString() { |
| 236 | StringBuilder out = new StringBuilder("NfcFService: "); |
| 237 | out.append(getComponent()); |
| 238 | out.append(", description: " + mDescription); |
| 239 | out.append(", System Code: " + mSystemCode); |
| 240 | if (mDynamicSystemCode != null) { |
| 241 | out.append(", dynamic System Code: " + mDynamicSystemCode); |
| 242 | } |
| 243 | out.append(", NFCID2: " + mNfcid2); |
| 244 | if (mDynamicNfcid2 != null) { |
| 245 | out.append(", dynamic NFCID2: " + mDynamicNfcid2); |
| 246 | } |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 247 | out.append(", T3T PMM:" + mT3tPmm); |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 248 | return out.toString(); |
| 249 | } |
| 250 | |
| 251 | @Override |
| 252 | public boolean equals(Object o) { |
| 253 | if (this == o) return true; |
| 254 | if (!(o instanceof NfcFServiceInfo)) return false; |
| 255 | NfcFServiceInfo thatService = (NfcFServiceInfo) o; |
| 256 | |
| 257 | if (!thatService.getComponent().equals(this.getComponent())) return false; |
| 258 | if (!thatService.mSystemCode.equalsIgnoreCase(this.mSystemCode)) return false; |
| 259 | if (!thatService.mNfcid2.equalsIgnoreCase(this.mNfcid2)) return false; |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 260 | if (!thatService.mT3tPmm.equalsIgnoreCase(this.mT3tPmm)) return false; |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 261 | return true; |
| 262 | } |
| 263 | |
| 264 | @Override |
| 265 | public int hashCode() { |
| 266 | return getComponent().hashCode(); |
| 267 | } |
| 268 | |
| 269 | @Override |
| 270 | public int describeContents() { |
| 271 | return 0; |
| 272 | } |
| 273 | |
| 274 | @Override |
| 275 | public void writeToParcel(Parcel dest, int flags) { |
| 276 | mService.writeToParcel(dest, flags); |
| 277 | dest.writeString(mDescription); |
| 278 | dest.writeString(mSystemCode); |
| 279 | dest.writeInt(mDynamicSystemCode != null ? 1 : 0); |
| 280 | if (mDynamicSystemCode != null) { |
| 281 | dest.writeString(mDynamicSystemCode); |
| 282 | } |
| 283 | dest.writeString(mNfcid2); |
| 284 | dest.writeInt(mDynamicNfcid2 != null ? 1 : 0); |
| 285 | if (mDynamicNfcid2 != null) { |
| 286 | dest.writeString(mDynamicNfcid2); |
| 287 | } |
| 288 | dest.writeInt(mUid); |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 289 | dest.writeString(mT3tPmm); |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 290 | }; |
| 291 | |
| 292 | public static final Parcelable.Creator<NfcFServiceInfo> CREATOR = |
| 293 | new Parcelable.Creator<NfcFServiceInfo>() { |
| 294 | @Override |
| 295 | public NfcFServiceInfo createFromParcel(Parcel source) { |
| 296 | ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source); |
| 297 | String description = source.readString(); |
| 298 | String systemCode = source.readString(); |
| 299 | String dynamicSystemCode = null; |
| 300 | if (source.readInt() != 0) { |
| 301 | dynamicSystemCode = source.readString(); |
| 302 | } |
| 303 | String nfcid2 = source.readString(); |
| 304 | String dynamicNfcid2 = null; |
| 305 | if (source.readInt() != 0) { |
| 306 | dynamicNfcid2 = source.readString(); |
| 307 | } |
| 308 | int uid = source.readInt(); |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 309 | String t3tPmm = source.readString(); |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 310 | NfcFServiceInfo service = new NfcFServiceInfo(info, description, |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 311 | systemCode, dynamicSystemCode, nfcid2, dynamicNfcid2, uid, t3tPmm); |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 312 | return service; |
| 313 | } |
| 314 | |
| 315 | @Override |
| 316 | public NfcFServiceInfo[] newArray(int size) { |
| 317 | return new NfcFServiceInfo[size]; |
| 318 | } |
| 319 | }; |
| 320 | |
| 321 | public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { |
| 322 | pw.println(" " + getComponent() + |
| 323 | " (Description: " + getDescription() + ")"); |
| 324 | pw.println(" System Code: " + getSystemCode()); |
| 325 | pw.println(" NFCID2: " + getNfcid2()); |
Love Khanna | ca26b12 | 2017-04-10 17:46:53 +0530 | [diff] [blame] | 326 | pw.println(" T3tPmm: " + getT3tPmm()); |
Yoshinobu Ito | c52adfe | 2016-01-22 18:14:18 +0900 | [diff] [blame] | 327 | } |
| 328 | } |
| 329 | |