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("&lt;"); break;
290f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                case '>':  sb.append("&gt;"); break;
291f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                case '\"': sb.append("&quot;"); break;
292f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                case '\'': sb.append("&#039;"); break;
293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                case '&':  sb.append("&amp;"); 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