Util.java revision d2db70880e6159413932f747eb82df3e925852c1
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; 30c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Liimport android.hardware.Camera; 3110fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Liimport android.hardware.Camera.Parameters; 326227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatraimport android.hardware.Camera.Size; 338ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Liimport android.net.Uri; 34dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Liimport android.os.Build; 358ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Liimport android.os.ParcelFileDescriptor; 3610208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Liimport android.telephony.TelephonyManager; 3716ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Liimport android.util.DisplayMetrics; 38101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.util.Log; 396227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatraimport android.view.Display; 40ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Changimport android.view.Surface; 41601ce56b034f111b2875e7636776f2f359f6a156Owen Linimport android.view.View; 4216ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Liimport android.view.WindowManager; 43101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 44101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport java.io.Closeable; 458ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Liimport java.io.IOException; 4610208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Liimport java.lang.reflect.Method; 471efb18228a45952d699af280482e1c51a4582690Owen Linimport java.util.List; 4810fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Liimport java.util.StringTokenizer; 49101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 50101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin/** 51101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Collection of utility functions used in this package. 52101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 53101d528d59f447847d5c6b7578642132c2b76f4fOwen Linpublic class Util { 5434fe2a9d33a5b4ce49862ce4558a36c62ba6d540Chih-Chung Chang private static final String TAG = "Util"; 559e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li private static final int DIRECTION_LEFT = 0; 569e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li private static final int DIRECTION_RIGHT = 1; 579e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li private static final int DIRECTION_UP = 2; 589e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li private static final int DIRECTION_DOWN = 3; 59101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 601efb18228a45952d699af280482e1c51a4582690Owen Lin public static final String REVIEW_ACTION = "com.android.camera.action.REVIEW"; 6135688439f40f00a1376dcfab6e6495989d82e433Wei-Ta Chen 62bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau // Private intent extras. Test only. 639e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li private static final String EXTRAS_CAMERA_FACING = 649e1fcfe35695fd1e71d6c86f28075ca356e5bad5Wu-cheng Li "android.intent.extras.CAMERA_FACING"; 65bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 66bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang private static boolean sIsTabletUI; 6716ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li private static float sPixelDensity = 1; 68bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang 69101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin private Util() { 70101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 71101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 72bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang public static void initialize(Context context) { 73bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang sIsTabletUI = (context.getResources().getConfiguration().screenWidthDp >= 1024); 7416ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li 7516ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li DisplayMetrics metrics = new DisplayMetrics(); 7616ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li WindowManager wm = (WindowManager) 7716ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li context.getSystemService(Context.WINDOW_SERVICE); 7816ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li wm.getDefaultDisplay().getMetrics(metrics); 7916ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li sPixelDensity = metrics.density; 80bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang } 81bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang 82bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang public static boolean isTabletUI() { 83bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang return sIsTabletUI; 84bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang } 85bed7386688cd7810cba23732ab71f370fe3222ffChung-yih Wang 8616ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li public static int dpToPixel(int dp) { 8716ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li return Math.round(sPixelDensity * dp); 8816ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li } 8916ca94d73bfe07f280e381595709b56c2681b2bcWu-cheng Li 90101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Rotates the bitmap by the specified degree. 91101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // If a new bitmap is created, the original bitmap is recycled. 92101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap rotate(Bitmap b, int degrees) { 939cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li return rotateAndMirror(b, degrees, false); 949cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } 959cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li 969cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li // Rotates and/or mirrors the bitmap. If a new bitmap is created, the 979cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li // original bitmap is recycled. 989cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li public static Bitmap rotateAndMirror(Bitmap b, int degrees, boolean mirror) { 999cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li if ((degrees != 0 || mirror) && b != null) { 100101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Matrix m = new Matrix(); 101101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin m.setRotate(degrees, 102101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin (float) b.getWidth() / 2, (float) b.getHeight() / 2); 1039cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li if (mirror) { 1049cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li m.postScale(-1, 1); 1059cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li degrees = (degrees + 360) % 360; 1069cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li if (degrees == 0 || degrees == 180) { 1079cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li m.postTranslate((float) b.getWidth(), 0); 1089cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } else if (degrees == 90 || degrees == 270) { 1099cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li m.postTranslate((float) b.getHeight(), 0); 1109cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } else { 1119cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li throw new IllegalArgumentException("Invalid degrees=" + degrees); 1129cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } 1139cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } 1149cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li 115101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 116101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap b2 = Bitmap.createBitmap( 117101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b, 0, 0, b.getWidth(), b.getHeight(), m, true); 118101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (b != b2) { 119101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b.recycle(); 120101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b = b2; 121101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 122101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (OutOfMemoryError ex) { 123101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // We have no memory to rotate. Return the original bitmap. 124101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 125101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 126101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return b; 127101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 128101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 129101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /* 130ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * Compute the sample size as a function of minSideLength 131ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * and maxNumOfPixels. 1323c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * minSideLength is used to specify that minimal width or height of a 1333c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * bitmap. 1343c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * maxNumOfPixels is used to specify the maximal size in pixels that is 1353c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * tolerable in terms of memory usage. 136ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * 137ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * The function returns a sample size based on the constraints. 1386bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh * Both size and minSideLength can be passed in as -1 139ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * which indicates no care of the corresponding constraint. 140ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * The functions prefers returning a sample size that 1416bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh * generates a smaller bitmap, unless minSideLength = -1. 1423c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * 1433c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * Also, the function rounds up the sample size to a power of 2 or multiple 1443c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * of 8 because BitmapFactory only honors sample size this way. 1453c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * For example, BitmapFactory downsamples an image by 2 even though the 1463c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * request is 3. So we round up the sample size to avoid OOM. 147101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 148ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang public static int computeSampleSize(BitmapFactory.Options options, 149ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang int minSideLength, int maxNumOfPixels) { 1503c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen int initialSize = computeInitialSampleSize(options, minSideLength, 1513c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen maxNumOfPixels); 1523c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen 1533c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen int roundedSize; 154522e836abc90bcb2d4e7a4ac37e269154d06c715Chih-Chung Chang if (initialSize <= 8) { 1553c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen roundedSize = 1; 1563c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen while (roundedSize < initialSize) { 1573c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen roundedSize <<= 1; 1583c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } 1593c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } else { 1603c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen roundedSize = (initialSize + 7) / 8 * 8; 1613c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } 1623c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen 1633c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen return roundedSize; 1643c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } 1653c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen 1663c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen private static int computeInitialSampleSize(BitmapFactory.Options options, 1673c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen int minSideLength, int maxNumOfPixels) { 168ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang double w = options.outWidth; 169ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang double h = options.outHeight; 170ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang 1716bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh int lowerBound = (maxNumOfPixels < 0) ? 1 : 172ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels)); 1736bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh int upperBound = (minSideLength < 0) ? 128 : 174ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang (int) Math.min(Math.floor(w / minSideLength), 175ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang Math.floor(h / minSideLength)); 176ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang 177f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen if (upperBound < lowerBound) { 178f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen // return the larger one when there is no overlapping zone. 179f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen return lowerBound; 180f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen } 181f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen 1826bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh if (maxNumOfPixels < 0 && minSideLength < 0) { 183ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang return 1; 1846bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh } else if (minSideLength < 0) { 185ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang return lowerBound; 186ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang } else { 187ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang return upperBound; 188101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 189101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 190101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 191cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang public static Bitmap makeBitmap(byte[] jpegData, int maxNumOfPixels) { 192cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang try { 193cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang BitmapFactory.Options options = new BitmapFactory.Options(); 194cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inJustDecodeBounds = true; 195cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, 196cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options); 197cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang if (options.mCancel || options.outWidth == -1 198cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang || options.outHeight == -1) { 199cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang return null; 200cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang } 201cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inSampleSize = computeSampleSize( 2026bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh options, -1, maxNumOfPixels); 203cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inJustDecodeBounds = false; 204cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang 205cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inDither = false; 206cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inPreferredConfig = Bitmap.Config.ARGB_8888; 207cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, 208cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options); 209cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang } catch (OutOfMemoryError ex) { 210cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang Log.e(TAG, "Got oom exception ", ex); 211cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang return null; 212cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang } 213c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 214c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 2156bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh public static void closeSilently(Closeable c) { 2166bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh if (c == null) return; 2176bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh try { 2186bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh c.close(); 2196bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh } catch (Throwable t) { 2206bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh // do nothing 2216bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh } 2226bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh } 2236bca5289166b1444f4b98538343a24d35f46dda5Chia-chi Yeh 224341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang public static void Assert(boolean cond) { 225341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang if (!cond) { 226341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang throw new AssertionError(); 227341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang } 228341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang } 229059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin 230dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li public static android.hardware.Camera openCamera(Activity activity, int cameraId) 231dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li throws CameraHardwareException, CameraDisabledException { 232dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li // Check if device policy has disabled the camera. 233dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService( 234dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li Context.DEVICE_POLICY_SERVICE); 235dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li if (dpm.getCameraDisabled(null)) { 236dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li throw new CameraDisabledException(); 237dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } 238dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li 239dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li try { 240dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li return CameraHolder.instance().open(cameraId); 241dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } catch (CameraHardwareException e) { 242dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li // In eng build, we throw the exception so that test tool 243dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li // can detect it and report it 244dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li if ("eng".equals(Build.TYPE)) { 245dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li throw new RuntimeException("openCamera failed", e); 246dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } else { 247dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li throw e; 248dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } 249dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } 250dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li } 251dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li 252dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li public static void showErrorAndFinish(final Activity activity, int msgId) { 2533f3c857e3f34650c15d764810335024654b0fcc3Owen Lin DialogInterface.OnClickListener buttonListener = 2543f3c857e3f34650c15d764810335024654b0fcc3Owen Lin new DialogInterface.OnClickListener() { 2553f3c857e3f34650c15d764810335024654b0fcc3Owen Lin public void onClick(DialogInterface dialog, int which) { 2563f3c857e3f34650c15d764810335024654b0fcc3Owen Lin activity.finish(); 2573f3c857e3f34650c15d764810335024654b0fcc3Owen Lin } 2583f3c857e3f34650c15d764810335024654b0fcc3Owen Lin }; 2593f3c857e3f34650c15d764810335024654b0fcc3Owen Lin new AlertDialog.Builder(activity) 2603f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .setCancelable(false) 261db0757dc9c627e7c5206104664028e386ade7d03Wu-cheng Li .setIconAttribute(android.R.attr.alertDialogIcon) 262dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li .setTitle(R.string.camera_error_title) 263dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li .setMessage(msgId) 2643f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .setNeutralButton(R.string.details_ok, buttonListener) 2653f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .show(); 2663f3c857e3f34650c15d764810335024654b0fcc3Owen Lin } 2672c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin 26873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin public static <T> T checkNotNull(T object) { 26973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin if (object == null) throw new NullPointerException(); 27073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin return object; 27173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin } 27273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin 27373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin public static boolean equals(Object a, Object b) { 27473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin return (a == b) || (a == null ? false : a.equals(b)); 27573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin } 2764de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2774de149ceb47f2c251f646419907424bfb67d2b64Owen Lin public static int nextPowerOf2(int n) { 2784de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n -= 1; 2794de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 16; 2804de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 8; 2814de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 4; 2824de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 2; 2834de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 1; 2844de149ceb47f2c251f646419907424bfb67d2b64Owen Lin return n + 1; 2854de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 28633be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin 28733be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin public static float distance(float x, float y, float sx, float sy) { 28833be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin float dx = x - sx; 28933be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin float dy = y - sy; 29033be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin return (float) Math.sqrt(dx * dx + dy * dy); 29133be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin } 29233be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin 29333be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin public static int clamp(int x, int min, int max) { 29433be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin if (x > max) return max; 29533be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin if (x < min) return min; 29633be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin return x; 29733be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin } 298ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang 2994aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li public static int getDisplayRotation(Activity activity) { 300ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang int rotation = activity.getWindowManager().getDefaultDisplay() 301ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang .getRotation(); 302ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang switch (rotation) { 3034aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_0: return 0; 3044aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_90: return 90; 3054aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_180: return 180; 3064aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_270: return 270; 307ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang } 3084aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li return 0; 3094aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li } 310ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang 3114b602592e0d189499b22d107d997b83e798b5bd9Wu-cheng Li public static int getDisplayOrientation(int degrees, int cameraId) { 3124b602592e0d189499b22d107d997b83e798b5bd9Wu-cheng Li // See android.hardware.Camera.setDisplayOrientation for 313c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li // documentation. 314c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li Camera.CameraInfo info = new Camera.CameraInfo(); 315c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li Camera.getCameraInfo(cameraId, info); 316c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li int result; 317c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 318c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li result = (info.orientation + degrees) % 360; 319c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li result = (360 - result) % 360; // compensate the mirror 320c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li } else { // back-facing 321c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li result = (info.orientation - degrees + 360) % 360; 322c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li } 3234b602592e0d189499b22d107d997b83e798b5bd9Wu-cheng Li return result; 324ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang } 3256227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3266227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra public static Size getOptimalPreviewSize(Activity currentActivity, 3276227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra List<Size> sizes, double targetRatio) { 3280fad45d0d64569098f4daf34ff7e5ae785601304Wu-cheng Li // Use a very small tolerance because we want an exact match. 3290fad45d0d64569098f4daf34ff7e5ae785601304Wu-cheng Li final double ASPECT_TOLERANCE = 0.001; 3306227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (sizes == null) return null; 3316227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3326227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra Size optimalSize = null; 3336227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra double minDiff = Double.MAX_VALUE; 3346227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3356227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // Because of bugs of overlay and layout, we sometimes will try to 3366227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // layout the viewfinder in the portrait orientation and thus get the 3376227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // wrong size of mSurfaceView. When we change the preview size, the 3386227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // new overlay will be created before the old one closed, which causes 3396227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // an exception. For now, just get the screen size 3406227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3416227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra Display display = currentActivity.getWindowManager().getDefaultDisplay(); 3426227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra int targetHeight = Math.min(display.getHeight(), display.getWidth()); 3436227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3446227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (targetHeight <= 0) { 3456227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // We don't know the size of SurfaceView, use screen height 3466227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra targetHeight = display.getHeight(); 3476227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3486227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3496227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // Try to find an size match aspect ratio and size 3506227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra for (Size size : sizes) { 3516227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra double ratio = (double) size.width / size.height; 3526227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; 3536227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (Math.abs(size.height - targetHeight) < minDiff) { 3546227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra optimalSize = size; 3556227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra minDiff = Math.abs(size.height - targetHeight); 3566227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3576227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3586227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3590fad45d0d64569098f4daf34ff7e5ae785601304Wu-cheng Li // Cannot find the one match the aspect ratio. This should not happen. 3600fad45d0d64569098f4daf34ff7e5ae785601304Wu-cheng Li // Ignore the requirement. 3616227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (optimalSize == null) { 3620fad45d0d64569098f4daf34ff7e5ae785601304Wu-cheng Li Log.w(TAG, "No preview size match the aspect ratio"); 3636227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra minDiff = Double.MAX_VALUE; 3646227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra for (Size size : sizes) { 3656227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (Math.abs(size.height - targetHeight) < minDiff) { 3666227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra optimalSize = size; 3676227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra minDiff = Math.abs(size.height - targetHeight); 3686227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3696227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3706227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3716227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra return optimalSize; 3726227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 37310fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li 37410fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li public static void dumpParameters(Parameters parameters) { 37510fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li String flattened = parameters.flatten(); 37610fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li StringTokenizer tokenizer = new StringTokenizer(flattened, ";"); 37710fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li Log.d(TAG, "Dump all camera parameters:"); 37810fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li while (tokenizer.hasMoreElements()) { 37910fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li Log.d(TAG, tokenizer.nextToken()); 38010fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li } 38110fb15e4b1a8cd4acae1a745ada98cf9fac5a809Wu-cheng Li } 38210208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li 3834a045a8e858706f56a6ffb5187960768f861f007Wu-cheng Li public static float[] convertZoomRatios(List<Integer> zoomRatios) { 3844a045a8e858706f56a6ffb5187960768f861f007Wu-cheng Li float result[] = new float[zoomRatios.size()]; 3854a045a8e858706f56a6ffb5187960768f861f007Wu-cheng Li for (int i = 0, n = result.length; i < n; ++i) { 3864a045a8e858706f56a6ffb5187960768f861f007Wu-cheng Li result[i] = (float) zoomRatios.get(i) / 100f; 3874a045a8e858706f56a6ffb5187960768f861f007Wu-cheng Li } 3884a045a8e858706f56a6ffb5187960768f861f007Wu-cheng Li return result; 3894a045a8e858706f56a6ffb5187960768f861f007Wu-cheng Li } 3904a045a8e858706f56a6ffb5187960768f861f007Wu-cheng Li 391dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li /** 39210208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li * Returns whether the device is voice-capable (meaning, it can do MMS). 39310208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li */ 39410208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li public static boolean isMmsCapable(Context context) { 39510208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li TelephonyManager telephonyManager = (TelephonyManager) 39610208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li context.getSystemService(Context.TELEPHONY_SERVICE); 39710208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li if (telephonyManager == null) { 39810208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li return false; 39910208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li } 40010208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li 40110208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li try { 40210208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li Class partypes[] = new Class[0]; 40310208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li Method sIsVoiceCapable = TelephonyManager.class.getMethod( 40410208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li "isVoiceCapable", partypes); 40510208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li 40610208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li Object arglist[] = new Object[0]; 40710208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li Object retobj = sIsVoiceCapable.invoke(telephonyManager, arglist); 40810208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li return (Boolean) retobj; 40910208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li } catch (java.lang.reflect.InvocationTargetException ite) { 41010208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li // Failure, must be another device. 41110208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li // Assume that it is voice capable. 412feaf2ccff42c44b74be814b66296f9ddedcc9aa9Wu-cheng Li } catch (IllegalAccessException iae) { 41310208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li // Failure, must be an other device. 41410208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li // Assume that it is voice capable. 41510208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li } catch (NoSuchMethodException nsme) { 41610208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li } 41710208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li return true; 41810208b3b4e2e9ca5af27be49356288531e3cd45bWu-cheng Li } 419bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 420bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau // This is for test only. Allow the camera to launch the specific camera. 421bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau public static int getCameraFacingIntentExtras(Activity currentActivity) { 422bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau int cameraId = -1; 423bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 424bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau int intentCameraId = 425bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau currentActivity.getIntent().getIntExtra(Util.EXTRAS_CAMERA_FACING, -1); 426bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 427bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau if (isFrontCameraIntent(intentCameraId)) { 428bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau // Check if the front camera exist 429bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau int frontCameraId = CameraHolder.instance().getFrontCameraId(); 430bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau if (frontCameraId != -1) { 431bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau cameraId = frontCameraId; 432bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 433bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } else if (isBackCameraIntent(intentCameraId)) { 434bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau // Check if the back camera exist 435bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau int backCameraId = CameraHolder.instance().getBackCameraId(); 436bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau if (backCameraId != -1) { 437bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau cameraId = backCameraId; 438bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 439bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 440bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau return cameraId; 441bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 442bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 443bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau private static boolean isFrontCameraIntent(int intentCameraId) { 444bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau return (intentCameraId == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT); 445bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 446bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 447bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau private static boolean isBackCameraIntent(int intentCameraId) { 448bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau return (intentCameraId == android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK); 449bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau } 450bbe9db4d12978f220aeb0379731b548420bbd6dbYu Shan Emily Lau 45197d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li private static int mLocation[] = new int[2]; 45297d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li 45397d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li // This method is not thread-safe. 45497d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li public static boolean pointInView(float x, float y, View v) { 45597d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li v.getLocationInWindow(mLocation); 45697d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li return x >= mLocation[0] && x < (mLocation[0] + v.getWidth()) 45797d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li && y >= mLocation[1] && y < (mLocation[1] + v.getHeight()); 45897d089d718dc92c0e9ccc3c923066cf4f0101c35Wu-cheng Li } 4598ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li 4608ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li public static boolean isUriValid(Uri uri, ContentResolver resolver) { 4618ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li if (uri == null) return false; 4628ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li 4638ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li try { 4648ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r"); 4658ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li if (pfd == null) { 4668ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li Log.e(TAG, "Fail to open URI. URI=" + uri); 4678ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li return false; 4688ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 4698ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li pfd.close(); 4708ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } catch (IOException ex) { 4718ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li return false; 4728ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 4738ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li return true; 4748ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 4758ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li 4768ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li public static void viewUri(Uri uri, Context context) { 4778ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li if (!isUriValid(uri, context.getContentResolver())) { 4788ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li Log.e(TAG, "Uri invalid. uri=" + uri); 4798ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li return; 4808ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 4818ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li 4828ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li try { 4838ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li context.startActivity(new Intent(Util.REVIEW_ACTION, uri)); 4848ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } catch (ActivityNotFoundException ex) { 4858ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li try { 4868ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li context.startActivity(new Intent(Intent.ACTION_VIEW, uri)); 4878ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } catch (ActivityNotFoundException e) { 4888ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li Log.e(TAG, "review image fail. uri=" + uri, e); 4898ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 4908ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 4918ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li } 492d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li 493d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation, 494d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li int viewWidth, int viewHeight) { 495d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li // Need mirror for front camera. 496d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li matrix.setScale(mirror ? -1 : 1, 1); 497d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li // This is the value for android.hardware.Camera.setDisplayOrientation. 498d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li matrix.postRotate(displayOrientation); 499d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li // Camera driver coordinates range from (-1000, -1000) to (1000, 1000). 500d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li // UI coordinates range from (0, 0) to (width, height). 501d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li matrix.postScale(viewWidth / 2000f, viewHeight / 2000f); 502d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li matrix.postTranslate(viewWidth / 2f, viewHeight / 2f); 503d2db70880e6159413932f747eb82df3e925852c1Wu-cheng Li } 504101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin} 505