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