| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.internal.content; |
| |
| import android.os.FileUtils; |
| import android.os.IBinder; |
| import android.os.RemoteException; |
| import android.os.ServiceManager; |
| import android.os.storage.IMountService; |
| import android.os.storage.StorageResultCode; |
| import android.util.Log; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Collections; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipFile; |
| import java.util.zip.ZipOutputStream; |
| |
| import libcore.io.IoUtils; |
| |
| /** |
| * Constants used internally between the PackageManager |
| * and media container service transports. |
| * Some utility methods to invoke MountService api. |
| */ |
| public class PackageHelper { |
| public static final int RECOMMEND_INSTALL_INTERNAL = 1; |
| public static final int RECOMMEND_INSTALL_EXTERNAL = 2; |
| public static final int RECOMMEND_FAILED_INSUFFICIENT_STORAGE = -1; |
| public static final int RECOMMEND_FAILED_INVALID_APK = -2; |
| public static final int RECOMMEND_FAILED_INVALID_LOCATION = -3; |
| public static final int RECOMMEND_FAILED_ALREADY_EXISTS = -4; |
| public static final int RECOMMEND_MEDIA_UNAVAILABLE = -5; |
| public static final int RECOMMEND_FAILED_INVALID_URI = -6; |
| public static final int RECOMMEND_FAILED_VERSION_DOWNGRADE = -7; |
| |
| private static final boolean localLOGV = true; |
| private static final String TAG = "PackageHelper"; |
| // App installation location settings values |
| public static final int APP_INSTALL_AUTO = 0; |
| public static final int APP_INSTALL_INTERNAL = 1; |
| public static final int APP_INSTALL_EXTERNAL = 2; |
| |
| public static IMountService getMountService() throws RemoteException { |
| 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 String createSdDir(int sizeMb, String cid, String sdEncKey, int uid, |
| boolean isExternal) { |
| // Create mount point via MountService |
| 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 String mountSdDir(String cid, String key, int ownerUid) { |
| try { |
| int rc = getMountService().mountSecureContainer(cid, key, ownerUid); |
| 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 boolean unMountSdDir(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; |
| } |
| |
| public static boolean renameSdDir(String oldId, 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 String getSdDir(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 String getSdFilesystem(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 boolean finalizeSdDir(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 boolean destroySdDir(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 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 boolean isContainerMounted(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 int extractPublicFiles(String packagePath, File publicZipFile) |
| throws IOException { |
| final FileOutputStream fstr; |
| final ZipOutputStream publicZipOutStream; |
| |
| if (publicZipFile == null) { |
| fstr = null; |
| publicZipOutStream = null; |
| } else { |
| fstr = new FileOutputStream(publicZipFile); |
| publicZipOutStream = new ZipOutputStream(fstr); |
| } |
| |
| int size = 0; |
| |
| try { |
| final ZipFile privateZip = new ZipFile(packagePath); |
| 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; |
| } |
| |
| private static void copyZipEntry(ZipEntry zipEntry, ZipFile inZipFile, |
| ZipOutputStream outZipStream) throws IOException { |
| 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 boolean fixSdPermissions(String cid, int gid, 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; |
| } |
| } |