Add multiple camera support for in MediaProfiles.

Change-Id: Ie89568a0f5f5fd08ede77e33f9a559215d6bed9a
diff --git a/api/current.xml b/api/current.xml
index 9145462..5d71cad 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -87294,6 +87294,21 @@
 <parameter name="quality" type="int">
 </parameter>
 </method>
+<method name="get"
+ return="android.media.CamcorderProfile"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cameraId" type="int">
+</parameter>
+<parameter name="quality" type="int">
+</parameter>
+</method>
 <field name="QUALITY_HIGH"
  type="int"
  transient="false"
@@ -87466,6 +87481,21 @@
 <parameter name="quality" type="int">
 </parameter>
 </method>
+<method name="getJpegEncodingQualityParameter"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cameraId" type="int">
+</parameter>
+<parameter name="quality" type="int">
+</parameter>
+</method>
 <field name="QUALITY_HIGH"
  type="int"
  transient="false"
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
index a4eea2a..c3cd361 100644
--- a/include/media/MediaProfiles.h
+++ b/include/media/MediaProfiles.h
@@ -48,8 +48,8 @@
     static MediaProfiles* getInstance();
 
     /**
-     * Returns the value for the given param name at the given quality level,
-     * or -1 if error.
+     * Returns the value for the given param name for the given camera at
+     * the given quality level, or -1 if error.
      *
      * Supported param name are:
      * duration - the recording duration.
@@ -64,7 +64,8 @@
      * aud.hz - audio sample rate
      * aud.ch - number of audio channels
      */
-    int getCamcorderProfileParamByName(const char *name, camcorder_quality quality) const;
+    int getCamcorderProfileParamByName(const char *name, int cameraId,
+                                       camcorder_quality quality) const;
 
     /**
      * Returns the output file formats supported.
@@ -124,12 +125,7 @@
     /**
      * Returns the number of image encoding quality levels supported.
      */
-    Vector<int> getImageEncodingQualityLevels() const;
-
-    /**
-     * Returns the maximum amount of memory in bytes we can use for decoding a JPEG file.
-     */
-    int getImageDecodingMaxMemory() const;
+    Vector<int> getImageEncodingQualityLevels(int cameraId) const;
 
 private:
     MediaProfiles& operator=(const MediaProfiles&);  // Don't call me
@@ -171,7 +167,8 @@
 
     struct CamcorderProfile {
         CamcorderProfile()
-            : mFileFormat(OUTPUT_FORMAT_THREE_GPP),
+            : mCameraId(0),
+              mFileFormat(OUTPUT_FORMAT_THREE_GPP),
               mQuality(CAMCORDER_QUALITY_HIGH),
               mDuration(0),
               mVideoCodec(0),
@@ -182,6 +179,7 @@
             delete mAudioCodec;
         }
 
+        int mCameraId;
         output_format mFileFormat;
         camcorder_quality mQuality;
         int mDuration;
@@ -249,6 +247,11 @@
         int tag;
     };
 
+    struct ImageEncodingQualityLevels {
+        int mCameraId;
+        Vector<int> mLevels;
+    };
+
     // Debug
     static void logVideoCodec(const VideoCodec& codec);
     static void logAudioCodec(const AudioCodec& codec);
@@ -267,9 +270,11 @@
     static VideoDecoderCap* createVideoDecoderCap(const char **atts);
     static VideoEncoderCap* createVideoEncoderCap(const char **atts);
     static AudioEncoderCap* createAudioEncoderCap(const char **atts);
-    static CamcorderProfile* createCamcorderProfile(const char **atts);
-    static int getImageEncodingQualityLevel(const char **atts);
-    static int getImageDecodingMaxMemory(const char **atts);
+    static CamcorderProfile* createCamcorderProfile(int cameraId, const char **atts);
+    static int getCameraId(const char **atts);
+
+    ImageEncodingQualityLevels* findImageEncodingQualityLevels(int cameraId) const;
+    void addImageEncodingQualityLevel(int cameraId, const char** atts);
 
     // Customized element tag handler for parsing the xml configuration file.
     static void startElementHandler(void *userData, const char *name, const char **atts);
@@ -303,6 +308,7 @@
     static bool sIsInitialized;
     static MediaProfiles *sInstance;
     static Mutex sLock;
+    int mCurrentCameraId;
 
     Vector<CamcorderProfile*> mCamcorderProfiles;
     Vector<AudioEncoderCap*>  mAudioEncoders;
@@ -310,8 +316,7 @@
     Vector<AudioDecoderCap*>  mAudioDecoders;
     Vector<VideoDecoderCap*>  mVideoDecoders;
     Vector<output_format>     mEncoderOutputFileFormats;
-    Vector<int>               mImageEncodingQualityLevels;
-    int                       mImageDecodingMaxMemory;
+    Vector<ImageEncodingQualityLevels *>  mImageEncodingQualityLevels;
 };
 
 }; // namespace android
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index 64d6460..a27df57 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -119,15 +119,26 @@
     public int audioChannels;
 
     /**
-     * Returns the camcorder profile for the given quality level.
+     * Returns the camcorder profile for the default camera at the given
+     * quality level.
      * @param quality the target quality level for the camcorder profile
      */
     public static CamcorderProfile get(int quality) {
+        return get(0, quality);
+    }
+
+    /**
+     * Returns the camcorder profile for the given camera at the given
+     * quality level.
+     * @param cameraId the id for the camera
+     * @param quality the target quality level for the camcorder profile
+     */
+    public static CamcorderProfile get(int cameraId, int quality) {
         if (quality < QUALITY_LOW || quality > QUALITY_HIGH) {
             String errMessage = "Unsupported quality level: " + quality;
             throw new IllegalArgumentException(errMessage);
         }
-        return native_get_camcorder_profile(quality);
+        return native_get_camcorder_profile(cameraId, quality);
     }
 
     static {
@@ -165,5 +176,6 @@
 
     // Methods implemented by JNI
     private static native final void native_init();
-    private static native final CamcorderProfile native_get_camcorder_profile(int quality);
+    private static native final CamcorderProfile native_get_camcorder_profile(
+            int cameraId, int quality);
 }
diff --git a/media/java/android/media/CameraProfile.java b/media/java/android/media/CameraProfile.java
index f8d3935..6a0be08 100644
--- a/media/java/android/media/CameraProfile.java
+++ b/media/java/android/media/CameraProfile.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import java.util.Arrays;
+import java.util.HashMap;
 
 /**
  * The CameraProfile class is used to retrieve the pre-defined still image
@@ -40,36 +41,55 @@
     /*
      * Cache the Jpeg encoding quality parameters
      */
-    private static final int[] sJpegEncodingQualityParameters;
+    private static final HashMap<Integer, int[]> sCache = new HashMap<Integer, int[]>();
 
     /**
      * Returns a pre-defined still image capture (jpeg) quality level
-     * used for the given quality level in the Camera application.
+     * used for the given quality level in the Camera application for
+     * the default camera.
      *
      * @param quality The target quality level
      */
     public static int getJpegEncodingQualityParameter(int quality) {
+        return getJpegEncodingQualityParameter(0, quality);
+    }
+
+    /**
+     * Returns a pre-defined still image capture (jpeg) quality level
+     * used for the given quality level in the Camera application for
+     * the specified camera.
+     *
+     * @param cameraId The id of the camera
+     * @param quality The target quality level
+     */
+    public static int getJpegEncodingQualityParameter(int cameraId, int quality) {
         if (quality < QUALITY_LOW || quality > QUALITY_HIGH) {
             throw new IllegalArgumentException("Unsupported quality level: " + quality);
         }
-        return sJpegEncodingQualityParameters[quality];
+        synchronized (sCache) {
+            int[] levels = sCache.get(cameraId);
+            if (levels == null) {
+                levels = getImageEncodingQualityLevels(cameraId);
+                sCache.put(cameraId, levels);
+            }
+            return levels[quality];
+        }
     }
 
     static {
         System.loadLibrary("media_jni");
         native_init();
-        sJpegEncodingQualityParameters = getImageEncodingQualityLevels();
     }
 
-    private static int[] getImageEncodingQualityLevels() {
-        int nLevels = native_get_num_image_encoding_quality_levels();
+    private static int[] getImageEncodingQualityLevels(int cameraId) {
+        int nLevels = native_get_num_image_encoding_quality_levels(cameraId);
         if (nLevels != QUALITY_HIGH + 1) {
             throw new RuntimeException("Unexpected Jpeg encoding quality levels " + nLevels);
         }
 
         int[] levels = new int[nLevels];
         for (int i = 0; i < nLevels; ++i) {
-            levels[i] = native_get_image_encoding_quality_level(i);
+            levels[i] = native_get_image_encoding_quality_level(cameraId, i);
         }
         Arrays.sort(levels);  // Lower quality level ALWAYS comes before higher one
         return levels;
@@ -77,6 +97,6 @@
 
     // Methods implemented by JNI
     private static native final void native_init();
-    private static native final int native_get_num_image_encoding_quality_levels();
-    private static native final int native_get_image_encoding_quality_level(int index);
+    private static native final int native_get_num_image_encoding_quality_levels(int cameraId);
+    private static native final int native_get_image_encoding_quality_level(int cameraId, int index);
 }
diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp
index 7d7533a..cce9fd0 100644
--- a/media/jni/android_media_MediaProfiles.cpp
+++ b/media/jni/android_media_MediaProfiles.cpp
@@ -162,26 +162,26 @@
 }
 
 static jobject
-android_media_MediaProfiles_native_get_camcorder_profile(JNIEnv *env, jobject thiz, jint quality)
+android_media_MediaProfiles_native_get_camcorder_profile(JNIEnv *env, jobject thiz, jint id, jint quality)
 {
-    LOGV("native_get_camcorder_profile: %d", quality);
+    LOGV("native_get_camcorder_profile: %d %d", id, quality);
     if (quality != CAMCORDER_QUALITY_HIGH && quality != CAMCORDER_QUALITY_LOW) {
         jniThrowException(env, "java/lang/RuntimeException", "Unknown camcorder profile quality");
         return NULL;
     }
 
     camcorder_quality q = static_cast<camcorder_quality>(quality);
-    int duration         = sProfiles->getCamcorderProfileParamByName("duration", q);
-    int fileFormat       = sProfiles->getCamcorderProfileParamByName("file.format", q);
-    int videoCodec       = sProfiles->getCamcorderProfileParamByName("vid.codec",   q);
-    int videoBitRate     = sProfiles->getCamcorderProfileParamByName("vid.bps",     q);
-    int videoFrameRate   = sProfiles->getCamcorderProfileParamByName("vid.fps",     q);
-    int videoFrameWidth  = sProfiles->getCamcorderProfileParamByName("vid.width",   q);
-    int videoFrameHeight = sProfiles->getCamcorderProfileParamByName("vid.height",  q);
-    int audioCodec       = sProfiles->getCamcorderProfileParamByName("aud.codec",   q);
-    int audioBitRate     = sProfiles->getCamcorderProfileParamByName("aud.bps",     q);
-    int audioSampleRate  = sProfiles->getCamcorderProfileParamByName("aud.hz",      q);
-    int audioChannels    = sProfiles->getCamcorderProfileParamByName("aud.ch",      q);
+    int duration         = sProfiles->getCamcorderProfileParamByName("duration",    id, q);
+    int fileFormat       = sProfiles->getCamcorderProfileParamByName("file.format", id, q);
+    int videoCodec       = sProfiles->getCamcorderProfileParamByName("vid.codec",   id, q);
+    int videoBitRate     = sProfiles->getCamcorderProfileParamByName("vid.bps",     id, q);
+    int videoFrameRate   = sProfiles->getCamcorderProfileParamByName("vid.fps",     id, q);
+    int videoFrameWidth  = sProfiles->getCamcorderProfileParamByName("vid.width",   id, q);
+    int videoFrameHeight = sProfiles->getCamcorderProfileParamByName("vid.height",  id, q);
+    int audioCodec       = sProfiles->getCamcorderProfileParamByName("aud.codec",   id, q);
+    int audioBitRate     = sProfiles->getCamcorderProfileParamByName("aud.bps",     id, q);
+    int audioSampleRate  = sProfiles->getCamcorderProfileParamByName("aud.hz",      id, q);
+    int audioChannels    = sProfiles->getCamcorderProfileParamByName("aud.ch",      id, q);
 
     // Check on the values retrieved
     if (duration == -1 || fileFormat == -1 || videoCodec == -1 || audioCodec == -1 ||
@@ -253,17 +253,17 @@
 }
 
 static jint
-android_media_MediaProfiles_native_get_num_image_encoding_quality_levels(JNIEnv *env, jobject thiz)
+android_media_MediaProfiles_native_get_num_image_encoding_quality_levels(JNIEnv *env, jobject thiz, jint cameraId)
 {
     LOGV("native_get_num_image_encoding_quality_levels");
-    return sProfiles->getImageEncodingQualityLevels().size();
+    return sProfiles->getImageEncodingQualityLevels(cameraId).size();
 }
 
 static jint
-android_media_MediaProfiles_native_get_image_encoding_quality_level(JNIEnv *env, jobject thiz, jint index)
+android_media_MediaProfiles_native_get_image_encoding_quality_level(JNIEnv *env, jobject thiz, jint cameraId, jint index)
 {
     LOGV("native_get_image_encoding_quality_level");
-    Vector<int> levels = sProfiles->getImageEncodingQualityLevels();
+    Vector<int> levels = sProfiles->getImageEncodingQualityLevels(cameraId);
     if (index < 0 || index >= levels.size()) {
         jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary");
         return -1;
@@ -287,7 +287,7 @@
 
 static JNINativeMethod gMethodsForCamcorderProfileClass[] = {
     {"native_init",                            "()V",                    (void *)android_media_MediaProfiles_native_init},
-    {"native_get_camcorder_profile",           "(I)Landroid/media/CamcorderProfile;",
+    {"native_get_camcorder_profile",           "(II)Landroid/media/CamcorderProfile;",
                                                                          (void *)android_media_MediaProfiles_native_get_camcorder_profile},
 };
 
@@ -302,8 +302,8 @@
 static JNINativeMethod gMethodsForCameraProfileClass[] = {
     {"native_init",                            "()V",                    (void *)android_media_MediaProfiles_native_init},
     {"native_get_num_image_encoding_quality_levels",
-                                               "()I",                    (void *)android_media_MediaProfiles_native_get_num_image_encoding_quality_levels},
-    {"native_get_image_encoding_quality_level","(I)I",                   (void *)android_media_MediaProfiles_native_get_image_encoding_quality_level},
+                                               "(I)I",                   (void *)android_media_MediaProfiles_native_get_num_image_encoding_quality_levels},
+    {"native_get_image_encoding_quality_level","(II)I",                   (void *)android_media_MediaProfiles_native_get_image_encoding_quality_level},
 };
 
 static const char* const kEncoderCapabilitiesClassPathName = "android/media/EncoderCapabilities";
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 1263373..3869389 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -272,7 +272,7 @@
 }
 
 /*static*/ MediaProfiles::CamcorderProfile*
-MediaProfiles::createCamcorderProfile(const char **atts)
+MediaProfiles::createCamcorderProfile(int cameraId, const char **atts)
 {
     CHECK(!strcmp("quality",    atts[0]) &&
           !strcmp("fileFormat", atts[2]) &&
@@ -287,16 +287,47 @@
     CHECK(fileFormat != -1);
 
     MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+    profile->mCameraId = cameraId;
     profile->mFileFormat = static_cast<output_format>(fileFormat);
     profile->mQuality = static_cast<camcorder_quality>(quality);
     profile->mDuration = atoi(atts[5]);
     return profile;
 }
 
-/*static*/ int
-MediaProfiles::getImageEncodingQualityLevel(const char** atts)
+MediaProfiles::ImageEncodingQualityLevels*
+MediaProfiles::findImageEncodingQualityLevels(int cameraId) const
+{
+    int n = mImageEncodingQualityLevels.size();
+    for (int i = 0; i < n; i++) {
+        ImageEncodingQualityLevels *levels = mImageEncodingQualityLevels[i];
+        if (levels->mCameraId == cameraId) {
+            return levels;
+        }
+    }
+    return NULL;
+}
+
+void MediaProfiles::addImageEncodingQualityLevel(int cameraId, const char** atts)
 {
     CHECK(!strcmp("quality", atts[0]));
+    int quality = atoi(atts[1]);
+    LOGV("%s: cameraId=%d, quality=%d\n", __func__, cameraId, quality);
+    ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
+
+    if (levels == NULL) {
+        levels = new ImageEncodingQualityLevels();
+        levels->mCameraId = cameraId;
+        mImageEncodingQualityLevels.add(levels);
+    }
+
+    levels->mLevels.add(quality);
+}
+
+/*static*/ int
+MediaProfiles::getCameraId(const char** atts)
+{
+    if (!atts[0]) return 0;  // default cameraId = 0
+    CHECK(!strcmp("cameraId", atts[0]));
     return atoi(atts[1]);
 }
 
@@ -322,10 +353,13 @@
         profiles->mAudioDecoders.add(createAudioDecoderCap(atts));
     } else if (strcmp("EncoderOutputFileFormat", name) == 0) {
         profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts));
+    } else if (strcmp("CamcorderProfiles", name) == 0) {
+        profiles->mCurrentCameraId = getCameraId(atts);
     } else if (strcmp("EncoderProfile", name) == 0) {
-        profiles->mCamcorderProfiles.add(createCamcorderProfile(atts));
+        profiles->mCamcorderProfiles.add(
+            createCamcorderProfile(profiles->mCurrentCameraId, atts));
     } else if (strcmp("ImageEncoding", name) == 0) {
-        profiles->mImageEncodingQualityLevels.add(getImageEncodingQualityLevel(atts));
+        profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
     }
 }
 
@@ -383,7 +417,8 @@
         new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20);
 
     AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
-    CamcorderProfile *profile = new CamcorderProfile;
+    CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+    profile->mCameraId = 0;
     profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
     profile->mQuality = CAMCORDER_QUALITY_HIGH;
     profile->mDuration = 60;
@@ -402,6 +437,7 @@
         new MediaProfiles::AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
 
     MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+    profile->mCameraId = 0;
     profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
     profile->mQuality = CAMCORDER_QUALITY_LOW;
     profile->mDuration = 30;
@@ -458,9 +494,12 @@
 /*static*/ void
 MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles)
 {
-    profiles->mImageEncodingQualityLevels.add(70);
-    profiles->mImageEncodingQualityLevels.add(80);
-    profiles->mImageEncodingQualityLevels.add(90);
+    ImageEncodingQualityLevels *levels = new ImageEncodingQualityLevels();
+    levels->mCameraId = 0;
+    levels->mLevels.add(70);
+    levels->mLevels.add(80);
+    levels->mLevels.add(90);
+    profiles->mImageEncodingQualityLevels.add(levels);
 }
 
 /*static*/ MediaProfiles*
@@ -629,19 +668,24 @@
     return decoders;  // copy out
 }
 
-int MediaProfiles::getCamcorderProfileParamByName(const char *name, camcorder_quality quality) const
+int MediaProfiles::getCamcorderProfileParamByName(const char *name,
+                                                  int cameraId,
+                                                  camcorder_quality quality) const
 {
-    LOGV("getCamcorderProfileParamByName: %s for quality %d", name, quality);
+    LOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d",
+         name, cameraId, quality);
 
     int index = -1;
     for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
-        if (mCamcorderProfiles[i]->mQuality == quality) {
+        if (mCamcorderProfiles[i]->mCameraId == cameraId &&
+            mCamcorderProfiles[i]->mQuality == quality) {
             index = i;
             break;
         }
     }
     if (index == -1) {
-        LOGE("The given camcorder profile quality %d is not found", quality);
+        LOGE("The given camcorder profile camera %d quality %d is not found",
+             cameraId, quality);
         return -1;
     }
 
@@ -657,13 +701,18 @@
     if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodec->mChannels;
     if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodec->mSampleRate;
 
-    LOGE("The given camcorder profile param name %s is not found", name);
+    LOGE("The given camcorder profile param id %d name %s is not found", cameraId, name);
     return -1;
 }
 
-Vector<int> MediaProfiles::getImageEncodingQualityLevels() const
+Vector<int> MediaProfiles::getImageEncodingQualityLevels(int cameraId) const
 {
-    return mImageEncodingQualityLevels;  // copy out
+    Vector<int> result;
+    ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
+    if (levels != NULL) {
+        result = levels->mLevels;  // copy out
+    }
+    return result;
 }
 
 MediaProfiles::~MediaProfiles()