Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / base / android / java / src / org / chromium / base / ApiCompatibilityUtils.java
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.base;
6
7 import android.animation.ValueAnimator;
8 import android.annotation.TargetApi;
9 import android.app.ActivityOptions;
10 import android.app.Notification;
11 import android.app.PendingIntent;
12 import android.content.Context;
13 import android.content.Intent;
14 import android.content.res.Configuration;
15 import android.graphics.drawable.Drawable;
16 import android.os.Build;
17 import android.os.Bundle;
18 import android.provider.Settings;
19 import android.view.View;
20 import android.view.ViewGroup.MarginLayoutParams;
21 import android.view.ViewTreeObserver;
22 import android.widget.ImageView;
23 import android.widget.RemoteViews;
24 import android.widget.TextView;
25
26 /**
27  * Utility class to use new APIs that were added after ICS (API level 14).
28  */
29 public class ApiCompatibilityUtils {
30
31     private static final String TAG = "ApiCompatibilityUtils";
32
33     private ApiCompatibilityUtils() {
34     }
35
36     /**
37      * Returns true if view's layout direction is right-to-left.
38      *
39      * @param view the View whose layout is being considered
40      */
41     public static boolean isLayoutRtl(View view) {
42         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
43             return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
44         } else {
45             // All layouts are LTR before JB MR1.
46             return false;
47         }
48     }
49
50     /**
51      * @see Configuration#getLayoutDirection()
52      */
53     public static int getLayoutDirection(Configuration configuration) {
54         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
55             return configuration.getLayoutDirection();
56         } else {
57             // All layouts are LTR before JB MR1.
58             return View.LAYOUT_DIRECTION_LTR;
59         }
60     }
61
62     /**
63      * @return True if the running version of the Android supports printing.
64      */
65     public static boolean isPrintingSupported() {
66         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
67     }
68
69     /**
70      * @return True if the running version of the Android supports HTML clipboard.
71      */
72     public static boolean isHTMLClipboardSupported() {
73         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
74     }
75
76     /**
77      * @see android.view.View#setLayoutDirection(int)
78      */
79     public static void setLayoutDirection(View view, int layoutDirection) {
80         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
81             view.setLayoutDirection(layoutDirection);
82         } else {
83             // Do nothing. RTL layouts aren't supported before JB MR1.
84         }
85     }
86
87     /**
88      * @see android.view.View#setTextAlignment(int)
89      */
90     public static void setTextAlignment(View view, int textAlignment) {
91         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
92             view.setTextAlignment(textAlignment);
93         } else {
94             // Do nothing. RTL text isn't supported before JB MR1.
95         }
96     }
97
98     /**
99      * @see android.view.View#setTextDirection(int)
100      */
101     public static void setTextDirection(View view, int textDirection) {
102         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
103             view.setTextDirection(textDirection);
104         } else {
105             // Do nothing. RTL text isn't supported before JB MR1.
106         }
107     }
108
109     /**
110      * @see android.view.ViewGroup.MarginLayoutParams#setMarginEnd(int)
111      */
112     public static void setMarginEnd(MarginLayoutParams layoutParams, int end) {
113         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
114             layoutParams.setMarginEnd(end);
115         } else {
116             layoutParams.rightMargin = end;
117         }
118     }
119
120     /**
121      * @see android.view.ViewGroup.MarginLayoutParams#getMarginEnd()
122      */
123     public static int getMarginEnd(MarginLayoutParams layoutParams) {
124         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
125             return layoutParams.getMarginEnd();
126         } else {
127             return layoutParams.rightMargin;
128         }
129     }
130
131     /**
132      * @see android.view.ViewGroup.MarginLayoutParams#setMarginStart(int)
133      */
134     public static void setMarginStart(MarginLayoutParams layoutParams, int start) {
135         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
136             layoutParams.setMarginStart(start);
137         } else {
138             layoutParams.leftMargin = start;
139         }
140     }
141
142     /**
143      * @see android.view.ViewGroup.MarginLayoutParams#getMarginStart()
144      */
145     public static int getMarginStart(MarginLayoutParams layoutParams) {
146         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
147             return layoutParams.getMarginStart();
148         } else {
149             return layoutParams.leftMargin;
150         }
151     }
152
153     /**
154      * @see android.view.View#setPaddingRelative(int, int, int, int)
155      */
156     public static void setPaddingRelative(View view, int start, int top, int end, int bottom) {
157         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
158             view.setPaddingRelative(start, top, end, bottom);
159         } else {
160             // Before JB MR1, all layouts are left-to-right, so start == left, etc.
161             view.setPadding(start, top, end, bottom);
162         }
163     }
164
165     /**
166      * @see android.view.View#getPaddingStart()
167      */
168     public static int getPaddingStart(View view) {
169         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
170             return view.getPaddingStart();
171         } else {
172             // Before JB MR1, all layouts are left-to-right, so start == left.
173             return view.getPaddingLeft();
174         }
175     }
176
177     /**
178      * @see android.view.View#getPaddingEnd()
179      */
180     public static int getPaddingEnd(View view) {
181         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
182             return view.getPaddingEnd();
183         } else {
184             // Before JB MR1, all layouts are left-to-right, so end == right.
185             return view.getPaddingRight();
186         }
187     }
188
189     /**
190      * @see android.widget.TextView#setCompoundDrawablesRelative(Drawable, Drawable, Drawable,
191      *      Drawable)
192      */
193     public static void setCompoundDrawablesRelative(TextView textView, Drawable start, Drawable top,
194             Drawable end, Drawable bottom) {
195         if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
196             // On JB MR1, due to a platform bug, setCompoundDrawablesRelative() is a no-op if the
197             // view has ever been measured. As a workaround, use setCompoundDrawables() directly.
198             // See: http://crbug.com/368196 and http://crbug.com/361709
199             boolean isRtl = isLayoutRtl(textView);
200             textView.setCompoundDrawables(isRtl ? end : start, top, isRtl ? start : end, bottom);
201         } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
202             textView.setCompoundDrawablesRelative(start, top, end, bottom);
203         } else {
204             textView.setCompoundDrawables(start, top, end, bottom);
205         }
206     }
207
208     /**
209      * @see android.widget.TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable,
210      *      Drawable, Drawable, Drawable)
211      */
212     public static void setCompoundDrawablesRelativeWithIntrinsicBounds(TextView textView,
213             Drawable start, Drawable top, Drawable end, Drawable bottom) {
214         if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
215             // Work around the platform bug described in setCompoundDrawablesRelative() above.
216             boolean isRtl = isLayoutRtl(textView);
217             textView.setCompoundDrawablesWithIntrinsicBounds(isRtl ? end : start, top,
218                     isRtl ? start : end, bottom);
219         } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
220             textView.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
221         } else {
222             textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
223         }
224     }
225
226     /**
227      * @see android.widget.TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int,
228      *      int)
229      */
230     public static void setCompoundDrawablesRelativeWithIntrinsicBounds(TextView textView,
231             int start, int top, int end, int bottom) {
232         if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
233             // Work around the platform bug described in setCompoundDrawablesRelative() above.
234             boolean isRtl = isLayoutRtl(textView);
235             textView.setCompoundDrawablesWithIntrinsicBounds(isRtl ? end : start, top,
236                     isRtl ? start : end, bottom);
237         } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
238             textView.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
239         } else {
240             textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
241         }
242     }
243
244     /**
245      * @see android.view.View#postInvalidateOnAnimation()
246      */
247     public static void postInvalidateOnAnimation(View view) {
248         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
249             view.postInvalidateOnAnimation();
250         } else {
251             view.postInvalidate();
252         }
253     }
254
255     /**
256      * @see android.view.View#postOnAnimation()
257      */
258     public static void postOnAnimation(View view, Runnable action) {
259         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
260             view.postOnAnimation(action);
261         } else {
262             view.postDelayed(action, getFrameTime());
263         }
264     }
265
266     /**
267      * @see android.view.View#postOnAnimationDelayed()
268      */
269     public static void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
270         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
271             view.postOnAnimationDelayed(action, delayMillis);
272         } else {
273             view.postDelayed(action, getFrameTime() + delayMillis);
274         }
275     }
276
277     private static long getFrameTime() {
278         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
279             return ValueAnimator.getFrameDelay();
280         } else {
281             // Any reasonable fake frame delay will have to do.
282             return 10;
283         }
284     }
285
286     /**
287      * @see android.widget.RemoteViews#setContentDescription(int, CharSequence)
288      */
289     public static void setContentDescriptionForRemoteView(RemoteViews remoteViews, int viewId,
290             CharSequence contentDescription) {
291         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
292             remoteViews.setContentDescription(viewId, contentDescription);
293         } else {
294             // setContentDescription() is unavailable in earlier versions.
295         }
296     }
297
298     /**
299      * @see android.app.Activity#startActivity(Intent, Bundle)
300      */
301     public static void startActivity(Context context, Intent intent, Bundle options) {
302         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
303             context.startActivity(intent, options);
304         } else {
305             context.startActivity(intent);
306         }
307     }
308
309     /**
310      * @see android.app.ActivityOptions#toBundle()
311      */
312     public static Bundle toBundle(ActivityOptions options) {
313         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
314             return options.toBundle();
315         } else {
316             return null;
317         }
318     }
319
320     // These methods have a new name, and the old name is deprecated.
321
322     /**
323      * @see android.view.View#setBackground(Drawable)
324      */
325     @SuppressWarnings("deprecation")
326     public static void setBackgroundForView(View view, Drawable drawable) {
327         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
328             view.setBackground(drawable);
329         } else {
330             view.setBackgroundDrawable(drawable);
331         }
332     }
333
334     /**
335      * @see android.view.ViewTreeObserver#removeOnGlobalLayoutListener()
336      */
337     @SuppressWarnings("deprecation")
338     public static void removeOnGlobalLayoutListener(
339             View view, ViewTreeObserver.OnGlobalLayoutListener listener) {
340         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
341             view.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
342         } else {
343             view.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
344         }
345     }
346
347     /**
348      * @see android.widget.ImageView#setImageAlpha(int)
349      */
350     @SuppressWarnings("deprecation")
351     public static void setImageAlpha(ImageView iv, int alpha) {
352         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
353             iv.setImageAlpha(alpha);
354         } else {
355             iv.setAlpha(alpha);
356         }
357     }
358
359     /**
360      * @see android.app.PendingIntent#getCreatorPackage()
361      */
362     @SuppressWarnings("deprecation")
363     public static String getCreatorPackage(PendingIntent intent) {
364         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
365             return intent.getCreatorPackage();
366         } else {
367             return intent.getTargetPackage();
368         }
369     }
370
371     /**
372      * @see android.app.Notification.Builder#setLocalOnly(boolean)
373      */
374     @SuppressWarnings("deprecation")
375     public static Notification build(Notification.Builder builder) {
376         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
377             return builder.build();
378         } else {
379             return builder.getNotification();
380         }
381     }
382
383     /**
384      * @see android.provider.Settings.Global#DEVICE_PROVISIONED
385      */
386     @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
387     public static boolean isDeviceProvisioned(Context context) {
388         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) return true;
389         if (context == null) return true;
390         if (context.getContentResolver() == null) return true;
391         return Settings.Global.getInt(
392                 context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
393     }
394 }