diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/FragmentManager.java | 2 | ||||
| -rw-r--r-- | core/java/android/os/storage/IMountService.java | 59 | ||||
| -rw-r--r-- | core/java/android/view/KeyCharacterMap.java | 46 | ||||
| -rw-r--r-- | core/java/android/widget/Advanceable.java | 1 | ||||
| -rwxr-xr-x | core/java/com/android/internal/app/IMediaContainerService.aidl | 10 | ||||
| -rw-r--r-- | core/java/com/android/internal/app/RingtonePickerActivity.java | 362 | ||||
| -rw-r--r-- | core/java/com/android/internal/content/PackageHelper.java | 65 |
7 files changed, 148 insertions, 397 deletions
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 0519d3e..7e1daa4 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -1890,7 +1890,7 @@ final class FragmentManagerImpl extends FragmentManager { if (mActive != null) { for (int i=0; i<mAdded.size(); i++) { Fragment f = mAdded.get(i); - if (f != null && !f.mHidden) { + if (f != null && !f.mHidden && f.mUserVisibleHint) { if (f.onContextItemSelected(item)) { return true; } diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 0640d7e..f4abda6 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -252,7 +252,7 @@ public interface IMountService extends IInterface { * an int consistent with MountServiceResultCode */ public int createSecureContainer(String id, int sizeMb, String fstype, String key, - int ownerUid) throws RemoteException { + int ownerUid, boolean external) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); int _result; @@ -263,6 +263,7 @@ public interface IMountService extends IInterface { _data.writeString(fstype); _data.writeString(key); _data.writeInt(ownerUid); + _data.writeInt(external ? 1 : 0); mRemote.transact(Stub.TRANSACTION_createSecureContainer, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); @@ -711,6 +712,31 @@ public interface IMountService extends IInterface { } return _result; } + + /** + * Fix permissions in a container which has just been created and + * populated. Returns an int consistent with MountServiceResultCode + */ + public int fixPermissionsSecureContainer(String id, int gid, String filename) + throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(id); + _data.writeInt(gid); + _data.writeString(filename); + mRemote.transact(Stub.TRANSACTION_fixPermissionsSecureContainer, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + + } } private static final String DESCRIPTOR = "IMountService"; @@ -781,6 +807,8 @@ public interface IMountService extends IInterface { static final int TRANSACTION_verifyEncryptionPassword = IBinder.FIRST_CALL_TRANSACTION + 32; + static final int TRANSACTION_fixPermissionsSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 33; + /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. @@ -909,7 +937,10 @@ public interface IMountService extends IInterface { key = data.readString(); int ownerUid; ownerUid = data.readInt(); - int resultCode = createSecureContainer(id, sizeMb, fstype, key, ownerUid); + boolean external; + external = 0 != data.readInt(); + int resultCode = createSecureContainer(id, sizeMb, fstype, key, ownerUid, + external); reply.writeNoException(); reply.writeInt(resultCode); return true; @@ -1109,6 +1140,19 @@ public interface IMountService extends IInterface { reply.writeInt(result); return true; } + case TRANSACTION_fixPermissionsSecureContainer: { + data.enforceInterface(DESCRIPTOR); + String id; + id = data.readString(); + int gid; + gid = data.readInt(); + String filename; + filename = data.readString(); + int resultCode = fixPermissionsSecureContainer(id, gid, filename); + reply.writeNoException(); + reply.writeInt(resultCode); + return true; + } } return super.onTransact(code, data, reply, flags); } @@ -1118,8 +1162,8 @@ public interface IMountService extends IInterface { * Creates a secure container with the specified parameters. Returns an int * consistent with MountServiceResultCode */ - public int createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid) - throws RemoteException; + public int createSecureContainer(String id, int sizeMb, String fstype, String key, + int ownerUid, boolean external) throws RemoteException; /* * Destroy a secure container, and free up all resources associated with it. @@ -1317,4 +1361,11 @@ public interface IMountService extends IInterface { public Parcelable[] getVolumeList() throws RemoteException; public String getSecureContainerFilesystemPath(String id) throws RemoteException; + + /* + * Fix permissions in a container which has just been created and populated. + * Returns an int consistent with MountServiceResultCode + */ + public int fixPermissionsSecureContainer(String id, int gid, String filename) + throws RemoteException; } diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java index 1c61c6c..5b371eb 100644 --- a/core/java/android/view/KeyCharacterMap.java +++ b/core/java/android/view/KeyCharacterMap.java @@ -153,20 +153,26 @@ public class KeyCharacterMap implements Parcelable { private static final int ACCENT_BREVE = '\u02D8'; private static final int ACCENT_CARON = '\u02C7'; private static final int ACCENT_CEDILLA = '\u00B8'; + private static final int ACCENT_CIRCUMFLEX = '\u02C6'; private static final int ACCENT_COMMA_ABOVE = '\u1FBD'; private static final int ACCENT_COMMA_ABOVE_RIGHT = '\u02BC'; private static final int ACCENT_DOT_ABOVE = '\u02D9'; + private static final int ACCENT_DOT_BELOW = '.'; // approximate private static final int ACCENT_DOUBLE_ACUTE = '\u02DD'; private static final int ACCENT_GRAVE = '\u02CB'; - private static final int ACCENT_CIRCUMFLEX = '\u02C6'; + private static final int ACCENT_HOOK_ABOVE = '\u02C0'; + private static final int ACCENT_HORN = '\''; // approximate private static final int ACCENT_MACRON = '\u00AF'; private static final int ACCENT_MACRON_BELOW = '\u02CD'; private static final int ACCENT_OGONEK = '\u02DB'; private static final int ACCENT_REVERSED_COMMA_ABOVE = '\u02BD'; private static final int ACCENT_RING_ABOVE = '\u02DA'; + private static final int ACCENT_STROKE = '-'; // approximate private static final int ACCENT_TILDE = '\u02DC'; private static final int ACCENT_TURNED_COMMA_ABOVE = '\u02BB'; private static final int ACCENT_UMLAUT = '\u00A8'; + private static final int ACCENT_VERTICAL_LINE_ABOVE = '\u02C8'; + private static final int ACCENT_VERTICAL_LINE_BELOW = '\u02CC'; /* Legacy dead key display characters used in previous versions of the API. * We still support these characters by mapping them to their non-legacy version. */ @@ -188,11 +194,11 @@ public class KeyCharacterMap implements Parcelable { addCombining('\u0306', ACCENT_BREVE); addCombining('\u0307', ACCENT_DOT_ABOVE); addCombining('\u0308', ACCENT_UMLAUT); - //addCombining('\u0309', ACCENT_HOOK_ABOVE); + addCombining('\u0309', ACCENT_HOOK_ABOVE); addCombining('\u030A', ACCENT_RING_ABOVE); addCombining('\u030B', ACCENT_DOUBLE_ACUTE); addCombining('\u030C', ACCENT_CARON); - //addCombining('\u030D', ACCENT_VERTICAL_LINE_ABOVE); + addCombining('\u030D', ACCENT_VERTICAL_LINE_ABOVE); //addCombining('\u030E', ACCENT_DOUBLE_VERTICAL_LINE_ABOVE); //addCombining('\u030F', ACCENT_DOUBLE_GRAVE); //addCombining('\u0310', ACCENT_CANDRABINDU); @@ -201,13 +207,14 @@ public class KeyCharacterMap implements Parcelable { addCombining('\u0313', ACCENT_COMMA_ABOVE); addCombining('\u0314', ACCENT_REVERSED_COMMA_ABOVE); addCombining('\u0315', ACCENT_COMMA_ABOVE_RIGHT); - //addCombining('\u031B', ACCENT_HORN); - //addCombining('\u0323', ACCENT_DOT_BELOW); + addCombining('\u031B', ACCENT_HORN); + addCombining('\u0323', ACCENT_DOT_BELOW); //addCombining('\u0326', ACCENT_COMMA_BELOW); addCombining('\u0327', ACCENT_CEDILLA); addCombining('\u0328', ACCENT_OGONEK); - //addCombining('\u0329', ACCENT_VERTICAL_LINE_BELOW); + addCombining('\u0329', ACCENT_VERTICAL_LINE_BELOW); addCombining('\u0331', ACCENT_MACRON_BELOW); + addCombining('\u0335', ACCENT_STROKE); //addCombining('\u0342', ACCENT_PERISPOMENI); //addCombining('\u0344', ACCENT_DIALYTIKA_TONOS); //addCombining('\u0345', ACCENT_YPOGEGRAMMENI); @@ -235,6 +242,33 @@ public class KeyCharacterMap implements Parcelable { */ private static final SparseIntArray sDeadKeyCache = new SparseIntArray(); private static final StringBuilder sDeadKeyBuilder = new StringBuilder(); + static { + // Non-standard decompositions. + // Stroke modifier for Finnish multilingual keyboard and others. + addDeadKey(ACCENT_STROKE, 'D', '\u0110'); + addDeadKey(ACCENT_STROKE, 'G', '\u01e4'); + addDeadKey(ACCENT_STROKE, 'H', '\u0126'); + addDeadKey(ACCENT_STROKE, 'I', '\u0197'); + addDeadKey(ACCENT_STROKE, 'L', '\u0141'); + addDeadKey(ACCENT_STROKE, 'O', '\u00d8'); + addDeadKey(ACCENT_STROKE, 'T', '\u0166'); + addDeadKey(ACCENT_STROKE, 'd', '\u0111'); + addDeadKey(ACCENT_STROKE, 'g', '\u01e5'); + addDeadKey(ACCENT_STROKE, 'h', '\u0127'); + addDeadKey(ACCENT_STROKE, 'i', '\u0268'); + addDeadKey(ACCENT_STROKE, 'l', '\u0142'); + addDeadKey(ACCENT_STROKE, 'o', '\u00f8'); + addDeadKey(ACCENT_STROKE, 't', '\u0167'); + } + + private static void addDeadKey(int accent, int c, int result) { + final int combining = sAccentToCombining.get(accent); + if (combining == 0) { + throw new IllegalStateException("Invalid dead key declaration."); + } + final int combination = (combining << 16) | c; + sDeadKeyCache.put(combination, result); + } public static final Parcelable.Creator<KeyCharacterMap> CREATOR = new Parcelable.Creator<KeyCharacterMap>() { diff --git a/core/java/android/widget/Advanceable.java b/core/java/android/widget/Advanceable.java index dc13ebb7..ad8e101 100644 --- a/core/java/android/widget/Advanceable.java +++ b/core/java/android/widget/Advanceable.java @@ -21,7 +21,6 @@ package android.widget; * progressing through its set of children. The interface exists to give AppWidgetHosts a way of * taking responsibility for automatically advancing such collections. * - * @hide */ public interface Advanceable { diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl index 4322a20..727c094 100755 --- a/core/java/com/android/internal/app/IMediaContainerService.aidl +++ b/core/java/com/android/internal/app/IMediaContainerService.aidl @@ -22,14 +22,14 @@ import android.content.pm.PackageInfoLite; import android.content.res.ObbInfo; interface IMediaContainerService { - String copyResourceToContainer(in Uri packageURI, - String containerId, - String key, String resFileName); + String copyResourceToContainer(in Uri packageURI, String containerId, String key, + String resFileName, String publicResFileName, boolean isExternal, + boolean isForwardLocked); int copyResource(in Uri packageURI, in ParcelFileDescriptor outStream); PackageInfoLite getMinimalPackageInfo(in Uri fileUri, in int flags, in long threshold); - boolean checkInternalFreeStorage(in Uri fileUri, in long threshold); - boolean checkExternalFreeStorage(in Uri fileUri); + boolean checkInternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in long threshold); + boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked); ObbInfo getObbInfo(in String filename); long calculateDirectorySize(in String directory); /** Return file system stats: [0] is total bytes, [1] is available bytes */ diff --git a/core/java/com/android/internal/app/RingtonePickerActivity.java b/core/java/com/android/internal/app/RingtonePickerActivity.java deleted file mode 100644 index 36fc24e..0000000 --- a/core/java/com/android/internal/app/RingtonePickerActivity.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (C) 2007 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.app; - -import com.android.internal.app.AlertActivity; -import com.android.internal.app.AlertController; - -import android.content.DialogInterface; -import android.content.Intent; -import android.database.Cursor; -import android.media.Ringtone; -import android.media.RingtoneManager; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.provider.MediaStore; -import android.provider.Settings; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ListView; -import android.widget.TextView; - -/** - * The {@link RingtonePickerActivity} allows the user to choose one from all of the - * available ringtones. The chosen ringtone's URI will be persisted as a string. - * - * @see RingtoneManager#ACTION_RINGTONE_PICKER - */ -public final class RingtonePickerActivity extends AlertActivity implements - AdapterView.OnItemSelectedListener, Runnable, DialogInterface.OnClickListener, - AlertController.AlertParams.OnPrepareListViewListener { - - private static final String TAG = "RingtonePickerActivity"; - - private static final int DELAY_MS_SELECTION_PLAYED = 300; - - private static final String SAVE_CLICKED_POS = "clicked_pos"; - - private RingtoneManager mRingtoneManager; - - private Cursor mCursor; - private Handler mHandler; - - /** The position in the list of the 'Silent' item. */ - private int mSilentPos = -1; - - /** The position in the list of the 'Default' item. */ - private int mDefaultRingtonePos = -1; - - /** The position in the list of the last clicked item. */ - private int mClickedPos = -1; - - /** The position in the list of the ringtone to sample. */ - private int mSampleRingtonePos = -1; - - /** Whether this list has the 'Silent' item. */ - private boolean mHasSilentItem; - - /** The Uri to place a checkmark next to. */ - private Uri mExistingUri; - - /** The number of static items in the list. */ - private int mStaticItemCount; - - /** Whether this list has the 'Default' item. */ - private boolean mHasDefaultItem; - - /** The Uri to play when the 'Default' item is clicked. */ - private Uri mUriForDefaultItem; - - /** - * A Ringtone for the default ringtone. In most cases, the RingtoneManager - * will stop the previous ringtone. However, the RingtoneManager doesn't - * manage the default ringtone for us, so we should stop this one manually. - */ - private Ringtone mDefaultRingtone; - - private DialogInterface.OnClickListener mRingtoneClickListener = - new DialogInterface.OnClickListener() { - - /* - * On item clicked - */ - public void onClick(DialogInterface dialog, int which) { - // Save the position of most recently clicked item - mClickedPos = which; - - // Play clip - playRingtone(which, 0); - } - - }; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mHandler = new Handler(); - - Intent intent = getIntent(); - - /* - * Get whether to show the 'Default' item, and the URI to play when the - * default is clicked - */ - mHasDefaultItem = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); - mUriForDefaultItem = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI); - if (mUriForDefaultItem == null) { - mUriForDefaultItem = Settings.System.DEFAULT_RINGTONE_URI; - } - - if (savedInstanceState != null) { - mClickedPos = savedInstanceState.getInt(SAVE_CLICKED_POS, -1); - } - // Get whether to show the 'Silent' item - mHasSilentItem = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true); - - // Give the Activity so it can do managed queries - mRingtoneManager = new RingtoneManager(this); - - // Get whether to include DRM ringtones - boolean includeDrm = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_INCLUDE_DRM, - true); - mRingtoneManager.setIncludeDrm(includeDrm); - - // Get the types of ringtones to show - int types = intent.getIntExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, -1); - if (types != -1) { - mRingtoneManager.setType(types); - } - - mCursor = mRingtoneManager.getCursor(); - - // The volume keys will control the stream that we are choosing a ringtone for - setVolumeControlStream(mRingtoneManager.inferStreamType()); - - // Get the URI whose list item should have a checkmark - mExistingUri = intent - .getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI); - - final AlertController.AlertParams p = mAlertParams; - p.mCursor = mCursor; - p.mOnClickListener = mRingtoneClickListener; - p.mLabelColumn = MediaStore.Audio.Media.TITLE; - p.mIsSingleChoice = true; - p.mOnItemSelectedListener = this; - p.mPositiveButtonText = getString(com.android.internal.R.string.ok); - p.mPositiveButtonListener = this; - p.mNegativeButtonText = getString(com.android.internal.R.string.cancel); - p.mPositiveButtonListener = this; - p.mOnPrepareListViewListener = this; - - p.mTitle = intent.getCharSequenceExtra(RingtoneManager.EXTRA_RINGTONE_TITLE); - if (p.mTitle == null) { - p.mTitle = getString(com.android.internal.R.string.ringtone_picker_title); - } - - setupAlert(); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putInt(SAVE_CLICKED_POS, mClickedPos); - } - - public void onPrepareListView(ListView listView) { - - if (mHasDefaultItem) { - mDefaultRingtonePos = addDefaultRingtoneItem(listView); - - if (RingtoneManager.isDefault(mExistingUri)) { - mClickedPos = mDefaultRingtonePos; - } - } - - if (mHasSilentItem) { - mSilentPos = addSilentItem(listView); - - // The 'Silent' item should use a null Uri - if (mExistingUri == null) { - mClickedPos = mSilentPos; - } - } - - if (mClickedPos == -1) { - mClickedPos = getListPosition(mRingtoneManager.getRingtonePosition(mExistingUri)); - } - - // Put a checkmark next to an item. - mAlertParams.mCheckedItem = mClickedPos; - } - - /** - * Adds a static item to the top of the list. A static item is one that is not from the - * RingtoneManager. - * - * @param listView The ListView to add to. - * @param textResId The resource ID of the text for the item. - * @return The position of the inserted item. - */ - private int addStaticItem(ListView listView, int textResId) { - TextView textView = (TextView) getLayoutInflater().inflate( - com.android.internal.R.layout.select_dialog_singlechoice_holo, listView, false); - textView.setText(textResId); - listView.addHeaderView(textView); - mStaticItemCount++; - return listView.getHeaderViewsCount() - 1; - } - - private int addDefaultRingtoneItem(ListView listView) { - return addStaticItem(listView, com.android.internal.R.string.ringtone_default); - } - - private int addSilentItem(ListView listView) { - return addStaticItem(listView, com.android.internal.R.string.ringtone_silent); - } - - /* - * On click of Ok/Cancel buttons - */ - public void onClick(DialogInterface dialog, int which) { - boolean positiveResult = which == DialogInterface.BUTTON_POSITIVE; - - // Stop playing the previous ringtone - mRingtoneManager.stopPreviousRingtone(); - - if (positiveResult) { - Intent resultIntent = new Intent(); - Uri uri = null; - - if (mClickedPos == mDefaultRingtonePos) { - // Set it to the default Uri that they originally gave us - uri = mUriForDefaultItem; - } else if (mClickedPos == mSilentPos) { - // A null Uri is for the 'Silent' item - uri = null; - } else { - uri = mRingtoneManager.getRingtoneUri(getRingtoneManagerPosition(mClickedPos)); - } - - resultIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, uri); - setResult(RESULT_OK, resultIntent); - } else { - setResult(RESULT_CANCELED); - } - - getWindow().getDecorView().post(new Runnable() { - public void run() { - mCursor.deactivate(); - } - }); - - finish(); - } - - /* - * On item selected via keys - */ - public void onItemSelected(AdapterView parent, View view, int position, long id) { - playRingtone(position, DELAY_MS_SELECTION_PLAYED); - } - - public void onNothingSelected(AdapterView parent) { - } - - private void playRingtone(int position, int delayMs) { - mHandler.removeCallbacks(this); - mSampleRingtonePos = position; - mHandler.postDelayed(this, delayMs); - } - - public void run() { - - if (mSampleRingtonePos == mSilentPos) { - mRingtoneManager.stopPreviousRingtone(); - return; - } - - /* - * Stop the default ringtone, if it's playing (other ringtones will be - * stopped by the RingtoneManager when we get another Ringtone from it. - */ - if (mDefaultRingtone != null && mDefaultRingtone.isPlaying()) { - mDefaultRingtone.stop(); - mDefaultRingtone = null; - } - - Ringtone ringtone; - if (mSampleRingtonePos == mDefaultRingtonePos) { - if (mDefaultRingtone == null) { - mDefaultRingtone = RingtoneManager.getRingtone(this, mUriForDefaultItem); - } - ringtone = mDefaultRingtone; - - /* - * Normally the non-static RingtoneManager.getRingtone stops the - * previous ringtone, but we're getting the default ringtone outside - * of the RingtoneManager instance, so let's stop the previous - * ringtone manually. - */ - mRingtoneManager.stopPreviousRingtone(); - - } else { - ringtone = mRingtoneManager.getRingtone(getRingtoneManagerPosition(mSampleRingtonePos)); - } - - if (ringtone != null) { - ringtone.play(); - } - } - - @Override - protected void onStop() { - super.onStop(); - stopAnyPlayingRingtone(); - } - - @Override - protected void onPause() { - super.onPause(); - stopAnyPlayingRingtone(); - } - - private void stopAnyPlayingRingtone() { - - if (mDefaultRingtone != null && mDefaultRingtone.isPlaying()) { - mDefaultRingtone.stop(); - } - - if (mRingtoneManager != null) { - mRingtoneManager.stopPreviousRingtone(); - } - } - - private int getRingtoneManagerPosition(int listPos) { - return listPos - mStaticItemCount; - } - - private int getListPosition(int ringtoneManagerPos) { - - // If the manager position is -1 (for not found), return that - if (ringtoneManagerPos < 0) return ringtoneManagerPos; - - return ringtoneManagerPos + mStaticItemCount; - } - -} diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java index 61866e5..48ed561 100644 --- a/core/java/com/android/internal/content/PackageHelper.java +++ b/core/java/com/android/internal/content/PackageHelper.java @@ -67,8 +67,8 @@ public class PackageHelper { return null; } - public static String createSdDir(int sizeMb, String cid, - String sdEncKey, int uid) { + public static String createSdDir(int sizeMb, String cid, String sdEncKey, int uid, + boolean isExternal) { // Create mount point via MountService IMountService mountService = getMountService(); @@ -76,8 +76,8 @@ public class PackageHelper { Log.i(TAG, "Size of container " + sizeMb + " MB"); try { - int rc = mountService.createSecureContainer( - cid, sizeMb, "fat", sdEncKey, uid); + 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; @@ -206,10 +206,21 @@ public class PackageHelper { return false; } - public static void extractPublicFiles(String packagePath, File publicZipFile) + public static int extractPublicFiles(String packagePath, File publicZipFile) throws IOException { - final FileOutputStream fstr = new FileOutputStream(publicZipFile); - final ZipOutputStream publicZipOutStream = new ZipOutputStream(fstr); + 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 { @@ -219,25 +230,29 @@ public class PackageHelper { if ("AndroidManifest.xml".equals(zipEntryName) || "resources.arsc".equals(zipEntryName) || zipEntryName.startsWith("res/")) { - copyZipEntry(zipEntry, privateZip, publicZipOutStream); + size += zipEntry.getSize(); + if (publicZipFile != null) { + copyZipEntry(zipEntry, privateZip, publicZipOutStream); + } } } } finally { - try { - privateZip.close(); - } catch (IOException e) { - } + try { privateZip.close(); } catch (IOException e) {} } - 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); + 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, @@ -265,4 +280,18 @@ public class PackageHelper { 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; + } } |
