Merge "Update with latest translations."
diff --git a/src/com/android/music/MediaPickerActivity.java b/src/com/android/music/MediaPickerActivity.java
index 3261701..c06ea29 100644
--- a/src/com/android/music/MediaPickerActivity.java
+++ b/src/com/android/music/MediaPickerActivity.java
@@ -16,8 +16,6 @@
package com.android.music;
-import com.android.internal.database.SortCursor;
-
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
diff --git a/src/com/android/music/MediaPlaybackActivity.java b/src/com/android/music/MediaPlaybackActivity.java
index 6a2689f..baf1442 100644
--- a/src/com/android/music/MediaPlaybackActivity.java
+++ b/src/com/android/music/MediaPlaybackActivity.java
@@ -30,17 +30,16 @@
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.text.Layout;
@@ -54,7 +53,6 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
-import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
diff --git a/src/com/android/music/MediaPlaybackService.java b/src/com/android/music/MediaPlaybackService.java
index 77226d1..ed94634 100644
--- a/src/com/android/music/MediaPlaybackService.java
+++ b/src/com/android/music/MediaPlaybackService.java
@@ -34,8 +34,6 @@
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
-import android.os.Environment;
-import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -268,7 +266,7 @@
super.onCreate();
mPreferences = getSharedPreferences("Music", MODE_WORLD_READABLE | MODE_WORLD_WRITEABLE);
- mCardId = FileUtils.getFatVolumeId(Environment.getExternalStorageDirectory().getPath());
+ mCardId = MusicUtils.getCardId(this);
registerExternalStorageListener();
@@ -676,7 +674,7 @@
closeExternalStorageFiles(intent.getData().getPath());
} else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
mMediaMountedCount++;
- mCardId = FileUtils.getFatVolumeId(intent.getData().getPath());
+ mCardId = MusicUtils.getCardId(MediaPlaybackService.this);
reloadQueue();
notifyChange(QUEUE_CHANGED);
notifyChange(META_CHANGED);
diff --git a/src/com/android/music/MusicUtils.java b/src/com/android/music/MusicUtils.java
index 46c4eae..2262d03 100644
--- a/src/com/android/music/MusicUtils.java
+++ b/src/com/android/music/MusicUtils.java
@@ -1232,4 +1232,15 @@
v.setBackgroundDrawable(new BitmapDrawable(bg));
}
+ static int getCardId(Context context) {
+ ContentResolver res = context.getContentResolver();
+ Cursor c = res.query(Uri.parse("content://media/external/fs_id"), null, null, null, null);
+ int id = -1;
+ if (c != null) {
+ c.moveToFirst();
+ id = c.getInt(0);
+ c.close();
+ }
+ return id;
+ }
}
diff --git a/src/com/android/music/SortCursor.java b/src/com/android/music/SortCursor.java
new file mode 100644
index 0000000..9b17294
--- /dev/null
+++ b/src/com/android/music/SortCursor.java
@@ -0,0 +1,303 @@
+/*
+ * 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.music;
+
+import android.database.AbstractCursor;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.util.Log;
+
+/**
+ * A variant of MergeCursor that sorts the cursors being merged. If decent
+ * performance is ever obtained, it can be put back under android.database.
+ */
+public class SortCursor extends AbstractCursor
+{
+ private static final String TAG = "SortCursor";
+ private Cursor mCursor; // updated in onMove
+ private Cursor[] mCursors;
+ private int [] mSortColumns;
+ private final int ROWCACHESIZE = 64;
+ private int mRowNumCache[] = new int[ROWCACHESIZE];
+ private int mCursorCache[] = new int[ROWCACHESIZE];
+ private int mCurRowNumCache[][];
+ private int mLastCacheHit = -1;
+
+ private DataSetObserver mObserver = new DataSetObserver() {
+
+ @Override
+ public void onChanged() {
+ // Reset our position so the optimizations in move-related code
+ // don't screw us over
+ mPos = -1;
+ }
+
+ @Override
+ public void onInvalidated() {
+ mPos = -1;
+ }
+ };
+
+ public SortCursor(Cursor[] cursors, String sortcolumn)
+ {
+ mCursors = cursors;
+
+ int length = mCursors.length;
+ mSortColumns = new int[length];
+ for (int i = 0 ; i < length ; i++) {
+ if (mCursors[i] == null) continue;
+
+ // Register ourself as a data set observer
+ mCursors[i].registerDataSetObserver(mObserver);
+
+ mCursors[i].moveToFirst();
+
+ // We don't catch the exception
+ mSortColumns[i] = mCursors[i].getColumnIndexOrThrow(sortcolumn);
+ }
+ mCursor = null;
+ String smallest = "";
+ for (int j = 0 ; j < length; j++) {
+ if (mCursors[j] == null || mCursors[j].isAfterLast())
+ continue;
+ String current = mCursors[j].getString(mSortColumns[j]);
+ if (mCursor == null || current.compareToIgnoreCase(smallest) < 0) {
+ smallest = current;
+ mCursor = mCursors[j];
+ }
+ }
+
+ for (int i = mRowNumCache.length - 1; i >= 0; i--) {
+ mRowNumCache[i] = -2;
+ }
+ mCurRowNumCache = new int[ROWCACHESIZE][length];
+ }
+
+ @Override
+ public int getCount()
+ {
+ int count = 0;
+ int length = mCursors.length;
+ for (int i = 0 ; i < length ; i++) {
+ if (mCursors[i] != null) {
+ count += mCursors[i].getCount();
+ }
+ }
+ return count;
+ }
+
+ @Override
+ public boolean onMove(int oldPosition, int newPosition)
+ {
+ if (oldPosition == newPosition)
+ return true;
+
+ /* Find the right cursor
+ * Because the client of this cursor (the listadapter/view) tends
+ * to jump around in the cursor somewhat, a simple cache strategy
+ * is used to avoid having to search all cursors from the start.
+ * TODO: investigate strategies for optimizing random access and
+ * reverse-order access.
+ */
+
+ int cache_entry = newPosition % ROWCACHESIZE;
+
+ if (mRowNumCache[cache_entry] == newPosition) {
+ int which = mCursorCache[cache_entry];
+ mCursor = mCursors[which];
+ if (mCursor == null) {
+ Log.w(TAG, "onMove: cache results in a null cursor.");
+ return false;
+ }
+ mCursor.moveToPosition(mCurRowNumCache[cache_entry][which]);
+ mLastCacheHit = cache_entry;
+ return true;
+ }
+
+ mCursor = null;
+ int length = mCursors.length;
+
+ if (mLastCacheHit >= 0) {
+ for (int i = 0; i < length; i++) {
+ if (mCursors[i] == null) continue;
+ mCursors[i].moveToPosition(mCurRowNumCache[mLastCacheHit][i]);
+ }
+ }
+
+ if (newPosition < oldPosition || oldPosition == -1) {
+ for (int i = 0 ; i < length; i++) {
+ if (mCursors[i] == null) continue;
+ mCursors[i].moveToFirst();
+ }
+ oldPosition = 0;
+ }
+ if (oldPosition < 0) {
+ oldPosition = 0;
+ }
+
+ // search forward to the new position
+ int smallestIdx = -1;
+ for(int i = oldPosition; i <= newPosition; i++) {
+ String smallest = "";
+ smallestIdx = -1;
+ for (int j = 0 ; j < length; j++) {
+ if (mCursors[j] == null || mCursors[j].isAfterLast()) {
+ continue;
+ }
+ String current = mCursors[j].getString(mSortColumns[j]);
+ if (smallestIdx < 0 || current.compareToIgnoreCase(smallest) < 0) {
+ smallest = current;
+ smallestIdx = j;
+ }
+ }
+ if (i == newPosition) break;
+ if (mCursors[smallestIdx] != null) {
+ mCursors[smallestIdx].moveToNext();
+ }
+ }
+ mCursor = mCursors[smallestIdx];
+ mRowNumCache[cache_entry] = newPosition;
+ mCursorCache[cache_entry] = smallestIdx;
+ for (int i = 0; i < length; i++) {
+ if (mCursors[i] != null) {
+ mCurRowNumCache[cache_entry][i] = mCursors[i].getPosition();
+ }
+ }
+ mLastCacheHit = -1;
+ return true;
+ }
+
+ @Override
+ public String getString(int column)
+ {
+ return mCursor.getString(column);
+ }
+
+ @Override
+ public short getShort(int column)
+ {
+ return mCursor.getShort(column);
+ }
+
+ @Override
+ public int getInt(int column)
+ {
+ return mCursor.getInt(column);
+ }
+
+ @Override
+ public long getLong(int column)
+ {
+ return mCursor.getLong(column);
+ }
+
+ @Override
+ public float getFloat(int column)
+ {
+ return mCursor.getFloat(column);
+ }
+
+ @Override
+ public double getDouble(int column)
+ {
+ return mCursor.getDouble(column);
+ }
+
+ @Override
+ public boolean isNull(int column)
+ {
+ return mCursor.isNull(column);
+ }
+
+ @Override
+ public byte[] getBlob(int column)
+ {
+ return mCursor.getBlob(column);
+ }
+
+ @Override
+ public String[] getColumnNames()
+ {
+ if (mCursor != null) {
+ return mCursor.getColumnNames();
+ } else {
+ // All of the cursors may be empty, but they can still return
+ // this information.
+ int length = mCursors.length;
+ for (int i = 0 ; i < length ; i++) {
+ if (mCursors[i] != null) {
+ return mCursors[i].getColumnNames();
+ }
+ }
+ throw new IllegalStateException("No cursor that can return names");
+ }
+ }
+
+ @Override
+ public void deactivate()
+ {
+ int length = mCursors.length;
+ for (int i = 0 ; i < length ; i++) {
+ if (mCursors[i] == null) continue;
+ mCursors[i].deactivate();
+ }
+ }
+
+ @Override
+ public void close() {
+ int length = mCursors.length;
+ for (int i = 0 ; i < length ; i++) {
+ if (mCursors[i] == null) continue;
+ mCursors[i].close();
+ }
+ }
+
+ @Override
+ public void registerDataSetObserver(DataSetObserver observer) {
+ int length = mCursors.length;
+ for (int i = 0 ; i < length ; i++) {
+ if (mCursors[i] != null) {
+ mCursors[i].registerDataSetObserver(observer);
+ }
+ }
+ }
+
+ @Override
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ int length = mCursors.length;
+ for (int i = 0 ; i < length ; i++) {
+ if (mCursors[i] != null) {
+ mCursors[i].unregisterDataSetObserver(observer);
+ }
+ }
+ }
+
+ @Override
+ public boolean requery()
+ {
+ int length = mCursors.length;
+ for (int i = 0 ; i < length ; i++) {
+ if (mCursors[i] == null) continue;
+
+ if (mCursors[i].requery() == false) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/tests/src/com/android/music/stress/MusicPlaybackStress.java b/tests/src/com/android/music/stress/MusicPlaybackStress.java
index 80661f2..9e7fd74 100644
--- a/tests/src/com/android/music/stress/MusicPlaybackStress.java
+++ b/tests/src/com/android/music/stress/MusicPlaybackStress.java
@@ -27,7 +27,6 @@
import android.view.KeyEvent;
import android.util.Log;
import android.content.Context;
-import android.os.ServiceManager;
import com.android.music.MusicBrowserActivity;