1101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin/* 2101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Copyright (C) 2009 The Android Open Source Project 3101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * 4101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * you may not use this file except in compliance with the License. 6101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * You may obtain a copy of the License at 7101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * 8101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * http://www.apache.org/licenses/LICENSE-2.0 9101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * 10101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Unless required by applicable law or agreed to in writing, software 11101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * See the License for the specific language governing permissions and 14101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * limitations under the License. 15101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 16101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 17937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Linpackage com.android.camera; 18101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 193f3c857e3f34650c15d764810335024654b0fcc3Owen Linimport android.app.Activity; 203f3c857e3f34650c15d764810335024654b0fcc3Owen Linimport android.app.AlertDialog; 21dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Liimport android.app.admin.DevicePolicyManager; 228ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Liimport android.content.ActivityNotFoundException; 238ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Liimport android.content.ContentResolver; 24dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Liimport android.content.Context; 253f3c857e3f34650c15d764810335024654b0fcc3Owen Linimport android.content.DialogInterface; 268ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Liimport android.content.Intent; 27101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.Bitmap; 28101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.BitmapFactory; 29101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.Matrix; 30048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huangimport android.graphics.Rect; 31048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huangimport android.graphics.RectF; 32c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Liimport android.hardware.Camera; 33a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Liimport android.hardware.Camera.CameraInfo; 3410fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Liimport android.hardware.Camera.Parameters; 356227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatraimport android.hardware.Camera.Size; 36a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Liimport android.location.Location; 378ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Liimport android.net.Uri; 38dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Liimport android.os.Build; 398ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Liimport android.os.ParcelFileDescriptor; 40a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chenimport android.provider.Settings; 4110208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Liimport android.telephony.TelephonyManager; 4216ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Liimport android.util.DisplayMetrics; 43101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.util.Log; 446227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatraimport android.view.Display; 45a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Liimport android.view.OrientationEventListener; 46ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Changimport android.view.Surface; 47601ce56b034f111b2875e7636776f2f359f6a156Owen Linimport android.view.View; 48e0861e7473d042bdd9c935f3bdf50ae220891b6cWu-cheng Liimport android.view.Window; 4916ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Liimport android.view.WindowManager; 50ea136afa2f4d38428ad486df5fb0a24db8314a3dChih-yu Huangimport android.view.animation.AlphaAnimation; 51ea136afa2f4d38428ad486df5fb0a24db8314a3dChih-yu Huangimport android.view.animation.Animation; 52101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 53101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport java.io.Closeable; 548ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Liimport java.io.IOException; 5510208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Liimport java.lang.reflect.Method; 56757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Liimport java.text.SimpleDateFormat; 57757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Liimport java.util.Date; 581efb18228a45952d699af280482e1c51a4582690Owen Linimport java.util.List; 5910fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Liimport java.util.StringTokenizer; 60101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 61101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin/** 62101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Collection of utility functions used in this package. 63101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 64101d528d59f447847d5c6b7578642132c2b76f4fOwen Linpublic class Util { 6534fe2a9d33a5b4ce49862ce4558a36c62ba6d540Chih-Chung Chang private static final String TAG = "Util"; 669e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li private static final int DIRECTION_LEFT = 0; 679e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li private static final int DIRECTION_RIGHT = 1; 689e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li private static final int DIRECTION_UP = 2; 699e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li private static final int DIRECTION_DOWN = 3; 70101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 71a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen // The brightness setting used when it is set to automatic in the system. 72a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen // The reason why it is set to 0.7 is just because 1.0 is too bright. 73a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen // Use the same setting among the Camera, VideoCamera and Panorama modes. 74a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen private static final float DEFAULT_CAMERA_BRIGHTNESS = 0.7f; 75a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen 76131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala // Orientation hysteresis amount used in rounding, in degrees 77131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala public static final int ORIENTATION_HYSTERESIS = 5; 78131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala 791efb18228a45952d699af280482e1c51a4582690Owen Lin public static final String REVIEW_ACTION = "com.android.camera.action.REVIEW"; 8035688439f40f00a1376dcfab6e6495989d82e433Wei-Ta Chen 81bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau // Private intent extras. Test only. 829e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li private static final String EXTRAS_CAMERA_FACING = 839e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li "android.intent.extras.CAMERA_FACING"; 84bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 85bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang private static boolean sIsTabletUI; 8616ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li private static float sPixelDensity = 1; 87ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang private static ImageFileNamer sImageFileNamer; 88bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang 89101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin private Util() { 90101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 91101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 92bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang public static void initialize(Context context) { 934c7b291018e08dbb4bc1712d95117a294fa1416cWu-cheng Li sIsTabletUI = (context.getResources().getConfiguration().smallestScreenWidthDp >= 600); 9416ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li 9516ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li DisplayMetrics metrics = new DisplayMetrics(); 9616ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li WindowManager wm = (WindowManager) 9716ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li context.getSystemService(Context.WINDOW_SERVICE); 9816ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li wm.getDefaultDisplay().getMetrics(metrics); 9916ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li sPixelDensity = metrics.density; 100ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang sImageFileNamer = new ImageFileNamer( 101ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang context.getString(R.string.image_file_name_format)); 102bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang } 103bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang 104bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang public static boolean isTabletUI() { 105bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang return sIsTabletUI; 106bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang } 107bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang 10816ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li public static int dpToPixel(int dp) { 10916ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li return Math.round(sPixelDensity * dp); 11016ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li } 11116ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li 112101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Rotates the bitmap by the specified degree. 113101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // If a new bitmap is created, the original bitmap is recycled. 114101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap rotate(Bitmap b, int degrees) { 1159cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li return rotateAndMirror(b, degrees, false); 1169cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } 1179cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li 1189cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li // Rotates and/or mirrors the bitmap. If a new bitmap is created, the 1199cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li // original bitmap is recycled. 1209cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li public static Bitmap rotateAndMirror(Bitmap b, int degrees, boolean mirror) { 1219cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li if ((degrees != 0 || mirror) && b != null) { 122101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Matrix m = new Matrix(); 123b416f542580970aeac320219b80137b1e9f8d4cdMike Dodd // Mirror first. 124b416f542580970aeac320219b80137b1e9f8d4cdMike Dodd // horizontal flip + rotation = -rotation + horizontal flip 1259cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li if (mirror) { 1269cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li m.postScale(-1, 1); 1279cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li degrees = (degrees + 360) % 360; 1289cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li if (degrees == 0 || degrees == 180) { 1299cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li m.postTranslate((float) b.getWidth(), 0); 1309cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } else if (degrees == 90 || degrees == 270) { 1319cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li m.postTranslate((float) b.getHeight(), 0); 1329cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } else { 1339cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li throw new IllegalArgumentException("Invalid degrees=" + degrees); 1349cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } 1359cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } 136b416f542580970aeac320219b80137b1e9f8d4cdMike Dodd if (degrees != 0) { 137b416f542580970aeac320219b80137b1e9f8d4cdMike Dodd // clockwise 138b416f542580970aeac320219b80137b1e9f8d4cdMike Dodd m.postRotate(degrees, 139b416f542580970aeac320219b80137b1e9f8d4cdMike Dodd (float) b.getWidth() / 2, (float) b.getHeight() / 2); 140b416f542580970aeac320219b80137b1e9f8d4cdMike Dodd } 1419cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li 142101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 143101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap b2 = Bitmap.createBitmap( 144101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b, 0, 0, b.getWidth(), b.getHeight(), m, true); 145101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (b != b2) { 146101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b.recycle(); 147101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b = b2; 148101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 149101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (OutOfMemoryError ex) { 150101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // We have no memory to rotate. Return the original bitmap. 151101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 152101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 153101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return b; 154101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 155101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 156101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /* 157ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * Compute the sample size as a function of minSideLength 158ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * and maxNumOfPixels. 1593c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * minSideLength is used to specify that minimal width or height of a 1603c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * bitmap. 1613c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * maxNumOfPixels is used to specify the maximal size in pixels that is 1623c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * tolerable in terms of memory usage. 163ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * 164ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * The function returns a sample size based on the constraints. 1656bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh * Both size and minSideLength can be passed in as -1 166ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * which indicates no care of the corresponding constraint. 167ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * The functions prefers returning a sample size that 1686bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh * generates a smaller bitmap, unless minSideLength = -1. 1693c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * 1703c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * Also, the function rounds up the sample size to a power of 2 or multiple 1713c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * of 8 because BitmapFactory only honors sample size this way. 1723c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * For example, BitmapFactory downsamples an image by 2 even though the 1733c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * request is 3. So we round up the sample size to avoid OOM. 174101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 175ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang public static int computeSampleSize(BitmapFactory.Options options, 176ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang int minSideLength, int maxNumOfPixels) { 1773c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen int initialSize = computeInitialSampleSize(options, minSideLength, 1783c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen maxNumOfPixels); 1793c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen 1803c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen int roundedSize; 181522e836abc90bcb2d4e7a4ac37e269154d06c715Chih-Chung Chang if (initialSize <= 8) { 1823c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen roundedSize = 1; 1833c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen while (roundedSize < initialSize) { 1843c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen roundedSize <<= 1; 1853c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } 1863c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } else { 1873c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen roundedSize = (initialSize + 7) / 8 * 8; 1883c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } 1893c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen 1903c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen return roundedSize; 1913c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } 1923c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen 1933c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen private static int computeInitialSampleSize(BitmapFactory.Options options, 1943c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen int minSideLength, int maxNumOfPixels) { 195ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang double w = options.outWidth; 196ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang double h = options.outHeight; 197ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang 1986bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh int lowerBound = (maxNumOfPixels < 0) ? 1 : 199ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels)); 2006bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh int upperBound = (minSideLength < 0) ? 128 : 201ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang (int) Math.min(Math.floor(w / minSideLength), 202ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang Math.floor(h / minSideLength)); 203ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang 204f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen if (upperBound < lowerBound) { 205f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen // return the larger one when there is no overlapping zone. 206f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen return lowerBound; 207f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen } 208f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen 2096bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh if (maxNumOfPixels < 0 && minSideLength < 0) { 210ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang return 1; 2116bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh } else if (minSideLength < 0) { 212ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang return lowerBound; 213ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang } else { 214ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang return upperBound; 215101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 216101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 217101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 218cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang public static Bitmap makeBitmap(byte[] jpegData, int maxNumOfPixels) { 219cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang try { 220cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang BitmapFactory.Options options = new BitmapFactory.Options(); 221cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inJustDecodeBounds = true; 222cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, 223cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options); 224cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang if (options.mCancel || options.outWidth == -1 225cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang || options.outHeight == -1) { 226cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang return null; 227cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang } 228cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inSampleSize = computeSampleSize( 2296bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh options, -1, maxNumOfPixels); 230cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inJustDecodeBounds = false; 231cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang 232cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inDither = false; 233cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inPreferredConfig = Bitmap.Config.ARGB_8888; 234cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, 235cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options); 236cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang } catch (OutOfMemoryError ex) { 237cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang Log.e(TAG, "Got oom exception ", ex); 238cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang return null; 239cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang } 240c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 241c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 2426bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh public static void closeSilently(Closeable c) { 2436bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh if (c == null) return; 2446bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh try { 2456bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh c.close(); 2466bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh } catch (Throwable t) { 2476bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh // do nothing 2486bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh } 2496bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh } 2506bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh 251341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang public static void Assert(boolean cond) { 252341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang if (!cond) { 253341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang throw new AssertionError(); 254341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang } 255341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang } 256059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin 257dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li public static android.hardware.Camera openCamera(Activity activity, int cameraId) 258dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li throws CameraHardwareException, CameraDisabledException { 259dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li // Check if device policy has disabled the camera. 260dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService( 261dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li Context.DEVICE_POLICY_SERVICE); 262dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li if (dpm.getCameraDisabled(null)) { 263dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li throw new CameraDisabledException(); 264dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } 265dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li 266dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li try { 267dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li return CameraHolder.instance().open(cameraId); 268dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } catch (CameraHardwareException e) { 269dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li // In eng build, we throw the exception so that test tool 270dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li // can detect it and report it 271dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li if ("eng".equals(Build.TYPE)) { 272dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li throw new RuntimeException("openCamera failed", e); 273dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } else { 274dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li throw e; 275dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } 276dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } 277dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } 278dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li 279dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li public static void showErrorAndFinish(final Activity activity, int msgId) { 2803f3c857e3f34650c15d764810335024654b0fcc3Owen Lin DialogInterface.OnClickListener buttonListener = 2813f3c857e3f34650c15d764810335024654b0fcc3Owen Lin new DialogInterface.OnClickListener() { 2823f3c857e3f34650c15d764810335024654b0fcc3Owen Lin public void onClick(DialogInterface dialog, int which) { 2833f3c857e3f34650c15d764810335024654b0fcc3Owen Lin activity.finish(); 2843f3c857e3f34650c15d764810335024654b0fcc3Owen Lin } 2853f3c857e3f34650c15d764810335024654b0fcc3Owen Lin }; 2863f3c857e3f34650c15d764810335024654b0fcc3Owen Lin new AlertDialog.Builder(activity) 2873f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .setCancelable(false) 288db0757dc9c627e7c5206104664028e386ade7d03Wu-cheng Li .setIconAttribute(android.R.attr.alertDialogIcon) 289dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li .setTitle(R.string.camera_error_title) 290dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li .setMessage(msgId) 29122d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong .setNeutralButton(R.string.dialog_ok, buttonListener) 2923f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .show(); 2933f3c857e3f34650c15d764810335024654b0fcc3Owen Lin } 2942c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin 29573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin public static <T> T checkNotNull(T object) { 29673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin if (object == null) throw new NullPointerException(); 29773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin return object; 29873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin } 29973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin 30073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin public static boolean equals(Object a, Object b) { 30173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin return (a == b) || (a == null ? false : a.equals(b)); 30273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin } 3034de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 3044de149ceb47f2c251f646419907424bfb67d2b64Owen Lin public static int nextPowerOf2(int n) { 3054de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n -= 1; 3064de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 16; 3074de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 8; 3084de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 4; 3094de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 2; 3104de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 1; 3114de149ceb47f2c251f646419907424bfb67d2b64Owen Lin return n + 1; 3124de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 31333be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin 31433be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin public static float distance(float x, float y, float sx, float sy) { 31533be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin float dx = x - sx; 31633be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin float dy = y - sy; 31733be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin return (float) Math.sqrt(dx * dx + dy * dy); 31833be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin } 31933be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin 32033be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin public static int clamp(int x, int min, int max) { 32133be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin if (x > max) return max; 32233be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin if (x < min) return min; 32333be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin return x; 32433be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin } 325ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang 3264aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li public static int getDisplayRotation(Activity activity) { 327ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang int rotation = activity.getWindowManager().getDefaultDisplay() 328ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang .getRotation(); 329ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang switch (rotation) { 3304aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_0: return 0; 3314aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_90: return 90; 3324aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_180: return 180; 3334aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_270: return 270; 334ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang } 3354aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li return 0; 3364aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li } 337ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang 3384b602592e0d189499b22d107d997b83e798b5bd9Wu-cheng Li public static int getDisplayOrientation(int degrees, int cameraId) { 3394b602592e0d189499b22d107d997b83e798b5bd9Wu-cheng Li // See android.hardware.Camera.setDisplayOrientation for 340c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li // documentation. 341c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li Camera.CameraInfo info = new Camera.CameraInfo(); 342c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li Camera.getCameraInfo(cameraId, info); 343c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li int result; 344c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 345c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li result = (info.orientation + degrees) % 360; 346c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li result = (360 - result) % 360; // compensate the mirror 347c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li } else { // back-facing 348c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li result = (info.orientation - degrees + 360) % 360; 349c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li } 3504b602592e0d189499b22d107d997b83e798b5bd9Wu-cheng Li return result; 351ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang } 3526227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 353e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen public static int getCameraOrientation(int cameraId) { 354e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen Camera.CameraInfo info = new Camera.CameraInfo(); 355e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen Camera.getCameraInfo(cameraId, info); 356e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return info.orientation; 357e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } 358e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen 359131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala public static int roundOrientation(int orientation, int orientationHistory) { 360131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala boolean changeOrientation = false; 361131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) { 362131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala changeOrientation = true; 363131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala } else { 364131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala int dist = Math.abs(orientation - orientationHistory); 365131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala dist = Math.min( dist, 360 - dist ); 366131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala changeOrientation = ( dist >= 45 + ORIENTATION_HYSTERESIS ); 367131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala } 368131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala if (changeOrientation) { 369131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala return ((orientation + 45) / 90 * 90) % 360; 370131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala } 371131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala return orientationHistory; 372131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala } 373131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala 3746227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra public static Size getOptimalPreviewSize(Activity currentActivity, 3756227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra List<Size> sizes, double targetRatio) { 3760fad45d0d64569098f4daf34ff7e5ae785601304Wu-cheng Li // Use a very small tolerance because we want an exact match. 3770fad45d0d64569098f4daf34ff7e5ae785601304Wu-cheng Li final double ASPECT_TOLERANCE = 0.001; 3786227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (sizes == null) return null; 3796227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3806227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra Size optimalSize = null; 3816227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra double minDiff = Double.MAX_VALUE; 3826227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3836227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // Because of bugs of overlay and layout, we sometimes will try to 3846227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // layout the viewfinder in the portrait orientation and thus get the 3856227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // wrong size of mSurfaceView. When we change the preview size, the 3866227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // new overlay will be created before the old one closed, which causes 3876227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // an exception. For now, just get the screen size 3886227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3896227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra Display display = currentActivity.getWindowManager().getDefaultDisplay(); 3906227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra int targetHeight = Math.min(display.getHeight(), display.getWidth()); 3916227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3926227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (targetHeight <= 0) { 3936227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // We don't know the size of SurfaceView, use screen height 3946227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra targetHeight = display.getHeight(); 3956227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3966227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3976227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // Try to find an size match aspect ratio and size 3986227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra for (Size size : sizes) { 3996227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra double ratio = (double) size.width / size.height; 4006227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; 4016227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (Math.abs(size.height - targetHeight) < minDiff) { 4026227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra optimalSize = size; 4036227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra minDiff = Math.abs(size.height - targetHeight); 4046227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 4056227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 4066227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 4070fad45d0d64569098f4daf34ff7e5ae785601304Wu-cheng Li // Cannot find the one match the aspect ratio. This should not happen. 4080fad45d0d64569098f4daf34ff7e5ae785601304Wu-cheng Li // Ignore the requirement. 4096227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (optimalSize == null) { 4100fad45d0d64569098f4daf34ff7e5ae785601304Wu-cheng Li Log.w(TAG, "No preview size match the aspect ratio"); 4116227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra minDiff = Double.MAX_VALUE; 4126227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra for (Size size : sizes) { 4136227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (Math.abs(size.height - targetHeight) < minDiff) { 4146227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra optimalSize = size; 4156227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra minDiff = Math.abs(size.height - targetHeight); 4166227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 4176227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 4186227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 4196227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra return optimalSize; 4206227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 42110fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li 4221d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang // Returns the largest picture size which matches the given aspect ratio. 4231d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang public static Size getOptimalVideoSnapshotPictureSize( 4241d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang List<Size> sizes, double targetRatio) { 4251d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang // Use a very small tolerance because we want an exact match. 4261d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang final double ASPECT_TOLERANCE = 0.001; 4271d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang if (sizes == null) return null; 4281d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang 4291d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang Size optimalSize = null; 4301d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang 4311d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang // Try to find a size matches aspect ratio and has the largest width 4321d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang for (Size size : sizes) { 4331d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang double ratio = (double) size.width / size.height; 4341d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; 4351d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang if (optimalSize == null || size.width > optimalSize.width) { 4361d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang optimalSize = size; 4371d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang } 4381d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang } 4391d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang 4401d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang // Cannot find one that matches the aspect ratio. This should not happen. 4411d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang // Ignore the requirement. 4421d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang if (optimalSize == null) { 4431d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang Log.w(TAG, "No picture size match the aspect ratio"); 4441d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang for (Size size : sizes) { 4451d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang if (optimalSize == null || size.width > optimalSize.width) { 4461d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang optimalSize = size; 4471d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang } 4481d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang } 4491d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang } 4501d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang return optimalSize; 4511d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang } 4521d965984ecf6c6233967a1f5d5a24f21fd2e450dChih-Chung Chang 45310fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li public static void dumpParameters(Parameters parameters) { 45410fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li String flattened = parameters.flatten(); 45510fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li StringTokenizer tokenizer = new StringTokenizer(flattened, ";"); 45610fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li Log.d(TAG, "Dump all camera parameters:"); 45710fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li while (tokenizer.hasMoreElements()) { 45810fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li Log.d(TAG, tokenizer.nextToken()); 45910fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li } 46010fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li } 46110208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li 462dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li /** 46310208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li * Returns whether the device is voice-capable (meaning, it can do MMS). 46410208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li */ 46510208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li public static boolean isMmsCapable(Context context) { 46610208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li TelephonyManager telephonyManager = (TelephonyManager) 46710208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li context.getSystemService(Context.TELEPHONY_SERVICE); 46810208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li if (telephonyManager == null) { 46910208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li return false; 47010208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li } 47110208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li 47210208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li try { 47310208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li Class partypes[] = new Class[0]; 47410208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li Method sIsVoiceCapable = TelephonyManager.class.getMethod( 47510208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li "isVoiceCapable", partypes); 47610208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li 47710208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li Object arglist[] = new Object[0]; 47810208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li Object retobj = sIsVoiceCapable.invoke(telephonyManager, arglist); 47910208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li return (Boolean) retobj; 48010208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li } catch (java.lang.reflect.InvocationTargetException ite) { 48110208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li // Failure, must be another device. 48210208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li // Assume that it is voice capable. 483feaf2ccff42c44b74be814b66296f9ddedcc9aa9Wu-cheng Li } catch (IllegalAccessException iae) { 48410208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li // Failure, must be an other device. 48510208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li // Assume that it is voice capable. 48610208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li } catch (NoSuchMethodException nsme) { 48710208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li } 48810208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li return true; 48910208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li } 490bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 491bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau // This is for test only. Allow the camera to launch the specific camera. 492bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau public static int getCameraFacingIntentExtras(Activity currentActivity) { 493bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau int cameraId = -1; 494bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 495bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau int intentCameraId = 496bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau currentActivity.getIntent().getIntExtra(Util.EXTRAS_CAMERA_FACING, -1); 497bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 498bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau if (isFrontCameraIntent(intentCameraId)) { 499bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau // Check if the front camera exist 500bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau int frontCameraId = CameraHolder.instance().getFrontCameraId(); 501bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau if (frontCameraId != -1) { 502bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau cameraId = frontCameraId; 503bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 504bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } else if (isBackCameraIntent(intentCameraId)) { 505bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau // Check if the back camera exist 506bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau int backCameraId = CameraHolder.instance().getBackCameraId(); 507bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau if (backCameraId != -1) { 508bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau cameraId = backCameraId; 509bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 510bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 511bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau return cameraId; 512bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 513bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 514bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau private static boolean isFrontCameraIntent(int intentCameraId) { 515bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau return (intentCameraId == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT); 516bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 517bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 518bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau private static boolean isBackCameraIntent(int intentCameraId) { 519bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau return (intentCameraId == android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK); 520bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 521bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 52297d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li private static int mLocation[] = new int[2]; 52397d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li 52497d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li // This method is not thread-safe. 52597d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li public static boolean pointInView(float x, float y, View v) { 52697d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li v.getLocationInWindow(mLocation); 52797d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li return x >= mLocation[0] && x < (mLocation[0] + v.getWidth()) 52897d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li && y >= mLocation[1] && y < (mLocation[1] + v.getHeight()); 52997d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li } 5308ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li 5318ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li public static boolean isUriValid(Uri uri, ContentResolver resolver) { 5328ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li if (uri == null) return false; 5338ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li 5348ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li try { 5358ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r"); 5368ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li if (pfd == null) { 5378ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li Log.e(TAG, "Fail to open URI. URI=" + uri); 5388ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li return false; 5398ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 5408ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li pfd.close(); 5418ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } catch (IOException ex) { 5428ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li return false; 5438ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 5448ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li return true; 5458ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 5468ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li 5478ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li public static void viewUri(Uri uri, Context context) { 5488ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li if (!isUriValid(uri, context.getContentResolver())) { 5498ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li Log.e(TAG, "Uri invalid. uri=" + uri); 5508ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li return; 5518ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 5528ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li 5538ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li try { 5548ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li context.startActivity(new Intent(Util.REVIEW_ACTION, uri)); 5558ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } catch (ActivityNotFoundException ex) { 5568ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li try { 5578ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li context.startActivity(new Intent(Intent.ACTION_VIEW, uri)); 5588ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } catch (ActivityNotFoundException e) { 5598ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li Log.e(TAG, "review image fail. uri=" + uri, e); 5608ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 5618ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 5628ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 563d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li 564048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang public static void dumpRect(RectF rect, String msg) { 565048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang Log.v(TAG, msg + "=(" + rect.left + "," + rect.top 566048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang + "," + rect.right + "," + rect.bottom + ")"); 567048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang } 568048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang 569048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang public static void rectFToRect(RectF rectF, Rect rect) { 570048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang rect.left = Math.round(rectF.left); 571048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang rect.top = Math.round(rectF.top); 572048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang rect.right = Math.round(rectF.right); 573048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang rect.bottom = Math.round(rectF.bottom); 574048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang } 575048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang 576d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation, 577d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li int viewWidth, int viewHeight) { 578d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li // Need mirror for front camera. 579d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li matrix.setScale(mirror ? -1 : 1, 1); 580d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li // This is the value for android.hardware.Camera.setDisplayOrientation. 581d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li matrix.postRotate(displayOrientation); 582d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li // Camera driver coordinates range from (-1000, -1000) to (1000, 1000). 583d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li // UI coordinates range from (0, 0) to (width, height). 584d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li matrix.postScale(viewWidth / 2000f, viewHeight / 2000f); 585d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li matrix.postTranslate(viewWidth / 2f, viewHeight / 2f); 586d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li } 587757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Li 588757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Li public static String createJpegName(long dateTaken) { 589ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang synchronized (sImageFileNamer) { 590ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang return sImageFileNamer.generateName(dateTaken); 591ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang } 592757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Li } 593757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Li 594757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Li public static void broadcastNewPicture(Context context, Uri uri) { 595757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Li context.sendBroadcast(new Intent(android.hardware.Camera.ACTION_NEW_PICTURE, uri)); 596757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Li // Keep compatibility 597757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Li context.sendBroadcast(new Intent("com.android.camera.NEW_PICTURE", uri)); 598757b67951f40850b1ac3102dc0b6fe8977615a4aWu-cheng Li } 599ea136afa2f4d38428ad486df5fb0a24db8314a3dChih-yu Huang 600ea136afa2f4d38428ad486df5fb0a24db8314a3dChih-yu Huang public static void fadeIn(View view) { 60130f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang if (view.getVisibility() == View.VISIBLE) return; 60230f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang 603ea136afa2f4d38428ad486df5fb0a24db8314a3dChih-yu Huang view.setVisibility(View.VISIBLE); 604ea136afa2f4d38428ad486df5fb0a24db8314a3dChih-yu Huang Animation animation = new AlphaAnimation(0F, 1F); 60530f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang animation.setDuration(400); 60630f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang view.startAnimation(animation); 60730f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang } 60830f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang 60930f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang public static void fadeOut(View view) { 61030f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang if (view.getVisibility() != View.VISIBLE) return; 61130f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang 61230f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang Animation animation = new AlphaAnimation(1F, 0F); 61330f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang animation.setDuration(400); 614ea136afa2f4d38428ad486df5fb0a24db8314a3dChih-yu Huang view.startAnimation(animation); 61530f0481931beed547656f2c7bc6290ecc9b01ac3Chih-yu Huang view.setVisibility(View.GONE); 616ea136afa2f4d38428ad486df5fb0a24db8314a3dChih-yu Huang } 617a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li 618a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li public static void setRotationParameter(Parameters parameters, int cameraId, int orientation) { 619a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li // See android.hardware.Camera.Parameters.setRotation for 620a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li // documentation. 621a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li int rotation = 0; 622a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li if (orientation != OrientationEventListener.ORIENTATION_UNKNOWN) { 623a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li CameraInfo info = CameraHolder.instance().getCameraInfo()[cameraId]; 624a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { 625a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li rotation = (info.orientation - orientation + 360) % 360; 626a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } else { // back-facing camera 627a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li rotation = (info.orientation + orientation) % 360; 628a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } 629a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } 630a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li parameters.setRotation(rotation); 631a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } 632a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li 633a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li public static void setGpsParameters(Parameters parameters, Location loc) { 634a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li // Clear previous GPS location from the parameters. 635a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li parameters.removeGpsData(); 636a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li 637a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li // We always encode GpsTimeStamp 638a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li parameters.setGpsTimestamp(System.currentTimeMillis() / 1000); 639a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li 640a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li // Set GPS location. 641a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li if (loc != null) { 642a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li double lat = loc.getLatitude(); 643a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li double lon = loc.getLongitude(); 644a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li boolean hasLatLon = (lat != 0.0d) || (lon != 0.0d); 645a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li 646a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li if (hasLatLon) { 647a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li Log.d(TAG, "Set gps location"); 648a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li parameters.setGpsLatitude(lat); 649a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li parameters.setGpsLongitude(lon); 650a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li parameters.setGpsProcessingMethod(loc.getProvider().toUpperCase()); 651a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li if (loc.hasAltitude()) { 652a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li parameters.setGpsAltitude(loc.getAltitude()); 653a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } else { 654a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li // for NETWORK_PROVIDER location provider, we may have 655a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li // no altitude information, but the driver needs it, so 656a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li // we fake one. 657a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li parameters.setGpsAltitude(0); 658a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } 659a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li if (loc.getTime() != 0) { 660a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li // Location.getTime() is UTC in milliseconds. 661a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li // gps-timestamp is UTC in seconds. 662a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li long utcTimeSeconds = loc.getTime() / 1000; 663a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li parameters.setGpsTimestamp(utcTimeSeconds); 664a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } 665a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } else { 666a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li loc = null; 667a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } 668a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } 669a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li } 670e0861e7473d042bdd9c935f3bdf50ae220891b6cWu-cheng Li 671e0861e7473d042bdd9c935f3bdf50ae220891b6cWu-cheng Li public static void enterLightsOutMode(Window window) { 672e0861e7473d042bdd9c935f3bdf50ae220891b6cWu-cheng Li WindowManager.LayoutParams params = window.getAttributes(); 673e0861e7473d042bdd9c935f3bdf50ae220891b6cWu-cheng Li params.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE; 674e0861e7473d042bdd9c935f3bdf50ae220891b6cWu-cheng Li window.setAttributes(params); 675e0861e7473d042bdd9c935f3bdf50ae220891b6cWu-cheng Li } 676a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen 677a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen public static void initializeScreenBrightness(Window win, ContentResolver resolver) { 678a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen // Overright the brightness settings if it is automatic 679a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen int mode = Settings.System.getInt(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, 680a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); 681a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen if (mode == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC) { 682a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen WindowManager.LayoutParams winParams = win.getAttributes(); 683a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen winParams.screenBrightness = DEFAULT_CAMERA_BRIGHTNESS; 684a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen win.setAttributes(winParams); 685a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen } 686a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen } 687ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang 688ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang private static class ImageFileNamer { 689ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang private SimpleDateFormat mFormat; 690ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang 691ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang // The date (in milliseconds) used to generate the last name. 692ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang private long mLastDate; 693ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang 694ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang // Number of names generated for the same second. 695ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang private int mSameSecondCount; 696ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang 697ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang public ImageFileNamer(String format) { 698ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang mFormat = new SimpleDateFormat(format); 699ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang } 700ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang 701ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang public String generateName(long dateTaken) { 702ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang Date date = new Date(dateTaken); 703ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang String result = mFormat.format(date); 704ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang 705ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang // If the last name was generated for the same second, 706ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang // we append _1, _2, etc to the name. 707ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang if (dateTaken / 1000 == mLastDate / 1000) { 708ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang mSameSecondCount++; 709ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang result += "_" + mSameSecondCount; 710ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang } else { 711ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang mLastDate = dateTaken; 712ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang mSameSecondCount = 0; 713ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang } 714ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang 715ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang return result; 716ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang } 717ee740f1254232cbe5b8dd34c0c957866c03e7787Chih-Chung Chang } 718101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin} 719