dom/camera/GonkCameraParameters.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /*
     2  * Copyright (C) 2013-2014 Mozilla Foundation
     3  *
     4  * Licensed under the Apache License, Version 2.0 (the "License");
     5  * you may not use this file except in compliance with the License.
     6  * You may obtain a copy of the License at
     7  *
     8  *      http://www.apache.org/licenses/LICENSE-2.0
     9  *
    10  * Unless required by applicable law or agreed to in writing, software
    11  * distributed under the License is distributed on an "AS IS" BASIS,
    12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  * See the License for the specific language governing permissions and
    14  * limitations under the License.
    15  */
    17 #include "GonkCameraParameters.h"
    18 #include "camera/CameraParameters.h"
    19 #include "ICameraControl.h"
    20 #include "CameraCommon.h"
    22 using namespace mozilla;
    23 using namespace android;
    25 /* static */ const char*
    26 GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey)
    27 {
    28   switch (aKey) {
    29     case CAMERA_PARAM_PREVIEWSIZE:
    30       return KEY_PREVIEW_SIZE;
    31     case CAMERA_PARAM_PREVIEWFORMAT:
    32       return KEY_PREVIEW_FORMAT;
    33     case CAMERA_PARAM_PREVIEWFRAMERATE:
    34       return KEY_PREVIEW_FRAME_RATE;
    35     case CAMERA_PARAM_EFFECT:
    36       return KEY_EFFECT;
    37     case CAMERA_PARAM_WHITEBALANCE:
    38       return KEY_WHITE_BALANCE;
    39     case CAMERA_PARAM_SCENEMODE:
    40       return KEY_SCENE_MODE;
    41     case CAMERA_PARAM_FLASHMODE:
    42       return KEY_FLASH_MODE;
    43     case CAMERA_PARAM_FOCUSMODE:
    44       return KEY_FOCUS_MODE;
    45     case CAMERA_PARAM_ZOOM:
    46       return KEY_ZOOM;
    47     case CAMERA_PARAM_METERINGAREAS:
    48       return KEY_METERING_AREAS;
    49     case CAMERA_PARAM_FOCUSAREAS:
    50       return KEY_FOCUS_AREAS;
    51     case CAMERA_PARAM_FOCALLENGTH:
    52       return KEY_FOCAL_LENGTH;
    53     case CAMERA_PARAM_FOCUSDISTANCENEAR:
    54       return KEY_FOCUS_DISTANCES;
    55     case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
    56       return KEY_FOCUS_DISTANCES;
    57     case CAMERA_PARAM_FOCUSDISTANCEFAR:
    58       return KEY_FOCUS_DISTANCES;
    59     case CAMERA_PARAM_EXPOSURECOMPENSATION:
    60       return KEY_EXPOSURE_COMPENSATION;
    61     case CAMERA_PARAM_THUMBNAILQUALITY:
    62       return KEY_JPEG_THUMBNAIL_QUALITY;
    63     case CAMERA_PARAM_PICTURE_SIZE:
    64       return KEY_PICTURE_SIZE;
    65     case CAMERA_PARAM_PICTURE_FILEFORMAT:
    66       return KEY_PICTURE_FORMAT;
    67     case CAMERA_PARAM_PICTURE_ROTATION:
    68       return KEY_ROTATION;
    69     case CAMERA_PARAM_PICTURE_DATETIME:
    70       // Not every platform defines a KEY_EXIF_DATETIME;
    71       // for those that don't, we use the raw string key, and if the platform
    72       // doesn't support it, it will be ignored.
    73       //
    74       // See bug 832494.
    75       return "exif-datetime";
    76     case CAMERA_PARAM_VIDEOSIZE:
    77       return KEY_VIDEO_SIZE;
    78     case CAMERA_PARAM_ISOMODE:
    79       // Not every platform defines KEY_ISO_MODE;
    80       // for those that don't, we use the raw string key.
    81       return "iso";
    82     case CAMERA_PARAM_LUMINANCE:
    83       return "luminance-condition";
    84     case CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE:
    85       // Not every platform defines KEY_QC_HDR_NEED_1X;
    86       // for those that don't, we use the raw string key.
    87       return "hdr-need-1x";
    89     case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
    90       return KEY_SUPPORTED_PREVIEW_SIZES;
    91     case CAMERA_PARAM_SUPPORTED_PICTURESIZES:
    92       return KEY_SUPPORTED_PICTURE_SIZES;
    93     case CAMERA_PARAM_SUPPORTED_VIDEOSIZES:
    94       return KEY_SUPPORTED_VIDEO_SIZES;
    95     case CAMERA_PARAM_SUPPORTED_PICTUREFORMATS:
    96       return KEY_SUPPORTED_PICTURE_FORMATS;
    97     case CAMERA_PARAM_SUPPORTED_WHITEBALANCES:
    98       return KEY_SUPPORTED_WHITE_BALANCE;
    99     case CAMERA_PARAM_SUPPORTED_SCENEMODES:
   100       return KEY_SUPPORTED_SCENE_MODES;
   101     case CAMERA_PARAM_SUPPORTED_EFFECTS:
   102       return KEY_SUPPORTED_EFFECTS;
   103     case CAMERA_PARAM_SUPPORTED_FLASHMODES:
   104       return KEY_SUPPORTED_FLASH_MODES;
   105     case CAMERA_PARAM_SUPPORTED_FOCUSMODES:
   106       return KEY_SUPPORTED_FOCUS_MODES;
   107     case CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS:
   108       return KEY_MAX_NUM_FOCUS_AREAS;
   109     case CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS:
   110       return KEY_MAX_NUM_METERING_AREAS;
   111     case CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION:
   112       return KEY_MIN_EXPOSURE_COMPENSATION;
   113     case CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION:
   114       return KEY_MAX_EXPOSURE_COMPENSATION;
   115     case CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP:
   116       return KEY_EXPOSURE_COMPENSATION_STEP;
   117     case CAMERA_PARAM_SUPPORTED_ZOOM:
   118       return KEY_ZOOM_SUPPORTED;
   119     case CAMERA_PARAM_SUPPORTED_ZOOMRATIOS:
   120       return KEY_ZOOM_RATIOS;
   121     case CAMERA_PARAM_SUPPORTED_MAXDETECTEDFACES:
   122       return KEY_MAX_NUM_DETECTED_FACES_HW;
   123     case CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES:
   124       return KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES;
   125     case CAMERA_PARAM_SUPPORTED_ISOMODES:
   126       // Not every platform defines KEY_SUPPORTED_ISO_MODES;
   127       // for those that don't, we use the raw string key.
   128       return "iso-values";
   129     default:
   130       DOM_CAMERA_LOGE("Unhandled camera parameter value %u\n", aKey);
   131       return nullptr;
   132   }
   133 }
   135 GonkCameraParameters::GonkCameraParameters()
   136   : mLock(PR_NewRWLock(PR_RWLOCK_RANK_NONE, "GonkCameraParameters.Lock"))
   137   , mDirty(false)
   138   , mInitialized(false)
   139 {
   140   MOZ_COUNT_CTOR(GonkCameraParameters);
   141   if (!mLock) {
   142     MOZ_CRASH("OOM getting new PRRWLock");
   143   }
   144 }
   146 GonkCameraParameters::~GonkCameraParameters()
   147 {
   148   MOZ_COUNT_DTOR(GonkCameraParameters);
   149   if (mLock) {
   150     PR_DestroyRWLock(mLock);
   151     mLock = nullptr;
   152   }
   153 }
   155 nsresult
   156 GonkCameraParameters::MapIsoToGonk(const nsAString& aIso, nsACString& aIsoOut)
   157 {
   158   if (aIso.EqualsASCII("hjr")) {
   159     aIsoOut = "ISO_HJR";
   160   } else if (aIso.EqualsASCII("auto")) {
   161     aIsoOut = "auto";
   162   } else {
   163     nsAutoCString v = NS_LossyConvertUTF16toASCII(aIso);
   164     unsigned int iso;
   165     if (sscanf(v.get(), "%u", &iso) != 1) {
   166       return NS_ERROR_FAILURE;
   167     }
   168     aIsoOut = nsPrintfCString("ISO%u", iso);
   169   }
   171   return NS_OK;
   172 }
   174 nsresult
   175 GonkCameraParameters::MapIsoFromGonk(const char* aIso, nsAString& aIsoOut)
   176 {
   177   if (strcmp(aIso, "ISO_HJR") == 0) {
   178     aIsoOut.AssignASCII("hjr");
   179   } else if (strcmp(aIso, "auto") == 0) {
   180     aIsoOut.AssignASCII("auto");
   181   } else {
   182     unsigned int iso;
   183     if (sscanf(aIso, "ISO%u", &iso) != 1) {
   184       return NS_ERROR_FAILURE;
   185     }
   186     aIsoOut.AppendInt(iso);
   187   }
   189   return NS_OK;
   190 }
   192 // Any members that need to be initialized on the first parameter pull
   193 // need to get handled in here.
   194 nsresult
   195 GonkCameraParameters::Initialize()
   196 {
   197   nsresult rv;
   199   rv = GetImpl(CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION, mExposureCompensationMin);
   200   if (NS_FAILED(rv)) {
   201     NS_WARNING("Failed to initialize minimum exposure compensation");
   202     mExposureCompensationMin = 0;
   203   }
   204   rv = GetImpl(CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP, mExposureCompensationStep);
   205   if (NS_FAILED(rv)) {
   206     NS_WARNING("Failed to initialize exposure compensation step size");
   207     mExposureCompensationStep = 0;
   208   }
   210   rv = GetListAsArray(CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, mZoomRatios);
   211   if (NS_FAILED(rv)) {
   212     // zoom is not supported
   213     mZoomRatios.Clear();
   214   }
   215   for (uint32_t i = 1; i < mZoomRatios.Length(); ++i) {
   216     // Make sure the camera gave us a properly sorted zoom ratio list!
   217     if (mZoomRatios[i] < mZoomRatios[i - 1]) {
   218       NS_WARNING("Zoom ratios list is out of order, discarding");
   219       DOM_CAMERA_LOGE("zoom[%d]=%fx < zoom[%d]=%fx is out of order\n",
   220         i, mZoomRatios[i] / 100.0, i - 1, mZoomRatios[i - 1] / 100.0);
   221       mZoomRatios.Clear();
   222       break;
   223     }
   224   }
   225   if (mZoomRatios.Length() == 0) {
   226     // Always report that we support at least 1.0x zoom.
   227     *mZoomRatios.AppendElement() = 100;
   228   }
   230   // The return code from GetListAsArray() doesn't matter. If it fails,
   231   // the isoModes array will be empty, and the subsequent loop won't
   232   // execute.
   233   nsTArray<nsCString> isoModes;
   234   GetListAsArray(CAMERA_PARAM_SUPPORTED_ISOMODES, isoModes);
   235   for (uint32_t i = 0; i < isoModes.Length(); ++i) {
   236     nsString v;
   237     rv = MapIsoFromGonk(isoModes[i].get(), v);
   238     if (NS_SUCCEEDED(rv)) {
   239       *mIsoModes.AppendElement() = v;
   240     }
   241   }
   243   mInitialized = true;
   244   return NS_OK;
   245 }
   247 // Handle nsAStrings
   248 nsresult
   249 GonkCameraParameters::SetTranslated(uint32_t aKey, const nsAString& aValue)
   250 {
   251   if (aKey == CAMERA_PARAM_ISOMODE) {
   252     nsAutoCString v;
   253     nsresult rv = MapIsoToGonk(aValue, v);
   254     if (NS_FAILED(rv)) {
   255       return rv;
   256     }
   257     return SetImpl(aKey, v.get());
   258   }
   260   return SetImpl(aKey, NS_ConvertUTF16toUTF8(aValue).get());
   261 }
   263 nsresult
   264 GonkCameraParameters::GetTranslated(uint32_t aKey, nsAString& aValue)
   265 {
   266   const char* val;
   267   nsresult rv = GetImpl(aKey, val);
   268   if (NS_FAILED(rv)) {
   269     return rv;
   270   }
   271   if (aKey == CAMERA_PARAM_ISOMODE) {
   272     rv = MapIsoFromGonk(val, aValue);
   273   } else if(val) {
   274     aValue.AssignASCII(val);
   275   } else {
   276     aValue.Truncate(0);
   277   }
   278   return rv;
   279 }
   281 // Handle ICameraControl::Sizes
   282 nsresult
   283 GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Size& aSize)
   284 {
   285   if (aSize.width > INT_MAX || aSize.height > INT_MAX) {
   286     // AOSP can only handle signed ints.
   287     DOM_CAMERA_LOGE("Camera parameter aKey=%d out of bounds (width=%u, height=%u)\n",
   288       aSize.width, aSize.height);
   289     return NS_ERROR_INVALID_ARG;
   290   }
   292   nsresult rv;
   294   switch (aKey) {
   295     case CAMERA_PARAM_THUMBNAILSIZE:
   296       // This is a special case--for some reason the thumbnail size
   297       // is accessed as two separate values instead of a tuple.
   298       // XXXmikeh - make this restore the original values on error
   299       rv = SetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, static_cast<int>(aSize.width));
   300       if (NS_SUCCEEDED(rv)) {
   301         rv = SetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, static_cast<int>(aSize.height));
   302       }
   303       break;
   305     case CAMERA_PARAM_VIDEOSIZE:
   306       // "record-size" is probably deprecated in later ICS;
   307       // might need to set "video-size" instead of "record-size";
   308       // for the time being, set both. See bug 795332.
   309       rv = SetImpl("record-size", nsPrintfCString("%ux%u", aSize.width, aSize.height).get());
   310       if (NS_FAILED(rv)) {
   311         break;
   312       }
   313       // intentional fallthrough
   315     default:
   316       rv = SetImpl(aKey, nsPrintfCString("%ux%u", aSize.width, aSize.height).get());
   317       break;
   318   }
   320   if (NS_FAILED(rv)) {
   321     DOM_CAMERA_LOGE("Camera parameter aKey=%d failed to set (0x%x)\n", aKey, rv);
   322   }
   323   return rv;
   324 }
   326 nsresult
   327 GonkCameraParameters::GetTranslated(uint32_t aKey, ICameraControl::Size& aSize)
   328 {
   329   nsresult rv;
   331   if (aKey == CAMERA_PARAM_THUMBNAILSIZE) {
   332     int width;
   333     int height;
   335     rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
   336     if (NS_FAILED(rv) || width < 0) {
   337       return NS_ERROR_FAILURE;
   338     }
   339     rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
   340     if (NS_FAILED(rv) || height < 0) {
   341       return NS_ERROR_FAILURE;
   342     }
   344     aSize.width = static_cast<uint32_t>(width);
   345     aSize.height = static_cast<uint32_t>(height);
   346     return NS_OK;
   347   }
   349   const char* value;
   350   rv = GetImpl(aKey, value);
   351   if (NS_FAILED(rv) || !value || *value == '\0') {
   352     DOM_CAMERA_LOGW("Camera parameter aKey=%d not available (0x%x)\n", aKey, rv);
   353     return NS_ERROR_NOT_AVAILABLE;
   354   }
   355   if (sscanf(value, "%ux%u", &aSize.width, &aSize.height) != 2) {
   356     DOM_CAMERA_LOGE("Camera parameter aKey=%d size tuple '%s' is invalid\n", aKey, value);
   357     return NS_ERROR_FAILURE;
   358   }
   359   return NS_OK;
   360 }
   362 // Handle arrays of ICameraControl::Regions
   363 nsresult
   364 GonkCameraParameters::SetTranslated(uint32_t aKey, const nsTArray<ICameraControl::Region>& aRegions)
   365 {
   366   uint32_t length = aRegions.Length();
   368   if (!length) {
   369     // This tells the camera driver to revert to automatic regioning.
   370     return SetImpl(aKey, "(0,0,0,0,0)");
   371   }
   373   nsCString s;
   375   for (uint32_t i = 0; i < length; ++i) {
   376     const ICameraControl::Region* r = &aRegions[i];
   377     s.AppendPrintf("(%d,%d,%d,%d,%d),", r->top, r->left, r->bottom, r->right, r->weight);
   378   }
   380   // remove the trailing comma
   381   s.Trim(",", false, true, true);
   383   return SetImpl(aKey, s.get());
   384 }
   386 nsresult
   387 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Region>& aRegions)
   388 {
   389   aRegions.Clear();
   391   const char* value;
   392   nsresult rv = GetImpl(aKey, value);
   393   if (NS_FAILED(rv) || !value || *value == '\0') {
   394     return NS_ERROR_FAILURE;
   395   }
   397   const char* p = value;
   398   uint32_t count = 1;
   400   // count the number of regions in the string
   401   while ((p = strstr(p, "),("))) {
   402     ++count;
   403     p += 3;
   404   }
   406   aRegions.SetCapacity(count);
   407   ICameraControl::Region* r;
   409   // parse all of the region sets
   410   uint32_t i;
   411   for (i = 0, p = value; p && i < count; ++i, p = strchr(p + 1, '(')) {
   412     r = aRegions.AppendElement();
   413     if (sscanf(p, "(%d,%d,%d,%d,%u)", &r->top, &r->left, &r->bottom, &r->right, &r->weight) != 5) {
   414       DOM_CAMERA_LOGE("%s:%d : region tuple has bad format: '%s'\n", __func__, __LINE__, p);
   415       aRegions.Clear();
   416       return NS_ERROR_FAILURE;
   417     }
   418   }
   420   return NS_OK;
   421 }
   423 // Handle ICameraControl::Positions
   424 nsresult
   425 GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Position& aPosition)
   426 {
   427   MOZ_ASSERT(aKey == CAMERA_PARAM_PICTURE_LOCATION);
   429   // Add any specified location information -- we don't care if these fail.
   430   if (!isnan(aPosition.latitude)) {
   431     DOM_CAMERA_LOGI("setting picture latitude to %lf\n", aPosition.latitude);
   432     SetImpl(Parameters::KEY_GPS_LATITUDE, nsPrintfCString("%lf", aPosition.latitude).get());
   433   }
   434   if (!isnan(aPosition.longitude)) {
   435     DOM_CAMERA_LOGI("setting picture longitude to %lf\n", aPosition.longitude);
   436     SetImpl(Parameters::KEY_GPS_LONGITUDE, nsPrintfCString("%lf", aPosition.longitude).get());
   437   }
   438   if (!isnan(aPosition.altitude)) {
   439     DOM_CAMERA_LOGI("setting picture altitude to %lf\n", aPosition.altitude);
   440     SetImpl(Parameters::KEY_GPS_ALTITUDE, nsPrintfCString("%lf", aPosition.altitude).get());
   441   }
   442   if (!isnan(aPosition.timestamp)) {
   443     DOM_CAMERA_LOGI("setting picture timestamp to %lf\n", aPosition.timestamp);
   444     SetImpl(Parameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aPosition.timestamp).get());
   445   }
   446   return NS_OK;
   447 }
   449 // Handle int64_ts
   450 nsresult
   451 GonkCameraParameters::SetTranslated(uint32_t aKey, const int64_t& aValue)
   452 {
   453   switch (aKey) {
   454     case CAMERA_PARAM_PICTURE_DATETIME:
   455       {
   456         // Add the non-GPS timestamp.  The EXIF date/time field is formatted as
   457         // "YYYY:MM:DD HH:MM:SS", without room for a time-zone; as such, the time
   458         // is meant to be stored as a local time.  Since we are given seconds from
   459         // Epoch GMT, we use localtime_r() to handle the conversion.
   460         time_t time = aValue;
   461         if (time != aValue) {
   462           DOM_CAMERA_LOGE("picture date/time '%llu' is too far in the future\n", aValue);
   463           return NS_ERROR_INVALID_ARG;
   464         }
   466         struct tm t;
   467         if (!localtime_r(&time, &t)) {
   468           DOM_CAMERA_LOGE("picture date/time couldn't be converted to local time: (%d) %s\n", errno, strerror(errno));
   469           return NS_ERROR_FAILURE;
   470         }
   472         char dateTime[20];
   473         if (!strftime(dateTime, sizeof(dateTime), "%Y:%m:%d %T", &t)) {
   474           DOM_CAMERA_LOGE("picture date/time couldn't be converted to string\n");
   475           return NS_ERROR_FAILURE;
   476         }
   478         DOM_CAMERA_LOGI("setting picture date/time to %s\n", dateTime);
   480         return SetImpl(CAMERA_PARAM_PICTURE_DATETIME, dateTime);
   481       }
   483     case CAMERA_PARAM_ISOMODE:
   484       {
   485         if (aValue > INT32_MAX) {
   486           DOM_CAMERA_LOGW("Can't set ISO mode = %lld, too big\n", aValue);
   487           return NS_ERROR_INVALID_ARG;
   488         }
   490         nsString s;
   491         s.AppendInt(aValue);
   492         return SetTranslated(CAMERA_PARAM_ISOMODE, s);
   493       }
   494   }
   496   // You can't actually pass 64-bit parameters to Gonk. :(
   497   int32_t v = static_cast<int32_t>(aValue);
   498   if (static_cast<int64_t>(v) != aValue) {
   499     return NS_ERROR_INVALID_ARG;;
   500   }
   501   return SetImpl(aKey, v);
   502 }
   504 nsresult
   505 GonkCameraParameters::GetTranslated(uint32_t aKey, int64_t& aValue)
   506 {
   507   int val;
   508   nsresult rv = GetImpl(aKey, val);
   509   if (NS_FAILED(rv)) {
   510     return rv;
   511   }
   512   aValue = val;
   513   return NS_OK;
   514 }
   516 // Handle doubles
   517 nsresult
   518 GonkCameraParameters::SetTranslated(uint32_t aKey, const double& aValue)
   519 {
   520   int index;
   521   int value;
   523   switch (aKey) {
   524     case CAMERA_PARAM_EXPOSURECOMPENSATION:
   525       if (mExposureCompensationStep == 0) {
   526         DOM_CAMERA_LOGE("Exposure compensation not supported, can't set %f\n", aValue);
   527         return NS_ERROR_NOT_AVAILABLE;
   528       }
   530       /**
   531        * Convert from real value to a Gonk index, round
   532        * to the nearest step; index is 1-based.
   533        */
   534       index =
   535         (aValue - mExposureCompensationMin + mExposureCompensationStep / 2) /
   536         mExposureCompensationStep + 1;
   537       DOM_CAMERA_LOGI("Exposure compensation = %f --> index = %d\n", aValue, index);
   538       return SetImpl(CAMERA_PARAM_EXPOSURECOMPENSATION, index);
   540     case CAMERA_PARAM_ZOOM:
   541       {
   542         /**
   543          * Convert from a real zoom multipler (e.g. 2.5x) to
   544          * the index of the nearest supported value.
   545          */
   546         value = aValue * 100.0;
   548         if (value <= mZoomRatios[0]) {
   549           index = 0;
   550         } else if (value >= mZoomRatios.LastElement()) {
   551           index = mZoomRatios.Length() - 1;
   552         } else {
   553           // mZoomRatios is sorted, so we can binary search it
   554           int bottom = 0;
   555           int top = mZoomRatios.Length() - 1;
   557           while (top >= bottom) {
   558             index = (top + bottom) / 2;
   559             if (value == mZoomRatios[index]) {
   560               // exact match
   561               break;
   562             }
   563             if (value > mZoomRatios[index] && value < mZoomRatios[index + 1]) {
   564               // the specified zoom value lies in this interval
   565               break;
   566             }
   567             if (value > mZoomRatios[index]) {
   568               bottom = index + 1;
   569             } else {
   570               top = index - 1;
   571             }
   572           }
   573         }
   574         DOM_CAMERA_LOGI("Zoom = %fx --> index = %d\n", aValue, index);
   575       }
   576       return SetImpl(CAMERA_PARAM_ZOOM, index);
   577   }
   579   return SetImpl(aKey, aValue);
   580 }
   582 nsresult
   583 GonkCameraParameters::GetTranslated(uint32_t aKey, double& aValue)
   584 {
   585   double val;
   586   int index = 0;
   587   double focusDistance[3];
   588   const char* s;
   589   nsresult rv;
   591   switch (aKey) {
   592     case CAMERA_PARAM_ZOOM:
   593       rv = GetImpl(aKey, index);
   594       if (NS_SUCCEEDED(rv) && index >= 0) {
   595         val = mZoomRatios[index] / 100.0;
   596       } else {
   597         // return 1x when zooming is not supported
   598         val = 1.0;
   599         rv = NS_OK;
   600       }
   601       break;
   603     /**
   604      * The gonk camera parameters API only exposes one focus distance property
   605      * that contains "Near,Optimum,Far" distances, in metres, where 'Far' may
   606      * be 'Infinity'.
   607      */
   608     case CAMERA_PARAM_FOCUSDISTANCEFAR:
   609       ++index;
   610       // intentional fallthrough
   612     case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
   613       ++index;
   614       // intentional fallthrough
   616     case CAMERA_PARAM_FOCUSDISTANCENEAR:
   617       rv = GetImpl(aKey, s);
   618       if (NS_SUCCEEDED(rv)) {
   619         if (sscanf(s, "%lf,%lf,%lf", &focusDistance[0], &focusDistance[1], &focusDistance[2]) == 3) {
   620           val = focusDistance[index];
   621         } else {
   622           val = 0.0;
   623         }
   624       }
   625       break;
   627     case CAMERA_PARAM_EXPOSURECOMPENSATION:
   628       rv = GetImpl(aKey, index);
   629       if (NS_SUCCEEDED(rv)) {
   630         if (!index) {
   631           // NaN indicates automatic exposure compensation
   632           val = NAN;
   633         } else {
   634           val = (index - 1) * mExposureCompensationStep + mExposureCompensationMin;
   635           DOM_CAMERA_LOGI("index = %d --> compensation = %f\n", index, val);
   636         }
   637       }
   638       break;
   640     default:
   641       rv = GetImpl(aKey, val);
   642       break;
   643   }
   645   if (NS_SUCCEEDED(rv)) {
   646     aValue = val;
   647   }
   648   return rv;
   649 }
   651 // Handle ints
   652 nsresult
   653 GonkCameraParameters::SetTranslated(uint32_t aKey, const int& aValue)
   654 {
   655   return SetImpl(aKey, aValue);
   656 }
   658 nsresult
   659 GonkCameraParameters::GetTranslated(uint32_t aKey, int& aValue)
   660 {
   661   return GetImpl(aKey, aValue);
   662 }
   664 // Handle uint32_ts -- Gonk only speaks int
   665 nsresult
   666 GonkCameraParameters::SetTranslated(uint32_t aKey, const uint32_t& aValue)
   667 {
   668   if (aValue > INT_MAX) {
   669     return NS_ERROR_INVALID_ARG;
   670   }
   672   int val = static_cast<int>(aValue);
   673   return SetImpl(aKey, val);
   674 }
   676 nsresult
   677 GonkCameraParameters::GetTranslated(uint32_t aKey, uint32_t& aValue)
   678 {
   679   int val;
   680   nsresult rv = GetImpl(aKey, val);
   681   if (NS_FAILED(rv)) {
   682     return rv;
   683   }
   684   if (val < 0) {
   685     return NS_ERROR_FAILURE;
   686   }
   688   aValue = val;
   689   return NS_OK;
   690 }
   692 // Handle bools
   693 nsresult
   694 GonkCameraParameters::SetTranslated(uint32_t aKey, const bool& aValue)
   695 {
   696   return SetImpl(aKey, aValue);
   697 }
   699 nsresult
   700 GonkCameraParameters::GetTranslated(uint32_t aKey, bool& aValue)
   701 {
   702   return GetImpl(aKey, aValue);
   703 }
   705 nsresult
   706 ParseItem(const char* aStart, const char* aEnd, ICameraControl::Size* aItem)
   707 {
   708   if (sscanf(aStart, "%ux%u", &aItem->width, &aItem->height) == 2) {
   709     return NS_OK;
   710   }
   712   DOM_CAMERA_LOGE("Size tuple has bad format: '%s'\n", __func__, __LINE__, aStart);
   713   return NS_ERROR_FAILURE;
   714 }
   716 nsresult
   717 ParseItem(const char* aStart, const char* aEnd, nsAString* aItem)
   718 {
   719   if (aEnd) {
   720     aItem->AssignASCII(aStart, aEnd - aStart);
   721   } else {
   722     aItem->AssignASCII(aStart);
   723   }
   724   return NS_OK;
   725 }
   727 nsresult
   728 ParseItem(const char* aStart, const char* aEnd, nsACString* aItem)
   729 {
   730   if (aEnd) {
   731     aItem->AssignASCII(aStart, aEnd - aStart);
   732   } else {
   733     aItem->AssignASCII(aStart);
   734   }
   735   return NS_OK;
   736 }
   738 nsresult
   739 ParseItem(const char* aStart, const char* aEnd, double* aItem)
   740 {
   741   if (sscanf(aStart, "%lf", aItem) == 1) {
   742     return NS_OK;
   743   }
   745   return NS_ERROR_FAILURE;
   746 }
   748 nsresult
   749 ParseItem(const char* aStart, const char* aEnd, int* aItem)
   750 {
   751   if (sscanf(aStart, "%d", aItem) == 1) {
   752     return NS_OK;
   753   }
   755   return NS_ERROR_FAILURE;
   756 }
   758 template<class T> nsresult
   759 GonkCameraParameters::GetListAsArray(uint32_t aKey, nsTArray<T>& aArray)
   760 {
   761   const char* p;
   762   nsresult rv = GetImpl(aKey, p);
   763   if (NS_FAILED(rv)) {
   764     return rv;
   765   }
   767   aArray.Clear();
   769   // If there is no value available, just return the empty array.
   770   if (!p) {
   771     DOM_CAMERA_LOGI("Camera parameter %d not available (value is null)\n", aKey);
   772     return NS_OK;
   773   }
   774   if (*p == '\0') {
   775     DOM_CAMERA_LOGI("Camera parameter %d not available (value is empty string)\n", aKey);
   776     return NS_OK;
   777   }
   779   const char* comma;
   781   while (p) {
   782     T* v = aArray.AppendElement();
   783     if (!v) {
   784       aArray.Clear();
   785       return NS_ERROR_OUT_OF_MEMORY;
   786     }
   787     comma = strchr(p, ',');
   788     if (comma != p) {
   789       rv = ParseItem(p, comma, v);
   790       if (NS_FAILED(rv)) {
   791         aArray.Clear();
   792         return rv;
   793       }
   794       p = comma;
   795     }
   796     if (p) {
   797       ++p;
   798     }
   799   }
   801   return NS_OK;
   802 }
   804 nsresult
   805 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<nsString>& aValues)
   806 {
   807   if (aKey == CAMERA_PARAM_SUPPORTED_ISOMODES) {
   808     aValues = mIsoModes;
   809     return NS_OK;
   810   }
   812   return GetListAsArray(aKey, aValues);
   813 }
   815 nsresult
   816 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<double>& aValues)
   817 {
   818   if (aKey == CAMERA_PARAM_SUPPORTED_ZOOMRATIOS) {
   819     aValues.Clear();
   820     for (uint32_t i = 0; i < mZoomRatios.Length(); ++i) {
   821       *aValues.AppendElement() = mZoomRatios[i] / 100.0;
   822     }
   823     return NS_OK;
   824   }
   826   return GetListAsArray(aKey, aValues);
   827 }
   829 nsresult
   830 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Size>& aSizes)
   831 {
   832   return GetListAsArray(aKey, aSizes);
   833 }

mercurial