Util.java revision 1efb18228a45952d699af280482e1c51a4582690
1c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger/*
2c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Copyright (C) 2009 The Android Open Source Project
3c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger *
4c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Licensed under the Apache License, Version 2.0 (the "License");
5c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * you may not use this file except in compliance with the License.
63f417819926108853433df184fbb358aaa85cefcAndroid Chromium Automerger * You may obtain a copy of the License at
7c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger *
8c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger *      http://www.apache.org/licenses/LICENSE-2.0
9c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger *
10c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Unless required by applicable law or agreed to in writing, software
11c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * distributed under the License is distributed on an "AS IS" BASIS,
12c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * See the License for the specific language governing permissions and
14c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * limitations under the License.
15c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger */
16c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
17c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerpackage com.android.camera;
18c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
19c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport com.android.camera.gallery.IImage;
20c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
21c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.app.Activity;
22c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.app.AlertDialog;
23c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.content.DialogInterface;
24c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.graphics.Bitmap;
25c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.graphics.BitmapFactory;
26c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.graphics.Matrix;
27c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.hardware.Camera.Size;
28c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.util.Log;
29c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.view.Display;
30c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.view.Surface;
31c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.view.View;
32c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.view.animation.Animation;
33c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.view.animation.TranslateAnimation;
34c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
35c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport java.io.Closeable;
36c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport java.util.List;
37c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
38c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger/**
39c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Collection of utility functions used in this package.
40c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger */
41c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerpublic class Util {
42c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    private static final String TAG = "Util";
43c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static final int DIRECTION_LEFT = 0;
44c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static final int DIRECTION_RIGHT = 1;
45c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static final int DIRECTION_UP = 2;
46c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static final int DIRECTION_DOWN = 3;
47c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
48c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static final String REVIEW_ACTION = "com.android.camera.action.REVIEW";
49c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
50c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    private Util() {
51c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
52c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
53c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    // Rotates the bitmap by the specified degree.
54c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    // If a new bitmap is created, the original bitmap is recycled.
55c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static Bitmap rotate(Bitmap b, int degrees) {
56c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if (degrees != 0 && b != null) {
57c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            Matrix m = new Matrix();
58c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            m.setRotate(degrees,
59c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                    (float) b.getWidth() / 2, (float) b.getHeight() / 2);
60c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            try {
61c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                Bitmap b2 = Bitmap.createBitmap(
62c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                        b, 0, 0, b.getWidth(), b.getHeight(), m, true);
63c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                if (b != b2) {
64c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                    b.recycle();
65c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                    b = b2;
66c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                }
67c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            } catch (OutOfMemoryError ex) {
68c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                // We have no memory to rotate. Return the original bitmap.
69c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            }
70c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
71c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return b;
72a715e94c5d62236fb7b1e050f175ed825a6373baAndroid Chromium Automerger    }
73c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
74c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    /*
75c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * Compute the sample size as a function of minSideLength
76c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * and maxNumOfPixels.
77c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * minSideLength is used to specify that minimal width or height of a
78c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * bitmap.
79c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * maxNumOfPixels is used to specify the maximal size in pixels that is
80c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * tolerable in terms of memory usage.
81c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     *
82c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * The function returns a sample size based on the constraints.
83c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * Both size and minSideLength can be passed in as IImage.UNCONSTRAINED,
84c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * which indicates no care of the corresponding constraint.
85c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * The functions prefers returning a sample size that
86c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * generates a smaller bitmap, unless minSideLength = IImage.UNCONSTRAINED.
87c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     *
88c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * Also, the function rounds up the sample size to a power of 2 or multiple
89c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * of 8 because BitmapFactory only honors sample size this way.
90c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * For example, BitmapFactory downsamples an image by 2 even though the
91c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     * request is 3. So we round up the sample size to avoid OOM.
92c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger     */
93c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static int computeSampleSize(BitmapFactory.Options options,
94c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            int minSideLength, int maxNumOfPixels) {
95c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        int initialSize = computeInitialSampleSize(options, minSideLength,
96c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                maxNumOfPixels);
97c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
98c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        int roundedSize;
99c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if (initialSize <= 8) {
100c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            roundedSize = 1;
101c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            while (roundedSize < initialSize) {
102c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                roundedSize <<= 1;
103c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            }
104c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        } else {
105c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            roundedSize = (initialSize + 7) / 8 * 8;
106c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
1078fc9c2daac27392f17b3c5ea83528686fe683ff0Android Chromium Automerger
108c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return roundedSize;
109c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
110c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
111c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    private static int computeInitialSampleSize(BitmapFactory.Options options,
112c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            int minSideLength, int maxNumOfPixels) {
113c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        double w = options.outWidth;
114c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        double h = options.outHeight;
115c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
116c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        int lowerBound = (maxNumOfPixels == IImage.UNCONSTRAINED) ? 1 :
117c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
118c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        int upperBound = (minSideLength == IImage.UNCONSTRAINED) ? 128 :
119c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                (int) Math.min(Math.floor(w / minSideLength),
120c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                Math.floor(h / minSideLength));
121c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
122c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if (upperBound < lowerBound) {
123c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            // return the larger one when there is no overlapping zone.
124c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            return lowerBound;
125c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
126a715e94c5d62236fb7b1e050f175ed825a6373baAndroid Chromium Automerger
127c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if ((maxNumOfPixels == IImage.UNCONSTRAINED) &&
128c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                (minSideLength == IImage.UNCONSTRAINED)) {
129c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            return 1;
130c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        } else if (minSideLength == IImage.UNCONSTRAINED) {
131c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            return lowerBound;
132c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        } else {
133c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            return upperBound;
134c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
135c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
136c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
137c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static <T>  int indexOf(T [] array, T s) {
138c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        for (int i = 0; i < array.length; i++) {
139c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            if (array[i].equals(s)) {
140c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                return i;
141c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            }
142c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
143c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return -1;
144c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
145c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
146c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static void closeSilently(Closeable c) {
147c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if (c == null) return;
148c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        try {
149c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            c.close();
150c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        } catch (Throwable t) {
151c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            // do nothing
152c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
153c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
154c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
155c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static Bitmap makeBitmap(byte[] jpegData, int maxNumOfPixels) {
156c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        try {
157c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            BitmapFactory.Options options = new BitmapFactory.Options();
158c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            options.inJustDecodeBounds = true;
159c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length,
160c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                    options);
161c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            if (options.mCancel || options.outWidth == -1
162c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                    || options.outHeight == -1) {
163c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                return null;
164c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            }
165c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            options.inSampleSize = computeSampleSize(
166c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                    options, IImage.UNCONSTRAINED, maxNumOfPixels);
167c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            options.inJustDecodeBounds = false;
168c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
169c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            options.inDither = false;
170c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
171c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length,
172c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                    options);
173c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        } catch (OutOfMemoryError ex) {
174c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            Log.e(TAG, "Got oom exception ", ex);
175c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            return null;
176c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
177c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
178c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
179c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static void Assert(boolean cond) {
180c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if (!cond) {
181c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            throw new AssertionError();
182c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
183c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
184c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
185c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static void showFatalErrorAndFinish(
186c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            final Activity activity, String title, String message) {
187c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        DialogInterface.OnClickListener buttonListener =
188c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                new DialogInterface.OnClickListener() {
189c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            public void onClick(DialogInterface dialog, int which) {
190c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                activity.finish();
191c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            }
192c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        };
193c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        new AlertDialog.Builder(activity)
194c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                .setCancelable(false)
195c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                .setIcon(android.R.drawable.ic_dialog_alert)
196c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                .setTitle(title)
197c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                .setMessage(message)
198c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                .setNeutralButton(R.string.details_ok, buttonListener)
199c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                .show();
200c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
201c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
202c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static Animation slideOut(View view, int to) {
203c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        view.setVisibility(View.INVISIBLE);
204c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        Animation anim;
205c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        switch (to) {
206c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            case DIRECTION_LEFT:
207c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                anim = new TranslateAnimation(0, -view.getWidth(), 0, 0);
208c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                break;
209c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            case DIRECTION_RIGHT:
210c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                anim = new TranslateAnimation(0, view.getWidth(), 0, 0);
211c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                break;
212c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            case DIRECTION_UP:
213c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                anim = new TranslateAnimation(0, 0, 0, -view.getHeight());
214c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                break;
215c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            case DIRECTION_DOWN:
216c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                anim = new TranslateAnimation(0, 0, 0, view.getHeight());
217c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                break;
218c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            default:
219c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                throw new IllegalArgumentException(Integer.toString(to));
220c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
221c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        anim.setDuration(500);
222c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        view.startAnimation(anim);
223c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return anim;
224c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
225c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
226c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static Animation slideIn(View view, int from) {
227c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        view.setVisibility(View.VISIBLE);
228c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        Animation anim;
229c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        switch (from) {
230c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            case DIRECTION_LEFT:
231c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                anim = new TranslateAnimation(-view.getWidth(), 0, 0, 0);
232c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                break;
233c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            case DIRECTION_RIGHT:
234c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                anim = new TranslateAnimation(view.getWidth(), 0, 0, 0);
235c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                break;
236c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            case DIRECTION_UP:
237c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                anim = new TranslateAnimation(0, 0, -view.getHeight(), 0);
238c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                break;
239c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            case DIRECTION_DOWN:
240c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                anim = new TranslateAnimation(0, 0, view.getHeight(), 0);
241c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                break;
242c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            default:
243c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                throw new IllegalArgumentException(Integer.toString(from));
244c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
245c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        anim.setDuration(500);
246c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        view.startAnimation(anim);
247c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return anim;
2488fa39d2e728ea8254a0cbd268c32772e8749c18dAndroid Chromium Automerger    }
249c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
250c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static <T> T checkNotNull(T object) {
251c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if (object == null) throw new NullPointerException();
252c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return object;
253c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
254c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
255c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static boolean equals(Object a, Object b) {
256c1f5fc681b0495f5e16a6c7a693d767dbefcfa5fTorne (Richard Coles)        return (a == b) || (a == null ? false : a.equals(b));
257c1f5fc681b0495f5e16a6c7a693d767dbefcfa5fTorne (Richard Coles)    }
258c1f5fc681b0495f5e16a6c7a693d767dbefcfa5fTorne (Richard Coles)
259c1f5fc681b0495f5e16a6c7a693d767dbefcfa5fTorne (Richard Coles)    public static boolean isPowerOf2(int n) {
260baf4b7536eee2d8fefabdab9be2901c4b04f1c85Android Chromium Automerger        return (n & -n) == n;
26170d70cb2626549aed2f50d8c08082ab27f9f1077Torne (Richard Coles)    }
262c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
263c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static int nextPowerOf2(int n) {
264c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        n -= 1;
265c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        n |= n >>> 16;
266c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        n |= n >>> 8;
267c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        n |= n >>> 4;
268c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        n |= n >>> 2;
269c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        n |= n >>> 1;
270c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return n + 1;
271c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
272c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
273c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static float distance(float x, float y, float sx, float sy) {
274c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        float dx = x - sx;
275c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        float dy = y - sy;
276c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return (float) Math.sqrt(dx * dx + dy * dy);
277c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
278c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
279c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static int clamp(int x, int min, int max) {
280c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if (x > max) return max;
281c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if (x < min) return min;
282c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return x;
283c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
284c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
285c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static int getDisplayRotation(Activity activity) {
286c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        int rotation = activity.getWindowManager().getDefaultDisplay()
287c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                .getRotation();
288c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        switch (rotation) {
2890fac7502a6e87bf94f7ec9e56364012aad1031e5Android Chromium Automerger            case Surface.ROTATION_0: return 0;
290a715e94c5d62236fb7b1e050f175ed825a6373baAndroid Chromium Automerger            case Surface.ROTATION_90: return 90;
291b3d0e079a65545810a4c3b5fc0852b028d0d617eBo Liu            case Surface.ROTATION_180: return 180;
292b3d0e079a65545810a4c3b5fc0852b028d0d617eBo Liu            case Surface.ROTATION_270: return 270;
293c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
294c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return 0;
295c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
296c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
297c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static void setCameraDisplayOrientation(Activity activity,
298c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            int cameraId, android.hardware.Camera camera) {
299c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        android.hardware.Camera.CameraInfo info =
300c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                new android.hardware.Camera.CameraInfo();
301c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        android.hardware.Camera.getCameraInfo(cameraId, info);
302c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        int degrees = getDisplayRotation(activity);
303c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        int result = (info.orientation - degrees + 360) % 360;
304c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        camera.setDisplayOrientation(result);
305c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
306c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
307c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    public static Size getOptimalPreviewSize(Activity currentActivity,
308c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            List<Size> sizes, double targetRatio) {
3098e6b6de2b0230c99212993c460bbeed9342bee30Dehao Chen        final double ASPECT_TOLERANCE = 0.05;
3108e6b6de2b0230c99212993c460bbeed9342bee30Dehao Chen        if (sizes == null) return null;
311c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
312c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        Size optimalSize = null;
313c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        double minDiff = Double.MAX_VALUE;
314c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
315c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        // Because of bugs of overlay and layout, we sometimes will try to
316c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        // layout the viewfinder in the portrait orientation and thus get the
317c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        // wrong size of mSurfaceView. When we change the preview size, the
318c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        // new overlay will be created before the old one closed, which causes
319c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        // an exception. For now, just get the screen size
320c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
321c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        Display display = currentActivity.getWindowManager().getDefaultDisplay();
322c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        int targetHeight = Math.min(display.getHeight(), display.getWidth());
323c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
324c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if (targetHeight <= 0) {
325c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            // We don't know the size of SurfaceView, use screen height
326c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            targetHeight = display.getHeight();
327c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
328c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
329c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        // Try to find an size match aspect ratio and size
330c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        for (Size size : sizes) {
331c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            double ratio = (double) size.width / size.height;
332c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
333c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            if (Math.abs(size.height - targetHeight) < minDiff) {
334c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                optimalSize = size;
335c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                minDiff = Math.abs(size.height - targetHeight);
336c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            }
337c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
338c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger
339c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        // Cannot find the one match the aspect ratio, ignore the requirement
340c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        if (optimalSize == null) {
341c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            Log.v(TAG, "No preview size match the aspect ratio");
342c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            minDiff = Double.MAX_VALUE;
343c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            for (Size size : sizes) {
344c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                if (Math.abs(size.height - targetHeight) < minDiff) {
345c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                    optimalSize = size;
346c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                    minDiff = Math.abs(size.height - targetHeight);
347c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger                }
348c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger            }
349c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        }
350c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger        return optimalSize;
351c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger    }
352c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger}
353c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger