Implement getDownloadStatus and add permission

- Implement getDownloadStatus in the manager
- Remove DownloadStatus and add constants in its place to reflect the
status of a single file
- Add ACT_AS_EMBMS_MIDDLEWARE permission

Change-Id: Ica8b8a872a8088a2aaf56d40926051225aa39e87
diff --git a/Android.mk b/Android.mk
index 5f759cb..aec1bde 100644
--- a/Android.mk
+++ b/Android.mk
@@ -550,7 +550,6 @@
 
 aidl_files := \
         frameworks/base/telephony/java/android/telephony/mbms/DownloadRequest.aidl \
-        frameworks/base/telephony/java/android/telephony/mbms/DownloadStatus.aidl \
         frameworks/base/telephony/java/android/telephony/mbms/FileInfo.aidl \
         frameworks/base/telephony/java/android/telephony/mbms/FileServiceInfo.aidl \
         frameworks/base/telephony/java/android/telephony/mbms/ServiceInfo.aidl \
diff --git a/api/current.txt b/api/current.txt
index 5d4a3f9..52e3422 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -114,6 +114,7 @@
     field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
+    field public static final java.lang.String SEND_EMBMS_INTENTS = "android.permission.SEND_EMBMS_INTENTS";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
     field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
diff --git a/api/system-current.txt b/api/system-current.txt
index 403d5c1..4e84643 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -206,6 +206,7 @@
     field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
     field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
     field public static final java.lang.String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
+    field public static final java.lang.String SEND_EMBMS_INTENTS = "android.permission.SEND_EMBMS_INTENTS";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
     field public static final java.lang.String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
diff --git a/api/test-current.txt b/api/test-current.txt
index 8ce51f9..fff208a 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -114,6 +114,7 @@
     field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
+    field public static final java.lang.String SEND_EMBMS_INTENTS = "android.permission.SEND_EMBMS_INTENTS";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
     field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d215416..387eb1d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1605,6 +1605,10 @@
     <permission android:name="android.permission.RECEIVE_STK_COMMANDS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an application to send EMBMS download intents to apps-->
+    <permission android:name="android.permission.SEND_EMBMS_INTENTS"
+        android:protectionLevel="signature|privileged" />
+
     <!-- Must be required by an ImsService to ensure that only the
          system can bind to it.
          <p>Protection level: signature|privileged
diff --git a/telephony/java/android/telephony/MbmsDownloadManager.java b/telephony/java/android/telephony/MbmsDownloadManager.java
index 231f2c8..5fa6a95 100644
--- a/telephony/java/android/telephony/MbmsDownloadManager.java
+++ b/telephony/java/android/telephony/MbmsDownloadManager.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.content.ComponentName;
 import android.content.Context;
@@ -26,9 +27,9 @@
 import android.net.Uri;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.telephony.mbms.FileInfo;
 import android.telephony.mbms.IDownloadCallback;
 import android.telephony.mbms.DownloadRequest;
-import android.telephony.mbms.DownloadStatus;
 import android.telephony.mbms.IMbmsDownloadManagerCallback;
 import android.telephony.mbms.MbmsDownloadManagerCallback;
 import android.telephony.mbms.MbmsDownloadReceiver;
@@ -40,6 +41,8 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -192,6 +195,18 @@
     public static final int RESULT_EXPIRED    = 3;
     // TODO - more results!
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({STATUS_UNKNOWN, STATUS_ACTIVELY_DOWNLOADING, STATUS_PENDING_DOWNLOAD,
+            STATUS_PENDING_REPAIR, STATUS_PENDING_DOWNLOAD_WINDOW})
+    public @interface DownloadStatus {}
+
+    public static final int STATUS_UNKNOWN = 0;
+    public static final int STATUS_ACTIVELY_DOWNLOADING = 1;
+    public static final int STATUS_PENDING_DOWNLOAD = 2;
+    public static final int STATUS_PENDING_REPAIR = 3;
+    public static final int STATUS_PENDING_DOWNLOAD_WINDOW = 4;
+
     private final Context mContext;
     private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
 
@@ -271,8 +286,6 @@
      * The serviceClasses argument lets the app filter on types of programming and is opaque data
      * negotiated beforehand between the app and the carrier.
      *
-     * Multiple calls replace the list of serviceClasses of interest.
-     *
      * This may throw an {@link MbmsException} containing one of the following errors:
      * {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
      * {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
@@ -282,6 +295,12 @@
      * callback can include any of the errors except:
      * {@link MbmsException#ERROR_UNABLE_TO_START_SERVICE}
      * {@link MbmsException#ERROR_END_OF_SESSION}
+     *
+     * @param classList A list of service classes which the app wishes to receive
+     *                  {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)} callbacks
+     *                  about. Subsequent calls to this method will replace this list of service
+     *                  classes (i.e. the middleware will no longer send updates for services
+     *                  matching classes only in the old list).
      */
     public void getFileServices(List<String> classList) throws MbmsException {
         IMbmsDownloadService downloadService = mService.get();
@@ -312,8 +331,9 @@
      * will default to a directory formed by the concatenation of the app's files directory and
      * {@link android.telephony.mbms.MbmsTempFileProvider#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY}.
      *
-     * This method may not be called while any download requests are still active. If this is
-     * the case, an {@link MbmsException} will be thrown with code
+     * Before calling this method, the app must cancel all of its pending
+     * {@link DownloadRequest}s via {@link #cancelDownload(DownloadRequest)}. If this is not done,
+     * an {@link MbmsException} will be thrown with code
      * {@link MbmsException#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT}
      *
      * The {@link File} supplied as a root temp file directory must already exist. If not, an
@@ -444,20 +464,30 @@
     }
 
     /**
-     * Gets information about current and known upcoming downloads.
+     * Gets information about the status of a file pending download.
      *
-     * Current is a straightforward count of the files being downloaded "now"
-     * for some definition of now (may be racey).
-     * Future downloads include counts of files with pending repair operations, counts of
-     * files with future downloads and indication of scheduled download times with unknown
-     * file details.
+     * If the middleware has not yet been properly initialized or if it has no records of the
+     * file indicated by {@code fileInfo} being associated with {@code downloadRequest},
+     * {@link #STATUS_UNKNOWN} will be returned.
      *
-     * May throw an IllegalArgumentException or RemoteException.
-     *
-     * If the DownloadRequest is unknown the results will be null.
+     * @param downloadRequest The download request to query.
+     * @param fileInfo The particular file within the request to get information on.
+     * @return The status of the download.
      */
-    public DownloadStatus getDownloadStatus(DownloadRequest downloadRequest) {
-        return null;
+    @DownloadStatus
+    public int getDownloadStatus(DownloadRequest downloadRequest, FileInfo fileInfo)
+            throws MbmsException {
+        IMbmsDownloadService downloadService = mService.get();
+        if (downloadService == null) {
+            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
+        }
+
+        try {
+            return downloadService.getDownloadStatus(downloadRequest, fileInfo);
+        } catch (RemoteException e) {
+            mService.set(null);
+            throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
+        }
     }
 
     /**
diff --git a/telephony/java/android/telephony/mbms/DownloadStatus.aidl b/telephony/java/android/telephony/mbms/DownloadStatus.aidl
deleted file mode 100755
index e7cfd39..0000000
--- a/telephony/java/android/telephony/mbms/DownloadStatus.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-** Copyright 2017, 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 android.telephony.mbms;
-
-parcelable DownloadStatus;
diff --git a/telephony/java/android/telephony/mbms/DownloadStatus.java b/telephony/java/android/telephony/mbms/DownloadStatus.java
deleted file mode 100644
index 90eb53f..0000000
--- a/telephony/java/android/telephony/mbms/DownloadStatus.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.telephony.mbms;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * A Parcelable class describing the status of a Cell-Broadcast download request
- * @hide
- */
-public class DownloadStatus implements Parcelable {
-    // includes downloads and active repair work
-    public final int activelyDownloading;
-
-    // files scheduled for future broadcast
-    public final int pendingDownloads;
-
-    // files scheduled for future repairs
-    public final int pendingRepairs;
-
-    // is a future download window scheduled with unknown
-    // number of files
-    public final boolean windowPending;
-
-    public DownloadStatus(int downloading, int downloads, int repairs, boolean window) {
-        activelyDownloading = downloading;
-        pendingDownloads = downloads;
-        pendingRepairs = repairs;
-        windowPending = window;
-    }
-
-    public static final Parcelable.Creator<DownloadStatus> CREATOR =
-            new Parcelable.Creator<DownloadStatus>() {
-        @Override
-        public DownloadStatus createFromParcel(Parcel in) {
-            return new DownloadStatus(in);
-        }
-
-        @Override
-        public DownloadStatus[] newArray(int size) {
-            return new DownloadStatus[size];
-        }
-    };
-
-    DownloadStatus(Parcel in) {
-        activelyDownloading = in.readInt();
-        pendingDownloads = in.readInt();
-        pendingRepairs = in.readInt();
-        windowPending = (in.readInt() == 1);
-    }
-
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(activelyDownloading);
-        dest.writeInt(pendingDownloads);
-        dest.writeInt(pendingRepairs);
-        dest.writeInt((windowPending ? 1 : 0));
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-}
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
index 7112e13..06be8a0 100755
--- a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
@@ -19,7 +19,7 @@
 import android.app.PendingIntent;
 import android.net.Uri;
 import android.telephony.mbms.DownloadRequest;
-import android.telephony.mbms.DownloadStatus;
+import android.telephony.mbms.FileInfo;
 import android.telephony.mbms.IMbmsDownloadManagerCallback;
 import android.telephony.mbms.IDownloadCallback;
 
@@ -41,7 +41,7 @@
 
     int cancelDownload(in DownloadRequest downloadRequest);
 
-    DownloadStatus getDownloadStatus(in DownloadRequest downloadRequest);
+    int getDownloadStatus(in DownloadRequest downloadRequest, in FileInfo fileInfo);
 
     /*
      * named this for 2 reasons:
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
index 58bda64..305d387 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
@@ -18,7 +18,7 @@
 
 import android.os.RemoteException;
 import android.telephony.mbms.DownloadRequest;
-import android.telephony.mbms.DownloadStatus;
+import android.telephony.mbms.FileInfo;
 import android.telephony.mbms.IDownloadCallback;
 import android.telephony.mbms.IMbmsDownloadManagerCallback;
 import android.telephony.mbms.MbmsException;
@@ -73,9 +73,15 @@
      * Sets the temp file root directory for this app/subscriptionId combination. The middleware
      * should persist {@code rootDirectoryPath} and send it back when sending intents to the
      * app's {@link android.telephony.mbms.MbmsDownloadReceiver}.
+     *
+     * If the calling app (as identified by the calling UID) currently has any pending download
+     * requests that have not been canceled, the middleware must return
+     * {@link MbmsException#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} here.
+     *
      * @param subscriptionId The subscription id the download is operating under.
      * @param rootDirectoryPath The path to the app's temp file root directory.
-     * @return {@link MbmsException#ERROR_MIDDLEWARE_NOT_YET_READY},
+     * @return {@link MbmsException#SUCCESS},
+     *         {@link MbmsException#ERROR_MIDDLEWARE_NOT_YET_READY},
      *         {@link MbmsException#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT},
      *         or {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
      */
@@ -87,6 +93,11 @@
 
     /**
      * Issues a request to download a set of files.
+     *
+     * The middleware should expect that {@link #setTempFileRootDirectory(int, String)} has been
+     * called for this app between when the app was installed and when this method is called. If
+     * this is not the case, an {@link IllegalStateException} may be thrown.
+     *
      * @param downloadRequest An object describing the set of files to be downloaded.
      * @param listener A listener through which the middleware can provide progress updates to
      *                 the app while both are still running.
@@ -122,9 +133,9 @@
     }
 
     @Override
-    public DownloadStatus getDownloadStatus(DownloadRequest downloadRequest)
+    public int getDownloadStatus(DownloadRequest downloadRequest, FileInfo fileInfo)
             throws RemoteException {
-        return null;
+        return 0;
     }
 
     @Override