FileDocCategorySizeDatePackage
PackageHelper.javaAPI DocAndroid 5.1 API17950Thu Mar 12 22:22:10 GMT 2015com.android.internal.content

PackageHelper

public class PackageHelper extends Object
Constants used internally between the PackageManager and media container service transports. Some utility methods to invoke MountService api.

Fields Summary
public static final int
RECOMMEND_INSTALL_INTERNAL
public static final int
RECOMMEND_INSTALL_EXTERNAL
public static final int
RECOMMEND_FAILED_INSUFFICIENT_STORAGE
public static final int
RECOMMEND_FAILED_INVALID_APK
public static final int
RECOMMEND_FAILED_INVALID_LOCATION
public static final int
RECOMMEND_FAILED_ALREADY_EXISTS
public static final int
RECOMMEND_MEDIA_UNAVAILABLE
public static final int
RECOMMEND_FAILED_INVALID_URI
public static final int
RECOMMEND_FAILED_VERSION_DOWNGRADE
private static final boolean
localLOGV
private static final String
TAG
public static final int
APP_INSTALL_AUTO
public static final int
APP_INSTALL_INTERNAL
public static final int
APP_INSTALL_EXTERNAL
Constructors Summary
Methods Summary
public static longcalculateInstalledSize(android.content.pm.PackageParser.PackageLite pkg, boolean isForwardLocked, java.lang.String abiOverride)

        NativeLibraryHelper.Handle handle = null;
        try {
            handle = NativeLibraryHelper.Handle.create(pkg);
            return calculateInstalledSize(pkg, handle, isForwardLocked, abiOverride);
        } finally {
            IoUtils.closeQuietly(handle);
        }
    
public static longcalculateInstalledSize(android.content.pm.PackageParser.PackageLite pkg, NativeLibraryHelper.Handle handle, boolean isForwardLocked, java.lang.String abiOverride)

        long sizeBytes = 0;

        // Include raw APKs, and possibly unpacked resources
        for (String codePath : pkg.getAllCodePaths()) {
            final File codeFile = new File(codePath);
            sizeBytes += codeFile.length();

            if (isForwardLocked) {
                sizeBytes += PackageHelper.extractPublicFiles(codeFile, null);
            }
        }

        // Include all relevant native code
        sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);

        return sizeBytes;
    
private static voidcopyZipEntry(java.util.zip.ZipEntry zipEntry, java.util.zip.ZipFile inZipFile, java.util.zip.ZipOutputStream outZipStream)

        byte[] buffer = new byte[4096];
        int num;

        ZipEntry newEntry;
        if (zipEntry.getMethod() == ZipEntry.STORED) {
            // Preserve the STORED method of the input entry.
            newEntry = new ZipEntry(zipEntry);
        } else {
            // Create a new entry so that the compressed len is recomputed.
            newEntry = new ZipEntry(zipEntry.getName());
        }
        outZipStream.putNextEntry(newEntry);

        final InputStream data = inZipFile.getInputStream(zipEntry);
        try {
            while ((num = data.read(buffer)) > 0) {
                outZipStream.write(buffer, 0, num);
            }
            outZipStream.flush();
        } finally {
            IoUtils.closeQuietly(data);
        }
    
public static java.lang.StringcreateSdDir(long sizeBytes, java.lang.String cid, java.lang.String sdEncKey, int uid, boolean isExternal)

        // Round up to nearest MB, plus another MB for filesystem overhead
        final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1;
        try {
            IMountService mountService = getMountService();

            if (localLOGV)
                Log.i(TAG, "Size of container " + sizeMb + " MB");

            int rc = mountService.createSecureContainer(cid, sizeMb, "ext4", sdEncKey, uid,
                    isExternal);
            if (rc != StorageResultCode.OperationSucceeded) {
                Log.e(TAG, "Failed to create secure container " + cid);
                return null;
            }
            String cachePath = mountService.getSecureContainerPath(cid);
            if (localLOGV) Log.i(TAG, "Created secure container " + cid +
                    " at " + cachePath);
                return cachePath;
        } catch (RemoteException e) {
            Log.e(TAG, "MountService running?");
        }
        return null;
    
public static booleandestroySdDir(java.lang.String cid)

        try {
            if (localLOGV) Log.i(TAG, "Forcibly destroying container " + cid);
            int rc = getMountService().destroySecureContainer(cid, true);
            if (rc != StorageResultCode.OperationSucceeded) {
                Log.i(TAG, "Failed to destroy container " + cid);
                return false;
            }
            return true;
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to destroy container " + cid +
                    " with exception " + e);
        }
        return false;
    
public static longextractPublicFiles(java.io.File apkFile, java.io.File publicZipFile)
Extract public files for the single given APK.

        final FileOutputStream fstr;
        final ZipOutputStream publicZipOutStream;

        if (publicZipFile == null) {
            fstr = null;
            publicZipOutStream = null;
        } else {
            fstr = new FileOutputStream(publicZipFile);
            publicZipOutStream = new ZipOutputStream(fstr);
            Log.d(TAG, "Extracting " + apkFile + " to " + publicZipFile);
        }

        long size = 0L;

        try {
            final ZipFile privateZip = new ZipFile(apkFile.getAbsolutePath());
            try {
                // Copy manifest, resources.arsc and res directory to public zip
                for (final ZipEntry zipEntry : Collections.list(privateZip.entries())) {
                    final String zipEntryName = zipEntry.getName();
                    if ("AndroidManifest.xml".equals(zipEntryName)
                            || "resources.arsc".equals(zipEntryName)
                            || zipEntryName.startsWith("res/")) {
                        size += zipEntry.getSize();
                        if (publicZipFile != null) {
                            copyZipEntry(zipEntry, privateZip, publicZipOutStream);
                        }
                    }
                }
            } finally {
                try { privateZip.close(); } catch (IOException e) {}
            }

            if (publicZipFile != null) {
                publicZipOutStream.finish();
                publicZipOutStream.flush();
                FileUtils.sync(fstr);
                publicZipOutStream.close();
                FileUtils.setPermissions(publicZipFile.getAbsolutePath(), FileUtils.S_IRUSR
                        | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IROTH, -1, -1);
            }
        } finally {
            IoUtils.closeQuietly(publicZipOutStream);
        }

        return size;
    
public static booleanfinalizeSdDir(java.lang.String cid)

        try {
            int rc = getMountService().finalizeSecureContainer(cid);
            if (rc != StorageResultCode.OperationSucceeded) {
                Log.i(TAG, "Failed to finalize container " + cid);
                return false;
            }
            return true;
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to finalize container " + cid +
                    " with exception " + e);
        }
        return false;
    
public static booleanfixSdPermissions(java.lang.String cid, int gid, java.lang.String filename)

        try {
            int rc = getMountService().fixPermissionsSecureContainer(cid, gid, filename);
            if (rc != StorageResultCode.OperationSucceeded) {
                Log.i(TAG, "Failed to fixperms container " + cid);
                return false;
            }
            return true;
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to fixperms container " + cid + " with exception " + e);
        }
        return false;
    
public static android.os.storage.IMountServicegetMountService()


          
        IBinder service = ServiceManager.getService("mount");
        if (service != null) {
            return IMountService.Stub.asInterface(service);
        } else {
            Log.e(TAG, "Can't get mount service");
            throw new RemoteException("Could not contact mount service");
        }
    
public static java.lang.StringgetSdDir(java.lang.String cid)

       try {
            return getMountService().getSecureContainerPath(cid);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to get container path for " + cid +
                " with exception " + e);
        }
        return null;
   
public static java.lang.StringgetSdFilesystem(java.lang.String cid)

       try {
            return getMountService().getSecureContainerFilesystemPath(cid);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to get container path for " + cid +
                " with exception " + e);
        }
        return null;
   
public static java.lang.String[]getSecureContainerList()

        try {
            return getMountService().getSecureContainerList();
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to get secure container list with exception" +
                    e);
        }
        return null;
    
public static booleanisContainerMounted(java.lang.String cid)

       try {
           return getMountService().isSecureContainerMounted(cid);
       } catch (RemoteException e) {
           Log.e(TAG, "Failed to find out if container " + cid + " mounted");
       }
       return false;
   
public static java.lang.StringmountSdDir(java.lang.String cid, java.lang.String key, int ownerUid)

        return mountSdDir(cid, key, ownerUid, true);
    
public static java.lang.StringmountSdDir(java.lang.String cid, java.lang.String key, int ownerUid, boolean readOnly)

        try {
            int rc = getMountService().mountSecureContainer(cid, key, ownerUid, readOnly);
            if (rc != StorageResultCode.OperationSucceeded) {
                Log.i(TAG, "Failed to mount container " + cid + " rc : " + rc);
                return null;
            }
            return getMountService().getSecureContainerPath(cid);
        } catch (RemoteException e) {
            Log.e(TAG, "MountService running?");
        }
        return null;
    
public static booleanrenameSdDir(java.lang.String oldId, java.lang.String newId)

       try {
           int rc = getMountService().renameSecureContainer(oldId, newId);
           if (rc != StorageResultCode.OperationSucceeded) {
               Log.e(TAG, "Failed to rename " + oldId + " to " +
                       newId + "with rc " + rc);
               return false;
           }
           return true;
       } catch (RemoteException e) {
           Log.i(TAG, "Failed ot rename  " + oldId + " to " + newId +
                   " with exception : " + e);
       }
       return false;
   
public static java.lang.StringreplaceEnd(java.lang.String str, java.lang.String before, java.lang.String after)

        if (!str.endsWith(before)) {
            throw new IllegalArgumentException(
                    "Expected " + str + " to end with " + before);
        }
        return str.substring(0, str.length() - before.length()) + after;
    
public static booleanresizeSdDir(long sizeBytes, java.lang.String cid, java.lang.String sdEncKey)

        // Round up to nearest MB, plus another MB for filesystem overhead
        final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1;
        try {
            IMountService mountService = getMountService();
            int rc = mountService.resizeSecureContainer(cid, sizeMb, sdEncKey);
            if (rc == StorageResultCode.OperationSucceeded) {
                return true;
            }
        } catch (RemoteException e) {
            Log.e(TAG, "MountService running?");
        }
        Log.e(TAG, "Failed to create secure container " + cid);
        return false;
    
public static intresolveInstallLocation(android.content.Context context, java.lang.String packageName, int installLocation, long sizeBytes, int installFlags)
Given a requested {@link PackageInfo#installLocation} and calculated install size, pick the actual location to install the app.

        ApplicationInfo existingInfo = null;
        try {
            existingInfo = context.getPackageManager().getApplicationInfo(packageName,
                    PackageManager.GET_UNINSTALLED_PACKAGES);
        } catch (NameNotFoundException ignored) {
        }

        final int prefer;
        final boolean checkBoth;
        if ((installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
            prefer = RECOMMEND_INSTALL_INTERNAL;
            checkBoth = false;
        } else if ((installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
            prefer = RECOMMEND_INSTALL_EXTERNAL;
            checkBoth = false;
        } else if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
            prefer = RECOMMEND_INSTALL_INTERNAL;
            checkBoth = false;
        } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
            prefer = RECOMMEND_INSTALL_EXTERNAL;
            checkBoth = true;
        } else if (installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
            // When app is already installed, prefer same medium
            if (existingInfo != null) {
                if ((existingInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                    prefer = RECOMMEND_INSTALL_EXTERNAL;
                } else {
                    prefer = RECOMMEND_INSTALL_INTERNAL;
                }
            } else {
                prefer = RECOMMEND_INSTALL_INTERNAL;
            }
            checkBoth = true;
        } else {
            prefer = RECOMMEND_INSTALL_INTERNAL;
            checkBoth = false;
        }

        final boolean emulated = Environment.isExternalStorageEmulated();
        final StorageManager storage = StorageManager.from(context);

        boolean fitsOnInternal = false;
        if (checkBoth || prefer == RECOMMEND_INSTALL_INTERNAL) {
            final File target = Environment.getDataDirectory();
            fitsOnInternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
        }

        boolean fitsOnExternal = false;
        if (!emulated && (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL)) {
            final File target = new UserEnvironment(UserHandle.USER_OWNER)
                    .getExternalStorageDirectory();
            // External is only an option when size is known
            if (sizeBytes > 0) {
                fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
            }
        }

        if (prefer == RECOMMEND_INSTALL_INTERNAL) {
            if (fitsOnInternal) {
                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
            }
        } else if (!emulated && prefer == RECOMMEND_INSTALL_EXTERNAL) {
            if (fitsOnExternal) {
                return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
            }
        }

        if (checkBoth) {
            if (fitsOnInternal) {
                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
            } else if (!emulated && fitsOnExternal) {
                return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
            }
        }

        /*
         * If they requested to be on the external media by default, return that
         * the media was unavailable. Otherwise, indicate there was insufficient
         * storage space available.
         */
        if (!emulated && (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL)
                && !Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            return PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE;
        } else {
            return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
        }
    
public static booleanunMountSdDir(java.lang.String cid)

    try {
        int rc = getMountService().unmountSecureContainer(cid, true);
        if (rc != StorageResultCode.OperationSucceeded) {
            Log.e(TAG, "Failed to unmount " + cid + " with rc " + rc);
            return false;
        }
        return true;
    } catch (RemoteException e) {
        Log.e(TAG, "MountService running?");
    }
        return false;