1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.common; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Context; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.pm.PackageInfo; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.pm.PackageManager.NameNotFoundException; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.database.Cursor; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.Build; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.ParcelFileDescriptor; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.text.TextUtils; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.util.Log; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.Closeable; 29aeb7d79d2a35f534276bc6bf8128349f9768ae6bRuben Brunkimport java.io.IOException; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.InterruptedIOException; 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class Utils { 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "Utils"; 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String DEBUG_TAG = "GalleryDebug"; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final long POLY64REV = 0x95AC9329AC4BC9B5L; 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final long INITIALCRC = 0xFFFFFFFFFFFFFFFFL; 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static long[] sCrcTable = new long[256]; 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 4162969344d617c34c1dae2ed26f73018a097be4ceOwen Lin private static final boolean IS_DEBUG_BUILD = 4262969344d617c34c1dae2ed26f73018a097be4ceOwen Lin Build.TYPE.equals("eng") || Build.TYPE.equals("userdebug"); 4362969344d617c34c1dae2ed26f73018a097be4ceOwen Lin 4462969344d617c34c1dae2ed26f73018a097be4ceOwen Lin private static final String MASK_STRING = "********************************"; 4562969344d617c34c1dae2ed26f73018a097be4ceOwen Lin 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Throws AssertionError if the input is false. 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static void assertTrue(boolean cond) { 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!cond) { 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new AssertionError(); 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 53cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang // Throws AssertionError with the message. We had a method having the form 54cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang // assertTrue(boolean cond, String message, Object ... args); 55cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang // However a call to that method will cause memory allocation even if the 56cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang // condition is false (due to autoboxing generated by "Object ... args"), 57cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang // so we don't use that anymore. 58cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang public static void fail(String message, Object ... args) { 59cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang throw new AssertionError( 60cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang args.length == 0 ? message : String.format(message, args)); 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Throws NullPointerException if the input is null. 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static <T> T checkNotNull(T object) { 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (object == null) throw new NullPointerException(); 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return object; 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns true if two input Object are both null or equal 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // to each other. 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static boolean equals(Object a, Object b) { 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return (a == b) || (a == null ? false : a.equals(b)); 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns the next power of two. 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns the input if it is already power of 2. 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Throws IllegalArgumentException if the input is <= 0 or 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // the answer overflows. 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int nextPowerOf2(int n) { 804ce48412b86ac28042bf70e4cbe051ffc3dd489dJohn Reck if (n <= 0 || n > (1 << 30)) throw new IllegalArgumentException("n is invalid: " + n); 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin n -= 1; 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin n |= n >> 16; 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin n |= n >> 8; 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin n |= n >> 4; 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin n |= n >> 2; 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin n |= n >> 1; 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return n + 1; 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns the previous power of two. 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns the input if it is already power of 2. 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Throws IllegalArgumentException if the input is <= 0 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int prevPowerOf2(int n) { 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (n <= 0) throw new IllegalArgumentException(); 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return Integer.highestOneBit(n); 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns the input value x clamped to the range [min, max]. 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int clamp(int x, int min, int max) { 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (x > max) return max; 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (x < min) return min; 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return x; 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns the input value x clamped to the range [min, max]. 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static float clamp(float x, float min, float max) { 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (x > max) return max; 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (x < min) return min; 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return x; 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Returns the input value x clamped to the range [min, max]. 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static long clamp(long x, long min, long max) { 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (x > max) return max; 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (x < min) return min; 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return x; 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static boolean isOpaque(int color) { 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return color >>> 24 == 0xFF; 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static void swap(int[] array, int i, int j) { 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int temp = array[i]; 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin array[i] = array[j]; 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin array[j] = temp; 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin /** 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * A function thats returns a 64-bit crc for string 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * @param in input string 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * @return a 64-bit crc value 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final long crc64Long(String in) { 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (in == null || in.length() == 0) { 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return 0; 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return crc64Long(getBytes(in)); 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin static { 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // http://bioinf.cs.ucl.ac.uk/downloads/crc64/crc64.c 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long part; 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < 256; i++) { 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin part = i; 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int j = 0; j < 8; j++) { 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long x = ((int) part & 1) != 0 ? POLY64REV : 0; 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin part = (part >> 1) ^ x; 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sCrcTable[i] = part; 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final long crc64Long(byte[] buffer) { 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long crc = INITIALCRC; 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int k = 0, n = buffer.length; k < n; ++k) { 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin crc = sCrcTable[(((int) crc) ^ buffer[k]) & 0xff] ^ (crc >> 8); 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return crc; 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static byte[] getBytes(String in) { 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin byte[] result = new byte[in.length() * 2]; 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int output = 0; 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (char ch : in.toCharArray()) { 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin result[output++] = (byte) (ch & 0xFF); 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin result[output++] = (byte) (ch >> 8); 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return result; 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static void closeSilently(Closeable c) { 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (c == null) return; 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin c.close(); 177aeb7d79d2a35f534276bc6bf8128349f9768ae6bRuben Brunk } catch (IOException t) { 178aeb7d79d2a35f534276bc6bf8128349f9768ae6bRuben Brunk Log.w(TAG, "close fail ", t); 179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int compare(long a, long b) { 183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return a < b ? -1 : a == b ? 0 : 1; 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int ceilLog2(float value) { 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int i; 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (i = 0; i < 31; i++) { 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if ((1 << i) >= value) break; 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return i; 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int floorLog2(float value) { 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int i; 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (i = 0; i < 31; i++) { 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if ((1 << i) > value) break; 198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return i - 1; 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static void closeSilently(ParcelFileDescriptor fd) { 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (fd != null) fd.close(); 205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "fail to close", t); 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static void closeSilently(Cursor cursor) { 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (cursor != null) cursor.close(); 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "fail to close", t); 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static float interpolateAngle( 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float source, float target, float progress) { 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // interpolate the angle from source to target 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // We make the difference in the range of [-179, 180], this is the 222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // shortest path to change source to target. 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float diff = target - source; 224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (diff < 0) diff += 360f; 225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (diff > 180) diff -= 360f; 226f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 227f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float result = source + diff * progress; 228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return result < 0 ? result + 360f : result; 229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static float interpolateScale( 232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float source, float target, float progress) { 233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return source + progress * (target - source); 234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 235f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 236f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static String ensureNotNull(String value) { 237f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return value == null ? "" : value; 238f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static float parseFloatSafely(String content, float defaultValue) { 241f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (content == null) return defaultValue; 242f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 243f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return Float.parseFloat(content); 244f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (NumberFormatException e) { 245f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return defaultValue; 246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 248f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static int parseIntSafely(String content, int defaultValue) { 250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (content == null) return defaultValue; 251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return Integer.parseInt(content); 253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (NumberFormatException e) { 254f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return defaultValue; 255f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 256f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 257f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 258f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static boolean isNullOrEmpty(String exifMake) { 259f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return TextUtils.isEmpty(exifMake); 260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 261f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 262f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static void waitWithoutInterrupt(Object object) { 263f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 264f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin object.wait(); 265f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (InterruptedException e) { 266f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "unexpected interrupt: " + object); 267f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 268f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 269f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 270f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static boolean handleInterrruptedException(Throwable e) { 271f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // A helper to deal with the interrupt exception 272f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // If an interrupt detected, we will setup the bit again. 273f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (e instanceof InterruptedIOException 274f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin || e instanceof InterruptedException) { 275f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Thread.currentThread().interrupt(); 276f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return true; 277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 278f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return false; 279f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 280f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 281f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin /** 282f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * @return String with special XML characters escaped. 283f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 284f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static String escapeXml(String s) { 285f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin StringBuilder sb = new StringBuilder(); 286f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0, len = s.length(); i < len; ++i) { 287f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin char c = s.charAt(i); 288f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin switch (c) { 289f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case '<': sb.append("<"); break; 290f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case '>': sb.append(">"); break; 291f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case '\"': sb.append("""); break; 292f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case '\'': sb.append("'"); break; 293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case '&': sb.append("&"); break; 294f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin default: sb.append(c); 295f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 296f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return sb.toString(); 298f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 299f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 300f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static String getUserAgent(Context context) { 301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin PackageInfo packageInfo; 302f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 303f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); 304f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (NameNotFoundException e) { 305f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new IllegalStateException("getPackageInfo failed"); 306f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 307f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return String.format("%s/%s; %s/%s/%s/%s; %s/%s/%s", 308f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin packageInfo.packageName, 309f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin packageInfo.versionName, 310f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Build.BRAND, 311f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Build.DEVICE, 312f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Build.MODEL, 313f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Build.ID, 314b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin Build.VERSION.SDK_INT, 315f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Build.VERSION.RELEASE, 316f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Build.VERSION.INCREMENTAL); 317f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 318f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 319f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static String[] copyOf(String[] source, int newSize) { 320f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String[] result = new String[newSize]; 321f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin newSize = Math.min(source.length, newSize); 322f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin System.arraycopy(source, 0, result, 0, newSize); 323f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return result; 324f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 325f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 32662969344d617c34c1dae2ed26f73018a097be4ceOwen Lin // Mask information for debugging only. It returns <code>info.toString()</code> directly 32762969344d617c34c1dae2ed26f73018a097be4ceOwen Lin // for debugging build (i.e., 'eng' and 'userdebug') and returns a mask ("****") 32862969344d617c34c1dae2ed26f73018a097be4ceOwen Lin // in release build to protect the information (e.g. for privacy issue). 32962969344d617c34c1dae2ed26f73018a097be4ceOwen Lin public static String maskDebugInfo(Object info) { 33062969344d617c34c1dae2ed26f73018a097be4ceOwen Lin if (info == null) return null; 33162969344d617c34c1dae2ed26f73018a097be4ceOwen Lin String s = info.toString(); 33262969344d617c34c1dae2ed26f73018a097be4ceOwen Lin int length = Math.min(s.length(), MASK_STRING.length()); 33362969344d617c34c1dae2ed26f73018a097be4ceOwen Lin return IS_DEBUG_BUILD ? s : MASK_STRING.substring(0, length); 33462969344d617c34c1dae2ed26f73018a097be4ceOwen Lin } 3354bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 3364bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // This method should be ONLY used for debugging. 3374bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static void debug(String message, Object ... args) { 3384bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin Log.v(DEBUG_TAG, String.format(message, args)); 3394bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin } 340f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 341