• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.content.pm;
18 
19 import android.content.ComponentName;
20 import android.content.Intent;
21 import android.content.IntentFilter;
22 import android.content.res.AssetManager;
23 import android.content.res.Configuration;
24 import android.content.res.Resources;
25 import android.content.res.TypedArray;
26 import android.content.res.XmlResourceParser;
27 import android.os.Binder;
28 import android.os.Build;
29 import android.os.Bundle;
30 import android.os.PatternMatcher;
31 import android.os.UserId;
32 import android.util.AttributeSet;
33 import android.util.Base64;
34 import android.util.DisplayMetrics;
35 import android.util.Log;
36 import android.util.Slog;
37 import android.util.TypedValue;
38 
39 import java.io.BufferedInputStream;
40 import java.io.File;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.lang.ref.WeakReference;
44 import java.security.KeyFactory;
45 import java.security.NoSuchAlgorithmException;
46 import java.security.PublicKey;
47 import java.security.cert.Certificate;
48 import java.security.cert.CertificateEncodingException;
49 import java.security.spec.EncodedKeySpec;
50 import java.security.spec.InvalidKeySpecException;
51 import java.security.spec.X509EncodedKeySpec;
52 import java.util.ArrayList;
53 import java.util.Enumeration;
54 import java.util.HashSet;
55 import java.util.Iterator;
56 import java.util.List;
57 import java.util.jar.Attributes;
58 import java.util.jar.JarEntry;
59 import java.util.jar.JarFile;
60 import java.util.jar.Manifest;
61 
62 import com.android.internal.util.XmlUtils;
63 
64 import org.xmlpull.v1.XmlPullParser;
65 import org.xmlpull.v1.XmlPullParserException;
66 
67 /**
68  * Package archive parsing
69  *
70  * {@hide}
71  */
72 public class PackageParser {
73     private static final boolean DEBUG_JAR = false;
74     private static final boolean DEBUG_PARSER = false;
75     private static final boolean DEBUG_BACKUP = false;
76 
77     /** File name in an APK for the Android manifest. */
78     private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
79 
80     /** @hide */
81     public static class NewPermissionInfo {
82         public final String name;
83         public final int sdkVersion;
84         public final int fileVersion;
85 
NewPermissionInfo(String name, int sdkVersion, int fileVersion)86         public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
87             this.name = name;
88             this.sdkVersion = sdkVersion;
89             this.fileVersion = fileVersion;
90         }
91     }
92 
93     /** @hide */
94     public static class SplitPermissionInfo {
95         public final String rootPerm;
96         public final String[] newPerms;
97         public final int targetSdk;
98 
SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk)99         public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
100             this.rootPerm = rootPerm;
101             this.newPerms = newPerms;
102             this.targetSdk = targetSdk;
103         }
104     }
105 
106     /**
107      * List of new permissions that have been added since 1.0.
108      * NOTE: These must be declared in SDK version order, with permissions
109      * added to older SDKs appearing before those added to newer SDKs.
110      * If sdkVersion is 0, then this is not a permission that we want to
111      * automatically add to older apps, but we do want to allow it to be
112      * granted during a platform update.
113      * @hide
114      */
115     public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
116         new PackageParser.NewPermissionInfo[] {
117             new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
118                     android.os.Build.VERSION_CODES.DONUT, 0),
119             new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
120                     android.os.Build.VERSION_CODES.DONUT, 0)
121     };
122 
123     /**
124      * List of permissions that have been split into more granular or dependent
125      * permissions.
126      * @hide
127      */
128     public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
129         new PackageParser.SplitPermissionInfo[] {
130             // READ_EXTERNAL_STORAGE is always required when an app requests
131             // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
132             // write access without read access.  The hack here with the target
133             // target SDK version ensures that this grant is always done.
134             new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
135                     new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
136                     android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
137             new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
138                     new String[] { android.Manifest.permission.READ_CALL_LOG },
139                     android.os.Build.VERSION_CODES.JELLY_BEAN),
140             new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
141                     new String[] { android.Manifest.permission.WRITE_CALL_LOG },
142                     android.os.Build.VERSION_CODES.JELLY_BEAN)
143     };
144 
145     private String mArchiveSourcePath;
146     private String[] mSeparateProcesses;
147     private boolean mOnlyCoreApps;
148     private static final int SDK_VERSION = Build.VERSION.SDK_INT;
149     private static final String SDK_CODENAME = "REL".equals(Build.VERSION.CODENAME)
150             ? null : Build.VERSION.CODENAME;
151 
152     private int mParseError = PackageManager.INSTALL_SUCCEEDED;
153 
154     private static final Object mSync = new Object();
155     private static WeakReference<byte[]> mReadBuffer;
156 
157     private static boolean sCompatibilityModeEnabled = true;
158     private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
159 
160     static class ParsePackageItemArgs {
161         final Package owner;
162         final String[] outError;
163         final int nameRes;
164         final int labelRes;
165         final int iconRes;
166         final int logoRes;
167 
168         String tag;
169         TypedArray sa;
170 
ParsePackageItemArgs(Package _owner, String[] _outError, int _nameRes, int _labelRes, int _iconRes, int _logoRes)171         ParsePackageItemArgs(Package _owner, String[] _outError,
172                 int _nameRes, int _labelRes, int _iconRes, int _logoRes) {
173             owner = _owner;
174             outError = _outError;
175             nameRes = _nameRes;
176             labelRes = _labelRes;
177             iconRes = _iconRes;
178             logoRes = _logoRes;
179         }
180     }
181 
182     static class ParseComponentArgs extends ParsePackageItemArgs {
183         final String[] sepProcesses;
184         final int processRes;
185         final int descriptionRes;
186         final int enabledRes;
187         int flags;
188 
ParseComponentArgs(Package _owner, String[] _outError, int _nameRes, int _labelRes, int _iconRes, int _logoRes, String[] _sepProcesses, int _processRes, int _descriptionRes, int _enabledRes)189         ParseComponentArgs(Package _owner, String[] _outError,
190                 int _nameRes, int _labelRes, int _iconRes, int _logoRes,
191                 String[] _sepProcesses, int _processRes,
192                 int _descriptionRes, int _enabledRes) {
193             super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes);
194             sepProcesses = _sepProcesses;
195             processRes = _processRes;
196             descriptionRes = _descriptionRes;
197             enabledRes = _enabledRes;
198         }
199     }
200 
201     /* Light weight package info.
202      * @hide
203      */
204     public static class PackageLite {
205         public final String packageName;
206         public final int installLocation;
207         public final VerifierInfo[] verifiers;
208 
PackageLite(String packageName, int installLocation, List<VerifierInfo> verifiers)209         public PackageLite(String packageName, int installLocation, List<VerifierInfo> verifiers) {
210             this.packageName = packageName;
211             this.installLocation = installLocation;
212             this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
213         }
214     }
215 
216     private ParsePackageItemArgs mParseInstrumentationArgs;
217     private ParseComponentArgs mParseActivityArgs;
218     private ParseComponentArgs mParseActivityAliasArgs;
219     private ParseComponentArgs mParseServiceArgs;
220     private ParseComponentArgs mParseProviderArgs;
221 
222     /** If set to true, we will only allow package files that exactly match
223      *  the DTD.  Otherwise, we try to get as much from the package as we
224      *  can without failing.  This should normally be set to false, to
225      *  support extensions to the DTD in future versions. */
226     private static final boolean RIGID_PARSER = false;
227 
228     private static final String TAG = "PackageParser";
229 
PackageParser(String archiveSourcePath)230     public PackageParser(String archiveSourcePath) {
231         mArchiveSourcePath = archiveSourcePath;
232     }
233 
setSeparateProcesses(String[] procs)234     public void setSeparateProcesses(String[] procs) {
235         mSeparateProcesses = procs;
236     }
237 
setOnlyCoreApps(boolean onlyCoreApps)238     public void setOnlyCoreApps(boolean onlyCoreApps) {
239         mOnlyCoreApps = onlyCoreApps;
240     }
241 
isPackageFilename(String name)242     private static final boolean isPackageFilename(String name) {
243         return name.endsWith(".apk");
244     }
245 
generatePackageInfo(PackageParser.Package p, int gids[], int flags, long firstInstallTime, long lastUpdateTime, HashSet<String> grantedPermissions)246     public static PackageInfo generatePackageInfo(PackageParser.Package p,
247             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
248             HashSet<String> grantedPermissions) {
249 
250         return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
251                 grantedPermissions, false, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
252                 UserId.getCallingUserId());
253     }
254 
255     /**
256      * Generate and return the {@link PackageInfo} for a parsed package.
257      *
258      * @param p the parsed package.
259      * @param flags indicating which optional information is included.
260      */
generatePackageInfo(PackageParser.Package p, int gids[], int flags, long firstInstallTime, long lastUpdateTime, HashSet<String> grantedPermissions, boolean stopped, int enabledState)261     public static PackageInfo generatePackageInfo(PackageParser.Package p,
262             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
263             HashSet<String> grantedPermissions, boolean stopped, int enabledState) {
264 
265         return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
266                 grantedPermissions, stopped, enabledState, UserId.getCallingUserId());
267     }
268 
generatePackageInfo(PackageParser.Package p, int gids[], int flags, long firstInstallTime, long lastUpdateTime, HashSet<String> grantedPermissions, boolean stopped, int enabledState, int userId)269     public static PackageInfo generatePackageInfo(PackageParser.Package p,
270             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
271             HashSet<String> grantedPermissions, boolean stopped, int enabledState, int userId) {
272 
273         PackageInfo pi = new PackageInfo();
274         pi.packageName = p.packageName;
275         pi.versionCode = p.mVersionCode;
276         pi.versionName = p.mVersionName;
277         pi.sharedUserId = p.mSharedUserId;
278         pi.sharedUserLabel = p.mSharedUserLabel;
279         pi.applicationInfo = generateApplicationInfo(p, flags, stopped, enabledState, userId);
280         pi.installLocation = p.installLocation;
281         pi.firstInstallTime = firstInstallTime;
282         pi.lastUpdateTime = lastUpdateTime;
283         if ((flags&PackageManager.GET_GIDS) != 0) {
284             pi.gids = gids;
285         }
286         if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
287             int N = p.configPreferences.size();
288             if (N > 0) {
289                 pi.configPreferences = new ConfigurationInfo[N];
290                 p.configPreferences.toArray(pi.configPreferences);
291             }
292             N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
293             if (N > 0) {
294                 pi.reqFeatures = new FeatureInfo[N];
295                 p.reqFeatures.toArray(pi.reqFeatures);
296             }
297         }
298         if ((flags&PackageManager.GET_ACTIVITIES) != 0) {
299             int N = p.activities.size();
300             if (N > 0) {
301                 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
302                     pi.activities = new ActivityInfo[N];
303                 } else {
304                     int num = 0;
305                     for (int i=0; i<N; i++) {
306                         if (p.activities.get(i).info.enabled) num++;
307                     }
308                     pi.activities = new ActivityInfo[num];
309                 }
310                 for (int i=0, j=0; i<N; i++) {
311                     final Activity activity = p.activities.get(i);
312                     if (activity.info.enabled
313                         || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
314                         pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags,
315                                 stopped, enabledState, userId);
316                     }
317                 }
318             }
319         }
320         if ((flags&PackageManager.GET_RECEIVERS) != 0) {
321             int N = p.receivers.size();
322             if (N > 0) {
323                 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
324                     pi.receivers = new ActivityInfo[N];
325                 } else {
326                     int num = 0;
327                     for (int i=0; i<N; i++) {
328                         if (p.receivers.get(i).info.enabled) num++;
329                     }
330                     pi.receivers = new ActivityInfo[num];
331                 }
332                 for (int i=0, j=0; i<N; i++) {
333                     final Activity activity = p.receivers.get(i);
334                     if (activity.info.enabled
335                         || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
336                         pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags,
337                                 stopped, enabledState, userId);
338                     }
339                 }
340             }
341         }
342         if ((flags&PackageManager.GET_SERVICES) != 0) {
343             int N = p.services.size();
344             if (N > 0) {
345                 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
346                     pi.services = new ServiceInfo[N];
347                 } else {
348                     int num = 0;
349                     for (int i=0; i<N; i++) {
350                         if (p.services.get(i).info.enabled) num++;
351                     }
352                     pi.services = new ServiceInfo[num];
353                 }
354                 for (int i=0, j=0; i<N; i++) {
355                     final Service service = p.services.get(i);
356                     if (service.info.enabled
357                         || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
358                         pi.services[j++] = generateServiceInfo(p.services.get(i), flags, stopped,
359                                 enabledState, userId);
360                     }
361                 }
362             }
363         }
364         if ((flags&PackageManager.GET_PROVIDERS) != 0) {
365             int N = p.providers.size();
366             if (N > 0) {
367                 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
368                     pi.providers = new ProviderInfo[N];
369                 } else {
370                     int num = 0;
371                     for (int i=0; i<N; i++) {
372                         if (p.providers.get(i).info.enabled) num++;
373                     }
374                     pi.providers = new ProviderInfo[num];
375                 }
376                 for (int i=0, j=0; i<N; i++) {
377                     final Provider provider = p.providers.get(i);
378                     if (provider.info.enabled
379                         || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
380                         pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags, stopped,
381                                 enabledState, userId);
382                     }
383                 }
384             }
385         }
386         if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
387             int N = p.instrumentation.size();
388             if (N > 0) {
389                 pi.instrumentation = new InstrumentationInfo[N];
390                 for (int i=0; i<N; i++) {
391                     pi.instrumentation[i] = generateInstrumentationInfo(
392                             p.instrumentation.get(i), flags);
393                 }
394             }
395         }
396         if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
397             int N = p.permissions.size();
398             if (N > 0) {
399                 pi.permissions = new PermissionInfo[N];
400                 for (int i=0; i<N; i++) {
401                     pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
402                 }
403             }
404             N = p.requestedPermissions.size();
405             if (N > 0) {
406                 pi.requestedPermissions = new String[N];
407                 pi.requestedPermissionsFlags = new int[N];
408                 for (int i=0; i<N; i++) {
409                     final String perm = p.requestedPermissions.get(i);
410                     pi.requestedPermissions[i] = perm;
411                     if (p.requestedPermissionsRequired.get(i)) {
412                         pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
413                     }
414                     if (grantedPermissions != null && grantedPermissions.contains(perm)) {
415                         pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
416                     }
417                 }
418             }
419         }
420         if ((flags&PackageManager.GET_SIGNATURES) != 0) {
421            int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
422            if (N > 0) {
423                 pi.signatures = new Signature[N];
424                 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
425             }
426         }
427         return pi;
428     }
429 
loadCertificates(JarFile jarFile, JarEntry je, byte[] readBuffer)430     private Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
431             byte[] readBuffer) {
432         try {
433             // We must read the stream for the JarEntry to retrieve
434             // its certificates.
435             InputStream is = new BufferedInputStream(jarFile.getInputStream(je));
436             while (is.read(readBuffer, 0, readBuffer.length) != -1) {
437                 // not using
438             }
439             is.close();
440             return je != null ? je.getCertificates() : null;
441         } catch (IOException e) {
442             Slog.w(TAG, "Exception reading " + je.getName() + " in "
443                     + jarFile.getName(), e);
444         } catch (RuntimeException e) {
445             Slog.w(TAG, "Exception reading " + je.getName() + " in "
446                     + jarFile.getName(), e);
447         }
448         return null;
449     }
450 
451     public final static int PARSE_IS_SYSTEM = 1<<0;
452     public final static int PARSE_CHATTY = 1<<1;
453     public final static int PARSE_MUST_BE_APK = 1<<2;
454     public final static int PARSE_IGNORE_PROCESSES = 1<<3;
455     public final static int PARSE_FORWARD_LOCK = 1<<4;
456     public final static int PARSE_ON_SDCARD = 1<<5;
457     public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
458 
getParseError()459     public int getParseError() {
460         return mParseError;
461     }
462 
parsePackage(File sourceFile, String destCodePath, DisplayMetrics metrics, int flags)463     public Package parsePackage(File sourceFile, String destCodePath,
464             DisplayMetrics metrics, int flags) {
465         mParseError = PackageManager.INSTALL_SUCCEEDED;
466 
467         mArchiveSourcePath = sourceFile.getPath();
468         if (!sourceFile.isFile()) {
469             Slog.w(TAG, "Skipping dir: " + mArchiveSourcePath);
470             mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
471             return null;
472         }
473         if (!isPackageFilename(sourceFile.getName())
474                 && (flags&PARSE_MUST_BE_APK) != 0) {
475             if ((flags&PARSE_IS_SYSTEM) == 0) {
476                 // We expect to have non-.apk files in the system dir,
477                 // so don't warn about them.
478                 Slog.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);
479             }
480             mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
481             return null;
482         }
483 
484         if (DEBUG_JAR)
485             Slog.d(TAG, "Scanning package: " + mArchiveSourcePath);
486 
487         XmlResourceParser parser = null;
488         AssetManager assmgr = null;
489         Resources res = null;
490         boolean assetError = true;
491         try {
492             assmgr = new AssetManager();
493             int cookie = assmgr.addAssetPath(mArchiveSourcePath);
494             if (cookie != 0) {
495                 res = new Resources(assmgr, metrics, null);
496                 assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
497                         Build.VERSION.RESOURCES_SDK_INT);
498                 parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
499                 assetError = false;
500             } else {
501                 Slog.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
502             }
503         } catch (Exception e) {
504             Slog.w(TAG, "Unable to read AndroidManifest.xml of "
505                     + mArchiveSourcePath, e);
506         }
507         if (assetError) {
508             if (assmgr != null) assmgr.close();
509             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
510             return null;
511         }
512         String[] errorText = new String[1];
513         Package pkg = null;
514         Exception errorException = null;
515         try {
516             // XXXX todo: need to figure out correct configuration.
517             pkg = parsePackage(res, parser, flags, errorText);
518         } catch (Exception e) {
519             errorException = e;
520             mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
521         }
522 
523 
524         if (pkg == null) {
525             // If we are only parsing core apps, then a null with INSTALL_SUCCEEDED
526             // just means to skip this app so don't make a fuss about it.
527             if (!mOnlyCoreApps || mParseError != PackageManager.INSTALL_SUCCEEDED) {
528                 if (errorException != null) {
529                     Slog.w(TAG, mArchiveSourcePath, errorException);
530                 } else {
531                     Slog.w(TAG, mArchiveSourcePath + " (at "
532                             + parser.getPositionDescription()
533                             + "): " + errorText[0]);
534                 }
535                 if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
536                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
537                 }
538             }
539             parser.close();
540             assmgr.close();
541             return null;
542         }
543 
544         parser.close();
545         assmgr.close();
546 
547         // Set code and resource paths
548         pkg.mPath = destCodePath;
549         pkg.mScanPath = mArchiveSourcePath;
550         //pkg.applicationInfo.sourceDir = destCodePath;
551         //pkg.applicationInfo.publicSourceDir = destRes;
552         pkg.mSignatures = null;
553 
554         return pkg;
555     }
556 
collectCertificates(Package pkg, int flags)557     public boolean collectCertificates(Package pkg, int flags) {
558         pkg.mSignatures = null;
559 
560         WeakReference<byte[]> readBufferRef;
561         byte[] readBuffer = null;
562         synchronized (mSync) {
563             readBufferRef = mReadBuffer;
564             if (readBufferRef != null) {
565                 mReadBuffer = null;
566                 readBuffer = readBufferRef.get();
567             }
568             if (readBuffer == null) {
569                 readBuffer = new byte[8192];
570                 readBufferRef = new WeakReference<byte[]>(readBuffer);
571             }
572         }
573 
574         try {
575             JarFile jarFile = new JarFile(mArchiveSourcePath);
576 
577             Certificate[] certs = null;
578 
579             if ((flags&PARSE_IS_SYSTEM) != 0) {
580                 // If this package comes from the system image, then we
581                 // can trust it...  we'll just use the AndroidManifest.xml
582                 // to retrieve its signatures, not validating all of the
583                 // files.
584                 JarEntry jarEntry = jarFile.getJarEntry(ANDROID_MANIFEST_FILENAME);
585                 certs = loadCertificates(jarFile, jarEntry, readBuffer);
586                 if (certs == null) {
587                     Slog.e(TAG, "Package " + pkg.packageName
588                             + " has no certificates at entry "
589                             + jarEntry.getName() + "; ignoring!");
590                     jarFile.close();
591                     mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
592                     return false;
593                 }
594                 if (DEBUG_JAR) {
595                     Slog.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry
596                             + " certs=" + (certs != null ? certs.length : 0));
597                     if (certs != null) {
598                         final int N = certs.length;
599                         for (int i=0; i<N; i++) {
600                             Slog.i(TAG, "  Public key: "
601                                     + certs[i].getPublicKey().getEncoded()
602                                     + " " + certs[i].getPublicKey());
603                         }
604                     }
605                 }
606             } else {
607                 Enumeration<JarEntry> entries = jarFile.entries();
608                 final Manifest manifest = jarFile.getManifest();
609                 while (entries.hasMoreElements()) {
610                     final JarEntry je = entries.nextElement();
611                     if (je.isDirectory()) continue;
612 
613                     final String name = je.getName();
614 
615                     if (name.startsWith("META-INF/"))
616                         continue;
617 
618                     if (ANDROID_MANIFEST_FILENAME.equals(name)) {
619                         final Attributes attributes = manifest.getAttributes(name);
620                         pkg.manifestDigest = ManifestDigest.fromAttributes(attributes);
621                     }
622 
623                     final Certificate[] localCerts = loadCertificates(jarFile, je, readBuffer);
624                     if (DEBUG_JAR) {
625                         Slog.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName()
626                                 + ": certs=" + certs + " ("
627                                 + (certs != null ? certs.length : 0) + ")");
628                     }
629 
630                     if (localCerts == null) {
631                         Slog.e(TAG, "Package " + pkg.packageName
632                                 + " has no certificates at entry "
633                                 + je.getName() + "; ignoring!");
634                         jarFile.close();
635                         mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
636                         return false;
637                     } else if (certs == null) {
638                         certs = localCerts;
639                     } else {
640                         // Ensure all certificates match.
641                         for (int i=0; i<certs.length; i++) {
642                             boolean found = false;
643                             for (int j=0; j<localCerts.length; j++) {
644                                 if (certs[i] != null &&
645                                         certs[i].equals(localCerts[j])) {
646                                     found = true;
647                                     break;
648                                 }
649                             }
650                             if (!found || certs.length != localCerts.length) {
651                                 Slog.e(TAG, "Package " + pkg.packageName
652                                         + " has mismatched certificates at entry "
653                                         + je.getName() + "; ignoring!");
654                                 jarFile.close();
655                                 mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
656                                 return false;
657                             }
658                         }
659                     }
660                 }
661             }
662             jarFile.close();
663 
664             synchronized (mSync) {
665                 mReadBuffer = readBufferRef;
666             }
667 
668             if (certs != null && certs.length > 0) {
669                 final int N = certs.length;
670                 pkg.mSignatures = new Signature[certs.length];
671                 for (int i=0; i<N; i++) {
672                     pkg.mSignatures[i] = new Signature(
673                             certs[i].getEncoded());
674                 }
675             } else {
676                 Slog.e(TAG, "Package " + pkg.packageName
677                         + " has no certificates; ignoring!");
678                 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
679                 return false;
680             }
681         } catch (CertificateEncodingException e) {
682             Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
683             mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
684             return false;
685         } catch (IOException e) {
686             Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
687             mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
688             return false;
689         } catch (RuntimeException e) {
690             Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
691             mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
692             return false;
693         }
694 
695         return true;
696     }
697 
698     /*
699      * Utility method that retrieves just the package name and install
700      * location from the apk location at the given file path.
701      * @param packageFilePath file location of the apk
702      * @param flags Special parse flags
703      * @return PackageLite object with package information or null on failure.
704      */
parsePackageLite(String packageFilePath, int flags)705     public static PackageLite parsePackageLite(String packageFilePath, int flags) {
706         AssetManager assmgr = null;
707         final XmlResourceParser parser;
708         final Resources res;
709         try {
710             assmgr = new AssetManager();
711             assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
712                     Build.VERSION.RESOURCES_SDK_INT);
713 
714             int cookie = assmgr.addAssetPath(packageFilePath);
715             if (cookie == 0) {
716                 return null;
717             }
718 
719             final DisplayMetrics metrics = new DisplayMetrics();
720             metrics.setToDefaults();
721             res = new Resources(assmgr, metrics, null);
722             parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
723         } catch (Exception e) {
724             if (assmgr != null) assmgr.close();
725             Slog.w(TAG, "Unable to read AndroidManifest.xml of "
726                     + packageFilePath, e);
727             return null;
728         }
729 
730         final AttributeSet attrs = parser;
731         final String errors[] = new String[1];
732         PackageLite packageLite = null;
733         try {
734             packageLite = parsePackageLite(res, parser, attrs, flags, errors);
735         } catch (IOException e) {
736             Slog.w(TAG, packageFilePath, e);
737         } catch (XmlPullParserException e) {
738             Slog.w(TAG, packageFilePath, e);
739         } finally {
740             if (parser != null) parser.close();
741             if (assmgr != null) assmgr.close();
742         }
743         if (packageLite == null) {
744             Slog.e(TAG, "parsePackageLite error: " + errors[0]);
745             return null;
746         }
747         return packageLite;
748     }
749 
validateName(String name, boolean requiresSeparator)750     private static String validateName(String name, boolean requiresSeparator) {
751         final int N = name.length();
752         boolean hasSep = false;
753         boolean front = true;
754         for (int i=0; i<N; i++) {
755             final char c = name.charAt(i);
756             if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
757                 front = false;
758                 continue;
759             }
760             if (!front) {
761                 if ((c >= '0' && c <= '9') || c == '_') {
762                     continue;
763                 }
764             }
765             if (c == '.') {
766                 hasSep = true;
767                 front = true;
768                 continue;
769             }
770             return "bad character '" + c + "'";
771         }
772         return hasSep || !requiresSeparator
773                 ? null : "must have at least one '.' separator";
774     }
775 
parsePackageName(XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)776     private static String parsePackageName(XmlPullParser parser,
777             AttributeSet attrs, int flags, String[] outError)
778             throws IOException, XmlPullParserException {
779 
780         int type;
781         while ((type = parser.next()) != XmlPullParser.START_TAG
782                 && type != XmlPullParser.END_DOCUMENT) {
783             ;
784         }
785 
786         if (type != XmlPullParser.START_TAG) {
787             outError[0] = "No start tag found";
788             return null;
789         }
790         if (DEBUG_PARSER)
791             Slog.v(TAG, "Root element name: '" + parser.getName() + "'");
792         if (!parser.getName().equals("manifest")) {
793             outError[0] = "No <manifest> tag";
794             return null;
795         }
796         String pkgName = attrs.getAttributeValue(null, "package");
797         if (pkgName == null || pkgName.length() == 0) {
798             outError[0] = "<manifest> does not specify package";
799             return null;
800         }
801         String nameError = validateName(pkgName, true);
802         if (nameError != null && !"android".equals(pkgName)) {
803             outError[0] = "<manifest> specifies bad package name \""
804                 + pkgName + "\": " + nameError;
805             return null;
806         }
807 
808         return pkgName.intern();
809     }
810 
parsePackageLite(Resources res, XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)811     private static PackageLite parsePackageLite(Resources res, XmlPullParser parser,
812             AttributeSet attrs, int flags, String[] outError) throws IOException,
813             XmlPullParserException {
814 
815         int type;
816         while ((type = parser.next()) != XmlPullParser.START_TAG
817                 && type != XmlPullParser.END_DOCUMENT) {
818             ;
819         }
820 
821         if (type != XmlPullParser.START_TAG) {
822             outError[0] = "No start tag found";
823             return null;
824         }
825         if (DEBUG_PARSER)
826             Slog.v(TAG, "Root element name: '" + parser.getName() + "'");
827         if (!parser.getName().equals("manifest")) {
828             outError[0] = "No <manifest> tag";
829             return null;
830         }
831         String pkgName = attrs.getAttributeValue(null, "package");
832         if (pkgName == null || pkgName.length() == 0) {
833             outError[0] = "<manifest> does not specify package";
834             return null;
835         }
836         String nameError = validateName(pkgName, true);
837         if (nameError != null && !"android".equals(pkgName)) {
838             outError[0] = "<manifest> specifies bad package name \""
839                 + pkgName + "\": " + nameError;
840             return null;
841         }
842         int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
843         for (int i = 0; i < attrs.getAttributeCount(); i++) {
844             String attr = attrs.getAttributeName(i);
845             if (attr.equals("installLocation")) {
846                 installLocation = attrs.getAttributeIntValue(i,
847                         PARSE_DEFAULT_INSTALL_LOCATION);
848                 break;
849             }
850         }
851 
852         // Only search the tree when the tag is directly below <manifest>
853         final int searchDepth = parser.getDepth() + 1;
854 
855         final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
856         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
857                 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
858             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
859                 continue;
860             }
861 
862             if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) {
863                 final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags, outError);
864                 if (verifier != null) {
865                     verifiers.add(verifier);
866                 }
867             }
868         }
869 
870         return new PackageLite(pkgName.intern(), installLocation, verifiers);
871     }
872 
873     /**
874      * Temporary.
875      */
stringToSignature(String str)876     static public Signature stringToSignature(String str) {
877         final int N = str.length();
878         byte[] sig = new byte[N];
879         for (int i=0; i<N; i++) {
880             sig[i] = (byte)str.charAt(i);
881         }
882         return new Signature(sig);
883     }
884 
parsePackage( Resources res, XmlResourceParser parser, int flags, String[] outError)885     private Package parsePackage(
886         Resources res, XmlResourceParser parser, int flags, String[] outError)
887         throws XmlPullParserException, IOException {
888         AttributeSet attrs = parser;
889 
890         mParseInstrumentationArgs = null;
891         mParseActivityArgs = null;
892         mParseServiceArgs = null;
893         mParseProviderArgs = null;
894 
895         String pkgName = parsePackageName(parser, attrs, flags, outError);
896         if (pkgName == null) {
897             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
898             return null;
899         }
900         int type;
901 
902         if (mOnlyCoreApps) {
903             boolean core = attrs.getAttributeBooleanValue(null, "coreApp", false);
904             if (!core) {
905                 mParseError = PackageManager.INSTALL_SUCCEEDED;
906                 return null;
907             }
908         }
909 
910         final Package pkg = new Package(pkgName);
911         boolean foundApp = false;
912 
913         TypedArray sa = res.obtainAttributes(attrs,
914                 com.android.internal.R.styleable.AndroidManifest);
915         pkg.mVersionCode = sa.getInteger(
916                 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
917         pkg.mVersionName = sa.getNonConfigurationString(
918                 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
919         if (pkg.mVersionName != null) {
920             pkg.mVersionName = pkg.mVersionName.intern();
921         }
922         String str = sa.getNonConfigurationString(
923                 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
924         if (str != null && str.length() > 0) {
925             String nameError = validateName(str, true);
926             if (nameError != null && !"android".equals(pkgName)) {
927                 outError[0] = "<manifest> specifies bad sharedUserId name \""
928                     + str + "\": " + nameError;
929                 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
930                 return null;
931             }
932             pkg.mSharedUserId = str.intern();
933             pkg.mSharedUserLabel = sa.getResourceId(
934                     com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
935         }
936         sa.recycle();
937 
938         pkg.installLocation = sa.getInteger(
939                 com.android.internal.R.styleable.AndroidManifest_installLocation,
940                 PARSE_DEFAULT_INSTALL_LOCATION);
941         pkg.applicationInfo.installLocation = pkg.installLocation;
942 
943         /* Set the global "forward lock" flag */
944         if ((flags & PARSE_FORWARD_LOCK) != 0) {
945             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
946         }
947 
948         /* Set the global "on SD card" flag */
949         if ((flags & PARSE_ON_SDCARD) != 0) {
950             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
951         }
952 
953         // Resource boolean are -1, so 1 means we don't know the value.
954         int supportsSmallScreens = 1;
955         int supportsNormalScreens = 1;
956         int supportsLargeScreens = 1;
957         int supportsXLargeScreens = 1;
958         int resizeable = 1;
959         int anyDensity = 1;
960 
961         int outerDepth = parser.getDepth();
962         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
963                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
964             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
965                 continue;
966             }
967 
968             String tagName = parser.getName();
969             if (tagName.equals("application")) {
970                 if (foundApp) {
971                     if (RIGID_PARSER) {
972                         outError[0] = "<manifest> has more than one <application>";
973                         mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
974                         return null;
975                     } else {
976                         Slog.w(TAG, "<manifest> has more than one <application>");
977                         XmlUtils.skipCurrentTag(parser);
978                         continue;
979                     }
980                 }
981 
982                 foundApp = true;
983                 if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
984                     return null;
985                 }
986             } else if (tagName.equals("permission-group")) {
987                 if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
988                     return null;
989                 }
990             } else if (tagName.equals("permission")) {
991                 if (parsePermission(pkg, res, parser, attrs, outError) == null) {
992                     return null;
993                 }
994             } else if (tagName.equals("permission-tree")) {
995                 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
996                     return null;
997                 }
998             } else if (tagName.equals("uses-permission")) {
999                 sa = res.obtainAttributes(attrs,
1000                         com.android.internal.R.styleable.AndroidManifestUsesPermission);
1001 
1002                 // Note: don't allow this value to be a reference to a resource
1003                 // that may change.
1004                 String name = sa.getNonResourceString(
1005                         com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
1006                 /* Not supporting optional permissions yet.
1007                 boolean required = sa.getBoolean(
1008                         com.android.internal.R.styleable.AndroidManifestUsesPermission_required, true);
1009                 */
1010 
1011                 sa.recycle();
1012 
1013                 if (name != null && !pkg.requestedPermissions.contains(name)) {
1014                     pkg.requestedPermissions.add(name.intern());
1015                     pkg.requestedPermissionsRequired.add(Boolean.TRUE);
1016                 }
1017 
1018                 XmlUtils.skipCurrentTag(parser);
1019 
1020             } else if (tagName.equals("uses-configuration")) {
1021                 ConfigurationInfo cPref = new ConfigurationInfo();
1022                 sa = res.obtainAttributes(attrs,
1023                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
1024                 cPref.reqTouchScreen = sa.getInt(
1025                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
1026                         Configuration.TOUCHSCREEN_UNDEFINED);
1027                 cPref.reqKeyboardType = sa.getInt(
1028                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
1029                         Configuration.KEYBOARD_UNDEFINED);
1030                 if (sa.getBoolean(
1031                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
1032                         false)) {
1033                     cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
1034                 }
1035                 cPref.reqNavigation = sa.getInt(
1036                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
1037                         Configuration.NAVIGATION_UNDEFINED);
1038                 if (sa.getBoolean(
1039                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
1040                         false)) {
1041                     cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
1042                 }
1043                 sa.recycle();
1044                 pkg.configPreferences.add(cPref);
1045 
1046                 XmlUtils.skipCurrentTag(parser);
1047 
1048             } else if (tagName.equals("uses-feature")) {
1049                 FeatureInfo fi = new FeatureInfo();
1050                 sa = res.obtainAttributes(attrs,
1051                         com.android.internal.R.styleable.AndroidManifestUsesFeature);
1052                 // Note: don't allow this value to be a reference to a resource
1053                 // that may change.
1054                 fi.name = sa.getNonResourceString(
1055                         com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
1056                 if (fi.name == null) {
1057                     fi.reqGlEsVersion = sa.getInt(
1058                             com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
1059                             FeatureInfo.GL_ES_VERSION_UNDEFINED);
1060                 }
1061                 if (sa.getBoolean(
1062                         com.android.internal.R.styleable.AndroidManifestUsesFeature_required,
1063                         true)) {
1064                     fi.flags |= FeatureInfo.FLAG_REQUIRED;
1065                 }
1066                 sa.recycle();
1067                 if (pkg.reqFeatures == null) {
1068                     pkg.reqFeatures = new ArrayList<FeatureInfo>();
1069                 }
1070                 pkg.reqFeatures.add(fi);
1071 
1072                 if (fi.name == null) {
1073                     ConfigurationInfo cPref = new ConfigurationInfo();
1074                     cPref.reqGlEsVersion = fi.reqGlEsVersion;
1075                     pkg.configPreferences.add(cPref);
1076                 }
1077 
1078                 XmlUtils.skipCurrentTag(parser);
1079 
1080             } else if (tagName.equals("uses-sdk")) {
1081                 if (SDK_VERSION > 0) {
1082                     sa = res.obtainAttributes(attrs,
1083                             com.android.internal.R.styleable.AndroidManifestUsesSdk);
1084 
1085                     int minVers = 0;
1086                     String minCode = null;
1087                     int targetVers = 0;
1088                     String targetCode = null;
1089 
1090                     TypedValue val = sa.peekValue(
1091                             com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
1092                     if (val != null) {
1093                         if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1094                             targetCode = minCode = val.string.toString();
1095                         } else {
1096                             // If it's not a string, it's an integer.
1097                             targetVers = minVers = val.data;
1098                         }
1099                     }
1100 
1101                     val = sa.peekValue(
1102                             com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
1103                     if (val != null) {
1104                         if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1105                             targetCode = minCode = val.string.toString();
1106                         } else {
1107                             // If it's not a string, it's an integer.
1108                             targetVers = val.data;
1109                         }
1110                     }
1111 
1112                     sa.recycle();
1113 
1114                     if (minCode != null) {
1115                         if (!minCode.equals(SDK_CODENAME)) {
1116                             if (SDK_CODENAME != null) {
1117                                 outError[0] = "Requires development platform " + minCode
1118                                         + " (current platform is " + SDK_CODENAME + ")";
1119                             } else {
1120                                 outError[0] = "Requires development platform " + minCode
1121                                         + " but this is a release platform.";
1122                             }
1123                             mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1124                             return null;
1125                         }
1126                     } else if (minVers > SDK_VERSION) {
1127                         outError[0] = "Requires newer sdk version #" + minVers
1128                                 + " (current version is #" + SDK_VERSION + ")";
1129                         mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1130                         return null;
1131                     }
1132 
1133                     if (targetCode != null) {
1134                         if (!targetCode.equals(SDK_CODENAME)) {
1135                             if (SDK_CODENAME != null) {
1136                                 outError[0] = "Requires development platform " + targetCode
1137                                         + " (current platform is " + SDK_CODENAME + ")";
1138                             } else {
1139                                 outError[0] = "Requires development platform " + targetCode
1140                                         + " but this is a release platform.";
1141                             }
1142                             mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1143                             return null;
1144                         }
1145                         // If the code matches, it definitely targets this SDK.
1146                         pkg.applicationInfo.targetSdkVersion
1147                                 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
1148                     } else {
1149                         pkg.applicationInfo.targetSdkVersion = targetVers;
1150                     }
1151                 }
1152 
1153                 XmlUtils.skipCurrentTag(parser);
1154 
1155             } else if (tagName.equals("supports-screens")) {
1156                 sa = res.obtainAttributes(attrs,
1157                         com.android.internal.R.styleable.AndroidManifestSupportsScreens);
1158 
1159                 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
1160                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
1161                         0);
1162                 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
1163                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
1164                         0);
1165                 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
1166                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
1167                         0);
1168 
1169                 // This is a trick to get a boolean and still able to detect
1170                 // if a value was actually set.
1171                 supportsSmallScreens = sa.getInteger(
1172                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
1173                         supportsSmallScreens);
1174                 supportsNormalScreens = sa.getInteger(
1175                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
1176                         supportsNormalScreens);
1177                 supportsLargeScreens = sa.getInteger(
1178                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
1179                         supportsLargeScreens);
1180                 supportsXLargeScreens = sa.getInteger(
1181                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
1182                         supportsXLargeScreens);
1183                 resizeable = sa.getInteger(
1184                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
1185                         resizeable);
1186                 anyDensity = sa.getInteger(
1187                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
1188                         anyDensity);
1189 
1190                 sa.recycle();
1191 
1192                 XmlUtils.skipCurrentTag(parser);
1193 
1194             } else if (tagName.equals("protected-broadcast")) {
1195                 sa = res.obtainAttributes(attrs,
1196                         com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
1197 
1198                 // Note: don't allow this value to be a reference to a resource
1199                 // that may change.
1200                 String name = sa.getNonResourceString(
1201                         com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
1202 
1203                 sa.recycle();
1204 
1205                 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
1206                     if (pkg.protectedBroadcasts == null) {
1207                         pkg.protectedBroadcasts = new ArrayList<String>();
1208                     }
1209                     if (!pkg.protectedBroadcasts.contains(name)) {
1210                         pkg.protectedBroadcasts.add(name.intern());
1211                     }
1212                 }
1213 
1214                 XmlUtils.skipCurrentTag(parser);
1215 
1216             } else if (tagName.equals("instrumentation")) {
1217                 if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
1218                     return null;
1219                 }
1220 
1221             } else if (tagName.equals("original-package")) {
1222                 sa = res.obtainAttributes(attrs,
1223                         com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1224 
1225                 String orig =sa.getNonConfigurationString(
1226                         com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
1227                 if (!pkg.packageName.equals(orig)) {
1228                     if (pkg.mOriginalPackages == null) {
1229                         pkg.mOriginalPackages = new ArrayList<String>();
1230                         pkg.mRealPackage = pkg.packageName;
1231                     }
1232                     pkg.mOriginalPackages.add(orig);
1233                 }
1234 
1235                 sa.recycle();
1236 
1237                 XmlUtils.skipCurrentTag(parser);
1238 
1239             } else if (tagName.equals("adopt-permissions")) {
1240                 sa = res.obtainAttributes(attrs,
1241                         com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1242 
1243                 String name = sa.getNonConfigurationString(
1244                         com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
1245 
1246                 sa.recycle();
1247 
1248                 if (name != null) {
1249                     if (pkg.mAdoptPermissions == null) {
1250                         pkg.mAdoptPermissions = new ArrayList<String>();
1251                     }
1252                     pkg.mAdoptPermissions.add(name);
1253                 }
1254 
1255                 XmlUtils.skipCurrentTag(parser);
1256 
1257             } else if (tagName.equals("uses-gl-texture")) {
1258                 // Just skip this tag
1259                 XmlUtils.skipCurrentTag(parser);
1260                 continue;
1261 
1262             } else if (tagName.equals("compatible-screens")) {
1263                 // Just skip this tag
1264                 XmlUtils.skipCurrentTag(parser);
1265                 continue;
1266 
1267             } else if (tagName.equals("eat-comment")) {
1268                 // Just skip this tag
1269                 XmlUtils.skipCurrentTag(parser);
1270                 continue;
1271 
1272             } else if (RIGID_PARSER) {
1273                 outError[0] = "Bad element under <manifest>: "
1274                     + parser.getName();
1275                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1276                 return null;
1277 
1278             } else {
1279                 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1280                         + " at " + mArchiveSourcePath + " "
1281                         + parser.getPositionDescription());
1282                 XmlUtils.skipCurrentTag(parser);
1283                 continue;
1284             }
1285         }
1286 
1287         if (!foundApp && pkg.instrumentation.size() == 0) {
1288             outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
1289             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1290         }
1291 
1292         final int NP = PackageParser.NEW_PERMISSIONS.length;
1293         StringBuilder implicitPerms = null;
1294         for (int ip=0; ip<NP; ip++) {
1295             final PackageParser.NewPermissionInfo npi
1296                     = PackageParser.NEW_PERMISSIONS[ip];
1297             if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
1298                 break;
1299             }
1300             if (!pkg.requestedPermissions.contains(npi.name)) {
1301                 if (implicitPerms == null) {
1302                     implicitPerms = new StringBuilder(128);
1303                     implicitPerms.append(pkg.packageName);
1304                     implicitPerms.append(": compat added ");
1305                 } else {
1306                     implicitPerms.append(' ');
1307                 }
1308                 implicitPerms.append(npi.name);
1309                 pkg.requestedPermissions.add(npi.name);
1310                 pkg.requestedPermissionsRequired.add(Boolean.TRUE);
1311             }
1312         }
1313         if (implicitPerms != null) {
1314             Slog.i(TAG, implicitPerms.toString());
1315         }
1316 
1317         final int NS = PackageParser.SPLIT_PERMISSIONS.length;
1318         for (int is=0; is<NS; is++) {
1319             final PackageParser.SplitPermissionInfo spi
1320                     = PackageParser.SPLIT_PERMISSIONS[is];
1321             if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
1322                     || !pkg.requestedPermissions.contains(spi.rootPerm)) {
1323                 continue;
1324             }
1325             for (int in=0; in<spi.newPerms.length; in++) {
1326                 final String perm = spi.newPerms[in];
1327                 if (!pkg.requestedPermissions.contains(perm)) {
1328                     pkg.requestedPermissions.add(perm);
1329                     pkg.requestedPermissionsRequired.add(Boolean.TRUE);
1330                 }
1331             }
1332         }
1333 
1334         if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
1335                 && pkg.applicationInfo.targetSdkVersion
1336                         >= android.os.Build.VERSION_CODES.DONUT)) {
1337             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
1338         }
1339         if (supportsNormalScreens != 0) {
1340             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
1341         }
1342         if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
1343                 && pkg.applicationInfo.targetSdkVersion
1344                         >= android.os.Build.VERSION_CODES.DONUT)) {
1345             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
1346         }
1347         if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
1348                 && pkg.applicationInfo.targetSdkVersion
1349                         >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
1350             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
1351         }
1352         if (resizeable < 0 || (resizeable > 0
1353                 && pkg.applicationInfo.targetSdkVersion
1354                         >= android.os.Build.VERSION_CODES.DONUT)) {
1355             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
1356         }
1357         if (anyDensity < 0 || (anyDensity > 0
1358                 && pkg.applicationInfo.targetSdkVersion
1359                         >= android.os.Build.VERSION_CODES.DONUT)) {
1360             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
1361         }
1362 
1363         return pkg;
1364     }
1365 
buildClassName(String pkg, CharSequence clsSeq, String[] outError)1366     private static String buildClassName(String pkg, CharSequence clsSeq,
1367             String[] outError) {
1368         if (clsSeq == null || clsSeq.length() <= 0) {
1369             outError[0] = "Empty class name in package " + pkg;
1370             return null;
1371         }
1372         String cls = clsSeq.toString();
1373         char c = cls.charAt(0);
1374         if (c == '.') {
1375             return (pkg + cls).intern();
1376         }
1377         if (cls.indexOf('.') < 0) {
1378             StringBuilder b = new StringBuilder(pkg);
1379             b.append('.');
1380             b.append(cls);
1381             return b.toString().intern();
1382         }
1383         if (c >= 'a' && c <= 'z') {
1384             return cls.intern();
1385         }
1386         outError[0] = "Bad class name " + cls + " in package " + pkg;
1387         return null;
1388     }
1389 
buildCompoundName(String pkg, CharSequence procSeq, String type, String[] outError)1390     private static String buildCompoundName(String pkg,
1391             CharSequence procSeq, String type, String[] outError) {
1392         String proc = procSeq.toString();
1393         char c = proc.charAt(0);
1394         if (pkg != null && c == ':') {
1395             if (proc.length() < 2) {
1396                 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
1397                         + ": must be at least two characters";
1398                 return null;
1399             }
1400             String subName = proc.substring(1);
1401             String nameError = validateName(subName, false);
1402             if (nameError != null) {
1403                 outError[0] = "Invalid " + type + " name " + proc + " in package "
1404                         + pkg + ": " + nameError;
1405                 return null;
1406             }
1407             return (pkg + proc).intern();
1408         }
1409         String nameError = validateName(proc, true);
1410         if (nameError != null && !"system".equals(proc)) {
1411             outError[0] = "Invalid " + type + " name " + proc + " in package "
1412                     + pkg + ": " + nameError;
1413             return null;
1414         }
1415         return proc.intern();
1416     }
1417 
buildProcessName(String pkg, String defProc, CharSequence procSeq, int flags, String[] separateProcesses, String[] outError)1418     private static String buildProcessName(String pkg, String defProc,
1419             CharSequence procSeq, int flags, String[] separateProcesses,
1420             String[] outError) {
1421         if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
1422             return defProc != null ? defProc : pkg;
1423         }
1424         if (separateProcesses != null) {
1425             for (int i=separateProcesses.length-1; i>=0; i--) {
1426                 String sp = separateProcesses[i];
1427                 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
1428                     return pkg;
1429                 }
1430             }
1431         }
1432         if (procSeq == null || procSeq.length() <= 0) {
1433             return defProc;
1434         }
1435         return buildCompoundName(pkg, procSeq, "process", outError);
1436     }
1437 
buildTaskAffinityName(String pkg, String defProc, CharSequence procSeq, String[] outError)1438     private static String buildTaskAffinityName(String pkg, String defProc,
1439             CharSequence procSeq, String[] outError) {
1440         if (procSeq == null) {
1441             return defProc;
1442         }
1443         if (procSeq.length() <= 0) {
1444             return null;
1445         }
1446         return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
1447     }
1448 
parsePermissionGroup(Package owner, int flags, Resources res, XmlPullParser parser, AttributeSet attrs, String[] outError)1449     private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res,
1450             XmlPullParser parser, AttributeSet attrs, String[] outError)
1451         throws XmlPullParserException, IOException {
1452         PermissionGroup perm = new PermissionGroup(owner);
1453 
1454         TypedArray sa = res.obtainAttributes(attrs,
1455                 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
1456 
1457         if (!parsePackageItemInfo(owner, perm.info, outError,
1458                 "<permission-group>", sa,
1459                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
1460                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
1461                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
1462                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo)) {
1463             sa.recycle();
1464             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1465             return null;
1466         }
1467 
1468         perm.info.descriptionRes = sa.getResourceId(
1469                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
1470                 0);
1471         perm.info.flags = 0;
1472         perm.info.priority = sa.getInt(
1473                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
1474         if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
1475             perm.info.priority = 0;
1476         }
1477 
1478         sa.recycle();
1479 
1480         if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm,
1481                 outError)) {
1482             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1483             return null;
1484         }
1485 
1486         owner.permissionGroups.add(perm);
1487 
1488         return perm;
1489     }
1490 
parsePermission(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs, String[] outError)1491     private Permission parsePermission(Package owner, Resources res,
1492             XmlPullParser parser, AttributeSet attrs, String[] outError)
1493         throws XmlPullParserException, IOException {
1494         Permission perm = new Permission(owner);
1495 
1496         TypedArray sa = res.obtainAttributes(attrs,
1497                 com.android.internal.R.styleable.AndroidManifestPermission);
1498 
1499         if (!parsePackageItemInfo(owner, perm.info, outError,
1500                 "<permission>", sa,
1501                 com.android.internal.R.styleable.AndroidManifestPermission_name,
1502                 com.android.internal.R.styleable.AndroidManifestPermission_label,
1503                 com.android.internal.R.styleable.AndroidManifestPermission_icon,
1504                 com.android.internal.R.styleable.AndroidManifestPermission_logo)) {
1505             sa.recycle();
1506             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1507             return null;
1508         }
1509 
1510         // Note: don't allow this value to be a reference to a resource
1511         // that may change.
1512         perm.info.group = sa.getNonResourceString(
1513                 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
1514         if (perm.info.group != null) {
1515             perm.info.group = perm.info.group.intern();
1516         }
1517 
1518         perm.info.descriptionRes = sa.getResourceId(
1519                 com.android.internal.R.styleable.AndroidManifestPermission_description,
1520                 0);
1521 
1522         perm.info.protectionLevel = sa.getInt(
1523                 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
1524                 PermissionInfo.PROTECTION_NORMAL);
1525 
1526         sa.recycle();
1527 
1528         if (perm.info.protectionLevel == -1) {
1529             outError[0] = "<permission> does not specify protectionLevel";
1530             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1531             return null;
1532         }
1533 
1534         perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
1535 
1536         if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
1537             if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
1538                     PermissionInfo.PROTECTION_SIGNATURE) {
1539                 outError[0] = "<permission>  protectionLevel specifies a flag but is "
1540                         + "not based on signature type";
1541                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1542                 return null;
1543             }
1544         }
1545 
1546         if (!parseAllMetaData(res, parser, attrs, "<permission>", perm,
1547                 outError)) {
1548             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1549             return null;
1550         }
1551 
1552         owner.permissions.add(perm);
1553 
1554         return perm;
1555     }
1556 
parsePermissionTree(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs, String[] outError)1557     private Permission parsePermissionTree(Package owner, Resources res,
1558             XmlPullParser parser, AttributeSet attrs, String[] outError)
1559         throws XmlPullParserException, IOException {
1560         Permission perm = new Permission(owner);
1561 
1562         TypedArray sa = res.obtainAttributes(attrs,
1563                 com.android.internal.R.styleable.AndroidManifestPermissionTree);
1564 
1565         if (!parsePackageItemInfo(owner, perm.info, outError,
1566                 "<permission-tree>", sa,
1567                 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
1568                 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
1569                 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
1570                 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo)) {
1571             sa.recycle();
1572             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1573             return null;
1574         }
1575 
1576         sa.recycle();
1577 
1578         int index = perm.info.name.indexOf('.');
1579         if (index > 0) {
1580             index = perm.info.name.indexOf('.', index+1);
1581         }
1582         if (index < 0) {
1583             outError[0] = "<permission-tree> name has less than three segments: "
1584                 + perm.info.name;
1585             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1586             return null;
1587         }
1588 
1589         perm.info.descriptionRes = 0;
1590         perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
1591         perm.tree = true;
1592 
1593         if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm,
1594                 outError)) {
1595             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1596             return null;
1597         }
1598 
1599         owner.permissions.add(perm);
1600 
1601         return perm;
1602     }
1603 
parseInstrumentation(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs, String[] outError)1604     private Instrumentation parseInstrumentation(Package owner, Resources res,
1605             XmlPullParser parser, AttributeSet attrs, String[] outError)
1606         throws XmlPullParserException, IOException {
1607         TypedArray sa = res.obtainAttributes(attrs,
1608                 com.android.internal.R.styleable.AndroidManifestInstrumentation);
1609 
1610         if (mParseInstrumentationArgs == null) {
1611             mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
1612                     com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
1613                     com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
1614                     com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
1615                     com.android.internal.R.styleable.AndroidManifestInstrumentation_logo);
1616             mParseInstrumentationArgs.tag = "<instrumentation>";
1617         }
1618 
1619         mParseInstrumentationArgs.sa = sa;
1620 
1621         Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
1622                 new InstrumentationInfo());
1623         if (outError[0] != null) {
1624             sa.recycle();
1625             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1626             return null;
1627         }
1628 
1629         String str;
1630         // Note: don't allow this value to be a reference to a resource
1631         // that may change.
1632         str = sa.getNonResourceString(
1633                 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
1634         a.info.targetPackage = str != null ? str.intern() : null;
1635 
1636         a.info.handleProfiling = sa.getBoolean(
1637                 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
1638                 false);
1639 
1640         a.info.functionalTest = sa.getBoolean(
1641                 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
1642                 false);
1643 
1644         sa.recycle();
1645 
1646         if (a.info.targetPackage == null) {
1647             outError[0] = "<instrumentation> does not specify targetPackage";
1648             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1649             return null;
1650         }
1651 
1652         if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a,
1653                 outError)) {
1654             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1655             return null;
1656         }
1657 
1658         owner.instrumentation.add(a);
1659 
1660         return a;
1661     }
1662 
parseApplication(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)1663     private boolean parseApplication(Package owner, Resources res,
1664             XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
1665         throws XmlPullParserException, IOException {
1666         final ApplicationInfo ai = owner.applicationInfo;
1667         final String pkgName = owner.applicationInfo.packageName;
1668 
1669         TypedArray sa = res.obtainAttributes(attrs,
1670                 com.android.internal.R.styleable.AndroidManifestApplication);
1671 
1672         String name = sa.getNonConfigurationString(
1673                 com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
1674         if (name != null) {
1675             ai.className = buildClassName(pkgName, name, outError);
1676             if (ai.className == null) {
1677                 sa.recycle();
1678                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1679                 return false;
1680             }
1681         }
1682 
1683         String manageSpaceActivity = sa.getNonConfigurationString(
1684                 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, 0);
1685         if (manageSpaceActivity != null) {
1686             ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
1687                     outError);
1688         }
1689 
1690         boolean allowBackup = sa.getBoolean(
1691                 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
1692         if (allowBackup) {
1693             ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
1694 
1695             // backupAgent, killAfterRestore, and restoreAnyVersion are only relevant
1696             // if backup is possible for the given application.
1697             String backupAgent = sa.getNonConfigurationString(
1698                     com.android.internal.R.styleable.AndroidManifestApplication_backupAgent, 0);
1699             if (backupAgent != null) {
1700                 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
1701                 if (DEBUG_BACKUP) {
1702                     Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
1703                             + " from " + pkgName + "+" + backupAgent);
1704                 }
1705 
1706                 if (sa.getBoolean(
1707                         com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
1708                         true)) {
1709                     ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
1710                 }
1711                 if (sa.getBoolean(
1712                         com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
1713                         false)) {
1714                     ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
1715                 }
1716             }
1717         }
1718 
1719         TypedValue v = sa.peekValue(
1720                 com.android.internal.R.styleable.AndroidManifestApplication_label);
1721         if (v != null && (ai.labelRes=v.resourceId) == 0) {
1722             ai.nonLocalizedLabel = v.coerceToString();
1723         }
1724 
1725         ai.icon = sa.getResourceId(
1726                 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
1727         ai.logo = sa.getResourceId(
1728                 com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
1729         ai.theme = sa.getResourceId(
1730                 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
1731         ai.descriptionRes = sa.getResourceId(
1732                 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
1733 
1734         if ((flags&PARSE_IS_SYSTEM) != 0) {
1735             if (sa.getBoolean(
1736                     com.android.internal.R.styleable.AndroidManifestApplication_persistent,
1737                     false)) {
1738                 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
1739             }
1740         }
1741 
1742         if (sa.getBoolean(
1743                 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
1744                 false)) {
1745             ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
1746         }
1747 
1748         if (sa.getBoolean(
1749                 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
1750                 false)) {
1751             ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
1752         }
1753 
1754         boolean hardwareAccelerated = sa.getBoolean(
1755                 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
1756                 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
1757 
1758         if (sa.getBoolean(
1759                 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
1760                 true)) {
1761             ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
1762         }
1763 
1764         if (sa.getBoolean(
1765                 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
1766                 false)) {
1767             ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
1768         }
1769 
1770         if (sa.getBoolean(
1771                 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
1772                 true)) {
1773             ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
1774         }
1775 
1776         if (sa.getBoolean(
1777                 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
1778                 false)) {
1779             ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
1780         }
1781 
1782         if (sa.getBoolean(
1783                 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
1784                 false)) {
1785             ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
1786         }
1787 
1788         if (sa.getBoolean(
1789                 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
1790                 false /* default is no RTL support*/)) {
1791             ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
1792         }
1793 
1794         String str;
1795         str = sa.getNonConfigurationString(
1796                 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
1797         ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
1798 
1799         if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1800             str = sa.getNonConfigurationString(
1801                     com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity, 0);
1802         } else {
1803             // Some older apps have been seen to use a resource reference
1804             // here that on older builds was ignored (with a warning).  We
1805             // need to continue to do this for them so they don't break.
1806             str = sa.getNonResourceString(
1807                     com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
1808         }
1809         ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
1810                 str, outError);
1811 
1812         if (outError[0] == null) {
1813             CharSequence pname;
1814             if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1815                 pname = sa.getNonConfigurationString(
1816                         com.android.internal.R.styleable.AndroidManifestApplication_process, 0);
1817             } else {
1818                 // Some older apps have been seen to use a resource reference
1819                 // here that on older builds was ignored (with a warning).  We
1820                 // need to continue to do this for them so they don't break.
1821                 pname = sa.getNonResourceString(
1822                         com.android.internal.R.styleable.AndroidManifestApplication_process);
1823             }
1824             ai.processName = buildProcessName(ai.packageName, null, pname,
1825                     flags, mSeparateProcesses, outError);
1826 
1827             ai.enabled = sa.getBoolean(
1828                     com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
1829 
1830             if (false) {
1831                 if (sa.getBoolean(
1832                         com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
1833                         false)) {
1834                     ai.flags |= ApplicationInfo.FLAG_CANT_SAVE_STATE;
1835 
1836                     // A heavy-weight application can not be in a custom process.
1837                     // We can do direct compare because we intern all strings.
1838                     if (ai.processName != null && ai.processName != ai.packageName) {
1839                         outError[0] = "cantSaveState applications can not use custom processes";
1840                     }
1841                 }
1842             }
1843         }
1844 
1845         ai.uiOptions = sa.getInt(
1846                 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
1847 
1848         sa.recycle();
1849 
1850         if (outError[0] != null) {
1851             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1852             return false;
1853         }
1854 
1855         final int innerDepth = parser.getDepth();
1856 
1857         int type;
1858         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1859                 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
1860             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1861                 continue;
1862             }
1863 
1864             String tagName = parser.getName();
1865             if (tagName.equals("activity")) {
1866                 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
1867                         hardwareAccelerated);
1868                 if (a == null) {
1869                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1870                     return false;
1871                 }
1872 
1873                 owner.activities.add(a);
1874 
1875             } else if (tagName.equals("receiver")) {
1876                 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
1877                 if (a == null) {
1878                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1879                     return false;
1880                 }
1881 
1882                 owner.receivers.add(a);
1883 
1884             } else if (tagName.equals("service")) {
1885                 Service s = parseService(owner, res, parser, attrs, flags, outError);
1886                 if (s == null) {
1887                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1888                     return false;
1889                 }
1890 
1891                 owner.services.add(s);
1892 
1893             } else if (tagName.equals("provider")) {
1894                 Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
1895                 if (p == null) {
1896                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1897                     return false;
1898                 }
1899 
1900                 owner.providers.add(p);
1901 
1902             } else if (tagName.equals("activity-alias")) {
1903                 Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
1904                 if (a == null) {
1905                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1906                     return false;
1907                 }
1908 
1909                 owner.activities.add(a);
1910 
1911             } else if (parser.getName().equals("meta-data")) {
1912                 // note: application meta-data is stored off to the side, so it can
1913                 // remain null in the primary copy (we like to avoid extra copies because
1914                 // it can be large)
1915                 if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
1916                         outError)) == null) {
1917                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1918                     return false;
1919                 }
1920 
1921             } else if (tagName.equals("uses-library")) {
1922                 sa = res.obtainAttributes(attrs,
1923                         com.android.internal.R.styleable.AndroidManifestUsesLibrary);
1924 
1925                 // Note: don't allow this value to be a reference to a resource
1926                 // that may change.
1927                 String lname = sa.getNonResourceString(
1928                         com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
1929                 boolean req = sa.getBoolean(
1930                         com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
1931                         true);
1932 
1933                 sa.recycle();
1934 
1935                 if (lname != null) {
1936                     if (req) {
1937                         if (owner.usesLibraries == null) {
1938                             owner.usesLibraries = new ArrayList<String>();
1939                         }
1940                         if (!owner.usesLibraries.contains(lname)) {
1941                             owner.usesLibraries.add(lname.intern());
1942                         }
1943                     } else {
1944                         if (owner.usesOptionalLibraries == null) {
1945                             owner.usesOptionalLibraries = new ArrayList<String>();
1946                         }
1947                         if (!owner.usesOptionalLibraries.contains(lname)) {
1948                             owner.usesOptionalLibraries.add(lname.intern());
1949                         }
1950                     }
1951                 }
1952 
1953                 XmlUtils.skipCurrentTag(parser);
1954 
1955             } else if (tagName.equals("uses-package")) {
1956                 // Dependencies for app installers; we don't currently try to
1957                 // enforce this.
1958                 XmlUtils.skipCurrentTag(parser);
1959 
1960             } else {
1961                 if (!RIGID_PARSER) {
1962                     Slog.w(TAG, "Unknown element under <application>: " + tagName
1963                             + " at " + mArchiveSourcePath + " "
1964                             + parser.getPositionDescription());
1965                     XmlUtils.skipCurrentTag(parser);
1966                     continue;
1967                 } else {
1968                     outError[0] = "Bad element under <application>: " + tagName;
1969                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1970                     return false;
1971                 }
1972             }
1973         }
1974 
1975         return true;
1976     }
1977 
parsePackageItemInfo(Package owner, PackageItemInfo outInfo, String[] outError, String tag, TypedArray sa, int nameRes, int labelRes, int iconRes, int logoRes)1978     private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
1979             String[] outError, String tag, TypedArray sa,
1980             int nameRes, int labelRes, int iconRes, int logoRes) {
1981         String name = sa.getNonConfigurationString(nameRes, 0);
1982         if (name == null) {
1983             outError[0] = tag + " does not specify android:name";
1984             return false;
1985         }
1986 
1987         outInfo.name
1988             = buildClassName(owner.applicationInfo.packageName, name, outError);
1989         if (outInfo.name == null) {
1990             return false;
1991         }
1992 
1993         int iconVal = sa.getResourceId(iconRes, 0);
1994         if (iconVal != 0) {
1995             outInfo.icon = iconVal;
1996             outInfo.nonLocalizedLabel = null;
1997         }
1998 
1999         int logoVal = sa.getResourceId(logoRes, 0);
2000         if (logoVal != 0) {
2001             outInfo.logo = logoVal;
2002         }
2003 
2004         TypedValue v = sa.peekValue(labelRes);
2005         if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
2006             outInfo.nonLocalizedLabel = v.coerceToString();
2007         }
2008 
2009         outInfo.packageName = owner.packageName;
2010 
2011         return true;
2012     }
2013 
parseActivity(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs, int flags, String[] outError, boolean receiver, boolean hardwareAccelerated)2014     private Activity parseActivity(Package owner, Resources res,
2015             XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
2016             boolean receiver, boolean hardwareAccelerated)
2017             throws XmlPullParserException, IOException {
2018         TypedArray sa = res.obtainAttributes(attrs,
2019                 com.android.internal.R.styleable.AndroidManifestActivity);
2020 
2021         if (mParseActivityArgs == null) {
2022             mParseActivityArgs = new ParseComponentArgs(owner, outError,
2023                     com.android.internal.R.styleable.AndroidManifestActivity_name,
2024                     com.android.internal.R.styleable.AndroidManifestActivity_label,
2025                     com.android.internal.R.styleable.AndroidManifestActivity_icon,
2026                     com.android.internal.R.styleable.AndroidManifestActivity_logo,
2027                     mSeparateProcesses,
2028                     com.android.internal.R.styleable.AndroidManifestActivity_process,
2029                     com.android.internal.R.styleable.AndroidManifestActivity_description,
2030                     com.android.internal.R.styleable.AndroidManifestActivity_enabled);
2031         }
2032 
2033         mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
2034         mParseActivityArgs.sa = sa;
2035         mParseActivityArgs.flags = flags;
2036 
2037         Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
2038         if (outError[0] != null) {
2039             sa.recycle();
2040             return null;
2041         }
2042 
2043         final boolean setExported = sa.hasValue(
2044                 com.android.internal.R.styleable.AndroidManifestActivity_exported);
2045         if (setExported) {
2046             a.info.exported = sa.getBoolean(
2047                     com.android.internal.R.styleable.AndroidManifestActivity_exported, false);
2048         }
2049 
2050         a.info.theme = sa.getResourceId(
2051                 com.android.internal.R.styleable.AndroidManifestActivity_theme, 0);
2052 
2053         a.info.uiOptions = sa.getInt(
2054                 com.android.internal.R.styleable.AndroidManifestActivity_uiOptions,
2055                 a.info.applicationInfo.uiOptions);
2056 
2057         String parentName = sa.getNonConfigurationString(
2058                 com.android.internal.R.styleable.AndroidManifestActivity_parentActivityName, 0);
2059         if (parentName != null) {
2060             String parentClassName = buildClassName(a.info.packageName, parentName, outError);
2061             if (outError[0] == null) {
2062                 a.info.parentActivityName = parentClassName;
2063             } else {
2064                 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
2065                         parentName);
2066                 outError[0] = null;
2067             }
2068         }
2069 
2070         String str;
2071         str = sa.getNonConfigurationString(
2072                 com.android.internal.R.styleable.AndroidManifestActivity_permission, 0);
2073         if (str == null) {
2074             a.info.permission = owner.applicationInfo.permission;
2075         } else {
2076             a.info.permission = str.length() > 0 ? str.toString().intern() : null;
2077         }
2078 
2079         str = sa.getNonConfigurationString(
2080                 com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity, 0);
2081         a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
2082                 owner.applicationInfo.taskAffinity, str, outError);
2083 
2084         a.info.flags = 0;
2085         if (sa.getBoolean(
2086                 com.android.internal.R.styleable.AndroidManifestActivity_multiprocess,
2087                 false)) {
2088             a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
2089         }
2090 
2091         if (sa.getBoolean(
2092                 com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch,
2093                 false)) {
2094             a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
2095         }
2096 
2097         if (sa.getBoolean(
2098                 com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch,
2099                 false)) {
2100             a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
2101         }
2102 
2103         if (sa.getBoolean(
2104                 com.android.internal.R.styleable.AndroidManifestActivity_noHistory,
2105                 false)) {
2106             a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
2107         }
2108 
2109         if (sa.getBoolean(
2110                 com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState,
2111                 false)) {
2112             a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
2113         }
2114 
2115         if (sa.getBoolean(
2116                 com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded,
2117                 false)) {
2118             a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
2119         }
2120 
2121         if (sa.getBoolean(
2122                 com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents,
2123                 false)) {
2124             a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2125         }
2126 
2127         if (sa.getBoolean(
2128                 com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting,
2129                 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
2130             a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
2131         }
2132 
2133         if (sa.getBoolean(
2134                 com.android.internal.R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs,
2135                 false)) {
2136             a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
2137         }
2138 
2139         if (sa.getBoolean(
2140                 com.android.internal.R.styleable.AndroidManifestActivity_immersive,
2141                 false)) {
2142             a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
2143         }
2144 
2145         if (!receiver) {
2146             if (sa.getBoolean(
2147                     com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
2148                     hardwareAccelerated)) {
2149                 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
2150             }
2151 
2152             a.info.launchMode = sa.getInt(
2153                     com.android.internal.R.styleable.AndroidManifestActivity_launchMode,
2154                     ActivityInfo.LAUNCH_MULTIPLE);
2155             a.info.screenOrientation = sa.getInt(
2156                     com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation,
2157                     ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
2158             a.info.configChanges = sa.getInt(
2159                     com.android.internal.R.styleable.AndroidManifestActivity_configChanges,
2160                     0);
2161             a.info.softInputMode = sa.getInt(
2162                     com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
2163                     0);
2164         } else {
2165             a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2166             a.info.configChanges = 0;
2167         }
2168 
2169         sa.recycle();
2170 
2171         if (receiver && (owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
2172             // A heavy-weight application can not have receives in its main process
2173             // We can do direct compare because we intern all strings.
2174             if (a.info.processName == owner.packageName) {
2175                 outError[0] = "Heavy-weight applications can not have receivers in main process";
2176             }
2177         }
2178 
2179         if (outError[0] != null) {
2180             return null;
2181         }
2182 
2183         int outerDepth = parser.getDepth();
2184         int type;
2185         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2186                && (type != XmlPullParser.END_TAG
2187                        || parser.getDepth() > outerDepth)) {
2188             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2189                 continue;
2190             }
2191 
2192             if (parser.getName().equals("intent-filter")) {
2193                 ActivityIntentInfo intent = new ActivityIntentInfo(a);
2194                 if (!parseIntent(res, parser, attrs, flags, intent, outError, !receiver)) {
2195                     return null;
2196                 }
2197                 if (intent.countActions() == 0) {
2198                     Slog.w(TAG, "No actions in intent filter at "
2199                             + mArchiveSourcePath + " "
2200                             + parser.getPositionDescription());
2201                 } else {
2202                     a.intents.add(intent);
2203                 }
2204             } else if (parser.getName().equals("meta-data")) {
2205                 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
2206                         outError)) == null) {
2207                     return null;
2208                 }
2209             } else {
2210                 if (!RIGID_PARSER) {
2211                     Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
2212                     if (receiver) {
2213                         Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
2214                                 + " at " + mArchiveSourcePath + " "
2215                                 + parser.getPositionDescription());
2216                     } else {
2217                         Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
2218                                 + " at " + mArchiveSourcePath + " "
2219                                 + parser.getPositionDescription());
2220                     }
2221                     XmlUtils.skipCurrentTag(parser);
2222                     continue;
2223                 } else {
2224                     if (receiver) {
2225                         outError[0] = "Bad element under <receiver>: " + parser.getName();
2226                     } else {
2227                         outError[0] = "Bad element under <activity>: " + parser.getName();
2228                     }
2229                     return null;
2230                 }
2231             }
2232         }
2233 
2234         if (!setExported) {
2235             a.info.exported = a.intents.size() > 0;
2236         }
2237 
2238         return a;
2239     }
2240 
parseActivityAlias(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)2241     private Activity parseActivityAlias(Package owner, Resources res,
2242             XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2243             throws XmlPullParserException, IOException {
2244         TypedArray sa = res.obtainAttributes(attrs,
2245                 com.android.internal.R.styleable.AndroidManifestActivityAlias);
2246 
2247         String targetActivity = sa.getNonConfigurationString(
2248                 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity, 0);
2249         if (targetActivity == null) {
2250             outError[0] = "<activity-alias> does not specify android:targetActivity";
2251             sa.recycle();
2252             return null;
2253         }
2254 
2255         targetActivity = buildClassName(owner.applicationInfo.packageName,
2256                 targetActivity, outError);
2257         if (targetActivity == null) {
2258             sa.recycle();
2259             return null;
2260         }
2261 
2262         if (mParseActivityAliasArgs == null) {
2263             mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
2264                     com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
2265                     com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
2266                     com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
2267                     com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
2268                     mSeparateProcesses,
2269                     0,
2270                     com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
2271                     com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
2272             mParseActivityAliasArgs.tag = "<activity-alias>";
2273         }
2274 
2275         mParseActivityAliasArgs.sa = sa;
2276         mParseActivityAliasArgs.flags = flags;
2277 
2278         Activity target = null;
2279 
2280         final int NA = owner.activities.size();
2281         for (int i=0; i<NA; i++) {
2282             Activity t = owner.activities.get(i);
2283             if (targetActivity.equals(t.info.name)) {
2284                 target = t;
2285                 break;
2286             }
2287         }
2288 
2289         if (target == null) {
2290             outError[0] = "<activity-alias> target activity " + targetActivity
2291                     + " not found in manifest";
2292             sa.recycle();
2293             return null;
2294         }
2295 
2296         ActivityInfo info = new ActivityInfo();
2297         info.targetActivity = targetActivity;
2298         info.configChanges = target.info.configChanges;
2299         info.flags = target.info.flags;
2300         info.icon = target.info.icon;
2301         info.logo = target.info.logo;
2302         info.labelRes = target.info.labelRes;
2303         info.nonLocalizedLabel = target.info.nonLocalizedLabel;
2304         info.launchMode = target.info.launchMode;
2305         info.processName = target.info.processName;
2306         if (info.descriptionRes == 0) {
2307             info.descriptionRes = target.info.descriptionRes;
2308         }
2309         info.screenOrientation = target.info.screenOrientation;
2310         info.taskAffinity = target.info.taskAffinity;
2311         info.theme = target.info.theme;
2312         info.softInputMode = target.info.softInputMode;
2313         info.uiOptions = target.info.uiOptions;
2314         info.parentActivityName = target.info.parentActivityName;
2315 
2316         Activity a = new Activity(mParseActivityAliasArgs, info);
2317         if (outError[0] != null) {
2318             sa.recycle();
2319             return null;
2320         }
2321 
2322         final boolean setExported = sa.hasValue(
2323                 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
2324         if (setExported) {
2325             a.info.exported = sa.getBoolean(
2326                     com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
2327         }
2328 
2329         String str;
2330         str = sa.getNonConfigurationString(
2331                 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
2332         if (str != null) {
2333             a.info.permission = str.length() > 0 ? str.toString().intern() : null;
2334         }
2335 
2336         String parentName = sa.getNonConfigurationString(
2337                 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
2338                 0);
2339         if (parentName != null) {
2340             String parentClassName = buildClassName(a.info.packageName, parentName, outError);
2341             if (outError[0] == null) {
2342                 a.info.parentActivityName = parentClassName;
2343             } else {
2344                 Log.e(TAG, "Activity alias " + a.info.name +
2345                         " specified invalid parentActivityName " + parentName);
2346                 outError[0] = null;
2347             }
2348         }
2349 
2350         sa.recycle();
2351 
2352         if (outError[0] != null) {
2353             return null;
2354         }
2355 
2356         int outerDepth = parser.getDepth();
2357         int type;
2358         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2359                && (type != XmlPullParser.END_TAG
2360                        || parser.getDepth() > outerDepth)) {
2361             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2362                 continue;
2363             }
2364 
2365             if (parser.getName().equals("intent-filter")) {
2366                 ActivityIntentInfo intent = new ActivityIntentInfo(a);
2367                 if (!parseIntent(res, parser, attrs, flags, intent, outError, true)) {
2368                     return null;
2369                 }
2370                 if (intent.countActions() == 0) {
2371                     Slog.w(TAG, "No actions in intent filter at "
2372                             + mArchiveSourcePath + " "
2373                             + parser.getPositionDescription());
2374                 } else {
2375                     a.intents.add(intent);
2376                 }
2377             } else if (parser.getName().equals("meta-data")) {
2378                 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
2379                         outError)) == null) {
2380                     return null;
2381                 }
2382             } else {
2383                 if (!RIGID_PARSER) {
2384                     Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
2385                             + " at " + mArchiveSourcePath + " "
2386                             + parser.getPositionDescription());
2387                     XmlUtils.skipCurrentTag(parser);
2388                     continue;
2389                 } else {
2390                     outError[0] = "Bad element under <activity-alias>: " + parser.getName();
2391                     return null;
2392                 }
2393             }
2394         }
2395 
2396         if (!setExported) {
2397             a.info.exported = a.intents.size() > 0;
2398         }
2399 
2400         return a;
2401     }
2402 
parseProvider(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)2403     private Provider parseProvider(Package owner, Resources res,
2404             XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2405             throws XmlPullParserException, IOException {
2406         TypedArray sa = res.obtainAttributes(attrs,
2407                 com.android.internal.R.styleable.AndroidManifestProvider);
2408 
2409         if (mParseProviderArgs == null) {
2410             mParseProviderArgs = new ParseComponentArgs(owner, outError,
2411                     com.android.internal.R.styleable.AndroidManifestProvider_name,
2412                     com.android.internal.R.styleable.AndroidManifestProvider_label,
2413                     com.android.internal.R.styleable.AndroidManifestProvider_icon,
2414                     com.android.internal.R.styleable.AndroidManifestProvider_logo,
2415                     mSeparateProcesses,
2416                     com.android.internal.R.styleable.AndroidManifestProvider_process,
2417                     com.android.internal.R.styleable.AndroidManifestProvider_description,
2418                     com.android.internal.R.styleable.AndroidManifestProvider_enabled);
2419             mParseProviderArgs.tag = "<provider>";
2420         }
2421 
2422         mParseProviderArgs.sa = sa;
2423         mParseProviderArgs.flags = flags;
2424 
2425         Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
2426         if (outError[0] != null) {
2427             sa.recycle();
2428             return null;
2429         }
2430 
2431         p.info.exported = sa.getBoolean(
2432                 com.android.internal.R.styleable.AndroidManifestProvider_exported, true);
2433 
2434         String cpname = sa.getNonConfigurationString(
2435                 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
2436 
2437         p.info.isSyncable = sa.getBoolean(
2438                 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
2439                 false);
2440 
2441         String permission = sa.getNonConfigurationString(
2442                 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
2443         String str = sa.getNonConfigurationString(
2444                 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
2445         if (str == null) {
2446             str = permission;
2447         }
2448         if (str == null) {
2449             p.info.readPermission = owner.applicationInfo.permission;
2450         } else {
2451             p.info.readPermission =
2452                 str.length() > 0 ? str.toString().intern() : null;
2453         }
2454         str = sa.getNonConfigurationString(
2455                 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
2456         if (str == null) {
2457             str = permission;
2458         }
2459         if (str == null) {
2460             p.info.writePermission = owner.applicationInfo.permission;
2461         } else {
2462             p.info.writePermission =
2463                 str.length() > 0 ? str.toString().intern() : null;
2464         }
2465 
2466         p.info.grantUriPermissions = sa.getBoolean(
2467                 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
2468                 false);
2469 
2470         p.info.multiprocess = sa.getBoolean(
2471                 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
2472                 false);
2473 
2474         p.info.initOrder = sa.getInt(
2475                 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
2476                 0);
2477 
2478         sa.recycle();
2479 
2480         if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
2481             // A heavy-weight application can not have providers in its main process
2482             // We can do direct compare because we intern all strings.
2483             if (p.info.processName == owner.packageName) {
2484                 outError[0] = "Heavy-weight applications can not have providers in main process";
2485                 return null;
2486             }
2487         }
2488 
2489         if (cpname == null) {
2490             outError[0] = "<provider> does not incude authorities attribute";
2491             return null;
2492         }
2493         p.info.authority = cpname.intern();
2494 
2495         if (!parseProviderTags(res, parser, attrs, p, outError)) {
2496             return null;
2497         }
2498 
2499         return p;
2500     }
2501 
parseProviderTags(Resources res, XmlPullParser parser, AttributeSet attrs, Provider outInfo, String[] outError)2502     private boolean parseProviderTags(Resources res,
2503             XmlPullParser parser, AttributeSet attrs,
2504             Provider outInfo, String[] outError)
2505             throws XmlPullParserException, IOException {
2506         int outerDepth = parser.getDepth();
2507         int type;
2508         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2509                && (type != XmlPullParser.END_TAG
2510                        || parser.getDepth() > outerDepth)) {
2511             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2512                 continue;
2513             }
2514 
2515             if (parser.getName().equals("meta-data")) {
2516                 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
2517                         outInfo.metaData, outError)) == null) {
2518                     return false;
2519                 }
2520 
2521             } else if (parser.getName().equals("grant-uri-permission")) {
2522                 TypedArray sa = res.obtainAttributes(attrs,
2523                         com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
2524 
2525                 PatternMatcher pa = null;
2526 
2527                 String str = sa.getNonConfigurationString(
2528                         com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
2529                 if (str != null) {
2530                     pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
2531                 }
2532 
2533                 str = sa.getNonConfigurationString(
2534                         com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
2535                 if (str != null) {
2536                     pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
2537                 }
2538 
2539                 str = sa.getNonConfigurationString(
2540                         com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
2541                 if (str != null) {
2542                     pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
2543                 }
2544 
2545                 sa.recycle();
2546 
2547                 if (pa != null) {
2548                     if (outInfo.info.uriPermissionPatterns == null) {
2549                         outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
2550                         outInfo.info.uriPermissionPatterns[0] = pa;
2551                     } else {
2552                         final int N = outInfo.info.uriPermissionPatterns.length;
2553                         PatternMatcher[] newp = new PatternMatcher[N+1];
2554                         System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
2555                         newp[N] = pa;
2556                         outInfo.info.uriPermissionPatterns = newp;
2557                     }
2558                     outInfo.info.grantUriPermissions = true;
2559                 } else {
2560                     if (!RIGID_PARSER) {
2561                         Slog.w(TAG, "Unknown element under <path-permission>: "
2562                                 + parser.getName() + " at " + mArchiveSourcePath + " "
2563                                 + parser.getPositionDescription());
2564                         XmlUtils.skipCurrentTag(parser);
2565                         continue;
2566                     } else {
2567                         outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
2568                         return false;
2569                     }
2570                 }
2571                 XmlUtils.skipCurrentTag(parser);
2572 
2573             } else if (parser.getName().equals("path-permission")) {
2574                 TypedArray sa = res.obtainAttributes(attrs,
2575                         com.android.internal.R.styleable.AndroidManifestPathPermission);
2576 
2577                 PathPermission pa = null;
2578 
2579                 String permission = sa.getNonConfigurationString(
2580                         com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
2581                 String readPermission = sa.getNonConfigurationString(
2582                         com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
2583                 if (readPermission == null) {
2584                     readPermission = permission;
2585                 }
2586                 String writePermission = sa.getNonConfigurationString(
2587                         com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
2588                 if (writePermission == null) {
2589                     writePermission = permission;
2590                 }
2591 
2592                 boolean havePerm = false;
2593                 if (readPermission != null) {
2594                     readPermission = readPermission.intern();
2595                     havePerm = true;
2596                 }
2597                 if (writePermission != null) {
2598                     writePermission = writePermission.intern();
2599                     havePerm = true;
2600                 }
2601 
2602                 if (!havePerm) {
2603                     if (!RIGID_PARSER) {
2604                         Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
2605                                 + parser.getName() + " at " + mArchiveSourcePath + " "
2606                                 + parser.getPositionDescription());
2607                         XmlUtils.skipCurrentTag(parser);
2608                         continue;
2609                     } else {
2610                         outError[0] = "No readPermission or writePermssion for <path-permission>";
2611                         return false;
2612                     }
2613                 }
2614 
2615                 String path = sa.getNonConfigurationString(
2616                         com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
2617                 if (path != null) {
2618                     pa = new PathPermission(path,
2619                             PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
2620                 }
2621 
2622                 path = sa.getNonConfigurationString(
2623                         com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
2624                 if (path != null) {
2625                     pa = new PathPermission(path,
2626                             PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
2627                 }
2628 
2629                 path = sa.getNonConfigurationString(
2630                         com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
2631                 if (path != null) {
2632                     pa = new PathPermission(path,
2633                             PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
2634                 }
2635 
2636                 sa.recycle();
2637 
2638                 if (pa != null) {
2639                     if (outInfo.info.pathPermissions == null) {
2640                         outInfo.info.pathPermissions = new PathPermission[1];
2641                         outInfo.info.pathPermissions[0] = pa;
2642                     } else {
2643                         final int N = outInfo.info.pathPermissions.length;
2644                         PathPermission[] newp = new PathPermission[N+1];
2645                         System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
2646                         newp[N] = pa;
2647                         outInfo.info.pathPermissions = newp;
2648                     }
2649                 } else {
2650                     if (!RIGID_PARSER) {
2651                         Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
2652                                 + parser.getName() + " at " + mArchiveSourcePath + " "
2653                                 + parser.getPositionDescription());
2654                         XmlUtils.skipCurrentTag(parser);
2655                         continue;
2656                     }
2657                     outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
2658                     return false;
2659                 }
2660                 XmlUtils.skipCurrentTag(parser);
2661 
2662             } else {
2663                 if (!RIGID_PARSER) {
2664                     Slog.w(TAG, "Unknown element under <provider>: "
2665                             + parser.getName() + " at " + mArchiveSourcePath + " "
2666                             + parser.getPositionDescription());
2667                     XmlUtils.skipCurrentTag(parser);
2668                     continue;
2669                 } else {
2670                     outError[0] = "Bad element under <provider>: " + parser.getName();
2671                     return false;
2672                 }
2673             }
2674         }
2675         return true;
2676     }
2677 
parseService(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)2678     private Service parseService(Package owner, Resources res,
2679             XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2680             throws XmlPullParserException, IOException {
2681         TypedArray sa = res.obtainAttributes(attrs,
2682                 com.android.internal.R.styleable.AndroidManifestService);
2683 
2684         if (mParseServiceArgs == null) {
2685             mParseServiceArgs = new ParseComponentArgs(owner, outError,
2686                     com.android.internal.R.styleable.AndroidManifestService_name,
2687                     com.android.internal.R.styleable.AndroidManifestService_label,
2688                     com.android.internal.R.styleable.AndroidManifestService_icon,
2689                     com.android.internal.R.styleable.AndroidManifestService_logo,
2690                     mSeparateProcesses,
2691                     com.android.internal.R.styleable.AndroidManifestService_process,
2692                     com.android.internal.R.styleable.AndroidManifestService_description,
2693                     com.android.internal.R.styleable.AndroidManifestService_enabled);
2694             mParseServiceArgs.tag = "<service>";
2695         }
2696 
2697         mParseServiceArgs.sa = sa;
2698         mParseServiceArgs.flags = flags;
2699 
2700         Service s = new Service(mParseServiceArgs, new ServiceInfo());
2701         if (outError[0] != null) {
2702             sa.recycle();
2703             return null;
2704         }
2705 
2706         final boolean setExported = sa.hasValue(
2707                 com.android.internal.R.styleable.AndroidManifestService_exported);
2708         if (setExported) {
2709             s.info.exported = sa.getBoolean(
2710                     com.android.internal.R.styleable.AndroidManifestService_exported, false);
2711         }
2712 
2713         String str = sa.getNonConfigurationString(
2714                 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
2715         if (str == null) {
2716             s.info.permission = owner.applicationInfo.permission;
2717         } else {
2718             s.info.permission = str.length() > 0 ? str.toString().intern() : null;
2719         }
2720 
2721         s.info.flags = 0;
2722         if (sa.getBoolean(
2723                 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
2724                 false)) {
2725             s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
2726         }
2727         if (sa.getBoolean(
2728                 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
2729                 false)) {
2730             s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
2731         }
2732 
2733         sa.recycle();
2734 
2735         if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
2736             // A heavy-weight application can not have services in its main process
2737             // We can do direct compare because we intern all strings.
2738             if (s.info.processName == owner.packageName) {
2739                 outError[0] = "Heavy-weight applications can not have services in main process";
2740                 return null;
2741             }
2742         }
2743 
2744         int outerDepth = parser.getDepth();
2745         int type;
2746         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2747                && (type != XmlPullParser.END_TAG
2748                        || parser.getDepth() > outerDepth)) {
2749             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2750                 continue;
2751             }
2752 
2753             if (parser.getName().equals("intent-filter")) {
2754                 ServiceIntentInfo intent = new ServiceIntentInfo(s);
2755                 if (!parseIntent(res, parser, attrs, flags, intent, outError, false)) {
2756                     return null;
2757                 }
2758 
2759                 s.intents.add(intent);
2760             } else if (parser.getName().equals("meta-data")) {
2761                 if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData,
2762                         outError)) == null) {
2763                     return null;
2764                 }
2765             } else {
2766                 if (!RIGID_PARSER) {
2767                     Slog.w(TAG, "Unknown element under <service>: "
2768                             + parser.getName() + " at " + mArchiveSourcePath + " "
2769                             + parser.getPositionDescription());
2770                     XmlUtils.skipCurrentTag(parser);
2771                     continue;
2772                 } else {
2773                     outError[0] = "Bad element under <service>: " + parser.getName();
2774                     return null;
2775                 }
2776             }
2777         }
2778 
2779         if (!setExported) {
2780             s.info.exported = s.intents.size() > 0;
2781         }
2782 
2783         return s;
2784     }
2785 
parseAllMetaData(Resources res, XmlPullParser parser, AttributeSet attrs, String tag, Component outInfo, String[] outError)2786     private boolean parseAllMetaData(Resources res,
2787             XmlPullParser parser, AttributeSet attrs, String tag,
2788             Component outInfo, String[] outError)
2789             throws XmlPullParserException, IOException {
2790         int outerDepth = parser.getDepth();
2791         int type;
2792         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2793                && (type != XmlPullParser.END_TAG
2794                        || parser.getDepth() > outerDepth)) {
2795             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2796                 continue;
2797             }
2798 
2799             if (parser.getName().equals("meta-data")) {
2800                 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
2801                         outInfo.metaData, outError)) == null) {
2802                     return false;
2803                 }
2804             } else {
2805                 if (!RIGID_PARSER) {
2806                     Slog.w(TAG, "Unknown element under " + tag + ": "
2807                             + parser.getName() + " at " + mArchiveSourcePath + " "
2808                             + parser.getPositionDescription());
2809                     XmlUtils.skipCurrentTag(parser);
2810                     continue;
2811                 } else {
2812                     outError[0] = "Bad element under " + tag + ": " + parser.getName();
2813                     return false;
2814                 }
2815             }
2816         }
2817         return true;
2818     }
2819 
parseMetaData(Resources res, XmlPullParser parser, AttributeSet attrs, Bundle data, String[] outError)2820     private Bundle parseMetaData(Resources res,
2821             XmlPullParser parser, AttributeSet attrs,
2822             Bundle data, String[] outError)
2823             throws XmlPullParserException, IOException {
2824 
2825         TypedArray sa = res.obtainAttributes(attrs,
2826                 com.android.internal.R.styleable.AndroidManifestMetaData);
2827 
2828         if (data == null) {
2829             data = new Bundle();
2830         }
2831 
2832         String name = sa.getNonConfigurationString(
2833                 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
2834         if (name == null) {
2835             outError[0] = "<meta-data> requires an android:name attribute";
2836             sa.recycle();
2837             return null;
2838         }
2839 
2840         name = name.intern();
2841 
2842         TypedValue v = sa.peekValue(
2843                 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
2844         if (v != null && v.resourceId != 0) {
2845             //Slog.i(TAG, "Meta data ref " + name + ": " + v);
2846             data.putInt(name, v.resourceId);
2847         } else {
2848             v = sa.peekValue(
2849                     com.android.internal.R.styleable.AndroidManifestMetaData_value);
2850             //Slog.i(TAG, "Meta data " + name + ": " + v);
2851             if (v != null) {
2852                 if (v.type == TypedValue.TYPE_STRING) {
2853                     CharSequence cs = v.coerceToString();
2854                     data.putString(name, cs != null ? cs.toString().intern() : null);
2855                 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
2856                     data.putBoolean(name, v.data != 0);
2857                 } else if (v.type >= TypedValue.TYPE_FIRST_INT
2858                         && v.type <= TypedValue.TYPE_LAST_INT) {
2859                     data.putInt(name, v.data);
2860                 } else if (v.type == TypedValue.TYPE_FLOAT) {
2861                     data.putFloat(name, v.getFloat());
2862                 } else {
2863                     if (!RIGID_PARSER) {
2864                         Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
2865                                 + parser.getName() + " at " + mArchiveSourcePath + " "
2866                                 + parser.getPositionDescription());
2867                     } else {
2868                         outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
2869                         data = null;
2870                     }
2871                 }
2872             } else {
2873                 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
2874                 data = null;
2875             }
2876         }
2877 
2878         sa.recycle();
2879 
2880         XmlUtils.skipCurrentTag(parser);
2881 
2882         return data;
2883     }
2884 
parseVerifier(Resources res, XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)2885     private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
2886             AttributeSet attrs, int flags, String[] outError) throws XmlPullParserException,
2887             IOException {
2888         final TypedArray sa = res.obtainAttributes(attrs,
2889                 com.android.internal.R.styleable.AndroidManifestPackageVerifier);
2890 
2891         final String packageName = sa.getNonResourceString(
2892                 com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
2893 
2894         final String encodedPublicKey = sa.getNonResourceString(
2895                 com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
2896 
2897         sa.recycle();
2898 
2899         if (packageName == null || packageName.length() == 0) {
2900             Slog.i(TAG, "verifier package name was null; skipping");
2901             return null;
2902         } else if (encodedPublicKey == null) {
2903             Slog.i(TAG, "verifier " + packageName + " public key was null; skipping");
2904         }
2905 
2906         EncodedKeySpec keySpec;
2907         try {
2908             final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
2909             keySpec = new X509EncodedKeySpec(encoded);
2910         } catch (IllegalArgumentException e) {
2911             Slog.i(TAG, "Could not parse verifier " + packageName + " public key; invalid Base64");
2912             return null;
2913         }
2914 
2915         /* First try the key as an RSA key. */
2916         try {
2917             final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
2918             final PublicKey publicKey = keyFactory.generatePublic(keySpec);
2919             return new VerifierInfo(packageName, publicKey);
2920         } catch (NoSuchAlgorithmException e) {
2921             Log.wtf(TAG, "Could not parse public key because RSA isn't included in build");
2922             return null;
2923         } catch (InvalidKeySpecException e) {
2924             // Not a RSA public key.
2925         }
2926 
2927         /* Now try it as a DSA key. */
2928         try {
2929             final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
2930             final PublicKey publicKey = keyFactory.generatePublic(keySpec);
2931             return new VerifierInfo(packageName, publicKey);
2932         } catch (NoSuchAlgorithmException e) {
2933             Log.wtf(TAG, "Could not parse public key because DSA isn't included in build");
2934             return null;
2935         } catch (InvalidKeySpecException e) {
2936             // Not a DSA public key.
2937         }
2938 
2939         return null;
2940     }
2941 
2942     private static final String ANDROID_RESOURCES
2943             = "http://schemas.android.com/apk/res/android";
2944 
parseIntent(Resources res, XmlPullParser parser, AttributeSet attrs, int flags, IntentInfo outInfo, String[] outError, boolean isActivity)2945     private boolean parseIntent(Resources res,
2946             XmlPullParser parser, AttributeSet attrs, int flags,
2947             IntentInfo outInfo, String[] outError, boolean isActivity)
2948             throws XmlPullParserException, IOException {
2949 
2950         TypedArray sa = res.obtainAttributes(attrs,
2951                 com.android.internal.R.styleable.AndroidManifestIntentFilter);
2952 
2953         int priority = sa.getInt(
2954                 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
2955         outInfo.setPriority(priority);
2956 
2957         TypedValue v = sa.peekValue(
2958                 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
2959         if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
2960             outInfo.nonLocalizedLabel = v.coerceToString();
2961         }
2962 
2963         outInfo.icon = sa.getResourceId(
2964                 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
2965 
2966         outInfo.logo = sa.getResourceId(
2967                 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
2968 
2969         sa.recycle();
2970 
2971         int outerDepth = parser.getDepth();
2972         int type;
2973         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2974                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2975             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2976                 continue;
2977             }
2978 
2979             String nodeName = parser.getName();
2980             if (nodeName.equals("action")) {
2981                 String value = attrs.getAttributeValue(
2982                         ANDROID_RESOURCES, "name");
2983                 if (value == null || value == "") {
2984                     outError[0] = "No value supplied for <android:name>";
2985                     return false;
2986                 }
2987                 XmlUtils.skipCurrentTag(parser);
2988 
2989                 outInfo.addAction(value);
2990             } else if (nodeName.equals("category")) {
2991                 String value = attrs.getAttributeValue(
2992                         ANDROID_RESOURCES, "name");
2993                 if (value == null || value == "") {
2994                     outError[0] = "No value supplied for <android:name>";
2995                     return false;
2996                 }
2997                 XmlUtils.skipCurrentTag(parser);
2998 
2999                 outInfo.addCategory(value);
3000 
3001             } else if (nodeName.equals("data")) {
3002                 sa = res.obtainAttributes(attrs,
3003                         com.android.internal.R.styleable.AndroidManifestData);
3004 
3005                 String str = sa.getNonConfigurationString(
3006                         com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
3007                 if (str != null) {
3008                     try {
3009                         outInfo.addDataType(str);
3010                     } catch (IntentFilter.MalformedMimeTypeException e) {
3011                         outError[0] = e.toString();
3012                         sa.recycle();
3013                         return false;
3014                     }
3015                 }
3016 
3017                 str = sa.getNonConfigurationString(
3018                         com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
3019                 if (str != null) {
3020                     outInfo.addDataScheme(str);
3021                 }
3022 
3023                 String host = sa.getNonConfigurationString(
3024                         com.android.internal.R.styleable.AndroidManifestData_host, 0);
3025                 String port = sa.getNonConfigurationString(
3026                         com.android.internal.R.styleable.AndroidManifestData_port, 0);
3027                 if (host != null) {
3028                     outInfo.addDataAuthority(host, port);
3029                 }
3030 
3031                 str = sa.getNonConfigurationString(
3032                         com.android.internal.R.styleable.AndroidManifestData_path, 0);
3033                 if (str != null) {
3034                     outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
3035                 }
3036 
3037                 str = sa.getNonConfigurationString(
3038                         com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
3039                 if (str != null) {
3040                     outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
3041                 }
3042 
3043                 str = sa.getNonConfigurationString(
3044                         com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
3045                 if (str != null) {
3046                     outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
3047                 }
3048 
3049                 sa.recycle();
3050                 XmlUtils.skipCurrentTag(parser);
3051             } else if (!RIGID_PARSER) {
3052                 Slog.w(TAG, "Unknown element under <intent-filter>: "
3053                         + parser.getName() + " at " + mArchiveSourcePath + " "
3054                         + parser.getPositionDescription());
3055                 XmlUtils.skipCurrentTag(parser);
3056             } else {
3057                 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
3058                 return false;
3059             }
3060         }
3061 
3062         outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
3063 
3064         if (DEBUG_PARSER) {
3065             final StringBuilder cats = new StringBuilder("Intent d=");
3066             cats.append(outInfo.hasDefault);
3067             cats.append(", cat=");
3068 
3069             final Iterator<String> it = outInfo.categoriesIterator();
3070             if (it != null) {
3071                 while (it.hasNext()) {
3072                     cats.append(' ');
3073                     cats.append(it.next());
3074                 }
3075             }
3076             Slog.d(TAG, cats.toString());
3077         }
3078 
3079         return true;
3080     }
3081 
3082     public final static class Package {
3083         public String packageName;
3084 
3085         // For now we only support one application per package.
3086         public final ApplicationInfo applicationInfo = new ApplicationInfo();
3087 
3088         public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
3089         public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
3090         public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
3091         public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
3092         public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
3093         public final ArrayList<Service> services = new ArrayList<Service>(0);
3094         public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
3095 
3096         public final ArrayList<String> requestedPermissions = new ArrayList<String>();
3097         public final ArrayList<Boolean> requestedPermissionsRequired = new ArrayList<Boolean>();
3098 
3099         public ArrayList<String> protectedBroadcasts;
3100 
3101         public ArrayList<String> usesLibraries = null;
3102         public ArrayList<String> usesOptionalLibraries = null;
3103         public String[] usesLibraryFiles = null;
3104 
3105         public ArrayList<String> mOriginalPackages = null;
3106         public String mRealPackage = null;
3107         public ArrayList<String> mAdoptPermissions = null;
3108 
3109         // We store the application meta-data independently to avoid multiple unwanted references
3110         public Bundle mAppMetaData = null;
3111 
3112         // If this is a 3rd party app, this is the path of the zip file.
3113         public String mPath;
3114 
3115         // The version code declared for this package.
3116         public int mVersionCode;
3117 
3118         // The version name declared for this package.
3119         public String mVersionName;
3120 
3121         // The shared user id that this package wants to use.
3122         public String mSharedUserId;
3123 
3124         // The shared user label that this package wants to use.
3125         public int mSharedUserLabel;
3126 
3127         // Signatures that were read from the package.
3128         public Signature mSignatures[];
3129 
3130         // For use by package manager service for quick lookup of
3131         // preferred up order.
3132         public int mPreferredOrder = 0;
3133 
3134         // For use by the package manager to keep track of the path to the
3135         // file an app came from.
3136         public String mScanPath;
3137 
3138         // For use by package manager to keep track of where it has done dexopt.
3139         public boolean mDidDexOpt;
3140 
3141         // // User set enabled state.
3142         // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
3143         //
3144         // // Whether the package has been stopped.
3145         // public boolean mSetStopped = false;
3146 
3147         // Additional data supplied by callers.
3148         public Object mExtras;
3149 
3150         // Whether an operation is currently pending on this package
3151         public boolean mOperationPending;
3152 
3153         /*
3154          *  Applications hardware preferences
3155          */
3156         public final ArrayList<ConfigurationInfo> configPreferences =
3157                 new ArrayList<ConfigurationInfo>();
3158 
3159         /*
3160          *  Applications requested features
3161          */
3162         public ArrayList<FeatureInfo> reqFeatures = null;
3163 
3164         public int installLocation;
3165 
3166         /**
3167          * Digest suitable for comparing whether this package's manifest is the
3168          * same as another.
3169          */
3170         public ManifestDigest manifestDigest;
3171 
Package(String _name)3172         public Package(String _name) {
3173             packageName = _name;
3174             applicationInfo.packageName = _name;
3175             applicationInfo.uid = -1;
3176         }
3177 
setPackageName(String newName)3178         public void setPackageName(String newName) {
3179             packageName = newName;
3180             applicationInfo.packageName = newName;
3181             for (int i=permissions.size()-1; i>=0; i--) {
3182                 permissions.get(i).setPackageName(newName);
3183             }
3184             for (int i=permissionGroups.size()-1; i>=0; i--) {
3185                 permissionGroups.get(i).setPackageName(newName);
3186             }
3187             for (int i=activities.size()-1; i>=0; i--) {
3188                 activities.get(i).setPackageName(newName);
3189             }
3190             for (int i=receivers.size()-1; i>=0; i--) {
3191                 receivers.get(i).setPackageName(newName);
3192             }
3193             for (int i=providers.size()-1; i>=0; i--) {
3194                 providers.get(i).setPackageName(newName);
3195             }
3196             for (int i=services.size()-1; i>=0; i--) {
3197                 services.get(i).setPackageName(newName);
3198             }
3199             for (int i=instrumentation.size()-1; i>=0; i--) {
3200                 instrumentation.get(i).setPackageName(newName);
3201             }
3202         }
3203 
hasComponentClassName(String name)3204         public boolean hasComponentClassName(String name) {
3205             for (int i=activities.size()-1; i>=0; i--) {
3206                 if (name.equals(activities.get(i).className)) {
3207                     return true;
3208                 }
3209             }
3210             for (int i=receivers.size()-1; i>=0; i--) {
3211                 if (name.equals(receivers.get(i).className)) {
3212                     return true;
3213                 }
3214             }
3215             for (int i=providers.size()-1; i>=0; i--) {
3216                 if (name.equals(providers.get(i).className)) {
3217                     return true;
3218                 }
3219             }
3220             for (int i=services.size()-1; i>=0; i--) {
3221                 if (name.equals(services.get(i).className)) {
3222                     return true;
3223                 }
3224             }
3225             for (int i=instrumentation.size()-1; i>=0; i--) {
3226                 if (name.equals(instrumentation.get(i).className)) {
3227                     return true;
3228                 }
3229             }
3230             return false;
3231         }
3232 
toString()3233         public String toString() {
3234             return "Package{"
3235                 + Integer.toHexString(System.identityHashCode(this))
3236                 + " " + packageName + "}";
3237         }
3238     }
3239 
3240     public static class Component<II extends IntentInfo> {
3241         public final Package owner;
3242         public final ArrayList<II> intents;
3243         public final String className;
3244         public Bundle metaData;
3245 
3246         ComponentName componentName;
3247         String componentShortName;
3248 
Component(Package _owner)3249         public Component(Package _owner) {
3250             owner = _owner;
3251             intents = null;
3252             className = null;
3253         }
3254 
Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo)3255         public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
3256             owner = args.owner;
3257             intents = new ArrayList<II>(0);
3258             String name = args.sa.getNonConfigurationString(args.nameRes, 0);
3259             if (name == null) {
3260                 className = null;
3261                 args.outError[0] = args.tag + " does not specify android:name";
3262                 return;
3263             }
3264 
3265             outInfo.name
3266                 = buildClassName(owner.applicationInfo.packageName, name, args.outError);
3267             if (outInfo.name == null) {
3268                 className = null;
3269                 args.outError[0] = args.tag + " does not have valid android:name";
3270                 return;
3271             }
3272 
3273             className = outInfo.name;
3274 
3275             int iconVal = args.sa.getResourceId(args.iconRes, 0);
3276             if (iconVal != 0) {
3277                 outInfo.icon = iconVal;
3278                 outInfo.nonLocalizedLabel = null;
3279             }
3280 
3281             int logoVal = args.sa.getResourceId(args.logoRes, 0);
3282             if (logoVal != 0) {
3283                 outInfo.logo = logoVal;
3284             }
3285 
3286             TypedValue v = args.sa.peekValue(args.labelRes);
3287             if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
3288                 outInfo.nonLocalizedLabel = v.coerceToString();
3289             }
3290 
3291             outInfo.packageName = owner.packageName;
3292         }
3293 
Component(final ParseComponentArgs args, final ComponentInfo outInfo)3294         public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
3295             this(args, (PackageItemInfo)outInfo);
3296             if (args.outError[0] != null) {
3297                 return;
3298             }
3299 
3300             if (args.processRes != 0) {
3301                 CharSequence pname;
3302                 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3303                     pname = args.sa.getNonConfigurationString(args.processRes, 0);
3304                 } else {
3305                     // Some older apps have been seen to use a resource reference
3306                     // here that on older builds was ignored (with a warning).  We
3307                     // need to continue to do this for them so they don't break.
3308                     pname = args.sa.getNonResourceString(args.processRes);
3309                 }
3310                 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
3311                         owner.applicationInfo.processName, pname,
3312                         args.flags, args.sepProcesses, args.outError);
3313             }
3314 
3315             if (args.descriptionRes != 0) {
3316                 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
3317             }
3318 
3319             outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
3320         }
3321 
Component(Component<II> clone)3322         public Component(Component<II> clone) {
3323             owner = clone.owner;
3324             intents = clone.intents;
3325             className = clone.className;
3326             componentName = clone.componentName;
3327             componentShortName = clone.componentShortName;
3328         }
3329 
getComponentName()3330         public ComponentName getComponentName() {
3331             if (componentName != null) {
3332                 return componentName;
3333             }
3334             if (className != null) {
3335                 componentName = new ComponentName(owner.applicationInfo.packageName,
3336                         className);
3337             }
3338             return componentName;
3339         }
3340 
getComponentShortName()3341         public String getComponentShortName() {
3342             if (componentShortName != null) {
3343                 return componentShortName;
3344             }
3345             ComponentName component = getComponentName();
3346             if (component != null) {
3347                 componentShortName = component.flattenToShortString();
3348             }
3349             return componentShortName;
3350         }
3351 
setPackageName(String packageName)3352         public void setPackageName(String packageName) {
3353             componentName = null;
3354             componentShortName = null;
3355         }
3356     }
3357 
3358     public final static class Permission extends Component<IntentInfo> {
3359         public final PermissionInfo info;
3360         public boolean tree;
3361         public PermissionGroup group;
3362 
Permission(Package _owner)3363         public Permission(Package _owner) {
3364             super(_owner);
3365             info = new PermissionInfo();
3366         }
3367 
Permission(Package _owner, PermissionInfo _info)3368         public Permission(Package _owner, PermissionInfo _info) {
3369             super(_owner);
3370             info = _info;
3371         }
3372 
setPackageName(String packageName)3373         public void setPackageName(String packageName) {
3374             super.setPackageName(packageName);
3375             info.packageName = packageName;
3376         }
3377 
toString()3378         public String toString() {
3379             return "Permission{"
3380                 + Integer.toHexString(System.identityHashCode(this))
3381                 + " " + info.name + "}";
3382         }
3383     }
3384 
3385     public final static class PermissionGroup extends Component<IntentInfo> {
3386         public final PermissionGroupInfo info;
3387 
PermissionGroup(Package _owner)3388         public PermissionGroup(Package _owner) {
3389             super(_owner);
3390             info = new PermissionGroupInfo();
3391         }
3392 
PermissionGroup(Package _owner, PermissionGroupInfo _info)3393         public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
3394             super(_owner);
3395             info = _info;
3396         }
3397 
setPackageName(String packageName)3398         public void setPackageName(String packageName) {
3399             super.setPackageName(packageName);
3400             info.packageName = packageName;
3401         }
3402 
toString()3403         public String toString() {
3404             return "PermissionGroup{"
3405                 + Integer.toHexString(System.identityHashCode(this))
3406                 + " " + info.name + "}";
3407         }
3408     }
3409 
copyNeeded(int flags, Package p, int enabledState, Bundle metaData)3410     private static boolean copyNeeded(int flags, Package p, int enabledState, Bundle metaData) {
3411         if (enabledState != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
3412             boolean enabled = enabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
3413             if (p.applicationInfo.enabled != enabled) {
3414                 return true;
3415             }
3416         }
3417         if ((flags & PackageManager.GET_META_DATA) != 0
3418                 && (metaData != null || p.mAppMetaData != null)) {
3419             return true;
3420         }
3421         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
3422                 && p.usesLibraryFiles != null) {
3423             return true;
3424         }
3425         return false;
3426     }
3427 
generateApplicationInfo(Package p, int flags, boolean stopped, int enabledState)3428     public static ApplicationInfo generateApplicationInfo(Package p, int flags, boolean stopped,
3429             int enabledState) {
3430         return generateApplicationInfo(p, flags, stopped, enabledState, UserId.getCallingUserId());
3431     }
3432 
generateApplicationInfo(Package p, int flags, boolean stopped, int enabledState, int userId)3433     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
3434             boolean stopped, int enabledState, int userId) {
3435         if (p == null) return null;
3436         if (!copyNeeded(flags, p, enabledState, null) && userId == 0) {
3437             // CompatibilityMode is global state. It's safe to modify the instance
3438             // of the package.
3439             if (!sCompatibilityModeEnabled) {
3440                 p.applicationInfo.disableCompatibilityMode();
3441             }
3442             if (stopped) {
3443                 p.applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
3444             } else {
3445                 p.applicationInfo.flags &= ~ApplicationInfo.FLAG_STOPPED;
3446             }
3447             if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
3448                 p.applicationInfo.enabled = true;
3449             } else if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
3450                     || enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
3451                 p.applicationInfo.enabled = false;
3452             }
3453             p.applicationInfo.enabledSetting = enabledState;
3454             return p.applicationInfo;
3455         }
3456 
3457         // Make shallow copy so we can store the metadata/libraries safely
3458         ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
3459         if (userId != 0) {
3460             ai.uid = UserId.getUid(userId, ai.uid);
3461             ai.dataDir = PackageManager.getDataDirForUser(userId, ai.packageName);
3462         }
3463         if ((flags & PackageManager.GET_META_DATA) != 0) {
3464             ai.metaData = p.mAppMetaData;
3465         }
3466         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
3467             ai.sharedLibraryFiles = p.usesLibraryFiles;
3468         }
3469         if (!sCompatibilityModeEnabled) {
3470             ai.disableCompatibilityMode();
3471         }
3472         if (stopped) {
3473             ai.flags |= ApplicationInfo.FLAG_STOPPED;
3474         } else {
3475             ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
3476         }
3477         if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
3478             ai.enabled = true;
3479         } else if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
3480                 || enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
3481             ai.enabled = false;
3482         }
3483         ai.enabledSetting = enabledState;
3484         return ai;
3485     }
3486 
generatePermissionInfo( Permission p, int flags)3487     public static final PermissionInfo generatePermissionInfo(
3488             Permission p, int flags) {
3489         if (p == null) return null;
3490         if ((flags&PackageManager.GET_META_DATA) == 0) {
3491             return p.info;
3492         }
3493         PermissionInfo pi = new PermissionInfo(p.info);
3494         pi.metaData = p.metaData;
3495         return pi;
3496     }
3497 
generatePermissionGroupInfo( PermissionGroup pg, int flags)3498     public static final PermissionGroupInfo generatePermissionGroupInfo(
3499             PermissionGroup pg, int flags) {
3500         if (pg == null) return null;
3501         if ((flags&PackageManager.GET_META_DATA) == 0) {
3502             return pg.info;
3503         }
3504         PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
3505         pgi.metaData = pg.metaData;
3506         return pgi;
3507     }
3508 
3509     public final static class Activity extends Component<ActivityIntentInfo> {
3510         public final ActivityInfo info;
3511 
Activity(final ParseComponentArgs args, final ActivityInfo _info)3512         public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
3513             super(args, _info);
3514             info = _info;
3515             info.applicationInfo = args.owner.applicationInfo;
3516         }
3517 
setPackageName(String packageName)3518         public void setPackageName(String packageName) {
3519             super.setPackageName(packageName);
3520             info.packageName = packageName;
3521         }
3522 
toString()3523         public String toString() {
3524             return "Activity{"
3525                 + Integer.toHexString(System.identityHashCode(this))
3526                 + " " + getComponentShortName() + "}";
3527         }
3528     }
3529 
generateActivityInfo(Activity a, int flags, boolean stopped, int enabledState, int userId)3530     public static final ActivityInfo generateActivityInfo(Activity a, int flags, boolean stopped,
3531             int enabledState, int userId) {
3532         if (a == null) return null;
3533         if (!copyNeeded(flags, a.owner, enabledState, a.metaData) && userId == 0) {
3534             return a.info;
3535         }
3536         // Make shallow copies so we can store the metadata safely
3537         ActivityInfo ai = new ActivityInfo(a.info);
3538         ai.metaData = a.metaData;
3539         ai.applicationInfo = generateApplicationInfo(a.owner, flags, stopped, enabledState, userId);
3540         return ai;
3541     }
3542 
3543     public final static class Service extends Component<ServiceIntentInfo> {
3544         public final ServiceInfo info;
3545 
Service(final ParseComponentArgs args, final ServiceInfo _info)3546         public Service(final ParseComponentArgs args, final ServiceInfo _info) {
3547             super(args, _info);
3548             info = _info;
3549             info.applicationInfo = args.owner.applicationInfo;
3550         }
3551 
setPackageName(String packageName)3552         public void setPackageName(String packageName) {
3553             super.setPackageName(packageName);
3554             info.packageName = packageName;
3555         }
3556 
toString()3557         public String toString() {
3558             return "Service{"
3559                 + Integer.toHexString(System.identityHashCode(this))
3560                 + " " + getComponentShortName() + "}";
3561         }
3562     }
3563 
generateServiceInfo(Service s, int flags, boolean stopped, int enabledState, int userId)3564     public static final ServiceInfo generateServiceInfo(Service s, int flags, boolean stopped,
3565             int enabledState, int userId) {
3566         if (s == null) return null;
3567         if (!copyNeeded(flags, s.owner, enabledState, s.metaData)
3568                 && userId == UserId.getUserId(s.info.applicationInfo.uid)) {
3569             return s.info;
3570         }
3571         // Make shallow copies so we can store the metadata safely
3572         ServiceInfo si = new ServiceInfo(s.info);
3573         si.metaData = s.metaData;
3574         si.applicationInfo = generateApplicationInfo(s.owner, flags, stopped, enabledState, userId);
3575         return si;
3576     }
3577 
3578     public final static class Provider extends Component {
3579         public final ProviderInfo info;
3580         public boolean syncable;
3581 
Provider(final ParseComponentArgs args, final ProviderInfo _info)3582         public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
3583             super(args, _info);
3584             info = _info;
3585             info.applicationInfo = args.owner.applicationInfo;
3586             syncable = false;
3587         }
3588 
Provider(Provider existingProvider)3589         public Provider(Provider existingProvider) {
3590             super(existingProvider);
3591             this.info = existingProvider.info;
3592             this.syncable = existingProvider.syncable;
3593         }
3594 
setPackageName(String packageName)3595         public void setPackageName(String packageName) {
3596             super.setPackageName(packageName);
3597             info.packageName = packageName;
3598         }
3599 
toString()3600         public String toString() {
3601             return "Provider{"
3602                 + Integer.toHexString(System.identityHashCode(this))
3603                 + " " + info.name + "}";
3604         }
3605     }
3606 
generateProviderInfo(Provider p, int flags, boolean stopped, int enabledState, int userId)3607     public static final ProviderInfo generateProviderInfo(Provider p, int flags, boolean stopped,
3608             int enabledState, int userId) {
3609         if (p == null) return null;
3610         if (!copyNeeded(flags, p.owner, enabledState, p.metaData)
3611                 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
3612                         || p.info.uriPermissionPatterns == null)
3613                 && userId == 0) {
3614             return p.info;
3615         }
3616         // Make shallow copies so we can store the metadata safely
3617         ProviderInfo pi = new ProviderInfo(p.info);
3618         pi.metaData = p.metaData;
3619         if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
3620             pi.uriPermissionPatterns = null;
3621         }
3622         pi.applicationInfo = generateApplicationInfo(p.owner, flags, stopped, enabledState, userId);
3623         return pi;
3624     }
3625 
3626     public final static class Instrumentation extends Component {
3627         public final InstrumentationInfo info;
3628 
Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info)3629         public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
3630             super(args, _info);
3631             info = _info;
3632         }
3633 
setPackageName(String packageName)3634         public void setPackageName(String packageName) {
3635             super.setPackageName(packageName);
3636             info.packageName = packageName;
3637         }
3638 
toString()3639         public String toString() {
3640             return "Instrumentation{"
3641                 + Integer.toHexString(System.identityHashCode(this))
3642                 + " " + getComponentShortName() + "}";
3643         }
3644     }
3645 
generateInstrumentationInfo( Instrumentation i, int flags)3646     public static final InstrumentationInfo generateInstrumentationInfo(
3647             Instrumentation i, int flags) {
3648         if (i == null) return null;
3649         if ((flags&PackageManager.GET_META_DATA) == 0) {
3650             return i.info;
3651         }
3652         InstrumentationInfo ii = new InstrumentationInfo(i.info);
3653         ii.metaData = i.metaData;
3654         return ii;
3655     }
3656 
3657     public static class IntentInfo extends IntentFilter {
3658         public boolean hasDefault;
3659         public int labelRes;
3660         public CharSequence nonLocalizedLabel;
3661         public int icon;
3662         public int logo;
3663     }
3664 
3665     public final static class ActivityIntentInfo extends IntentInfo {
3666         public final Activity activity;
3667 
ActivityIntentInfo(Activity _activity)3668         public ActivityIntentInfo(Activity _activity) {
3669             activity = _activity;
3670         }
3671 
toString()3672         public String toString() {
3673             return "ActivityIntentInfo{"
3674                 + Integer.toHexString(System.identityHashCode(this))
3675                 + " " + activity.info.name + "}";
3676         }
3677     }
3678 
3679     public final static class ServiceIntentInfo extends IntentInfo {
3680         public final Service service;
3681 
ServiceIntentInfo(Service _service)3682         public ServiceIntentInfo(Service _service) {
3683             service = _service;
3684         }
3685 
toString()3686         public String toString() {
3687             return "ServiceIntentInfo{"
3688                 + Integer.toHexString(System.identityHashCode(this))
3689                 + " " + service.info.name + "}";
3690         }
3691     }
3692 
3693     /**
3694      * @hide
3695      */
setCompatibilityModeEnabled(boolean compatibilityModeEnabled)3696     public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
3697         sCompatibilityModeEnabled = compatibilityModeEnabled;
3698     }
3699 }
3700