Merge the 2018-09-05 SPL branch from AOSP-Partner

* security-aosp-nyc-mr2-release:
  Rework thumbnail cleanup
  [DO NOT MERGE] Enforce user separation on external storage

Change-Id: I1d5578318d1981a34f1f1ce657bfa55a2d71615a
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1d8c46d..c087434 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -12,6 +12,7 @@
     <uses-permission android:name="android.permission.ACCESS_MTP" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 
     <application android:process="android.process.media"
                  android:label="@string/app_label"
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 65c9cd7..677d23a 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -1905,6 +1905,18 @@
                     + " AND datetaken<date_modified*5;");
         }
 
+        if (fromVersion < 701) {
+            db.execSQL("CREATE TABLE IF NOT EXISTS bookmarks (" +
+                " _id INTEGER PRIMARY KEY," +
+                " _data TEXT," +
+                " _display_name TEXT," +
+                " position INTEGER," +
+                " date_added INTEGER," +
+                " mime_type TEXT," +
+                " media_type TEXT" +
+                ");");
+        }
+
        if (fromVersion < 800) {
             // Delete albums and artists, then clear the modification time on songs, which
             // will cause the media scanner to rescan everything, rebuilding the artist and
@@ -2689,7 +2701,13 @@
             case MTP_OBJECT_REFERENCES:
                 int handle = Integer.parseInt(uri.getPathSegments().get(2));
                 return getObjectReferences(helper, db, handle);
-
+            case MEDIA_BOOKMARK:
+                qb.setTables("bookmarks");
+                break;
+            case MEDIA_BOOKMARK_ID:
+                qb.setTables("bookmarks");
+                qb.appendWhere("_id = " + uri.getPathSegments().get(2));
+                break;
             default:
                 throw new IllegalStateException("Unknown URL: " + uri.toString());
         }
@@ -3693,6 +3711,13 @@
                 }
                 break;
 
+            case MEDIA_BOOKMARK:
+                rowId = db.insert("bookmarks", "mime_type", initialValues);
+                if (rowId > 0) {
+                    newUri = ContentUris.withAppendedId(uri, rowId);
+                }
+                break;
+
             default:
                 throw new UnsupportedOperationException("Invalid URI " + uri);
         }
@@ -4125,6 +4150,13 @@
                 out.table = "files";
                 break;
 
+            case MEDIA_BOOKMARK_ID:
+                where = "_id=" + uri.getPathSegments().get(2);
+                // fall through
+            case MEDIA_BOOKMARK:
+                out.table = "bookmarks";
+                break;
+
             default:
                 throw new UnsupportedOperationException(
                         "Unknown or unsupported URL: " + uri.toString());
@@ -5961,6 +5993,8 @@
     // UsbReceiver calls insert() and delete() with this URI to tell us
     // when MTP is connected and disconnected
     private static final int MTP_CONNECTED = 705;
+    private static final int MEDIA_BOOKMARK = 1101;
+    private static final int MEDIA_BOOKMARK_ID = 1102;
 
     private static final UriMatcher URI_MATCHER =
             new UriMatcher(UriMatcher.NO_MATCH);
@@ -6059,6 +6093,8 @@
         // used by the music app's search activity
         URI_MATCHER.addURI("media", "*/audio/search/fancy", AUDIO_SEARCH_FANCY);
         URI_MATCHER.addURI("media", "*/audio/search/fancy/*", AUDIO_SEARCH_FANCY);
+        URI_MATCHER.addURI("media", "*/bookmark", MEDIA_BOOKMARK);
+        URI_MATCHER.addURI("media", "*/bookmark/#", MEDIA_BOOKMARK_ID);
     }
 
     private static String getVolumeName(Uri uri) {
diff --git a/src/com/android/providers/media/MtpService.java b/src/com/android/providers/media/MtpService.java
index f9e7a7f..1397993 100644
--- a/src/com/android/providers/media/MtpService.java
+++ b/src/com/android/providers/media/MtpService.java
@@ -30,6 +30,7 @@
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
 import android.util.Log;
+import android.util.BoostFramework;
 
 import java.io.File;
 import java.util.HashMap;
@@ -37,7 +38,10 @@
 public class MtpService extends Service {
     private static final String TAG = "MtpService";
     private static final boolean LOGD = false;
-
+    private BoostFramework mPerfBoost = null;
+    private boolean mIsPerfBoostEnabled = false;
+    private int mBoostParamVal[];
+    private boolean mIsPerfLockAcquired = false;
     // We restrict PTP to these subdirectories
     private static final String[] PTP_DIRECTORIES = new String[] {
         Environment.DIRECTORY_DCIM,
@@ -93,6 +97,11 @@
     @Override
     public void onCreate() {
         mStorageManager = StorageManager.from(this);
+        mIsPerfBoostEnabled = getApplicationContext().getResources().getBoolean(
+                com.android.internal.R.bool.config_enableBoostForMtp);
+        mBoostParamVal = getApplicationContext().getResources().getIntArray(
+                com.android.internal.R.array.mtpboost_param_value);
+
         synchronized (mBinder) {
             updateDisabledStateLocked();
             mStorageManager.registerListener(mStorageEventListener);
@@ -177,6 +186,11 @@
         if (mDatabase != null) {
             mDatabase.setServer(null);
         }
+        if (mIsPerfLockAcquired && mPerfBoost != null) {
+            mPerfBoost.perfLockRelease();
+            mIsPerfLockAcquired = false;
+            Log.d(TAG, "Perflock released for MTP ");
+        }
     }
 
     private final IMtpService.Stub mBinder =
@@ -237,6 +251,15 @@
         if (mServer != null) {
             mServer.addStorage(storage);
         }
+        if (mIsPerfBoostEnabled && mPerfBoost == null) {
+            mPerfBoost = new BoostFramework();
+        }
+        if (mPerfBoost != null && !mIsPerfLockAcquired) {
+            //Use big enough number here to hold the perflock for entire MTP session
+            mPerfBoost.perfLockAcquire(Integer.MAX_VALUE,mBoostParamVal);
+            Log.d(TAG, "perflock acquired for MTP ");
+            mIsPerfLockAcquired = true;
+        }
     }
 
     private void removeStorageLocked(StorageVolume volume) {
@@ -248,6 +271,11 @@
 
         Log.d(TAG, "Removing MTP storage " + Integer.toHexString(storage.getStorageId()) + " at "
                 + storage.getPath());
+        if (mIsPerfLockAcquired && mPerfBoost != null) {
+            mPerfBoost.perfLockRelease();
+            mIsPerfLockAcquired = false;
+            Log.d(TAG, "Perflock released for MTP ");
+        }
         if (mDatabase != null) {
             mDatabase.removeStorage(storage);
         }
diff --git a/src/com/android/providers/media/RingtonePickerActivity.java b/src/com/android/providers/media/RingtonePickerActivity.java
old mode 100644
new mode 100755
index 710787a..2d41876
--- a/src/com/android/providers/media/RingtonePickerActivity.java
+++ b/src/com/android/providers/media/RingtonePickerActivity.java
@@ -21,6 +21,7 @@
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
+import android.database.StaleDataException;
 import android.database.CursorWrapper;
 import android.media.AudioAttributes;
 import android.media.Ringtone;
@@ -353,7 +354,14 @@
             ringtone = mDefaultRingtone;
             mCurrentRingtone = null;
         } else {
-            ringtone = mRingtoneManager.getRingtone(getRingtoneManagerPosition(mSampleRingtonePos));
+            try {
+               ringtone =mRingtoneManager.getRingtone(
+                          getRingtoneManagerPosition(mSampleRingtonePos));
+            } catch (StaleDataException staleDataException) {
+               ringtone = null;
+            } catch (IllegalStateException illegalStateException) {
+               ringtone = null;
+            }
             mCurrentRingtone = ringtone;
         }
 
@@ -371,6 +379,7 @@
     @Override
     protected void onStop() {
         super.onStop();
+        mHandler.removeCallbacks(this);
         mCursor.deactivate();
 
         if (!isChangingConfigurations()) {