diff options
Diffstat (limited to 'media/java')
| -rw-r--r-- | media/java/android/media/AmrInputStream.java | 2 | ||||
| -rw-r--r-- | media/java/android/media/AsyncPlayer.java | 2 | ||||
| -rw-r--r-- | media/java/android/media/AudioManager.java | 47 | ||||
| -rw-r--r-- | media/java/android/media/AudioRecord.java | 2 | ||||
| -rw-r--r-- | media/java/android/media/AudioService.java | 61 | ||||
| -rw-r--r-- | media/java/android/media/ExifInterface.java | 2 | ||||
| -rw-r--r-- | media/java/android/media/MediaFile.java | 10 | ||||
| -rw-r--r-- | media/java/android/media/MediaInserter.java | 2 | ||||
| -rw-r--r-- | media/java/android/media/MediaRecorder.java | 21 | ||||
| -rw-r--r-- | media/java/android/media/MediaScanner.java | 40 | ||||
| -rw-r--r-- | media/java/android/media/MediaScannerConnection.java | 2 | ||||
| -rw-r--r-- | media/java/android/media/MiniThumbFile.java | 2 | ||||
| -rw-r--r-- | media/java/android/media/RemoteControlClient.java | 3 | ||||
| -rw-r--r-- | media/java/android/media/RingtoneManager.java | 2 | ||||
| -rwxr-xr-x | media/java/android/mtp/MtpDatabase.java | 46 | ||||
| -rw-r--r-- | media/java/android/mtp/MtpPropertyGroup.java | 10 |
16 files changed, 158 insertions, 96 deletions
diff --git a/media/java/android/media/AmrInputStream.java b/media/java/android/media/AmrInputStream.java index bc68472..8b7eee2 100644 --- a/media/java/android/media/AmrInputStream.java +++ b/media/java/android/media/AmrInputStream.java @@ -44,7 +44,7 @@ public final class AmrInputStream extends InputStream private int mGae; // result amr stream - private byte[] mBuf = new byte[SAMPLES_PER_FRAME * 2]; + private final byte[] mBuf = new byte[SAMPLES_PER_FRAME * 2]; private int mBufIn = 0; private int mBufOut = 0; diff --git a/media/java/android/media/AsyncPlayer.java b/media/java/android/media/AsyncPlayer.java index 09aec2e..804528e 100644 --- a/media/java/android/media/AsyncPlayer.java +++ b/media/java/android/media/AsyncPlayer.java @@ -49,7 +49,7 @@ public class AsyncPlayer { } } - private LinkedList<Command> mCmdQueue = new LinkedList(); + private final LinkedList<Command> mCmdQueue = new LinkedList(); private void startSound(Command cmd) { // Preparing can be slow, so if there is something else diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 936ec0f..78eb89f 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1509,7 +1509,7 @@ public class AudioManager { * Map to convert focus event listener IDs, as used in the AudioService audio focus stack, * to actual listener objects. */ - private HashMap<String, OnAudioFocusChangeListener> mAudioFocusIdListenerMap = + private final HashMap<String, OnAudioFocusChangeListener> mAudioFocusIdListenerMap = new HashMap<String, OnAudioFocusChangeListener>(); /** * Lock to prevent concurrent changes to the list of focus listeners for this AudioManager @@ -1524,7 +1524,7 @@ public class AudioManager { /** * Handler for audio focus events coming from the audio service. */ - private FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate = + private final FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate = new FocusEventHandlerDelegate(); /** @@ -1563,7 +1563,7 @@ public class AudioManager { } } - private IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() { + private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() { public void dispatchAudioFocusChange(int focusChange, String id) { Message m = mAudioFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id); @@ -1649,11 +1649,46 @@ public class AudioManager { mAudioFocusDispatcher, getIdForAudioFocusListener(l), mContext.getPackageName() /* package name */); } catch (RemoteException e) { - Log.e(TAG, "Can't call requestAudioFocus() from AudioService due to "+e); + Log.e(TAG, "Can't call requestAudioFocus() on AudioService due to "+e); } return status; } + /** + * @hide + * Used internally by telephony package to request audio focus. Will cause the focus request + * to be associated with the "voice communication" identifier only used in AudioService + * to identify this use case. + * @param streamType use STREAM_RING for focus requests when ringing, VOICE_CALL for + * the establishment of the call + * @param durationHint the type of focus request. AUDIOFOCUS_GAIN_TRANSIENT is recommended so + * media applications resume after a call + */ + public void requestAudioFocusForCall(int streamType, int durationHint) { + IAudioService service = getService(); + try { + service.requestAudioFocus(streamType, durationHint, mICallBack, null, + AudioService.IN_VOICE_COMM_FOCUS_ID, + "system" /* dump-friendly package name */); + } catch (RemoteException e) { + Log.e(TAG, "Can't call requestAudioFocusForCall() on AudioService due to "+e); + } + } + + /** + * @hide + * Used internally by telephony package to abandon audio focus, typically after a call or + * when ringing ends and the call is rejected or not answered. + * Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}. + */ + public void abandonAudioFocusForCall() { + IAudioService service = getService(); + try { + service.abandonAudioFocus(null, AudioService.IN_VOICE_COMM_FOCUS_ID); + } catch (RemoteException e) { + Log.e(TAG, "Can't call abandonAudioFocusForCall() on AudioService due to "+e); + } + } /** * Abandon audio focus. Causes the previous focus owner, if any, to receive focus. @@ -1668,7 +1703,7 @@ public class AudioManager { status = service.abandonAudioFocus(mAudioFocusDispatcher, getIdForAudioFocusListener(l)); } catch (RemoteException e) { - Log.e(TAG, "Can't call abandonAudioFocus() from AudioService due to "+e); + Log.e(TAG, "Can't call abandonAudioFocus() on AudioService due to "+e); } return status; } @@ -1920,7 +1955,7 @@ public class AudioManager { /** * {@hide} */ - private IBinder mICallBack = new Binder(); + private final IBinder mICallBack = new Binder(); /** * Checks whether the phone is in silent mode, with or without vibrate. diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 855e831..5cc24c0 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -161,7 +161,7 @@ public class AudioRecord /** * Lock to make sure mRecordingState updates are reflecting the actual state of the object. */ - private Object mRecordingStateLock = new Object(); + private final Object mRecordingStateLock = new Object(); /** * The listener the AudioRecord notifies when the record position reaches a marker * or for periodic updates during the progression of the record head. diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 2eafd68..13e3982 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -151,7 +151,7 @@ public class AudioService extends IAudioService.Stub { private boolean mMediaServerOk; private SoundPool mSoundPool; - private Object mSoundEffectsLock = new Object(); + private final Object mSoundEffectsLock = new Object(); private static final int NUM_SOUNDPOOL_CHANNELS = 4; private static final int SOUND_EFFECT_VOLUME = 1000; @@ -168,7 +168,7 @@ public class AudioService extends IAudioService.Stub { /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect * uses soundpool (second column) */ - private int[][] SOUND_EFFECT_FILES_MAP = new int[][] { + private final int[][] SOUND_EFFECT_FILES_MAP = new int[][] { {0, -1}, // FX_KEY_CLICK {0, -1}, // FX_FOCUS_NAVIGATION_UP {0, -1}, // FX_FOCUS_NAVIGATION_DOWN @@ -181,7 +181,7 @@ public class AudioService extends IAudioService.Stub { }; /** @hide Maximum volume index values for audio streams */ - private int[] MAX_STREAM_VOLUME = new int[] { + private final int[] MAX_STREAM_VOLUME = new int[] { 5, // STREAM_VOICE_CALL 7, // STREAM_SYSTEM 7, // STREAM_RING @@ -197,7 +197,7 @@ public class AudioService extends IAudioService.Stub { * of another stream: This avoids multiplying the volume settings for hidden * stream types that follow other stream behavior for volume settings * NOTE: do not create loops in aliases! */ - private int[] STREAM_VOLUME_ALIAS = new int[] { + private final int[] STREAM_VOLUME_ALIAS = new int[] { AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL AudioSystem.STREAM_SYSTEM, // STREAM_SYSTEM AudioSystem.STREAM_RING, // STREAM_RING @@ -210,7 +210,7 @@ public class AudioService extends IAudioService.Stub { AudioSystem.STREAM_MUSIC // STREAM_TTS }; - private AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() { + private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() { public void onError(int error) { switch (error) { case AudioSystem.AUDIO_STATUS_SERVER_DIED: @@ -270,17 +270,17 @@ public class AudioService extends IAudioService.Stub { private boolean mIsRinging = false; // Devices currently connected - private HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>(); + private final HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>(); // Forced device usage for communications private int mForcedUseForComm; // List of binder death handlers for setMode() client processes. // The last process to have called setMode() is at the top of the list. - private ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>(); + private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>(); // List of clients having issued a SCO start request - private ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>(); + private final ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>(); // BluetoothHeadset API to control SCO connection private BluetoothHeadset mBluetoothHeadset; @@ -992,8 +992,6 @@ public class AudioService extends IAudioService.Stub { if (mode != mMode) { status = AudioSystem.setPhoneState(mode); if (status == AudioSystem.AUDIO_STATUS_OK) { - // automatically handle audio focus for mode changes - handleFocusForCalls(mMode, mode, cb); mMode = mode; } else { if (hdlr != null) { @@ -1024,40 +1022,6 @@ public class AudioService extends IAudioService.Stub { return newModeOwnerPid; } - /** pre-condition: oldMode != newMode */ - private void handleFocusForCalls(int oldMode, int newMode, IBinder cb) { - // if ringing - if (newMode == AudioSystem.MODE_RINGTONE) { - // if not ringing silently - int ringVolume = AudioService.this.getStreamVolume(AudioManager.STREAM_RING); - if (ringVolume > 0) { - // request audio focus for the communication focus entry - requestAudioFocus(AudioManager.STREAM_RING, - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, cb, - null /* IAudioFocusDispatcher allowed to be null only for this clientId */, - IN_VOICE_COMM_FOCUS_ID /*clientId*/, - "system"); - - } - } - // if entering call - else if ((newMode == AudioSystem.MODE_IN_CALL) - || (newMode == AudioSystem.MODE_IN_COMMUNICATION)) { - // request audio focus for the communication focus entry - // (it's ok if focus was already requested during ringing) - requestAudioFocus(AudioManager.STREAM_RING, - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, cb, - null /* IAudioFocusDispatcher allowed to be null only for this clientId */, - IN_VOICE_COMM_FOCUS_ID /*clientId*/, - "system"); - } - // if exiting call - else if (newMode == AudioSystem.MODE_NORMAL) { - // abandon audio focus for communication focus entry - abandonAudioFocus(null, IN_VOICE_COMM_FOCUS_ID); - } - } - /** @see AudioManager#getMode() */ public int getMode() { return mMode; @@ -2896,9 +2860,10 @@ public class AudioService extends IAudioService.Stub { //========================================================================================== /* constant to identify focus stack entry that is used to hold the focus while the phone - * is ringing or during a call + * is ringing or during a call. Used by com.android.internal.telephony.CallManager when + * entering and exiting calls. */ - private final static String IN_VOICE_COMM_FOCUS_ID = "AudioFocus_For_Phone_Ring_And_Calls"; + public final static String IN_VOICE_COMM_FOCUS_ID = "AudioFocus_For_Phone_Ring_And_Calls"; private final static Object mAudioFocusLock = new Object(); @@ -2980,7 +2945,7 @@ public class AudioService extends IAudioService.Stub { } } - private Stack<FocusStackEntry> mFocusStack = new Stack<FocusStackEntry>(); + private final Stack<FocusStackEntry> mFocusStack = new Stack<FocusStackEntry>(); /** * Helper function: @@ -3357,7 +3322,7 @@ public class AudioService extends IAudioService.Stub { * synchronized on mRCStack, but also BEFORE on mFocusLock as any change in either * stack, audio focus or RC, can lead to a change in the remote control display */ - private Stack<RemoteControlStackEntry> mRCStack = new Stack<RemoteControlStackEntry>(); + private final Stack<RemoteControlStackEntry> mRCStack = new Stack<RemoteControlStackEntry>(); /** * Helper function: diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index 925f965..9d6c9f6 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -111,7 +111,7 @@ public class ExifInterface { // there can only be one user at a time for the native functions (and // they cannot keep state in the native code across function calls). We // use sLock to serialize the accesses. - private static Object sLock = new Object(); + private static final Object sLock = new Object(); /** * Reads Exif tags from the specified JPEG file. diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index e275aa6..7f7e284 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -120,18 +120,18 @@ public class MediaFile { } } - private static HashMap<String, MediaFileType> sFileTypeMap + private static final HashMap<String, MediaFileType> sFileTypeMap = new HashMap<String, MediaFileType>(); - private static HashMap<String, Integer> sMimeTypeMap + private static final HashMap<String, Integer> sMimeTypeMap = new HashMap<String, Integer>(); // maps file extension to MTP format code - private static HashMap<String, Integer> sFileTypeToFormatMap + private static final HashMap<String, Integer> sFileTypeToFormatMap = new HashMap<String, Integer>(); // maps mime type to MTP format code - private static HashMap<String, Integer> sMimeTypeToFormatMap + private static final HashMap<String, Integer> sMimeTypeToFormatMap = new HashMap<String, Integer>(); // maps MTP format code to mime type - private static HashMap<Integer, String> sFormatToMimeTypeMap + private static final HashMap<Integer, String> sFormatToMimeTypeMap = new HashMap<Integer, String>(); static void addFileType(String extension, int fileType, String mimeType) { diff --git a/media/java/android/media/MediaInserter.java b/media/java/android/media/MediaInserter.java index a998407..e92c710 100644 --- a/media/java/android/media/MediaInserter.java +++ b/media/java/android/media/MediaInserter.java @@ -32,7 +32,7 @@ import java.util.List; * {@hide} */ public class MediaInserter { - private HashMap<Uri, List<ContentValues>> mRowMap = + private final HashMap<Uri, List<ContentValues>> mRowMap = new HashMap<Uri, List<ContentValues>>(); private IContentProvider mProvider; diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 08e6032..85d99c1 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -138,10 +138,13 @@ public class MediaRecorder */ public final class AudioSource { /* Do not change these values without updating their counterparts - * in include/media/mediarecorder.h! + * in system/core/include/system/audio.h! */ private AudioSource() {} + + /** Default audio source **/ public static final int DEFAULT = 0; + /** Microphone audio source */ public static final int MIC = 1; @@ -201,18 +204,24 @@ public class MediaRecorder /** MPEG4 media file format*/ public static final int MPEG_4 = 2; - /** The following formats are audio only .aac or .amr formats **/ - /** @deprecated Deprecated in favor of AMR_NB */ - /** Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB */ - /** AMR NB file format */ + /** The following formats are audio only .aac or .amr formats */ + + /** + * AMR NB file format + * @deprecated Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB + */ public static final int RAW_AMR = 3; + /** AMR NB file format */ public static final int AMR_NB = 3; + /** AMR WB file format */ public static final int AMR_WB = 4; + /** @hide AAC ADIF file format */ public static final int AAC_ADIF = 5; - /** @hide AAC ADTS file format */ + + /** AAC ADTS file format */ public static final int AAC_ADTS = 6; /** @hide Stream over a socket, limited to a single stream */ diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index b06ef95..1c13fff 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -35,6 +35,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.SystemProperties; import android.provider.MediaStore; +import android.provider.MediaStore.Files.FileColumns; import android.provider.Settings; import android.provider.MediaStore.Audio; import android.provider.MediaStore.Files; @@ -58,6 +59,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.Locale; /** * Internal service helper that no-one should use directly. @@ -312,10 +314,8 @@ public class MediaScanner private final String mExternalStoragePath; - // WARNING: Bulk inserts sounded like a great idea and gave us a good performance improvement, - // but unfortunately it also introduced a number of bugs. All the known bugs were fixed, - // but we need more testing before enabling. - private static final boolean ENABLE_BULK_INSERTS = false; + /** whether to use bulk inserts or individual inserts for each item */ + private static final boolean ENABLE_BULK_INSERTS = true; // used when scanning the image database so we know whether we have to prune // old thumbnail files @@ -345,7 +345,7 @@ public class MediaScanner // this should be set when scanning files on a case insensitive file system. private boolean mCaseInsensitivePaths; - private BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); + private final BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); private static class FileCacheEntry { long mRowId; @@ -401,7 +401,7 @@ public class MediaScanner + Settings.System.ALARM_ALERT); } - private MyMediaScannerClient mClient = new MyMediaScannerClient(); + private final MyMediaScannerClient mClient = new MyMediaScannerClient(); private boolean isDrmEnabled() { String prop = SystemProperties.get("drm.service.enabled"); @@ -946,6 +946,22 @@ public class MediaScanner // path should never change, and we want to avoid replacing mixed cased paths // with squashed lower case paths values.remove(MediaStore.MediaColumns.DATA); + + int mediaType = 0; + if (!MediaScanner.isNoMediaPath(entry.mPath)) { + int fileType = MediaFile.getFileTypeForMimeType(mMimeType); + if (MediaFile.isAudioFileType(fileType)) { + mediaType = FileColumns.MEDIA_TYPE_AUDIO; + } else if (MediaFile.isVideoFileType(fileType)) { + mediaType = FileColumns.MEDIA_TYPE_VIDEO; + } else if (MediaFile.isImageFileType(fileType)) { + mediaType = FileColumns.MEDIA_TYPE_IMAGE; + } else if (MediaFile.isPlayListFileType(fileType)) { + mediaType = FileColumns.MEDIA_TYPE_PLAYLIST; + } + values.put(FileColumns.MEDIA_TYPE, mediaType); + } + mMediaProvider.update(result, values, null, null); } @@ -1035,7 +1051,7 @@ public class MediaScanner // First read existing files from the files table c = mMediaProvider.query(mFilesUri, FILES_PRESCAN_PROJECTION, - where, selectionArgs, null); + where, selectionArgs, null, null); if (c != null) { mWasEmptyPriorToScan = c.getCount() == 0; @@ -1072,7 +1088,7 @@ public class MediaScanner // compute original size of images mOriginalCount = 0; - c = mMediaProvider.query(mImagesUri, ID_PROJECTION, null, null, null); + c = mMediaProvider.query(mImagesUri, ID_PROJECTION, null, null, null, null); if (c != null) { mOriginalCount = c.getCount(); c.close(); @@ -1107,7 +1123,7 @@ public class MediaScanner new String [] { "_data" }, null, null, - null); + null, null); Log.v(TAG, "pruneDeadThumbnailFiles... " + c); if (c != null && c.moveToFirst()) { do { @@ -1180,6 +1196,10 @@ public class MediaScanner mMediaProvider.delete(ContentUris.withAppendedId(mFilesUri, entry.mRowId), null, null); iterator.remove(); + if (entry.mPath.toLowerCase(Locale.US).endsWith("/.nomedia")) { + File f = new File(path); + mMediaProvider.call(MediaStore.UNHIDE_CALL, f.getParent(), null); + } } } } @@ -1472,7 +1492,7 @@ public class MediaScanner if (bestMatch.mRowId == 0) { Cursor c = mMediaProvider.query(mAudioUri, ID_PROJECTION, MediaStore.Files.FileColumns.DATA + "=?", - new String[] { bestMatch.mPath }, null); + new String[] { bestMatch.mPath }, null, null); if (c != null) { if (c.moveToNext()) { bestMatch.mRowId = c.getLong(0); diff --git a/media/java/android/media/MediaScannerConnection.java b/media/java/android/media/MediaScannerConnection.java index 969da39..21b6e14 100644 --- a/media/java/android/media/MediaScannerConnection.java +++ b/media/java/android/media/MediaScannerConnection.java @@ -46,7 +46,7 @@ public class MediaScannerConnection implements ServiceConnection { private IMediaScannerService mService; private boolean mConnected; // true if connect() has been called since last disconnect() - private IMediaScannerListener.Stub mListener = new IMediaScannerListener.Stub() { + private final IMediaScannerListener.Stub mListener = new IMediaScannerListener.Stub() { public void scanCompleted(String path, Uri uri) { MediaScannerConnectionClient client = mClient; if (client != null) { diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java index df141c1..63b149c 100644 --- a/media/java/android/media/MiniThumbFile.java +++ b/media/java/android/media/MiniThumbFile.java @@ -52,7 +52,7 @@ public class MiniThumbFile { private RandomAccessFile mMiniThumbFile; private FileChannel mChannel; private ByteBuffer mBuffer; - private static Hashtable<String, MiniThumbFile> sThumbFiles = + private static final Hashtable<String, MiniThumbFile> sThumbFiles = new Hashtable<String, MiniThumbFile>(); /** diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java index 77acfe6..18b4ee6 100644 --- a/media/java/android/media/RemoteControlClient.java +++ b/media/java/android/media/RemoteControlClient.java @@ -576,6 +576,7 @@ public class RemoteControlClient /** * Cache for the metadata strings. * Access synchronized on mCacheLock + * This is re-initialized in apply() and so cannot be final. */ private Bundle mMetadata = new Bundle(); @@ -621,7 +622,7 @@ public class RemoteControlClient /** * The IRemoteControlClient implementation */ - private IRemoteControlClient mIRCC = new IRemoteControlClient.Stub() { + private final IRemoteControlClient mIRCC = new IRemoteControlClient.Stub() { public void onInformationRequested(int clientGeneration, int infoFlags, int artWidth, int artHeight) { diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java index 9c0819f..7aaf4aa 100644 --- a/media/java/android/media/RingtoneManager.java +++ b/media/java/android/media/RingtoneManager.java @@ -224,7 +224,7 @@ public class RingtoneManager { * If a column (item from this list) exists in the Cursor, its value must * be true (value of 1) for the row to be returned. */ - private List<String> mFilterColumns = new ArrayList<String>(); + private final List<String> mFilterColumns = new ArrayList<String>(); private boolean mStopPreviousRingtone = true; private Ringtone mPreviousRingtone; diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java index 19db1c0..18aa4b3 100755 --- a/media/java/android/mtp/MtpDatabase.java +++ b/media/java/android/mtp/MtpDatabase.java @@ -266,7 +266,7 @@ public class MtpDatabase { Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PATH_WHERE, - new String[] { path }, null); + new String[] { path }, null, null); if (c != null && c.getCount() > 0) { Log.w(TAG, "file already exists in beginSendObject: " + path); return -1; @@ -433,7 +433,7 @@ public class MtpDatabase { } } - return mMediaProvider.query(mObjectsUri, ID_PROJECTION, where, whereArgs, null); + return mMediaProvider.query(mObjectsUri, ID_PROJECTION, where, whereArgs, null, null); } private int[] getObjectList(int storageID, int format, int parent) { @@ -699,7 +699,7 @@ public class MtpDatabase { String path = null; String[] whereArgs = new String[] { Integer.toString(handle) }; try { - c = mMediaProvider.query(mObjectsUri, PATH_PROJECTION, ID_WHERE, whereArgs, null); + c = mMediaProvider.query(mObjectsUri, PATH_PROJECTION, ID_WHERE, whereArgs, null, null); if (c != null && c.moveToNext()) { path = c.getString(1); } @@ -752,6 +752,29 @@ public class MtpDatabase { return MtpConstants.RESPONSE_GENERAL_ERROR; } + // check if nomedia status changed + if (newFile.isDirectory()) { + // for directories, check if renamed from something hidden to something non-hidden + if (oldFile.getName().startsWith(".") && !newPath.startsWith(".")) { + // directory was unhidden + try { + mMediaProvider.call(MediaStore.UNHIDE_CALL, newPath, null); + } catch (RemoteException e) { + Log.e(TAG, "failed to unhide/rescan for " + newPath); + } + } + } else { + // for files, check if renamed from .nomedia to something else + if (oldFile.getName().toLowerCase(Locale.US).equals(".nomedia") + && !newPath.toLowerCase(Locale.US).equals(".nomedia")) { + try { + mMediaProvider.call(MediaStore.UNHIDE_CALL, oldFile.getParent(), null); + } catch (RemoteException e) { + Log.e(TAG, "failed to unhide/rescan for " + newPath); + } + } + } + return MtpConstants.RESPONSE_OK; } @@ -815,7 +838,7 @@ public class MtpDatabase { Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION, - ID_WHERE, new String[] { Integer.toString(handle) }, null); + ID_WHERE, new String[] { Integer.toString(handle) }, null, null); if (c != null && c.moveToNext()) { outStorageFormatParent[0] = c.getInt(1); outStorageFormatParent[1] = c.getInt(2); @@ -858,7 +881,7 @@ public class MtpDatabase { Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION, - ID_WHERE, new String[] { Integer.toString(handle) }, null); + ID_WHERE, new String[] { Integer.toString(handle) }, null, null); if (c != null && c.moveToNext()) { String path = c.getString(1); path.getChars(0, path.length(), outFilePath, 0); @@ -887,7 +910,7 @@ public class MtpDatabase { Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION, - ID_WHERE, new String[] { Integer.toString(handle) }, null); + ID_WHERE, new String[] { Integer.toString(handle) }, null, null); if (c != null && c.moveToNext()) { // don't convert to media path here, since we will be matching // against paths in the database matching /data/media @@ -915,6 +938,15 @@ public class MtpDatabase { Uri uri = Files.getMtpObjectsUri(mVolumeName, handle); if (mMediaProvider.delete(uri, null, null) > 0) { + if (format != MtpConstants.FORMAT_ASSOCIATION + && path.toLowerCase(Locale.US).endsWith("/.nomedia")) { + try { + String parentPath = path.substring(0, path.lastIndexOf("/")); + mMediaProvider.call(MediaStore.UNHIDE_CALL, parentPath, null); + } catch (RemoteException e) { + Log.e(TAG, "failed to unhide/rescan for " + path); + } + } return MtpConstants.RESPONSE_OK; } else { return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; @@ -933,7 +965,7 @@ public class MtpDatabase { Uri uri = Files.getMtpReferencesUri(mVolumeName, handle); Cursor c = null; try { - c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null); + c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null, null); if (c == null) { return null; } diff --git a/media/java/android/mtp/MtpPropertyGroup.java b/media/java/android/mtp/MtpPropertyGroup.java index 76c8569..dab5454 100644 --- a/media/java/android/mtp/MtpPropertyGroup.java +++ b/media/java/android/mtp/MtpPropertyGroup.java @@ -191,7 +191,7 @@ class MtpPropertyGroup { // for now we are only reading properties from the "objects" table c = mProvider.query(mUri, new String [] { Files.FileColumns._ID, column }, - ID_WHERE, new String[] { Integer.toString(id) }, null); + ID_WHERE, new String[] { Integer.toString(id) }, null, null); if (c != null && c.moveToNext()) { return c.getString(1); } else { @@ -211,7 +211,7 @@ class MtpPropertyGroup { try { c = mProvider.query(Audio.Media.getContentUri(mVolumeName), new String [] { Files.FileColumns._ID, column }, - ID_WHERE, new String[] { Integer.toString(id) }, null); + ID_WHERE, new String[] { Integer.toString(id) }, null, null); if (c != null && c.moveToNext()) { return c.getString(1); } else { @@ -232,7 +232,7 @@ class MtpPropertyGroup { Uri uri = Audio.Genres.getContentUriForAudioId(mVolumeName, id); c = mProvider.query(uri, new String [] { Files.FileColumns._ID, Audio.GenresColumns.NAME }, - null, null, null); + null, null, null, null); if (c != null && c.moveToNext()) { return c.getString(1); } else { @@ -254,7 +254,7 @@ class MtpPropertyGroup { // for now we are only reading properties from the "objects" table c = mProvider.query(mUri, new String [] { Files.FileColumns._ID, column }, - ID_WHERE, new String[] { Integer.toString(id) }, null); + ID_WHERE, new String[] { Integer.toString(id) }, null, null); if (c != null && c.moveToNext()) { return new Long(c.getLong(1)); } @@ -323,7 +323,7 @@ class MtpPropertyGroup { try { // don't query if not necessary if (depth > 0 || handle == 0xFFFFFFFF || mColumns.length > 1) { - c = mProvider.query(mUri, mColumns, where, whereArgs, null); + c = mProvider.query(mUri, mColumns, where, whereArgs, null, null); if (c == null) { return new MtpPropertyList(0, MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE); } |
