From f33a575c2b09095d58ad7af527113f767e4c37b1 Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Wed, 27 Jan 2010 15:35:43 -0800 Subject: [PATCH] Backport changes 7e94887988990e98b5c7738f393e10afa0d8ddb8 and fb5674fd0aa46a186dba92965fc5d11cd2630394 from Music2, to make it easier to share code between the two. --- src/com/android/music/AlbumBrowserActivity.java | 7 +- .../android/music/ArtistAlbumBrowserActivity.java | 6 +- src/com/android/music/MediaPickerActivity.java | 7 +- src/com/android/music/MediaPlaybackActivity.java | 8 ++- src/com/android/music/MusicBrowserActivity.java | 10 ++- src/com/android/music/MusicUtils.java | 76 ++++++++++++++++------ src/com/android/music/PlaylistBrowserActivity.java | 7 +- src/com/android/music/QueryBrowserActivity.java | 7 +- src/com/android/music/StreamStarter.java | 8 ++- src/com/android/music/TrackBrowserActivity.java | 7 +- 10 files changed, 106 insertions(+), 37 deletions(-) diff --git a/src/com/android/music/AlbumBrowserActivity.java b/src/com/android/music/AlbumBrowserActivity.java index d73cbcc..efea53b 100644 --- a/src/com/android/music/AlbumBrowserActivity.java +++ b/src/com/android/music/AlbumBrowserActivity.java @@ -16,6 +16,8 @@ package com.android.music; +import com.android.music.MusicUtils.ServiceToken; + import android.app.ListActivity; import android.app.SearchManager; import android.content.AsyncQueryHandler; @@ -75,6 +77,7 @@ public class AlbumBrowserActivity extends ListActivity private final static int SEARCH = CHILD_MENU_BASE; private static int mLastListPosCourse = -1; private static int mLastListPosFine = -1; + private ServiceToken mToken; public AlbumBrowserActivity() { @@ -94,7 +97,7 @@ public class AlbumBrowserActivity extends ListActivity requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); requestWindowFeature(Window.FEATURE_NO_TITLE); setVolumeControlStream(AudioManager.STREAM_MUSIC); - MusicUtils.bindToService(this, this); + mToken = MusicUtils.bindToService(this, this); IntentFilter f = new IntentFilter(); f.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED); @@ -160,7 +163,7 @@ public class AlbumBrowserActivity extends ListActivity mLastListPosFine = cv.getTop(); } } - MusicUtils.unbindFromService(this); + MusicUtils.unbindFromService(mToken); // If we have an adapter and didn't send it off to another activity yet, we should // close its cursor, which we do by assigning a null cursor to it. Doing this // instead of closing the cursor directly keeps the framework from accessing diff --git a/src/com/android/music/ArtistAlbumBrowserActivity.java b/src/com/android/music/ArtistAlbumBrowserActivity.java index 359c464..c0d52fb 100644 --- a/src/com/android/music/ArtistAlbumBrowserActivity.java +++ b/src/com/android/music/ArtistAlbumBrowserActivity.java @@ -16,6 +16,7 @@ package com.android.music; +import com.android.music.MusicUtils.ServiceToken; import com.android.music.QueryBrowserActivity.QueryListAdapter.QueryHandler; import android.app.ExpandableListActivity; @@ -77,6 +78,7 @@ public class ArtistAlbumBrowserActivity extends ExpandableListActivity private final static int SEARCH = CHILD_MENU_BASE; private static int mLastListPosCourse = -1; private static int mLastListPosFine = -1; + private ServiceToken mToken; /** Called when the activity is first created. */ @Override @@ -91,7 +93,7 @@ public class ArtistAlbumBrowserActivity extends ExpandableListActivity mCurrentArtistId = icicle.getString("selectedartist"); mCurrentArtistName = icicle.getString("selectedartistname"); } - MusicUtils.bindToService(this, this); + mToken = MusicUtils.bindToService(this, this); IntentFilter f = new IntentFilter(); f.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED); @@ -163,7 +165,7 @@ public class ArtistAlbumBrowserActivity extends ExpandableListActivity } } - MusicUtils.unbindFromService(this); + MusicUtils.unbindFromService(mToken); // If we have an adapter and didn't send it off to another activity yet, we should // close its cursor, which we do by assigning a null cursor to it. Doing this // instead of closing the cursor directly keeps the framework from accessing diff --git a/src/com/android/music/MediaPickerActivity.java b/src/com/android/music/MediaPickerActivity.java index c06ea29..ed67ab3 100644 --- a/src/com/android/music/MediaPickerActivity.java +++ b/src/com/android/music/MediaPickerActivity.java @@ -16,6 +16,8 @@ package com.android.music; +import com.android.music.MusicUtils.ServiceToken; + import android.app.ListActivity; import android.content.Context; import android.content.Intent; @@ -36,6 +38,7 @@ import java.util.ArrayList; public class MediaPickerActivity extends ListActivity implements MusicUtils.Defs { + private ServiceToken mToken; public MediaPickerActivity() { @@ -57,13 +60,13 @@ public class MediaPickerActivity extends ListActivity implements MusicUtils.Defs } else { setTitle(mFirstYear + "-" + mLastYear); } - MusicUtils.bindToService(this); + mToken = MusicUtils.bindToService(this); init(); } @Override public void onDestroy() { - MusicUtils.unbindFromService(this); + MusicUtils.unbindFromService(mToken); super.onDestroy(); if (mCursor != null) { mCursor.close(); diff --git a/src/com/android/music/MediaPlaybackActivity.java b/src/com/android/music/MediaPlaybackActivity.java index baf1442..c417eb2 100644 --- a/src/com/android/music/MediaPlaybackActivity.java +++ b/src/com/android/music/MediaPlaybackActivity.java @@ -16,6 +16,8 @@ package com.android.music; +import com.android.music.MusicUtils.ServiceToken; + import android.app.Activity; import android.app.AlertDialog; import android.app.KeyguardManager; @@ -83,6 +85,7 @@ public class MediaPlaybackActivity extends Activity implements MusicUtils.Defs, private AlbumArtHandler mAlbumArtHandler; private Toast mToast; private int mTouchSlop; + private ServiceToken mToken; public MediaPlaybackActivity() { @@ -471,7 +474,7 @@ public class MediaPlaybackActivity extends Activity implements MusicUtils.Defs, } mHandler.removeMessages(REFRESH); unregisterReceiver(mStatusListener); - MusicUtils.unbindFromService(this); + MusicUtils.unbindFromService(mToken); mService = null; super.onStop(); } @@ -487,7 +490,8 @@ public class MediaPlaybackActivity extends Activity implements MusicUtils.Defs, super.onStart(); paused = false; - if (false == MusicUtils.bindToService(this, osc)) { + mToken = MusicUtils.bindToService(this, osc); + if (mToken == null) { // something went wrong mHandler.sendEmptyMessage(QUIT); } diff --git a/src/com/android/music/MusicBrowserActivity.java b/src/com/android/music/MusicBrowserActivity.java index d82cdff..1c4a9d1 100644 --- a/src/com/android/music/MusicBrowserActivity.java +++ b/src/com/android/music/MusicBrowserActivity.java @@ -16,6 +16,8 @@ package com.android.music; +import com.android.music.MusicUtils.ServiceToken; + import android.app.Activity; import android.content.ComponentName; import android.content.Intent; @@ -27,6 +29,8 @@ import android.os.RemoteException; public class MusicBrowserActivity extends Activity implements MusicUtils.Defs { + private ServiceToken mToken; + public MusicBrowserActivity() { } @@ -47,13 +51,15 @@ public class MusicBrowserActivity extends Activity String shuf = getIntent().getStringExtra("autoshuffle"); if ("true".equals(shuf)) { - bindService((new Intent()).setClass(this, MediaPlaybackService.class), autoshuffle, 0); + mToken = MusicUtils.bindToService(this, autoshuffle); } } @Override public void onDestroy() { - MusicUtils.unbindFromService(this); + if (mToken != null) { + MusicUtils.unbindFromService(mToken); + } super.onDestroy(); } diff --git a/src/com/android/music/MusicUtils.java b/src/com/android/music/MusicUtils.java index ed9a3bf..d1314bf 100644 --- a/src/com/android/music/MusicUtils.java +++ b/src/com/android/music/MusicUtils.java @@ -22,6 +22,7 @@ import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; +import android.content.ContextWrapper; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; @@ -53,6 +54,7 @@ import android.view.SubMenu; import android.view.View; import android.view.ViewGroup; import android.view.Window; +import android.view.MenuItem.OnMenuItemClickListener; import android.widget.TabWidget; import android.widget.TextView; import android.widget.Toast; @@ -150,25 +152,36 @@ public class MusicUtils { public static IMediaPlaybackService sService = null; private static HashMap sConnectionMap = new HashMap(); - public static boolean bindToService(Context context) { + public static class ServiceToken { + ContextWrapper mWrappedContext; + ServiceToken(ContextWrapper context) { + mWrappedContext = context; + } + } + + public static ServiceToken bindToService(Context context) { return bindToService(context, null); } - public static boolean bindToService(Context context, ServiceConnection callback) { - context.startService(new Intent(context, MediaPlaybackService.class)); + public static ServiceToken bindToService(Context context, ServiceConnection callback) { + ContextWrapper cw = new ContextWrapper(context); + cw.startService(new Intent(cw, MediaPlaybackService.class)); ServiceBinder sb = new ServiceBinder(callback); - sConnectionMap.put(context, sb); - return context.bindService((new Intent()).setClass(context, - MediaPlaybackService.class), sb, 0); + if (cw.bindService((new Intent()).setClass(cw, MediaPlaybackService.class), sb, 0)) { + sConnectionMap.put(cw, sb); + return new ServiceToken(cw); + } + return null; } - - public static void unbindFromService(Context context) { - ServiceBinder sb = (ServiceBinder) sConnectionMap.remove(context); + + public static void unbindFromService(ServiceToken token) { + ContextWrapper cw = token.mWrappedContext; + ServiceBinder sb = sConnectionMap.remove(cw); if (sb == null) { Log.e("MusicUtils", "Trying to unbind for unknown Context"); return; } - context.unbindService(sb); + cw.unbindService(sb); if (sConnectionMap.isEmpty()) { // presumably there is nobody interested in the service at this point, // so don't hang on to the ServiceConnection @@ -282,7 +295,7 @@ public class MusicUtils { } private final static long [] sEmptyList = new long[0]; - + public static long [] getSongListForCursor(Cursor cursor) { if (cursor == null) { return sEmptyList; @@ -509,6 +522,34 @@ public class MusicUtils { } catch (RemoteException ex) { } } + + private static ContentValues[] sContentValuesCache = null; + + /** + * @param ids The source array containing all the ids to be added to the playlist + * @param offset Where in the 'ids' array we start reading + * @param len How many items to copy during this pass + * @param base The play order offset to use for this pass + */ + private static void makeInsertItems(long[] ids, int offset, int len, int base) { + // adjust 'len' if would extend beyond the end of the source array + if (offset + len > ids.length) { + len = ids.length - offset; + } + // allocate the ContentValues array, or reallocate if it is the wrong size + if (sContentValuesCache == null || sContentValuesCache.length != len) { + sContentValuesCache = new ContentValues[len]; + } + // fill in the ContentValues array with the right values for this pass + for (int i = 0; i < len; i++) { + if (sContentValuesCache[i] == null) { + sContentValuesCache[i] = new ContentValues(); + } + + sContentValuesCache[i].put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, base + offset + i); + sContentValuesCache[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, ids[offset + i]); + } + } public static void addToPlaylist(Context context, long [] ids, long playlistid) { if (ids == null) { @@ -517,7 +558,6 @@ public class MusicUtils { Log.e("MusicBase", "ListSelection null"); } else { int size = ids.length; - ContentValues values [] = new ContentValues[size]; ContentResolver resolver = context.getContentResolver(); // need to determine the number of items currently in the playlist, // so the play_order field can be maintained. @@ -529,15 +569,13 @@ public class MusicUtils { cur.moveToFirst(); int base = cur.getInt(0); cur.close(); - - for (int i = 0; i < size; i++) { - values[i] = new ContentValues(); - values[i].put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + i)); - values[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, ids[i]); + int numinserted = 0; + for (int i = 0; i < size; i += 1000) { + makeInsertItems(ids, i, 1000, base); + numinserted += resolver.bulkInsert(uri, sContentValuesCache); } - resolver.bulkInsert(uri, values); String message = context.getResources().getQuantityString( - R.plurals.NNNtrackstoplaylist, size, Integer.valueOf(size)); + R.plurals.NNNtrackstoplaylist, numinserted, numinserted); Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); //mLastPlaylistSelected = playlistid; } diff --git a/src/com/android/music/PlaylistBrowserActivity.java b/src/com/android/music/PlaylistBrowserActivity.java index a582e61..8c79e64 100644 --- a/src/com/android/music/PlaylistBrowserActivity.java +++ b/src/com/android/music/PlaylistBrowserActivity.java @@ -16,6 +16,8 @@ package com.android.music; +import com.android.music.MusicUtils.ServiceToken; + import android.app.ListActivity; import android.content.AsyncQueryHandler; import android.content.BroadcastReceiver; @@ -72,6 +74,7 @@ public class PlaylistBrowserActivity extends ListActivity private static int mLastListPosFine = -1; private boolean mCreateShortcut; + private ServiceToken mToken; public PlaylistBrowserActivity() { @@ -92,7 +95,7 @@ public class PlaylistBrowserActivity extends ListActivity requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); requestWindowFeature(Window.FEATURE_NO_TITLE); setVolumeControlStream(AudioManager.STREAM_MUSIC); - MusicUtils.bindToService(this, new ServiceConnection() { + mToken = MusicUtils.bindToService(this, new ServiceConnection() { public void onServiceConnected(ComponentName classname, IBinder obj) { if (Intent.ACTION_VIEW.equals(action)) { long id = Long.parseLong(intent.getExtras().getString("playlist")); @@ -180,7 +183,7 @@ public class PlaylistBrowserActivity extends ListActivity mLastListPosFine = cv.getTop(); } } - MusicUtils.unbindFromService(this); + MusicUtils.unbindFromService(mToken); // If we have an adapter and didn't send it off to another activity yet, we should // close its cursor, which we do by assigning a null cursor to it. Doing this // instead of closing the cursor directly keeps the framework from accessing diff --git a/src/com/android/music/QueryBrowserActivity.java b/src/com/android/music/QueryBrowserActivity.java index 896ca8f..977650c 100644 --- a/src/com/android/music/QueryBrowserActivity.java +++ b/src/com/android/music/QueryBrowserActivity.java @@ -16,6 +16,8 @@ package com.android.music; +import com.android.music.MusicUtils.ServiceToken; + import android.app.ListActivity; import android.app.SearchManager; import android.content.AsyncQueryHandler; @@ -66,6 +68,7 @@ implements MusicUtils.Defs, ServiceConnection private QueryListAdapter mAdapter; private boolean mAdapterSent; private String mFilterString = ""; + private ServiceToken mToken; public QueryBrowserActivity() { @@ -78,7 +81,7 @@ implements MusicUtils.Defs, ServiceConnection super.onCreate(icicle); setVolumeControlStream(AudioManager.STREAM_MUSIC); mAdapter = (QueryListAdapter) getLastNonConfigurationInstance(); - MusicUtils.bindToService(this, this); + mToken = MusicUtils.bindToService(this, this); // defer the real work until we're bound to the service } @@ -195,7 +198,7 @@ implements MusicUtils.Defs, ServiceConnection @Override public void onDestroy() { - MusicUtils.unbindFromService(this); + MusicUtils.unbindFromService(mToken); unregisterReceiver(mScanListener); // If we have an adapter and didn't send it off to another activity yet, we should // close its cursor, which we do by assigning a null cursor to it. Doing this diff --git a/src/com/android/music/StreamStarter.java b/src/com/android/music/StreamStarter.java index a43dbf5..e823ee2 100644 --- a/src/com/android/music/StreamStarter.java +++ b/src/com/android/music/StreamStarter.java @@ -16,6 +16,8 @@ package com.android.music; +import com.android.music.MusicUtils.ServiceToken; + import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -34,6 +36,8 @@ import android.widget.Toast; public class StreamStarter extends Activity { + private ServiceToken mToken; + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -53,7 +57,7 @@ public class StreamStarter extends Activity public void onResume() { super.onResume(); - MusicUtils.bindToService(this, new ServiceConnection() { + mToken = MusicUtils.bindToService(this, new ServiceConnection() { public void onServiceConnected(ComponentName classname, IBinder obj) { try { IntentFilter f = new IntentFilter(); @@ -111,7 +115,7 @@ public class StreamStarter extends Activity } } unregisterReceiver(mStatusListener); - MusicUtils.unbindFromService(this); + MusicUtils.unbindFromService(mToken); super.onPause(); } } diff --git a/src/com/android/music/TrackBrowserActivity.java b/src/com/android/music/TrackBrowserActivity.java index cfece30..39bdeed 100644 --- a/src/com/android/music/TrackBrowserActivity.java +++ b/src/com/android/music/TrackBrowserActivity.java @@ -16,6 +16,8 @@ package com.android.music; +import com.android.music.MusicUtils.ServiceToken; + import android.app.ListActivity; import android.app.SearchManager; import android.content.AsyncQueryHandler; @@ -97,6 +99,7 @@ public class TrackBrowserActivity extends ListActivity private static int mLastListPosCourse = -1; private static int mLastListPosFine = -1; private boolean mUseLastListPos = false; + private ServiceToken mToken; public TrackBrowserActivity() { @@ -171,7 +174,7 @@ public class TrackBrowserActivity extends ListActivity mAdapter.setActivity(this); setListAdapter(mAdapter); } - MusicUtils.bindToService(this, this); + mToken = MusicUtils.bindToService(this, this); // don't set the album art until after the view has been layed out mTrackList.post(new Runnable() { @@ -248,7 +251,7 @@ public class TrackBrowserActivity extends ListActivity mLastListPosFine = cv.getTop(); } } - MusicUtils.unbindFromService(this); + MusicUtils.unbindFromService(mToken); try { if ("nowplaying".equals(mPlaylist)) { unregisterReceiverSafe(mNowPlayingListener); -- 2.11.0