From fe8b2477d2ad4db6e4287684845ecaacc9a21dfd Mon Sep 17 00:00:00 2001 From: Zach Johnson Date: Mon, 24 Aug 2015 16:33:16 -0700 Subject: Fix AudioAttributes.usageToString() string return values Change-Id: I75642d043d647c921259dad20df504dd2e551644 --- media/java/android/media/AudioAttributes.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'media') diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index 0f1be6b..e92f294 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -671,15 +671,15 @@ public final class AudioAttributes implements Parcelable { case USAGE_VOICE_COMMUNICATION: return new String("USAGE_VOICE_COMMUNICATION"); case USAGE_VOICE_COMMUNICATION_SIGNALLING: - return new String("USAGE_VOICE_COMMUNICATION"); + return new String("USAGE_VOICE_COMMUNICATION_SIGNALLING"); case USAGE_ALARM: return new String("USAGE_ALARM"); case USAGE_NOTIFICATION: return new String("USAGE_NOTIFICATION"); case USAGE_NOTIFICATION_RINGTONE: - return new String("USAGE_NOTIFICATION"); + return new String("USAGE_NOTIFICATION_RINGTONE"); case USAGE_NOTIFICATION_COMMUNICATION_REQUEST: - return new String("USAGE_NOTIFICATION"); + return new String("USAGE_NOTIFICATION_COMMUNICATION_REQUEST"); case USAGE_NOTIFICATION_COMMUNICATION_INSTANT: return new String("USAGE_NOTIFICATION_COMMUNICATION_INSTANT"); case USAGE_NOTIFICATION_COMMUNICATION_DELAYED: -- cgit v1.1 From f2cb9341ff864e6d9cc6797857665b2281643a74 Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Thu, 5 Nov 2015 16:44:52 -0800 Subject: Fix race condition when setting default ringtones If the device was powered off during first boot, after media scanner inserted some entries but before the default ringtone settings were set (or committed to disk), the default settings would not be set on subsequent boots. Bug: 18625739 Bug: 22349910 Change-Id: Iff07da59a9c6d53bf2950bd107ee74d02b7f48d6 --- media/java/android/media/MediaScanner.java | 89 ++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 28 deletions(-) (limited to 'media') diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 9ea6722..f36d640 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -20,6 +20,7 @@ import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; +import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; @@ -41,6 +42,7 @@ import android.provider.MediaStore.Files.FileColumns; import android.provider.MediaStore.Images; import android.provider.MediaStore.Video; import android.provider.Settings; +import android.provider.Settings.SettingNotFoundException; import android.sax.Element; import android.sax.ElementListener; import android.sax.RootElement; @@ -324,8 +326,6 @@ public class MediaScanner // used when scanning the image database so we know whether we have to prune // old thumbnail files private int mOriginalCount; - /** Whether the database had any entries in it before the scan started */ - private boolean mWasEmptyPriorToScan = false; /** Whether the scanner has set a default sound for the ringer ringtone. */ private boolean mDefaultRingtoneSet; /** Whether the scanner has set a default sound for the notification ringtone. */ @@ -535,6 +535,18 @@ public class MediaScanner if (mMtpObjectHandle != 0) { entry.mRowId = 0; } + + if ((!mDefaultNotificationSet && + doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) + || (!mDefaultRingtoneSet && + doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) + || (!mDefaultAlarmSet && + doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename))) { + Log.w(TAG, "forcing rescan of " + entry.mPath + + "since ringtone setting didn't finish"); + scanAlways = true; + } + // rescan for metadata if file was modified since last scan if (entry != null && (entry.mLastModifiedChanged || scanAlways)) { if (noMedia) { @@ -914,6 +926,26 @@ public class MediaScanner } Uri result = null; boolean needToSetSettings = false; + // Setting a flag in order not to use bulk insert for the file related with + // notifications, ringtones, and alarms, because the rowId of the inserted file is + // needed. + if (notifications && !mDefaultNotificationSet) { + if (TextUtils.isEmpty(mDefaultNotificationFilename) || + doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) { + needToSetSettings = true; + } + } else if (ringtones && !mDefaultRingtoneSet) { + if (TextUtils.isEmpty(mDefaultRingtoneFilename) || + doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) { + needToSetSettings = true; + } + } else if (alarms && !mDefaultAlarmSet) { + if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) || + doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) { + needToSetSettings = true; + } + } + if (rowId == 0) { if (mMtpObjectHandle != 0) { values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle); @@ -925,28 +957,6 @@ public class MediaScanner } values.put(Files.FileColumns.FORMAT, format); } - // Setting a flag in order not to use bulk insert for the file related with - // notifications, ringtones, and alarms, because the rowId of the inserted file is - // needed. - if (mWasEmptyPriorToScan) { - if (notifications && !mDefaultNotificationSet) { - if (TextUtils.isEmpty(mDefaultNotificationFilename) || - doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) { - needToSetSettings = true; - } - } else if (ringtones && !mDefaultRingtoneSet) { - if (TextUtils.isEmpty(mDefaultRingtoneFilename) || - doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) { - needToSetSettings = true; - } - } else if (alarms && !mDefaultAlarmSet) { - if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) || - doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) { - needToSetSettings = true; - } - } - } - // New file, insert it. // Directories need to be inserted before the files they contain, so they // get priority when bulk inserting. @@ -1016,13 +1026,20 @@ public class MediaScanner private void setSettingIfNotSet(String settingName, Uri uri, long rowId) { + if(wasSettingAlreadySet(settingName)) { + return; + } + String existingSettingValue = Settings.System.getString(mContext.getContentResolver(), settingName); if (TextUtils.isEmpty(existingSettingValue)) { // Set the setting to the given URI - Settings.System.putString(mContext.getContentResolver(), settingName, + + ContentResolver cr = mContext.getContentResolver(); + Settings.System.putString(cr, settingName, ContentUris.withAppendedId(uri, rowId).toString()); + Settings.System.putInt(cr, settingSetIndicatorName(settingName), 1); } } @@ -1050,6 +1067,20 @@ public class MediaScanner }; // end of anonymous MediaScannerClient instance + private String settingSetIndicatorName(String base) { + return base + "_set"; + } + + private boolean wasSettingAlreadySet(String name) { + ContentResolver cr = mContext.getContentResolver(); + String indicatorName = settingSetIndicatorName(name); + try { + return Settings.System.getInt(cr, indicatorName) != 0; + } catch (SettingNotFoundException e) { + return false; + } + } + private void prescan(String filePath, boolean prescanFiles) throws RemoteException { Cursor c = null; String where = null; @@ -1071,6 +1102,10 @@ public class MediaScanner selectionArgs = new String[] { "" }; } + mDefaultRingtoneSet = wasSettingAlreadySet(Settings.System.RINGTONE); + mDefaultNotificationSet = wasSettingAlreadySet(Settings.System.NOTIFICATION_SOUND); + mDefaultAlarmSet = wasSettingAlreadySet(Settings.System.ALARM_ALERT); + // Tell the provider to not delete the file. // If the file is truly gone the delete is unnecessary, and we want to avoid // accidentally deleting files that are really there (this may happen if the @@ -1089,7 +1124,6 @@ public class MediaScanner // with CursorWindow positioning. long lastId = Long.MIN_VALUE; Uri limitUri = mFilesUri.buildUpon().appendQueryParameter("limit", "1000").build(); - mWasEmptyPriorToScan = true; while (true) { selectionArgs[0] = "" + lastId; @@ -1108,7 +1142,6 @@ public class MediaScanner if (num == 0) { break; } - mWasEmptyPriorToScan = false; while (c.moveToNext()) { long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX); String path = c.getString(FILES_PRESCAN_PATH_COLUMN_INDEX); @@ -1260,7 +1293,7 @@ public class MediaScanner } } - private void postscan(String[] directories) throws RemoteException { + private void postscan(final String[] directories) throws RemoteException { // handle playlists last, after we know what media files are on the storage. if (mProcessPlaylists) { -- cgit v1.1 From 05ce0c6bb0e552701c23ce1fecd8392c9d39b31b Mon Sep 17 00:00:00 2001 From: Ian Pedowitz Date: Wed, 11 Nov 2015 21:38:04 +0000 Subject: Revert "Fix race condition when setting default ringtones" This reverts commit f2cb9341ff864e6d9cc6797857665b2281643a74. Change-Id: I151972052aea47bf8c6823eb8bbf8161c5a7a4f0 --- media/java/android/media/MediaScanner.java | 89 ++++++++++-------------------- 1 file changed, 28 insertions(+), 61 deletions(-) (limited to 'media') diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index f36d640..9ea6722 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -20,7 +20,6 @@ import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; -import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; @@ -42,7 +41,6 @@ import android.provider.MediaStore.Files.FileColumns; import android.provider.MediaStore.Images; import android.provider.MediaStore.Video; import android.provider.Settings; -import android.provider.Settings.SettingNotFoundException; import android.sax.Element; import android.sax.ElementListener; import android.sax.RootElement; @@ -326,6 +324,8 @@ public class MediaScanner // used when scanning the image database so we know whether we have to prune // old thumbnail files private int mOriginalCount; + /** Whether the database had any entries in it before the scan started */ + private boolean mWasEmptyPriorToScan = false; /** Whether the scanner has set a default sound for the ringer ringtone. */ private boolean mDefaultRingtoneSet; /** Whether the scanner has set a default sound for the notification ringtone. */ @@ -535,18 +535,6 @@ public class MediaScanner if (mMtpObjectHandle != 0) { entry.mRowId = 0; } - - if ((!mDefaultNotificationSet && - doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) - || (!mDefaultRingtoneSet && - doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) - || (!mDefaultAlarmSet && - doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename))) { - Log.w(TAG, "forcing rescan of " + entry.mPath + - "since ringtone setting didn't finish"); - scanAlways = true; - } - // rescan for metadata if file was modified since last scan if (entry != null && (entry.mLastModifiedChanged || scanAlways)) { if (noMedia) { @@ -926,26 +914,6 @@ public class MediaScanner } Uri result = null; boolean needToSetSettings = false; - // Setting a flag in order not to use bulk insert for the file related with - // notifications, ringtones, and alarms, because the rowId of the inserted file is - // needed. - if (notifications && !mDefaultNotificationSet) { - if (TextUtils.isEmpty(mDefaultNotificationFilename) || - doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) { - needToSetSettings = true; - } - } else if (ringtones && !mDefaultRingtoneSet) { - if (TextUtils.isEmpty(mDefaultRingtoneFilename) || - doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) { - needToSetSettings = true; - } - } else if (alarms && !mDefaultAlarmSet) { - if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) || - doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) { - needToSetSettings = true; - } - } - if (rowId == 0) { if (mMtpObjectHandle != 0) { values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle); @@ -957,6 +925,28 @@ public class MediaScanner } values.put(Files.FileColumns.FORMAT, format); } + // Setting a flag in order not to use bulk insert for the file related with + // notifications, ringtones, and alarms, because the rowId of the inserted file is + // needed. + if (mWasEmptyPriorToScan) { + if (notifications && !mDefaultNotificationSet) { + if (TextUtils.isEmpty(mDefaultNotificationFilename) || + doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) { + needToSetSettings = true; + } + } else if (ringtones && !mDefaultRingtoneSet) { + if (TextUtils.isEmpty(mDefaultRingtoneFilename) || + doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) { + needToSetSettings = true; + } + } else if (alarms && !mDefaultAlarmSet) { + if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) || + doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) { + needToSetSettings = true; + } + } + } + // New file, insert it. // Directories need to be inserted before the files they contain, so they // get priority when bulk inserting. @@ -1026,20 +1016,13 @@ public class MediaScanner private void setSettingIfNotSet(String settingName, Uri uri, long rowId) { - if(wasSettingAlreadySet(settingName)) { - return; - } - String existingSettingValue = Settings.System.getString(mContext.getContentResolver(), settingName); if (TextUtils.isEmpty(existingSettingValue)) { // Set the setting to the given URI - - ContentResolver cr = mContext.getContentResolver(); - Settings.System.putString(cr, settingName, + Settings.System.putString(mContext.getContentResolver(), settingName, ContentUris.withAppendedId(uri, rowId).toString()); - Settings.System.putInt(cr, settingSetIndicatorName(settingName), 1); } } @@ -1067,20 +1050,6 @@ public class MediaScanner }; // end of anonymous MediaScannerClient instance - private String settingSetIndicatorName(String base) { - return base + "_set"; - } - - private boolean wasSettingAlreadySet(String name) { - ContentResolver cr = mContext.getContentResolver(); - String indicatorName = settingSetIndicatorName(name); - try { - return Settings.System.getInt(cr, indicatorName) != 0; - } catch (SettingNotFoundException e) { - return false; - } - } - private void prescan(String filePath, boolean prescanFiles) throws RemoteException { Cursor c = null; String where = null; @@ -1102,10 +1071,6 @@ public class MediaScanner selectionArgs = new String[] { "" }; } - mDefaultRingtoneSet = wasSettingAlreadySet(Settings.System.RINGTONE); - mDefaultNotificationSet = wasSettingAlreadySet(Settings.System.NOTIFICATION_SOUND); - mDefaultAlarmSet = wasSettingAlreadySet(Settings.System.ALARM_ALERT); - // Tell the provider to not delete the file. // If the file is truly gone the delete is unnecessary, and we want to avoid // accidentally deleting files that are really there (this may happen if the @@ -1124,6 +1089,7 @@ public class MediaScanner // with CursorWindow positioning. long lastId = Long.MIN_VALUE; Uri limitUri = mFilesUri.buildUpon().appendQueryParameter("limit", "1000").build(); + mWasEmptyPriorToScan = true; while (true) { selectionArgs[0] = "" + lastId; @@ -1142,6 +1108,7 @@ public class MediaScanner if (num == 0) { break; } + mWasEmptyPriorToScan = false; while (c.moveToNext()) { long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX); String path = c.getString(FILES_PRESCAN_PATH_COLUMN_INDEX); @@ -1293,7 +1260,7 @@ public class MediaScanner } } - private void postscan(final String[] directories) throws RemoteException { + private void postscan(String[] directories) throws RemoteException { // handle playlists last, after we know what media files are on the storage. if (mProcessPlaylists) { -- cgit v1.1 From f60491183def4c46b4026afb4648544e7289ea5f Mon Sep 17 00:00:00 2001 From: Sridhar Vashist Date: Mon, 27 Jul 2015 13:30:21 -0500 Subject: MediaPlayer: Disable acquiring wakelocks based on property. Ignore setWakeMode based on system property. Wakelocks essential for playback will be held by audioflinger. Change-Id: I413cd873bf21e1e999dbf89a27802fbe1b6022c7 Signed-off-by: Sridhar Vashist --- media/java/android/media/MediaPlayer.java | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'media') diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 587d494..d1a1077 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -36,6 +36,7 @@ import android.os.Process; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemProperties; import android.provider.Settings; import android.system.ErrnoException; import android.system.OsConstants; @@ -1260,6 +1261,13 @@ public class MediaPlayer implements SubtitleController.Listener */ public void setWakeMode(Context context, int mode) { boolean washeld = false; + + /* Disable persistant wakelocks in media player based on property */ + if (SystemProperties.getBoolean("audio.offload.ignore_setawake", false) == true) { + Log.w(TAG, "IGNORING setWakeMode " + mode); + return; + } + if (mWakeLock != null) { if (mWakeLock.isHeld()) { washeld = true; -- cgit v1.1 From 8e79dae3f67aae032010ddbbef2f8032ace01263 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Wed, 2 Dec 2015 13:16:46 -0800 Subject: DO NOT MERGE Revert "MediaPlayer: Disable acquiring wakelocks based on property." This reverts commit f60491183def4c46b4026afb4648544e7289ea5f. --- media/java/android/media/MediaPlayer.java | 8 -------- 1 file changed, 8 deletions(-) (limited to 'media') diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index d1a1077..587d494 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -36,7 +36,6 @@ import android.os.Process; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemProperties; import android.provider.Settings; import android.system.ErrnoException; import android.system.OsConstants; @@ -1261,13 +1260,6 @@ public class MediaPlayer implements SubtitleController.Listener */ public void setWakeMode(Context context, int mode) { boolean washeld = false; - - /* Disable persistant wakelocks in media player based on property */ - if (SystemProperties.getBoolean("audio.offload.ignore_setawake", false) == true) { - Log.w(TAG, "IGNORING setWakeMode " + mode); - return; - } - if (mWakeLock != null) { if (mWakeLock.isHeld()) { washeld = true; -- cgit v1.1 From 0a887bcd5c5a8056735d221ad71afcff1f6eb1a6 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Mon, 30 Nov 2015 16:09:55 -0800 Subject: DO NOT MERGE SoundPool: add lock for findSample access from SoundPoolThread Sample decoding still occurs in SoundPoolThread without holding the SoundPool lock. Bug: 25781119 Change-Id: I11fde005aa9cf5438e0390a0d2dfe0ec1dd282e8 (cherry picked from commit 0275a982abecee683f16c827d405eafe51fb67ae) --- media/jni/soundpool/SoundPool.cpp | 41 ++++++++++++++++++++++++++------------- media/jni/soundpool/SoundPool.h | 4 ++-- 2 files changed, 29 insertions(+), 16 deletions(-) (limited to 'media') diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp index a705bcc..d4b54c3 100644 --- a/media/jni/soundpool/SoundPool.cpp +++ b/media/jni/soundpool/SoundPool.cpp @@ -187,6 +187,17 @@ bool SoundPool::startThreads() return mDecodeThread != NULL; } +sp SoundPool::findSample(int sampleID) +{ + Mutex::Autolock lock(&mLock); + return findSample_l(sampleID); +} + +sp SoundPool::findSample_l(int sampleID) +{ + return mSamples.valueFor(sampleID); +} + SoundChannel* SoundPool::findChannel(int channelID) { for (int i = 0; i < mMaxChannels; ++i) { @@ -211,18 +222,21 @@ int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unuse { ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d", fd, offset, length, priority); - Mutex::Autolock lock(&mLock); - sp sample = new Sample(++mNextSampleID, fd, offset, length); - mSamples.add(sample->sampleID(), sample); - doLoad(sample); - return sample->sampleID(); -} - -void SoundPool::doLoad(sp& sample) -{ - ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID()); - sample->startLoad(); - mDecodeThread->loadSample(sample->sampleID()); + int sampleID; + { + Mutex::Autolock lock(&mLock); + sampleID = ++mNextSampleID; + sp sample = new Sample(sampleID, fd, offset, length); + mSamples.add(sampleID, sample); + sample->startLoad(); + } + // mDecodeThread->loadSample() must be called outside of mLock. + // mDecodeThread->loadSample() may block on mDecodeThread message queue space; + // the message queue emptying may block on SoundPool::findSample(). + // + // It theoretically possible that sample loads might decode out-of-order. + mDecodeThread->loadSample(sampleID); + return sampleID; } bool SoundPool::unload(int sampleID) @@ -237,7 +251,6 @@ int SoundPool::play(int sampleID, float leftVolume, float rightVolume, { ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", sampleID, leftVolume, rightVolume, priority, loop, rate); - sp sample; SoundChannel* channel; int channelID; @@ -247,7 +260,7 @@ int SoundPool::play(int sampleID, float leftVolume, float rightVolume, return 0; } // is sample ready? - sample = findSample(sampleID); + sp sample(findSample_l(sampleID)); if ((sample == 0) || (sample->state() != Sample::READY)) { ALOGW(" sample %d not READY", sampleID); return 0; diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h index 4aacf53..98d2fa2 100644 --- a/media/jni/soundpool/SoundPool.h +++ b/media/jni/soundpool/SoundPool.h @@ -180,6 +180,7 @@ public: // called from SoundPoolThread void sampleLoaded(int sampleID); + sp findSample(int sampleID); // called from AudioTrack thread void done_l(SoundChannel* channel); @@ -191,8 +192,7 @@ public: private: SoundPool() {} // no default constructor bool startThreads(); - void doLoad(sp& sample); - sp findSample(int sampleID) { return mSamples.valueFor(sampleID); } + sp findSample_l(int sampleID); SoundChannel* findChannel (int channelID); SoundChannel* findNextChannel (int channelID); SoundChannel* allocateChannel_l(int priority, int sampleID); -- cgit v1.1 From 7d9fab680ee5309c6413e5547669582d3635e90b Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Thu, 5 Nov 2015 16:44:52 -0800 Subject: Fix race condition when setting default ringtones If the device was powered off during first boot, after media scanner inserted some entries but before the default ringtone settings were set (or committed to disk), the default settings would not be set on subsequent boots. Bug: 18625739 Bug: 22349910 Bug: 25633323 Change-Id: I8ff5d3c4f842297d0675e1f5cbe17c0709a14158 --- media/java/android/media/MediaScanner.java | 95 ++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 30 deletions(-) (limited to 'media') diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 9ea6722..4c8085f 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -20,6 +20,7 @@ import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; +import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; @@ -41,6 +42,7 @@ import android.provider.MediaStore.Files.FileColumns; import android.provider.MediaStore.Images; import android.provider.MediaStore.Video; import android.provider.Settings; +import android.provider.Settings.SettingNotFoundException; import android.sax.Element; import android.sax.ElementListener; import android.sax.RootElement; @@ -324,8 +326,6 @@ public class MediaScanner // used when scanning the image database so we know whether we have to prune // old thumbnail files private int mOriginalCount; - /** Whether the database had any entries in it before the scan started */ - private boolean mWasEmptyPriorToScan = false; /** Whether the scanner has set a default sound for the ringer ringtone. */ private boolean mDefaultRingtoneSet; /** Whether the scanner has set a default sound for the notification ringtone. */ @@ -529,12 +529,29 @@ public class MediaScanner FileEntry entry = beginFile(path, mimeType, lastModified, fileSize, isDirectory, noMedia); + if (entry == null) { + return null; + } + // if this file was just inserted via mtp, set the rowid to zero // (even though it already exists in the database), to trigger // the correct code path for updating its entry if (mMtpObjectHandle != 0) { entry.mRowId = 0; } + + if (entry.mPath != null && + ((!mDefaultNotificationSet && + doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) + || (!mDefaultRingtoneSet && + doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) + || (!mDefaultAlarmSet && + doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)))) { + Log.w(TAG, "forcing rescan of " + entry.mPath + + "since ringtone setting didn't finish"); + scanAlways = true; + } + // rescan for metadata if file was modified since last scan if (entry != null && (entry.mLastModifiedChanged || scanAlways)) { if (noMedia) { @@ -914,6 +931,26 @@ public class MediaScanner } Uri result = null; boolean needToSetSettings = false; + // Setting a flag in order not to use bulk insert for the file related with + // notifications, ringtones, and alarms, because the rowId of the inserted file is + // needed. + if (notifications && !mDefaultNotificationSet) { + if (TextUtils.isEmpty(mDefaultNotificationFilename) || + doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) { + needToSetSettings = true; + } + } else if (ringtones && !mDefaultRingtoneSet) { + if (TextUtils.isEmpty(mDefaultRingtoneFilename) || + doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) { + needToSetSettings = true; + } + } else if (alarms && !mDefaultAlarmSet) { + if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) || + doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) { + needToSetSettings = true; + } + } + if (rowId == 0) { if (mMtpObjectHandle != 0) { values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle); @@ -925,28 +962,6 @@ public class MediaScanner } values.put(Files.FileColumns.FORMAT, format); } - // Setting a flag in order not to use bulk insert for the file related with - // notifications, ringtones, and alarms, because the rowId of the inserted file is - // needed. - if (mWasEmptyPriorToScan) { - if (notifications && !mDefaultNotificationSet) { - if (TextUtils.isEmpty(mDefaultNotificationFilename) || - doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) { - needToSetSettings = true; - } - } else if (ringtones && !mDefaultRingtoneSet) { - if (TextUtils.isEmpty(mDefaultRingtoneFilename) || - doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) { - needToSetSettings = true; - } - } else if (alarms && !mDefaultAlarmSet) { - if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) || - doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) { - needToSetSettings = true; - } - } - } - // New file, insert it. // Directories need to be inserted before the files they contain, so they // get priority when bulk inserting. @@ -1016,14 +1031,18 @@ public class MediaScanner private void setSettingIfNotSet(String settingName, Uri uri, long rowId) { - String existingSettingValue = Settings.System.getString(mContext.getContentResolver(), - settingName); + if(wasSettingAlreadySet(settingName)) { + return; + } + ContentResolver cr = mContext.getContentResolver(); + String existingSettingValue = Settings.System.getString(cr, settingName); if (TextUtils.isEmpty(existingSettingValue)) { // Set the setting to the given URI - Settings.System.putString(mContext.getContentResolver(), settingName, + Settings.System.putString(cr, settingName, ContentUris.withAppendedId(uri, rowId).toString()); } + Settings.System.putInt(cr, settingSetIndicatorName(settingName), 1); } private int getFileTypeFromDrm(String path) { @@ -1050,6 +1069,20 @@ public class MediaScanner }; // end of anonymous MediaScannerClient instance + private String settingSetIndicatorName(String base) { + return base + "_set"; + } + + private boolean wasSettingAlreadySet(String name) { + ContentResolver cr = mContext.getContentResolver(); + String indicatorName = settingSetIndicatorName(name); + try { + return Settings.System.getInt(cr, indicatorName) != 0; + } catch (SettingNotFoundException e) { + return false; + } + } + private void prescan(String filePath, boolean prescanFiles) throws RemoteException { Cursor c = null; String where = null; @@ -1071,6 +1104,10 @@ public class MediaScanner selectionArgs = new String[] { "" }; } + mDefaultRingtoneSet = wasSettingAlreadySet(Settings.System.RINGTONE); + mDefaultNotificationSet = wasSettingAlreadySet(Settings.System.NOTIFICATION_SOUND); + mDefaultAlarmSet = wasSettingAlreadySet(Settings.System.ALARM_ALERT); + // Tell the provider to not delete the file. // If the file is truly gone the delete is unnecessary, and we want to avoid // accidentally deleting files that are really there (this may happen if the @@ -1089,7 +1126,6 @@ public class MediaScanner // with CursorWindow positioning. long lastId = Long.MIN_VALUE; Uri limitUri = mFilesUri.buildUpon().appendQueryParameter("limit", "1000").build(); - mWasEmptyPriorToScan = true; while (true) { selectionArgs[0] = "" + lastId; @@ -1108,7 +1144,6 @@ public class MediaScanner if (num == 0) { break; } - mWasEmptyPriorToScan = false; while (c.moveToNext()) { long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX); String path = c.getString(FILES_PRESCAN_PATH_COLUMN_INDEX); @@ -1260,7 +1295,7 @@ public class MediaScanner } } - private void postscan(String[] directories) throws RemoteException { + private void postscan(final String[] directories) throws RemoteException { // handle playlists last, after we know what media files are on the storage. if (mProcessPlaylists) { -- cgit v1.1