15b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu/*
25b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * Copyright (C) 2009 The Android Open Source Project
35b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu *
45b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * Licensed under the Apache License, Version 2.0 (the "License");
55b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * you may not use this file except in compliance with the License.
65b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * You may obtain a copy of the License at
75b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu *
85b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu *      http://www.apache.org/licenses/LICENSE-2.0
95b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu *
105b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * Unless required by applicable law or agreed to in writing, software
115b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * distributed under the License is distributed on an "AS IS" BASIS,
125b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * See the License for the specific language governing permissions and
145b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * limitations under the License.
155b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu */
165b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu
175b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapupackage com.android.internal.content;
185b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu
192782a478d0214cf71a32d4537fc9fb191d1072fbKenny Rootimport android.os.FileUtils;
20679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapuimport android.os.IBinder;
21679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapuimport android.os.RemoteException;
22679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapuimport android.os.ServiceManager;
232782a478d0214cf71a32d4537fc9fb191d1072fbKenny Rootimport android.os.storage.IMountService;
24679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapuimport android.os.storage.StorageResultCode;
25679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapuimport android.util.Log;
26679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
27679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapuimport java.io.File;
282782a478d0214cf71a32d4537fc9fb191d1072fbKenny Rootimport java.io.FileOutputStream;
292782a478d0214cf71a32d4537fc9fb191d1072fbKenny Rootimport java.io.IOException;
302782a478d0214cf71a32d4537fc9fb191d1072fbKenny Rootimport java.io.InputStream;
312782a478d0214cf71a32d4537fc9fb191d1072fbKenny Rootimport java.util.Collections;
322782a478d0214cf71a32d4537fc9fb191d1072fbKenny Rootimport java.util.zip.ZipEntry;
332782a478d0214cf71a32d4537fc9fb191d1072fbKenny Rootimport java.util.zip.ZipFile;
342782a478d0214cf71a32d4537fc9fb191d1072fbKenny Rootimport java.util.zip.ZipOutputStream;
352782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root
362782a478d0214cf71a32d4537fc9fb191d1072fbKenny Rootimport libcore.io.IoUtils;
37679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
385b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu/**
395b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * Constants used internally between the PackageManager
405b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu * and media container service transports.
41679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu * Some utility methods to invoke MountService api.
425b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu */
435b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapupublic class PackageHelper {
445b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu    public static final int RECOMMEND_INSTALL_INTERNAL = 1;
455b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu    public static final int RECOMMEND_INSTALL_EXTERNAL = 2;
465b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu    public static final int RECOMMEND_FAILED_INSUFFICIENT_STORAGE = -1;
475b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu    public static final int RECOMMEND_FAILED_INVALID_APK = -2;
48a2b6c3775ed6b8924232d6a01bae4a19740a15f8Suchi Amalapurapu    public static final int RECOMMEND_FAILED_INVALID_LOCATION = -3;
49a2b6c3775ed6b8924232d6a01bae4a19740a15f8Suchi Amalapurapu    public static final int RECOMMEND_FAILED_ALREADY_EXISTS = -4;
508a9ab24a5c9b595ac0268fcade4b5bbfe7c45c2dSuchi Amalapurapu    public static final int RECOMMEND_MEDIA_UNAVAILABLE = -5;
511ebd74acf9977daa42133507e970dab88e08f0efKenny Root    public static final int RECOMMEND_FAILED_INVALID_URI = -6;
521ebd74acf9977daa42133507e970dab88e08f0efKenny Root
53cf6eaeaae9e6745dd6e07540812c79821d7043c2Suchi Amalapurapu    private static final boolean localLOGV = true;
54679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    private static final String TAG = "PackageHelper";
55089262dc022d87e31eefc536025be6c015c7ebdeSuchi Amalapurapu    // App installation location settings values
56089262dc022d87e31eefc536025be6c015c7ebdeSuchi Amalapurapu    public static final int APP_INSTALL_AUTO = 0;
57089262dc022d87e31eefc536025be6c015c7ebdeSuchi Amalapurapu    public static final int APP_INSTALL_INTERNAL = 1;
58089262dc022d87e31eefc536025be6c015c7ebdeSuchi Amalapurapu    public static final int APP_INSTALL_EXTERNAL = 2;
59679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
6007ba2ae327dbf209da5bafee9cdcb40e03e29d58Kenny Root    public static IMountService getMountService() throws RemoteException {
61679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        IBinder service = ServiceManager.getService("mount");
62679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        if (service != null) {
63679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            return IMountService.Stub.asInterface(service);
64679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        } else {
65679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            Log.e(TAG, "Can't get mount service");
6607ba2ae327dbf209da5bafee9cdcb40e03e29d58Kenny Root            throw new RemoteException("Could not contact mount service");
67679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        }
68679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    }
69679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
706dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root    public static String createSdDir(int sizeMb, String cid, String sdEncKey, int uid,
716dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            boolean isExternal) {
72679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        // Create mount point via MountService
7307ba2ae327dbf209da5bafee9cdcb40e03e29d58Kenny Root        try {
7407ba2ae327dbf209da5bafee9cdcb40e03e29d58Kenny Root            IMountService mountService = getMountService();
7562e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root
7607ba2ae327dbf209da5bafee9cdcb40e03e29d58Kenny Root            if (localLOGV)
7707ba2ae327dbf209da5bafee9cdcb40e03e29d58Kenny Root                Log.i(TAG, "Size of container " + sizeMb + " MB");
78679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
796dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            int rc = mountService.createSecureContainer(cid, sizeMb, "ext4", sdEncKey, uid,
806dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                    isExternal);
81679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            if (rc != StorageResultCode.OperationSucceeded) {
82679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                Log.e(TAG, "Failed to create secure container " + cid);
83679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                return null;
84679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            }
85679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            String cachePath = mountService.getSecureContainerPath(cid);
86cf6eaeaae9e6745dd6e07540812c79821d7043c2Suchi Amalapurapu            if (localLOGV) Log.i(TAG, "Created secure container " + cid +
87679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                    " at " + cachePath);
88679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                return cachePath;
89679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        } catch (RemoteException e) {
90679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            Log.e(TAG, "MountService running?");
91679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        }
92679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        return null;
93679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    }
94679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
95679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu   public static String mountSdDir(String cid, String key, int ownerUid) {
96679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    try {
97679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        int rc = getMountService().mountSecureContainer(cid, key, ownerUid);
98679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        if (rc != StorageResultCode.OperationSucceeded) {
99679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            Log.i(TAG, "Failed to mount container " + cid + " rc : " + rc);
100679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            return null;
101679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        }
102679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        return getMountService().getSecureContainerPath(cid);
103679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    } catch (RemoteException e) {
104679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        Log.e(TAG, "MountService running?");
105679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    }
106679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    return null;
107679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu   }
108679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
109679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu   public static boolean unMountSdDir(String cid) {
110679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    try {
111cf6eaeaae9e6745dd6e07540812c79821d7043c2Suchi Amalapurapu        int rc = getMountService().unmountSecureContainer(cid, true);
112679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        if (rc != StorageResultCode.OperationSucceeded) {
113679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            Log.e(TAG, "Failed to unmount " + cid + " with rc " + rc);
114679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            return false;
115679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        }
116679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        return true;
117679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    } catch (RemoteException e) {
118679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        Log.e(TAG, "MountService running?");
119679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    }
120679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        return false;
121679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu   }
122679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
123679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu   public static boolean renameSdDir(String oldId, String newId) {
124679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu       try {
125679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu           int rc = getMountService().renameSecureContainer(oldId, newId);
126679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu           if (rc != StorageResultCode.OperationSucceeded) {
127679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu               Log.e(TAG, "Failed to rename " + oldId + " to " +
128679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                       newId + "with rc " + rc);
129679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu               return false;
130679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu           }
131679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu           return true;
132679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu       } catch (RemoteException e) {
133679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu           Log.i(TAG, "Failed ot rename  " + oldId + " to " + newId +
134679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                   " with exception : " + e);
135679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu       }
136679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu       return false;
137679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu   }
138679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
139679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu   public static String getSdDir(String cid) {
140679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu       try {
141679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            return getMountService().getSecureContainerPath(cid);
142679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        } catch (RemoteException e) {
143679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            Log.e(TAG, "Failed to get container path for " + cid +
144679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                " with exception " + e);
145679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        }
146679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        return null;
147679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu   }
148679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
149292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn   public static String getSdFilesystem(String cid) {
150292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn       try {
151292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn            return getMountService().getSecureContainerFilesystemPath(cid);
152292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn        } catch (RemoteException e) {
153292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn            Log.e(TAG, "Failed to get container path for " + cid +
154292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn                " with exception " + e);
155292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn        }
156292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn        return null;
157292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn   }
158292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn
159679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    public static boolean finalizeSdDir(String cid) {
160679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        try {
161679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            int rc = getMountService().finalizeSecureContainer(cid);
162679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            if (rc != StorageResultCode.OperationSucceeded) {
163679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                Log.i(TAG, "Failed to finalize container " + cid);
164679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                return false;
165679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            }
166679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            return true;
167679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        } catch (RemoteException e) {
168679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            Log.e(TAG, "Failed to finalize container " + cid +
169679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                    " with exception " + e);
170679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        }
171679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        return false;
172679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    }
173679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
174679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    public static boolean destroySdDir(String cid) {
175679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        try {
176cf6eaeaae9e6745dd6e07540812c79821d7043c2Suchi Amalapurapu            if (localLOGV) Log.i(TAG, "Forcibly destroying container " + cid);
177cf6eaeaae9e6745dd6e07540812c79821d7043c2Suchi Amalapurapu            int rc = getMountService().destroySecureContainer(cid, true);
178679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            if (rc != StorageResultCode.OperationSucceeded) {
179679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                Log.i(TAG, "Failed to destroy container " + cid);
180679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                return false;
181679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            }
182679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            return true;
183679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        } catch (RemoteException e) {
184679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            Log.e(TAG, "Failed to destroy container " + cid +
185679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                    " with exception " + e);
186679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        }
187679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        return false;
188679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    }
189679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
190679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    public static String[] getSecureContainerList() {
191679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        try {
192679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            return getMountService().getSecureContainerList();
193679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        } catch (RemoteException e) {
194679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu            Log.e(TAG, "Failed to get secure container list with exception" +
195679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu                    e);
196679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        }
197679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu        return null;
198679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu    }
199679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu
200679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu   public static boolean isContainerMounted(String cid) {
201679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu       try {
202679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu           return getMountService().isSecureContainerMounted(cid);
203679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu       } catch (RemoteException e) {
204679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu           Log.e(TAG, "Failed to find out if container " + cid + " mounted");
205679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu       }
206679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu       return false;
207679bba339ef6948091180c776d6a284cddd812f5Suchi Amalapurapu   }
2082782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root
2096dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root    public static int extractPublicFiles(String packagePath, File publicZipFile)
2102782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            throws IOException {
2116dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        final FileOutputStream fstr;
2126dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        final ZipOutputStream publicZipOutStream;
2136dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root
2146dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        if (publicZipFile == null) {
2156dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            fstr = null;
2166dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            publicZipOutStream = null;
2176dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        } else {
2186dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            fstr = new FileOutputStream(publicZipFile);
2196dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            publicZipOutStream = new ZipOutputStream(fstr);
2206dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        }
2216dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root
2226dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        int size = 0;
2236dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root
2242782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        try {
2252782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            final ZipFile privateZip = new ZipFile(packagePath);
2262782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            try {
2272782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root                // Copy manifest, resources.arsc and res directory to public zip
2282782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root                for (final ZipEntry zipEntry : Collections.list(privateZip.entries())) {
2292782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root                    final String zipEntryName = zipEntry.getName();
2302782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root                    if ("AndroidManifest.xml".equals(zipEntryName)
2312782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root                            || "resources.arsc".equals(zipEntryName)
2322782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root                            || zipEntryName.startsWith("res/")) {
2336dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                        size += zipEntry.getSize();
2346dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                        if (publicZipFile != null) {
2356dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                            copyZipEntry(zipEntry, privateZip, publicZipOutStream);
2366dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                        }
2372782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root                    }
2382782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root                }
2392782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            } finally {
2406dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                try { privateZip.close(); } catch (IOException e) {}
2412782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            }
2422782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root
2436dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            if (publicZipFile != null) {
2446dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                publicZipOutStream.finish();
2456dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                publicZipOutStream.flush();
2466dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                FileUtils.sync(fstr);
2476dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                publicZipOutStream.close();
2486dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                FileUtils.setPermissions(publicZipFile.getAbsolutePath(), FileUtils.S_IRUSR
2496dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                        | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IROTH, -1, -1);
2506dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            }
2512782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        } finally {
2522782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            IoUtils.closeQuietly(publicZipOutStream);
2532782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        }
2546dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root
2556dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        return size;
2562782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root    }
2572782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root
2582782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root    private static void copyZipEntry(ZipEntry zipEntry, ZipFile inZipFile,
2592782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            ZipOutputStream outZipStream) throws IOException {
2602782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        byte[] buffer = new byte[4096];
2612782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        int num;
2622782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root
2632782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        ZipEntry newEntry;
2642782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        if (zipEntry.getMethod() == ZipEntry.STORED) {
2652782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            // Preserve the STORED method of the input entry.
2662782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            newEntry = new ZipEntry(zipEntry);
2672782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        } else {
2682782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            // Create a new entry so that the compressed len is recomputed.
2692782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            newEntry = new ZipEntry(zipEntry.getName());
2702782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        }
2712782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        outZipStream.putNextEntry(newEntry);
2722782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root
2732782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        final InputStream data = inZipFile.getInputStream(zipEntry);
2742782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        try {
2752782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            while ((num = data.read(buffer)) > 0) {
2762782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root                outZipStream.write(buffer, 0, num);
2772782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            }
2782782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            outZipStream.flush();
2792782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        } finally {
2802782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root            IoUtils.closeQuietly(data);
2812782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root        }
2822782a478d0214cf71a32d4537fc9fb191d1072fbKenny Root    }
2836dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root
2846dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root    public static boolean fixSdPermissions(String cid, int gid, String filename) {
2856dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        try {
2866dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            int rc = getMountService().fixPermissionsSecureContainer(cid, gid, filename);
2876dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            if (rc != StorageResultCode.OperationSucceeded) {
2886dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                Log.i(TAG, "Failed to fixperms container " + cid);
2896dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root                return false;
2906dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            }
2916dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            return true;
2926dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        } catch (RemoteException e) {
2936dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root            Log.e(TAG, "Failed to fixperms container " + cid + " with exception " + e);
2946dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        }
2956dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root        return false;
2966dceb88f1c7c42c6ab43834af2c993d599895d82Kenny Root    }
2975b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu}
298