Merge "Flatten PrintHelper in support-core-utils: part 1" into oc-support-26.0-dev
diff --git a/.gitignore b/.gitignore
index e57740b..5e7ac49 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,13 @@
.classpath
.gradle
-.idea/
+.idea/*
+.idea/**/*
+!.idea/*/
!.idea/codeStyleSettings.xml
!.idea/copyright/AndroidCopyright.xml
!.idea/copyright/profiles_settings.xml
+!.idea/inspectionProfiles/SupportLib.xml
+!.idea/inspectionProfiles/profiles_settings.xml
!.idea/vcs.xml
.project
.settings/
diff --git a/.idea/inspectionProfiles/SupportLib.xml b/.idea/inspectionProfiles/SupportLib.xml
new file mode 100644
index 0000000..e0d21e6
--- /dev/null
+++ b/.idea/inspectionProfiles/SupportLib.xml
@@ -0,0 +1,53 @@
+<component name="InspectionProjectProfileManager">
+ <profile version="1.0">
+ <option name="myName" value="SupportLib" />
+ <inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
+ <option name="TOP_LEVEL_CLASS_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="" />
+ </value>
+ </option>
+ <option name="INNER_CLASS_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="" />
+ </value>
+ </option>
+ <option name="METHOD_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
+ </value>
+ </option>
+ <option name="FIELD_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="" />
+ </value>
+ </option>
+ <option name="IGNORE_DEPRECATED" value="false" />
+ <option name="IGNORE_JAVADOC_PERIOD" value="true" />
+ <option name="IGNORE_DUPLICATED_THROWS" value="false" />
+ <option name="IGNORE_POINT_TO_ITSELF" value="false" />
+ <option name="myAdditionalJavadocTags" value="hide,attr" />
+ </inspection_tool>
+ <inspection_tool class="WeakerAccess" enabled="false" level="WARNING" enabled_by_default="false">
+ <option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="true" />
+ <option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="true" />
+ <option name="SUGGEST_PRIVATE_FOR_INNERS" value="false" />
+ </inspection_tool>
+ <inspection_tool class="unused" enabled="true" level="WARNING" enabled_by_default="true" method="protected">
+ <option name="LOCAL_VARIABLE" value="true" />
+ <option name="FIELD" value="true" />
+ <option name="METHOD" value="true" />
+ <option name="CLASS" value="true" />
+ <option name="PARAMETER" value="true" />
+ <option name="REPORT_PARAMETER_FOR_PUBLIC_METHODS" value="true" />
+ <option name="ADD_MAINS_TO_ENTRIES" value="true" />
+ <option name="ADD_APPLET_TO_ENTRIES" value="true" />
+ <option name="ADD_SERVLET_TO_ENTRIES" value="true" />
+ <option name="ADD_NONJAVA_TO_ENTRIES" value="true" />
+ </inspection_tool>
+ </profile>
+</component>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..83490b5
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+ <settings>
+ <option name="PROJECT_PROFILE" value="SupportLib" />
+ <version value="1.0" />
+ </settings>
+</component>
\ No newline at end of file
diff --git a/api/26.0.0-SNAPSHOT.txt b/api/26.0.0-SNAPSHOT.txt
index 5d7496b..9e9a646 100644
--- a/api/26.0.0-SNAPSHOT.txt
+++ b/api/26.0.0-SNAPSHOT.txt
@@ -1900,16 +1900,19 @@
method public void unregisterInitCallback(android.support.text.emoji.EmojiCompat.InitCallback);
field public static final java.lang.String EDITOR_INFO_METAVERSION_KEY = "android.support.text.emoji.emojiCompat_metadataVersion";
field public static final java.lang.String EDITOR_INFO_REPLACE_ALL_KEY = "android.support.text.emoji.emojiCompat_replaceAll";
- field public static final int LOAD_STATE_FAILURE = 2; // 0x2
+ field public static final int LOAD_STATE_FAILED = 2; // 0x2
+ field public static final deprecated int LOAD_STATE_FAILURE = 2; // 0x2
field public static final int LOAD_STATE_LOADING = 0; // 0x0
- field public static final int LOAD_STATE_SUCCESS = 1; // 0x1
+ field public static final int LOAD_STATE_SUCCEEDED = 1; // 0x1
+ field public static final deprecated int LOAD_STATE_SUCCESS = 1; // 0x1
field public static final int REPLACE_STRATEGY_ALL = 1; // 0x1
field public static final int REPLACE_STRATEGY_DEFAULT = 0; // 0x0
field public static final int REPLACE_STRATEGY_NON_EXISTENT = 2; // 0x2
}
public static abstract class EmojiCompat.Config {
- ctor protected EmojiCompat.Config(android.support.text.emoji.EmojiCompat.MetadataLoader);
+ ctor protected EmojiCompat.Config(android.support.text.emoji.EmojiCompat.MetadataRepoLoader);
+ ctor protected deprecated EmojiCompat.Config(android.support.text.emoji.EmojiCompat.MetadataLoader);
method public android.support.text.emoji.EmojiCompat.Config registerInitCallback(android.support.text.emoji.EmojiCompat.InitCallback);
method public android.support.text.emoji.EmojiCompat.Config setEmojiSpanIndicatorColor(int);
method public android.support.text.emoji.EmojiCompat.Config setEmojiSpanIndicatorEnabled(boolean);
@@ -1923,16 +1926,26 @@
method public void onInitialized();
}
- public static abstract class EmojiCompat.LoaderCallback {
+ public static abstract deprecated class EmojiCompat.LoaderCallback {
ctor public EmojiCompat.LoaderCallback();
method public abstract void onFailed(java.lang.Throwable);
method public abstract void onLoaded(android.support.text.emoji.MetadataRepo);
}
- public static abstract interface EmojiCompat.MetadataLoader {
+ public static abstract deprecated interface EmojiCompat.MetadataLoader {
method public abstract void load(android.support.text.emoji.EmojiCompat.LoaderCallback);
}
+ public static abstract interface EmojiCompat.MetadataRepoLoader {
+ method public abstract void load(android.support.text.emoji.EmojiCompat.MetadataRepoLoaderCallback);
+ }
+
+ public static abstract class EmojiCompat.MetadataRepoLoaderCallback {
+ ctor public EmojiCompat.MetadataRepoLoaderCallback();
+ method public abstract void onFailed(java.lang.Throwable);
+ method public abstract void onLoaded(android.support.text.emoji.MetadataRepo);
+ }
+
public abstract class EmojiSpan extends android.text.style.ReplacementSpan {
method public int getSize(android.graphics.Paint, java.lang.CharSequence, int, int, android.graphics.Paint.FontMetricsInt);
}
@@ -2211,6 +2224,15 @@
method public android.support.transition.TransitionManager inflateTransitionManager(int, android.view.ViewGroup);
}
+ public class TransitionListenerAdapter implements android.support.transition.Transition.TransitionListener {
+ ctor public TransitionListenerAdapter();
+ method public void onTransitionCancel(android.support.transition.Transition);
+ method public void onTransitionEnd(android.support.transition.Transition);
+ method public void onTransitionPause(android.support.transition.Transition);
+ method public void onTransitionResume(android.support.transition.Transition);
+ method public void onTransitionStart(android.support.transition.Transition);
+ }
+
public class TransitionManager {
ctor public TransitionManager();
method public static void beginDelayedTransition(android.view.ViewGroup);
diff --git a/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy b/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy
index 0ffd3d7..677b63e 100644
--- a/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy
+++ b/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy
@@ -184,13 +184,12 @@
libraryVariant.getJavaCompile().setToolChain(toolChain);
libraryVariant.getJavaCompile().options.compilerArgs += [
- // TODO(aurimas): remove this once all these warnings are fixed.
- '-Xep:RectIntersectReturnValueIgnored:WARN',
'-XDcompilePolicy=simple', // Workaround for b/36098770
// Enforce the following checks.
'-Xep:MissingOverride:ERROR',
'-Xep:ClassNewInstance:ERROR',
+ '-Xep:SynchronizeOnNonFinalField:ERROR'
]
}
}
diff --git a/compat/api21/android/support/v4/app/NotificationCompatApi21.java b/compat/api21/android/support/v4/app/NotificationCompatApi21.java
index 44237f3..d56d87e 100644
--- a/compat/api21/android/support/v4/app/NotificationCompatApi21.java
+++ b/compat/api21/android/support/v4/app/NotificationCompatApi21.java
@@ -36,22 +36,6 @@
@RequiresApi(21)
class NotificationCompatApi21 {
-
- public static final String CATEGORY_CALL = Notification.CATEGORY_CALL;
- public static final String CATEGORY_MESSAGE = Notification.CATEGORY_MESSAGE;
- public static final String CATEGORY_EMAIL = Notification.CATEGORY_EMAIL;
- public static final String CATEGORY_EVENT = Notification.CATEGORY_EVENT;
- public static final String CATEGORY_PROMO = Notification.CATEGORY_PROMO;
- public static final String CATEGORY_ALARM = Notification.CATEGORY_ALARM;
- public static final String CATEGORY_PROGRESS = Notification.CATEGORY_PROGRESS;
- public static final String CATEGORY_SOCIAL = Notification.CATEGORY_SOCIAL;
- public static final String CATEGORY_ERROR = Notification.CATEGORY_ERROR;
- public static final String CATEGORY_TRANSPORT = Notification.CATEGORY_TRANSPORT;
- public static final String CATEGORY_SYSTEM = Notification.CATEGORY_SYSTEM;
- public static final String CATEGORY_SERVICE = Notification.CATEGORY_SERVICE;
- public static final String CATEGORY_RECOMMENDATION = Notification.CATEGORY_RECOMMENDATION;
- public static final String CATEGORY_STATUS = Notification.CATEGORY_STATUS;
-
private static final String KEY_AUTHOR = "author";
private static final String KEY_TEXT = "text";
private static final String KEY_MESSAGES = "messages";
diff --git a/compat/api23/android/support/v4/app/NotificationCompatApi23.java b/compat/api23/android/support/v4/app/NotificationCompatApi23.java
deleted file mode 100644
index 2f8216c..0000000
--- a/compat/api23/android/support/v4/app/NotificationCompatApi23.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v4.app;
-
-import android.app.Notification;
-import android.support.annotation.RequiresApi;
-
-@RequiresApi(23)
-class NotificationCompatApi23 {
-
- public static final String CATEGORY_REMINDER = Notification.CATEGORY_REMINDER;
-}
diff --git a/compat/api23/android/support/v4/hardware/fingerprint/FingerprintManagerCompatApi23.java b/compat/api23/android/support/v4/hardware/fingerprint/FingerprintManagerCompatApi23.java
index 72a21a3..2e23b85 100644
--- a/compat/api23/android/support/v4/hardware/fingerprint/FingerprintManagerCompatApi23.java
+++ b/compat/api23/android/support/v4/hardware/fingerprint/FingerprintManagerCompatApi23.java
@@ -18,6 +18,7 @@
import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
@@ -46,17 +47,26 @@
}
}
- public static boolean hasEnrolledFingerprints(Context context) {
+ // We expect developers to add android.permission.USE_FINGERPRINT to their manifest if they
+ // use this API.
+ @SuppressLint("MissingPermission")
+ static boolean hasEnrolledFingerprints(Context context) {
final FingerprintManager fp = getFingerprintManagerOrNull(context);
return (fp != null) && fp.hasEnrolledFingerprints();
}
- public static boolean isHardwareDetected(Context context) {
+ // We expect developers to add android.permission.USE_FINGERPRINT to their manifest if they
+ // use this API.
+ @SuppressLint("MissingPermission")
+ static boolean isHardwareDetected(Context context) {
final FingerprintManager fp = getFingerprintManagerOrNull(context);
return (fp != null) && fp.isHardwareDetected();
}
- public static void authenticate(Context context, CryptoObject crypto, int flags, Object cancel,
+ // We expect developers to add android.permission.USE_FINGERPRINT to their manifest if they
+ // use this API.
+ @SuppressLint("MissingPermission")
+ static void authenticate(Context context, CryptoObject crypto, int flags, Object cancel,
AuthenticationCallback callback, Handler handler) {
final FingerprintManager fp = getFingerprintManagerOrNull(context);
if (fp != null) {
diff --git a/compat/build.gradle b/compat/build.gradle
index 0274285..fc61134 100644
--- a/compat/build.gradle
+++ b/compat/build.gradle
@@ -13,6 +13,7 @@
androidTestCompile libs.mockito_core
androidTestCompile libs.dexmaker
androidTestCompile libs.dexmaker_mockito
+ androidTestCompile project(':support-testutils')
}
android {
diff --git a/compat/java/android/support/v4/app/JobIntentService.java b/compat/java/android/support/v4/app/JobIntentService.java
index daeb55b..0789039 100644
--- a/compat/java/android/support/v4/app/JobIntentService.java
+++ b/compat/java/android/support/v4/app/JobIntentService.java
@@ -26,12 +26,12 @@
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
-import android.support.v4.os.BuildCompat;
import android.util.Log;
import java.util.ArrayList;
@@ -93,10 +93,11 @@
static final boolean DEBUG = false;
CompatJobEngine mJobImpl;
- ArrayList<CompatWorkItem> mCompatQueue;
WorkEnqueuer mCompatWorkEnqueuer;
CommandProcessor mCurProcessor;
+ final ArrayList<CompatWorkItem> mCompatQueue;
+
static final Object sLock = new Object();
static final HashMap<Class, WorkEnqueuer> sClassWorkEnqueuer = new HashMap<>();
@@ -385,19 +386,22 @@
* Default empty constructor.
*/
public JobIntentService() {
+ if (Build.VERSION.SDK_INT >= 26) {
+ mCompatQueue = null;
+ } else {
+ mCompatQueue = new ArrayList<>();
+ }
}
@Override
public void onCreate() {
super.onCreate();
if (DEBUG) Log.d(TAG, "CREATING: " + this);
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
mJobImpl = new JobServiceEngineImpl(this);
- mCompatQueue = null;
mCompatWorkEnqueuer = null;
} else {
mJobImpl = null;
- mCompatQueue = new ArrayList<>();
mCompatWorkEnqueuer = getWorkEnqueuer(this, this.getClass(), false, 0);
mCompatWorkEnqueuer.serviceCreated();
}
@@ -476,7 +480,7 @@
static WorkEnqueuer getWorkEnqueuer(Context context, Class cls, boolean hasJobId, int jobId) {
WorkEnqueuer we = sClassWorkEnqueuer.get(cls);
if (we == null) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
if (!hasJobId) {
throw new IllegalArgumentException("Can't be here without a job id");
}
diff --git a/compat/java/android/support/v4/app/NotificationCompat.java b/compat/java/android/support/v4/app/NotificationCompat.java
index ec46c55..a93c763 100644
--- a/compat/java/android/support/v4/app/NotificationCompat.java
+++ b/compat/java/android/support/v4/app/NotificationCompat.java
@@ -36,7 +36,6 @@
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.annotation.RestrictTo;
-import android.support.v4.os.BuildCompat;
import android.support.v4.view.GravityCompat;
import android.view.Gravity;
import android.widget.RemoteViews;
@@ -451,67 +450,67 @@
/**
* Notification category: incoming call (voice or video) or similar synchronous communication request.
*/
- public static final String CATEGORY_CALL = NotificationCompatApi21.CATEGORY_CALL;
+ public static final String CATEGORY_CALL = Notification.CATEGORY_CALL;
/**
* Notification category: incoming direct message (SMS, instant message, etc.).
*/
- public static final String CATEGORY_MESSAGE = NotificationCompatApi21.CATEGORY_MESSAGE;
+ public static final String CATEGORY_MESSAGE = Notification.CATEGORY_MESSAGE;
/**
* Notification category: asynchronous bulk message (email).
*/
- public static final String CATEGORY_EMAIL = NotificationCompatApi21.CATEGORY_EMAIL;
+ public static final String CATEGORY_EMAIL = Notification.CATEGORY_EMAIL;
/**
* Notification category: calendar event.
*/
- public static final String CATEGORY_EVENT = NotificationCompatApi21.CATEGORY_EVENT;
+ public static final String CATEGORY_EVENT = Notification.CATEGORY_EVENT;
/**
* Notification category: promotion or advertisement.
*/
- public static final String CATEGORY_PROMO = NotificationCompatApi21.CATEGORY_PROMO;
+ public static final String CATEGORY_PROMO = Notification.CATEGORY_PROMO;
/**
* Notification category: alarm or timer.
*/
- public static final String CATEGORY_ALARM = NotificationCompatApi21.CATEGORY_ALARM;
+ public static final String CATEGORY_ALARM = Notification.CATEGORY_ALARM;
/**
* Notification category: progress of a long-running background operation.
*/
- public static final String CATEGORY_PROGRESS = NotificationCompatApi21.CATEGORY_PROGRESS;
+ public static final String CATEGORY_PROGRESS = Notification.CATEGORY_PROGRESS;
/**
* Notification category: social network or sharing update.
*/
- public static final String CATEGORY_SOCIAL = NotificationCompatApi21.CATEGORY_SOCIAL;
+ public static final String CATEGORY_SOCIAL = Notification.CATEGORY_SOCIAL;
/**
* Notification category: error in background operation or authentication status.
*/
- public static final String CATEGORY_ERROR = NotificationCompatApi21.CATEGORY_ERROR;
+ public static final String CATEGORY_ERROR = Notification.CATEGORY_ERROR;
/**
* Notification category: media transport control for playback.
*/
- public static final String CATEGORY_TRANSPORT = NotificationCompatApi21.CATEGORY_TRANSPORT;
+ public static final String CATEGORY_TRANSPORT = Notification.CATEGORY_TRANSPORT;
/**
* Notification category: system or device status update. Reserved for system use.
*/
- public static final String CATEGORY_SYSTEM = NotificationCompatApi21.CATEGORY_SYSTEM;
+ public static final String CATEGORY_SYSTEM = Notification.CATEGORY_SYSTEM;
/**
* Notification category: indication of running background service.
*/
- public static final String CATEGORY_SERVICE = NotificationCompatApi21.CATEGORY_SERVICE;
+ public static final String CATEGORY_SERVICE = Notification.CATEGORY_SERVICE;
/**
* Notification category: user-scheduled reminder.
*/
- public static final String CATEGORY_REMINDER = NotificationCompatApi23.CATEGORY_REMINDER;
+ public static final String CATEGORY_REMINDER = Notification.CATEGORY_REMINDER;
/**
* Notification category: a specific, timely recommendation for a single thing.
@@ -519,12 +518,12 @@
* want to read next.
*/
public static final String CATEGORY_RECOMMENDATION =
- NotificationCompatApi21.CATEGORY_RECOMMENDATION;
+ Notification.CATEGORY_RECOMMENDATION;
/**
* Notification category: ongoing information about device or contextual status.
*/
- public static final String CATEGORY_STATUS = NotificationCompatApi21.CATEGORY_STATUS;
+ public static final String CATEGORY_STATUS = Notification.CATEGORY_STATUS;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -946,7 +945,7 @@
}
static {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
IMPL = new NotificationCompatApi26Impl();
} else if (Build.VERSION.SDK_INT >= 24) {
IMPL = new NotificationCompatApi24Impl();
@@ -4336,10 +4335,10 @@
if (Build.VERSION.SDK_INT >= 20) {
return (notification.flags & Notification.FLAG_LOCAL_ONLY) != 0;
} else if (Build.VERSION.SDK_INT >= 19) {
- return notification.extras.getBoolean(NotificationCompatJellybean.EXTRA_LOCAL_ONLY);
+ return notification.extras.getBoolean(NotificationCompatExtras.EXTRA_LOCAL_ONLY);
} else if (Build.VERSION.SDK_INT >= 16) {
return NotificationCompatJellybean.getExtras(notification).getBoolean(
- NotificationCompatJellybean.EXTRA_LOCAL_ONLY);
+ NotificationCompatExtras.EXTRA_LOCAL_ONLY);
} else {
return false;
}
@@ -4353,10 +4352,10 @@
if (Build.VERSION.SDK_INT >= 20) {
return notification.getGroup();
} else if (Build.VERSION.SDK_INT >= 19) {
- return notification.extras.getString(NotificationCompatJellybean.EXTRA_GROUP_KEY);
+ return notification.extras.getString(NotificationCompatExtras.EXTRA_GROUP_KEY);
} else if (Build.VERSION.SDK_INT >= 16) {
return NotificationCompatJellybean.getExtras(notification).getString(
- NotificationCompatJellybean.EXTRA_GROUP_KEY);
+ NotificationCompatExtras.EXTRA_GROUP_KEY);
} else {
return null;
}
@@ -4372,10 +4371,10 @@
if (Build.VERSION.SDK_INT >= 20) {
return (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
} else if (Build.VERSION.SDK_INT >= 19) {
- return notification.extras.getBoolean(NotificationCompatJellybean.EXTRA_GROUP_SUMMARY);
+ return notification.extras.getBoolean(NotificationCompatExtras.EXTRA_GROUP_SUMMARY);
} else if (Build.VERSION.SDK_INT >= 16) {
return NotificationCompatJellybean.getExtras(notification).getBoolean(
- NotificationCompatJellybean.EXTRA_GROUP_SUMMARY);
+ NotificationCompatExtras.EXTRA_GROUP_SUMMARY);
} else {
return false;
}
@@ -4397,10 +4396,10 @@
if (Build.VERSION.SDK_INT >= 20) {
return notification.getSortKey();
} else if (Build.VERSION.SDK_INT >= 19) {
- return notification.extras.getString(NotificationCompatJellybean.EXTRA_SORT_KEY);
+ return notification.extras.getString(NotificationCompatExtras.EXTRA_SORT_KEY);
} else if (Build.VERSION.SDK_INT >= 16) {
return NotificationCompatJellybean.getExtras(notification).getString(
- NotificationCompatJellybean.EXTRA_SORT_KEY);
+ NotificationCompatExtras.EXTRA_SORT_KEY);
} else {
return null;
}
@@ -4410,7 +4409,7 @@
* @return the ID of the channel this notification posts to.
*/
public static String getChannelId(Notification notification) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return notification.getChannelId();
} else {
return null;
@@ -4428,7 +4427,7 @@
* canceled already.
*/
public static long getTimeoutAfter(Notification notification) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return notification.getTimeoutAfter();
} else {
return 0;
@@ -4447,7 +4446,7 @@
* {@link #BADGE_ICON_SMALL}, or {@link #BADGE_ICON_LARGE}.
*/
public static int getBadgeIconType(Notification notification) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return notification.getBadgeIconType();
} else {
return BADGE_ICON_NONE;
@@ -4459,7 +4458,7 @@
* notification supersedes, if any.
*/
public static String getShortcutId(Notification notification) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return notification.getShortcutId();
} else {
return null;
@@ -4472,7 +4471,7 @@
* {@link #GROUP_ALERT_SUMMARY}.
*/
public static int getGroupAlertBehavior(Notification notification) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return notification.getGroupAlertBehavior();
} else {
return GROUP_ALERT_ALL;
diff --git a/compat/java/android/support/v4/app/NotificationCompatExtras.java b/compat/java/android/support/v4/app/NotificationCompatExtras.java
index bf9ba0f..33bdd06 100644
--- a/compat/java/android/support/v4/app/NotificationCompatExtras.java
+++ b/compat/java/android/support/v4/app/NotificationCompatExtras.java
@@ -25,37 +25,35 @@
* the {@link android.app.Notification#FLAG_LOCAL_ONLY} field before it was available.
* If possible, use {@link NotificationCompat#getLocalOnly} to access this field.
*/
- public static final String EXTRA_LOCAL_ONLY = NotificationCompatJellybean.EXTRA_LOCAL_ONLY;
+ public static final String EXTRA_LOCAL_ONLY = "android.support.localOnly";
/**
* Extras key used internally by {@link NotificationCompat} to store the value set
* by {@link android.app.Notification.Builder#setGroup} before it was available.
* If possible, use {@link NotificationCompat#getGroup} to access this value.
*/
- public static final String EXTRA_GROUP_KEY = NotificationCompatJellybean.EXTRA_GROUP_KEY;
+ public static final String EXTRA_GROUP_KEY = "android.support.groupKey";
/**
* Extras key used internally by {@link NotificationCompat} to store the value set
* by {@link android.app.Notification.Builder#setGroupSummary} before it was available.
* If possible, use {@link NotificationCompat#isGroupSummary} to access this value.
*/
- public static final String EXTRA_GROUP_SUMMARY =
- NotificationCompatJellybean.EXTRA_GROUP_SUMMARY;
+ public static final String EXTRA_GROUP_SUMMARY = "android.support.isGroupSummary";
/**
* Extras key used internally by {@link NotificationCompat} to store the value set
* by {@link android.app.Notification.Builder#setSortKey} before it was available.
* If possible, use {@link NotificationCompat#getSortKey} to access this value.
*/
- public static final String EXTRA_SORT_KEY = NotificationCompatJellybean.EXTRA_SORT_KEY;
+ public static final String EXTRA_SORT_KEY = "android.support.sortKey";
/**
* Extras key used internally by {@link NotificationCompat} to store the value of
* the {@link android.app.Notification.Action#extras} field before it was available.
* If possible, use {@link NotificationCompat#getAction} to access this field.
*/
- public static final String EXTRA_ACTION_EXTRAS =
- NotificationCompatJellybean.EXTRA_ACTION_EXTRAS;
+ public static final String EXTRA_ACTION_EXTRAS = "android.support.actionExtras";
/**
* Extras key used internally by {@link NotificationCompat} to store the value of
@@ -63,8 +61,7 @@
* was available.
* If possible, use {@link NotificationCompat.Action#getRemoteInputs} to access this field.
*/
- public static final String EXTRA_REMOTE_INPUTS =
- NotificationCompatJellybean.EXTRA_REMOTE_INPUTS;
+ public static final String EXTRA_REMOTE_INPUTS = "android.support.remoteInputs";
private NotificationCompatExtras() {}
}
diff --git a/compat/java/android/support/v4/app/NotificationManagerCompat.java b/compat/java/android/support/v4/app/NotificationManagerCompat.java
index 582c570..8f4c4b4 100644
--- a/compat/java/android/support/v4/app/NotificationManagerCompat.java
+++ b/compat/java/android/support/v4/app/NotificationManagerCompat.java
@@ -66,8 +66,7 @@
* Notification extras key: if set to true, the posted notification should use
* the side channel for delivery instead of using notification manager.
*/
- public static final String EXTRA_USE_SIDE_CHANNEL =
- NotificationCompatJellybean.EXTRA_USE_SIDE_CHANNEL;
+ public static final String EXTRA_USE_SIDE_CHANNEL = "android.support.useSideChannel";
/**
* Intent action to register for on a service to receive side channel
diff --git a/compat/java/android/support/v4/app/RemoteInput.java b/compat/java/android/support/v4/app/RemoteInput.java
index 73eb388..6efa63c 100644
--- a/compat/java/android/support/v4/app/RemoteInput.java
+++ b/compat/java/android/support/v4/app/RemoteInput.java
@@ -37,7 +37,7 @@
private static final String TAG = "RemoteInput";
/** Label used to denote the clip data type used for remote input transport */
- public static final String RESULTS_CLIP_LABEL = RemoteInputCompatJellybean.RESULTS_CLIP_LABEL;
+ public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results";
/** Extra added to a clip data intent object to hold the text results bundle. */
public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
diff --git a/compat/java/android/support/v4/content/ContextCompat.java b/compat/java/android/support/v4/content/ContextCompat.java
index 2790234..9d8f551 100644
--- a/compat/java/android/support/v4/content/ContextCompat.java
+++ b/compat/java/android/support/v4/content/ContextCompat.java
@@ -30,7 +30,6 @@
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityOptionsCompat;
-import android.support.v4.os.BuildCompat;
import android.support.v4.os.EnvironmentCompat;
import android.util.Log;
import android.util.TypedValue;
@@ -557,7 +556,7 @@
* @see Context#startService()
*/
public static void startForegroundService(Context context, Intent intent) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
context.startForegroundService(intent);
} else {
// Pre-O behavior.
diff --git a/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java b/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java
index ecc9344..9cfc3d3 100644
--- a/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java
+++ b/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java
@@ -24,11 +24,11 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutManager;
+import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.v4.content.ContextCompat;
-import android.support.v4.os.BuildCompat;
import android.text.TextUtils;
/**
@@ -51,7 +51,7 @@
* {@code false} otherwise
*/
public static boolean isRequestPinShortcutSupported(@NonNull Context context) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return context.getSystemService(ShortcutManager.class).isRequestPinShortcutSupported();
}
@@ -88,7 +88,7 @@
*/
public static boolean requestPinShortcut(@NonNull final Context context,
@NonNull ShortcutInfoCompat shortcut, @Nullable final IntentSender callback) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return context.getSystemService(ShortcutManager.class).requestPinShortcut(
shortcut.toShortcutInfo(), callback);
}
@@ -132,7 +132,7 @@
public static Intent createShortcutResultIntent(@NonNull Context context,
@NonNull ShortcutInfoCompat shortcut) {
Intent result = null;
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
result = context.getSystemService(ShortcutManager.class)
.createShortcutResultIntent(shortcut.toShortcutInfo());
}
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompat.java b/compat/java/android/support/v4/graphics/TypefaceCompat.java
index e9b2edd..59be452 100644
--- a/compat/java/android/support/v4/graphics/TypefaceCompat.java
+++ b/compat/java/android/support/v4/graphics/TypefaceCompat.java
@@ -21,7 +21,8 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
-import android.net.Uri;
+import android.os.Build;
+import android.os.CancellationSignal;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
@@ -33,8 +34,7 @@
import android.support.v4.util.LruCache;
import android.widget.TextView;
-import java.nio.ByteBuffer;
-import java.util.Map;
+import java.io.File;
/**
* Helper for accessing features in {@link Typeface} in a backwards compatible fashion.
@@ -42,8 +42,18 @@
*/
@RestrictTo(LIBRARY_GROUP)
public class TypefaceCompat {
- // TODO(nona): Introduce API 24 implementation.
- private static final TypefaceCompatImpl sTypefaceCompatImpl = new TypefaceCompatBaseImpl();
+ private static final String TAG = "TypefaceCompat";
+
+ private static final TypefaceCompatImpl sTypefaceCompatImpl;
+ static {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && TypefaceCompatApi24Impl.isUsable()) {
+ sTypefaceCompatImpl = new TypefaceCompatApi24Impl();
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ sTypefaceCompatImpl = new TypefaceCompatApi21Impl();
+ } else {
+ sTypefaceCompatImpl = new TypefaceCompatBaseImpl();
+ }
+ }
/**
* Cache for Typeface objects dynamically loaded from assets.
@@ -51,17 +61,14 @@
private static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16);
interface TypefaceCompatImpl {
- // Create Typeface from font file in res/font directory.
- Typeface createFromResourcesFontFile(Context context, Resources resources, int id,
- int style);
-
// Create Typeface from XML which root node is "font-family"
Typeface createFromFontFamilyFilesResourceEntry(
- Context context, FontFamilyFilesResourceEntry entry, Resources resources, int id,
+ Context context, FontFamilyFilesResourceEntry entry, Resources resources,
int style);
- Typeface createTypeface(Context context, @NonNull FontInfo[] fonts,
- Map<Uri, ByteBuffer> uriBuffer);
+ Typeface createFromFontInfo(Context context,
+ @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts,
+ int style);
}
private TypefaceCompat() {}
@@ -103,7 +110,7 @@
providerEntry.getTimeout(), style);
} else {
typeface = sTypefaceCompatImpl.createFromFontFamilyFilesResourceEntry(
- context, (FontFamilyFilesResourceEntry) entry, resources, id, style);
+ context, (FontFamilyFilesResourceEntry) entry, resources, style);
}
if (typeface != null) {
sTypefaceCache.put(createResourceUid(resources, id, style), typeface);
@@ -117,19 +124,34 @@
@Nullable
public static Typeface createFromResourcesFontFile(
Context context, Resources resources, int id, int style) {
- Typeface typeface = sTypefaceCompatImpl.createFromResourcesFontFile(
- context, resources, id, style);
- if (typeface != null) {
- sTypefaceCache.put(createResourceUid(resources, id, style), typeface);
+ final File tmpFile = TypefaceCompatUtil.getTempFile(context);
+ if (tmpFile == null) {
+ return null;
}
- return typeface;
+ try {
+ if (!TypefaceCompatUtil.copyToFile(tmpFile, resources, id)) {
+ return null;
+ }
+ Typeface typeface = Typeface.createFromFile(tmpFile.getPath());
+ if (typeface != null) {
+ sTypefaceCache.put(createResourceUid(resources, id, style), typeface);
+ }
+ return typeface;
+ } catch (RuntimeException e) {
+ // This was thrown from Typeface.createFromFile when a Typeface could not be loaded.
+ // such as due to an invalid ttf or unreadable file. We don't want to throw that
+ // exception anymore.
+ return null;
+ } finally {
+ tmpFile.delete();
+ }
}
/**
* Create a Typeface from a given FontInfo list and a map that matches them to ByteBuffers.
*/
- public static Typeface createTypeface(Context context, @NonNull FontInfo[] fonts,
- Map<Uri, ByteBuffer> uriBuffer) {
- return sTypefaceCompatImpl.createTypeface(context, fonts, uriBuffer);
+ public static Typeface createFromFontInfo(Context context,
+ @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts, int style) {
+ return sTypefaceCompatImpl.createFromFontInfo(context, cancellationSignal, fonts, style);
}
}
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompatApi21Impl.java b/compat/java/android/support/v4/graphics/TypefaceCompatApi21Impl.java
new file mode 100644
index 0000000..a742004
--- /dev/null
+++ b/compat/java/android/support/v4/graphics/TypefaceCompatApi21Impl.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.graphics;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.graphics.Typeface;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.RestrictTo;
+import android.support.v4.provider.FontsContractCompat.FontInfo;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+
+/**
+ * Implementation of the Typeface compat methods for API 21 and above.
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+@RequiresApi(21)
+class TypefaceCompatApi21Impl extends TypefaceCompatBaseImpl {
+ private static final String TAG = "TypefaceCompatApi21Impl";
+
+ private File getFile(ParcelFileDescriptor fd) {
+ try {
+ final String path = Os.readlink("/proc/self/fd/" + fd.getFd());
+ // Check if the symbolic link points the regular file.
+ if (OsConstants.S_ISREG(Os.stat(path).st_mode)) {
+ return new File(path);
+ } else {
+ return null;
+ }
+ } catch (ErrnoException e) {
+ return null; // Mostly permission error.
+ }
+ }
+
+ @Override
+ public Typeface createFromFontInfo(Context context, CancellationSignal cancellationSignal,
+ @NonNull FontInfo[] fonts, int style) {
+ if (fonts.length < 1) {
+ return null;
+ }
+ final FontInfo bestFont = findBestInfo(fonts, style);
+ final ContentResolver resolver = context.getContentResolver();
+ try (ParcelFileDescriptor pfd =
+ resolver.openFileDescriptor(bestFont.getUri(), "r", cancellationSignal)) {
+ final File file = getFile(pfd);
+ if (file == null || !file.canRead()) {
+ // Unable to use the real file for creating Typeface. Fallback to copying
+ // implementation.
+ try (FileInputStream fis = new FileInputStream(pfd.getFileDescriptor())) {
+ return super.createFromInputStream(context, fis);
+ }
+ }
+ return Typeface.createFromFile(file);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+}
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java b/compat/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java
new file mode 100644
index 0000000..22d5f9d
--- /dev/null
+++ b/compat/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.graphics;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Typeface;
+import android.net.Uri;
+import android.os.CancellationSignal;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.RestrictTo;
+import android.support.v4.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry;
+import android.support.v4.content.res.FontResourcesParserCompat.FontFileResourceEntry;
+import android.support.v4.provider.FontsContractCompat.FontInfo;
+import android.support.v4.util.SimpleArrayMap;
+import android.util.Log;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+
+/**
+ * Implementation of the Typeface compat methods for API 24 and above.
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+@RequiresApi(24)
+class TypefaceCompatApi24Impl implements TypefaceCompat.TypefaceCompatImpl {
+ private static final String TAG = "TypefaceCompatApi24Impl";
+
+ private static final String FONT_FAMILY_CLASS = "android.graphics.FontFamily";
+ private static final String ADD_FONT_WEIGHT_STYLE_METHOD = "addFontWeightStyle";
+ private static final String CREATE_FROM_FAMILIES_WITH_DEFAULT_METHOD =
+ "createFromFamiliesWithDefault";
+ private static final Class sFontFamily;
+ private static final Constructor sFontFamilyCtor;
+ private static final Method sAddFontWeightStyle;
+ private static final Method sCreateFromFamiliesWithDefault;
+
+ static {
+ Class fontFamilyClass;
+ Constructor fontFamilyCtor;
+ Method addFontMethod;
+ Method createFromFamiliesWithDefaultMethod;
+ try {
+ fontFamilyClass = Class.forName(FONT_FAMILY_CLASS);
+ fontFamilyCtor = fontFamilyClass.getConstructor();
+ addFontMethod = fontFamilyClass.getMethod(ADD_FONT_WEIGHT_STYLE_METHOD,
+ ByteBuffer.class, Integer.TYPE, List.class, Integer.TYPE, Boolean.TYPE);
+ Object familyArray = Array.newInstance(fontFamilyClass, 1);
+ createFromFamiliesWithDefaultMethod =
+ Typeface.class.getMethod(CREATE_FROM_FAMILIES_WITH_DEFAULT_METHOD,
+ familyArray.getClass());
+ } catch (ClassNotFoundException | NoSuchMethodException e) {
+ Log.e(TAG, e.getClass().getName(), e);
+ fontFamilyClass = null;
+ fontFamilyCtor = null;
+ addFontMethod = null;
+ createFromFamiliesWithDefaultMethod = null;
+ }
+ sFontFamilyCtor = fontFamilyCtor;
+ sFontFamily = fontFamilyClass;
+ sAddFontWeightStyle = addFontMethod;
+ sCreateFromFamiliesWithDefault = createFromFamiliesWithDefaultMethod;
+ }
+
+ /**
+ * Returns true if API24 implementation is usable.
+ */
+ public static boolean isUsable() {
+ return sAddFontWeightStyle != null;
+ }
+
+ private static Object newFamily() {
+ try {
+ return sFontFamilyCtor.newInstance();
+ } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static boolean addFontWeightStyle(Object family, ByteBuffer buffer, int ttcIndex,
+ int weight, boolean style) {
+ try {
+ final Boolean result = (Boolean) sAddFontWeightStyle.invoke(
+ family, buffer, ttcIndex, null /* variation axis */, weight, style);
+ return result.booleanValue();
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static Typeface createFromFamiliesWithDefault(Object family) {
+ try {
+ Object familyArray = Array.newInstance(sFontFamily, 1);
+ Array.set(familyArray, 0, family);
+ return (Typeface) sCreateFromFamiliesWithDefault.invoke(
+ null /* static method */, familyArray);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Typeface createFromFontInfo(Context context,
+ @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts, int style) {
+ Object family = newFamily();
+ SimpleArrayMap<Uri, ByteBuffer> bufferCache = new SimpleArrayMap<>();
+
+ for (final FontInfo font : fonts) {
+ final Uri uri = font.getUri();
+ ByteBuffer buffer = bufferCache.get(uri);
+ if (buffer == null) {
+ buffer = TypefaceCompatUtil.mmap(context, cancellationSignal, uri);
+ bufferCache.put(uri, buffer);
+ }
+ if (!addFontWeightStyle(family, buffer, font.getTtcIndex(), font.getWeight(),
+ font.isItalic())) {
+ return null;
+ }
+ }
+ return createFromFamiliesWithDefault(family);
+ }
+
+ @Override
+ public Typeface createFromFontFamilyFilesResourceEntry(Context context,
+ FontFamilyFilesResourceEntry entry, Resources resources, int style) {
+ Object family = newFamily();
+ for (final FontFileResourceEntry e : entry.getEntries()) {
+ final ByteBuffer buffer =
+ TypefaceCompatUtil.copyToDirectBuffer(context, resources, e.getResourceId());
+ // TODO: support ttc index.
+ if (!addFontWeightStyle(family, buffer, 0, e.getWeight(), e.isItalic())) {
+ return null;
+ }
+ }
+ return createFromFamiliesWithDefault(family);
+ }
+}
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompatBaseImpl.java b/compat/java/android/support/v4/graphics/TypefaceCompatBaseImpl.java
index 86bcae8..55289eb 100644
--- a/compat/java/android/support/v4/graphics/TypefaceCompatBaseImpl.java
+++ b/compat/java/android/support/v4/graphics/TypefaceCompatBaseImpl.java
@@ -21,7 +21,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
-import android.net.Uri;
+import android.os.CancellationSignal;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
@@ -29,15 +29,10 @@
import android.support.v4.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry;
import android.support.v4.content.res.FontResourcesParserCompat.FontFileResourceEntry;
import android.support.v4.provider.FontsContractCompat.FontInfo;
-import android.util.Log;
-import java.io.Closeable;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.util.Map;
/**
* Implementation of the Typeface compat methods for API 14 and above.
@@ -49,169 +44,107 @@
private static final String TAG = "TypefaceCompatBaseImpl";
private static final String CACHE_FILE_PREFIX = "cached_font_";
+ private interface StyleExtractor<T> {
+ int getWeight(T t);
+ boolean isItalic(T t);
+ }
+
+ private static <T> T findBestFont(T[] fonts, int style, StyleExtractor<T> extractor) {
+ final int targetWeight = (style & Typeface.BOLD) == 0 ? 400 : 700;
+ final boolean isTargetItalic = (style & Typeface.ITALIC) != 0;
+
+ T best = null;
+ int bestScore = Integer.MAX_VALUE; // smaller is better
+
+ for (final T font : fonts) {
+ final int score = (Math.abs(extractor.getWeight(font) - targetWeight) * 2)
+ + (extractor.isItalic(font) == isTargetItalic ? 0 : 1);
+
+ if (best == null || bestScore > score) {
+ best = font;
+ bestScore = score;
+ }
+ }
+ return best;
+ }
+
+ protected FontInfo findBestInfo(FontInfo[] fonts, int style) {
+ return findBestFont(fonts, style, new StyleExtractor<FontInfo>() {
+ @Override
+ public int getWeight(FontInfo info) {
+ return info.getWeight();
+ }
+
+ @Override
+ public boolean isItalic(FontInfo info) {
+ return info.isItalic();
+ }
+ });
+ }
+
+ // Caller must close the stream.
+ protected Typeface createFromInputStream(Context context, InputStream is) {
+ final File tmpFile = TypefaceCompatUtil.getTempFile(context);
+ if (tmpFile == null) {
+ return null;
+ }
+ try {
+ if (!TypefaceCompatUtil.copyToFile(tmpFile, is)) {
+ return null;
+ }
+ return Typeface.createFromFile(tmpFile.getPath());
+ } catch (RuntimeException e) {
+ // This was thrown from Typeface.createFromFile when a Typeface could not be loaded,
+ // such as due to an invalid ttf or unreadable file. We don't want to throw that
+ // exception anymore.
+ return null;
+ } finally {
+ tmpFile.delete();
+ }
+ }
+
@Override
- public Typeface createTypeface(Context context, @NonNull FontInfo[] fonts,
- Map<Uri, ByteBuffer> uriBuffer) {
+ public Typeface createFromFontInfo(Context context,
+ @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts, int style) {
// When we load from file, we can only load one font so just take the first one.
if (fonts.length < 1) {
return null;
}
- Typeface typeface = null;
- FontInfo font = fonts[0];
- ByteBuffer buffer = uriBuffer.get(font.getUri());
- File tmpFile = copyToCacheFile(context, buffer);
- if (tmpFile != null) {
- try {
- typeface = Typeface.createFromFile(tmpFile.getPath());
- } catch (RuntimeException e) {
- // This was thrown from Typeface.createFromFile when a Typeface could not be loaded,
- // such as due to an invalid ttf or unreadable file. We don't want to throw that
- // exception anymore.
- return null;
- } finally {
- tmpFile.delete();
- }
- }
- return typeface;
- }
-
- private static File copyToCacheFile(Context context, final InputStream is) {
- FileOutputStream fos = null;
- File cacheFile;
- try {
- cacheFile = new File(context.getCacheDir(),
- CACHE_FILE_PREFIX + Thread.currentThread().getId());
- fos = new FileOutputStream(cacheFile, false);
-
- byte[] buffer = new byte[1024];
- int readLen;
- while ((readLen = is.read(buffer)) != -1) {
- fos.write(buffer, 0, readLen);
- }
- } catch (IOException e) {
- Log.e(TAG, "Error copying font file descriptor to temp local file.", e);
- return null;
- } finally {
- closeQuietly(is);
- closeQuietly(fos);
- }
- return cacheFile;
- }
-
- private static File copyToCacheFile(Context context, final ByteBuffer is) {
- FileOutputStream fos = null;
- File cacheFile;
- try {
- cacheFile = new File(context.getCacheDir(),
- CACHE_FILE_PREFIX + Thread.currentThread().getId());
- fos = new FileOutputStream(cacheFile, false);
-
- byte[] buffer = new byte[1024];
- while (is.hasRemaining()) {
- int len = Math.min(1024, is.remaining());
- is.get(buffer, 0, len);
- fos.write(buffer, 0, len);
- }
- } catch (IOException e) {
- Log.e(TAG, "Error copying font file descriptor to temp local file.", e);
- return null;
- } finally {
- closeQuietly(fos);
- }
- return cacheFile;
- }
-
- private static void closeQuietly(InputStream is) {
- if (is != null) {
- try {
- is.close();
- } catch (IOException io) {
- Log.e(TAG, "Error closing input stream", io);
- }
- }
- }
-
- @Nullable
- @Override
- public Typeface createFromResourcesFontFile(Context context, Resources resources, int id,
- int style) {
+ FontInfo font = findBestInfo(fonts, style);
InputStream is = null;
try {
- is = resources.openRawResource(id);
- return createTypeface(context, resources, is);
+ is = context.getContentResolver().openInputStream(font.getUri());
+ return createFromInputStream(context, is);
} catch (IOException e) {
return null;
} finally {
- closeQuietly(is);
+ TypefaceCompatUtil.closeQuietly(is);
}
}
- private FontFileResourceEntry findBestEntry(FontFamilyFilesResourceEntry entry,
- int targetWeight, boolean isTargetItalic) {
- FontFileResourceEntry bestEntry = null;
- int bestScore = Integer.MAX_VALUE; // smaller is better
-
- for (final FontFileResourceEntry e : entry.getEntries()) {
- final int score = (Math.abs(e.getWeight() - targetWeight) * 2)
- + (isTargetItalic == e.isItalic() ? 0 : 1);
-
- if (bestEntry == null || bestScore > score) {
- bestEntry = e;
- bestScore = score;
+ private FontFileResourceEntry findBestEntry(FontFamilyFilesResourceEntry entry, int style) {
+ return findBestFont(entry.getEntries(), style, new StyleExtractor<FontFileResourceEntry>() {
+ @Override
+ public int getWeight(FontFileResourceEntry entry) {
+ return entry.getWeight();
}
- }
- return bestEntry;
+
+ @Override
+ public boolean isItalic(FontFileResourceEntry entry) {
+ return entry.isItalic();
+ }
+ });
}
@Nullable
@Override
public Typeface createFromFontFamilyFilesResourceEntry(Context context,
- FontFamilyFilesResourceEntry entry, Resources resources, int id, int style) {
- FontFileResourceEntry best = findBestEntry(
- entry, ((style & Typeface.BOLD) == 0) ? 400 : 700, (style & Typeface.ITALIC) != 0);
+ FontFamilyFilesResourceEntry entry, Resources resources, int style) {
+ FontFileResourceEntry best = findBestEntry(entry, style);
if (best == null) {
return null;
}
-
- InputStream is = null;
- try {
- is = resources.openRawResource(best.getResourceId());
- return createTypeface(context, resources, is);
- } catch (IOException e) {
- // This is fine. The resource can be string type which indicates a name of Typeface.
- } finally {
- closeQuietly(is);
- }
- return null;
- }
-
- // Caller must close "is"
- Typeface createTypeface(Context context, Resources resources, InputStream is)
- throws IOException {
- File tmpFile = copyToCacheFile(context, is);
- if (tmpFile != null) {
- try {
- return Typeface.createFromFile(tmpFile.getPath());
- } catch (RuntimeException e) {
- // This was thrown from Typeface.createFromFile when a Typeface could not be loaded,
- // such as due to an invalid ttf or unreadable file. We don't want to throw that
- // exception anymore.
- android.util.Log.e(TAG, "Failed to create font", e);
- return null;
- } finally {
- tmpFile.delete();
- }
- }
- return null;
- }
-
- static void closeQuietly(Closeable stream) {
- if (stream != null) {
- try {
- stream.close();
- } catch (IOException io) {
- Log.e(TAG, "Error closing stream", io);
- }
- }
+ return TypefaceCompat.createFromResourcesFontFile(
+ context, resources, best.getResourceId(), style);
}
}
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompatUtil.java b/compat/java/android/support/v4/graphics/TypefaceCompatUtil.java
new file mode 100644
index 0000000..8d8beb2
--- /dev/null
+++ b/compat/java/android/support/v4/graphics/TypefaceCompatUtil.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.graphics;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.RestrictTo;
+import android.util.Log;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+
+/**
+ * Utility methods for TypefaceCompat.
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+class TypefaceCompatUtil {
+ private static final String TAG = "TypefaceCompatUtil";
+
+ private TypefaceCompatUtil() {} // Do not instantiate.
+
+ private static final String CACHE_FILE_PREFIX = ".font";
+
+ /**
+ * Creates a temp file.
+ *
+ * Returns null if failed to create temp file.
+ */
+ public static File getTempFile(Context context) {
+ final String prefix = CACHE_FILE_PREFIX + Process.myPid() + "-" + Process.myTid() + "-";
+ for (int i = 0; i < 100; ++i) {
+ final File file = new File(context.getCacheDir(), prefix + i);
+ try {
+ if (file.createNewFile()) {
+ return file;
+ }
+ } catch (IOException e) {
+ // ignore. Try next file.
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Copy the file contents to the direct byte buffer.
+ */
+ @RequiresApi(19)
+ private static ByteBuffer mmap(File file) {
+ try (FileInputStream fis = new FileInputStream(file)) {
+ FileChannel channel = fis.getChannel();
+ final long size = channel.size();
+ return channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Copy the file contents to the direct byte buffer.
+ */
+ @RequiresApi(19)
+ public static ByteBuffer mmap(Context context, CancellationSignal cancellationSignal, Uri uri) {
+ final ContentResolver resolver = context.getContentResolver();
+ try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r", cancellationSignal);
+ FileInputStream fis = new FileInputStream(pfd.getFileDescriptor())) {
+ FileChannel channel = fis.getChannel();
+ final long size = channel.size();
+ return channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Copy the resource contents to the direct byte buffer.
+ */
+ @RequiresApi(19)
+ public static ByteBuffer copyToDirectBuffer(Context context, Resources res, int id) {
+ File tmpFile = getTempFile(context);
+ if (tmpFile == null) {
+ return null;
+ }
+ try {
+ if (!copyToFile(tmpFile, res, id)) {
+ return null;
+ }
+ return mmap(tmpFile);
+ } finally {
+ tmpFile.delete();
+ }
+ }
+
+ /**
+ * Copy the input stream contents to file.
+ */
+ public static boolean copyToFile(File file, InputStream is) {
+ FileOutputStream os = null;
+ try {
+ os = new FileOutputStream(file, false);
+ byte[] buffer = new byte[1024];
+ int readLen;
+ while ((readLen = is.read(buffer)) != -1) {
+ os.write(buffer, 0, readLen);
+ }
+ return true;
+ } catch (IOException e) {
+ Log.e(TAG, "Error copying resource contents to temp file: " + e.getMessage());
+ return false;
+ } finally {
+ closeQuietly(os);
+ }
+ }
+
+ /**
+ * Copy the resource contents to file.
+ */
+ public static boolean copyToFile(File file, Resources res, int id) {
+ InputStream is = null;
+ try {
+ is = res.openRawResource(id);
+ return copyToFile(file, is);
+ } finally {
+ closeQuietly(is);
+ }
+ }
+
+ public static void closeQuietly(Closeable c) {
+ if (c != null) {
+ try {
+ c.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+}
diff --git a/compat/java/android/support/v4/graphics/drawable/IconCompat.java b/compat/java/android/support/v4/graphics/drawable/IconCompat.java
index c820366..c268d8b 100644
--- a/compat/java/android/support/v4/graphics/drawable/IconCompat.java
+++ b/compat/java/android/support/v4/graphics/drawable/IconCompat.java
@@ -34,7 +34,6 @@
import android.support.annotation.DrawableRes;
import android.support.annotation.RestrictTo;
import android.support.annotation.VisibleForTesting;
-import android.support.v4.os.BuildCompat;
/**
* Helper for accessing features in {@link android.graphics.drawable.Icon}
@@ -186,7 +185,7 @@
case TYPE_BITMAP:
return Icon.createWithBitmap((Bitmap) mObj1);
case TYPE_ADAPTIVE_BITMAP:
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return Icon.createWithAdaptiveBitmap((Bitmap) mObj1);
} else {
return Icon.createWithBitmap(createLegacyIconFromAdaptiveIcon((Bitmap) mObj1));
diff --git a/compat/java/android/support/v4/os/LocaleHelper.java b/compat/java/android/support/v4/os/LocaleHelper.java
index 539106c..f6fe7da 100644
--- a/compat/java/android/support/v4/os/LocaleHelper.java
+++ b/compat/java/android/support/v4/os/LocaleHelper.java
@@ -62,7 +62,7 @@
StringBuilder buf = new StringBuilder();
buf.append(locale.getLanguage());
final String country = locale.getCountry();
- if (country != null && !country.equals("")) {
+ if (country != null && !country.isEmpty()) {
buf.append("-");
buf.append(locale.getCountry());
}
diff --git a/compat/java/android/support/v4/os/LocaleListCompat.java b/compat/java/android/support/v4/os/LocaleListCompat.java
index 1185e98..d4a32f2 100644
--- a/compat/java/android/support/v4/os/LocaleListCompat.java
+++ b/compat/java/android/support/v4/os/LocaleListCompat.java
@@ -285,7 +285,7 @@
*/
@NonNull
public static LocaleListCompat forLanguageTags(@Nullable String list) {
- if (list == null || list.equals("")) {
+ if (list == null || list.isEmpty()) {
return getEmptyLocaleList();
} else {
final String[] tags = list.split(",");
diff --git a/compat/java/android/support/v4/os/LocaleListHelper.java b/compat/java/android/support/v4/os/LocaleListHelper.java
index 133ecfe..cfb24fb 100644
--- a/compat/java/android/support/v4/os/LocaleListHelper.java
+++ b/compat/java/android/support/v4/os/LocaleListHelper.java
@@ -271,7 +271,7 @@
@RestrictTo(LIBRARY_GROUP)
@NonNull
static LocaleListHelper forLanguageTags(@Nullable String list) {
- if (list == null || list.equals("")) {
+ if (list == null || list.isEmpty()) {
return getEmptyLocaleList();
} else {
final String[] tags = list.split(",");
diff --git a/compat/java/android/support/v4/provider/FontsContractCompat.java b/compat/java/android/support/v4/provider/FontsContractCompat.java
index ba44019..afa565c 100644
--- a/compat/java/android/support/v4/provider/FontsContractCompat.java
+++ b/compat/java/android/support/v4/provider/FontsContractCompat.java
@@ -19,6 +19,7 @@
import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import static android.support.v4.content.res.FontResourcesParserCompat.FetchStrategy;
+import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
@@ -51,19 +52,13 @@
import android.support.v4.util.SimpleArrayMap;
import android.widget.TextView;
-import java.io.FileInputStream;
-import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.concurrent.Callable;
/**
@@ -178,7 +173,8 @@
new SelfDestructiveThread("fonts", Process.THREAD_PRIORITY_BACKGROUND,
BACKGROUND_THREAD_KEEP_ALIVE_DURATION_MS);
- private static Typeface getFontInternal(final Context context, final FontRequest request) {
+ private static Typeface getFontInternal(final Context context, final FontRequest request,
+ int style) {
FontFamilyResult result;
try {
result = fetchFonts(context, null /* CancellationSignal */, request);
@@ -186,7 +182,8 @@
return null;
}
if (result.getStatusCode() == FontFamilyResult.STATUS_OK) {
- return buildTypeface(context, null /* CancellationSignal */, result.getFonts());
+ return TypefaceCompat.createFromFontInfo(context, null /* CancellationSignal */,
+ result.getFonts(), style);
}
return null;
}
@@ -200,7 +197,7 @@
@RestrictTo(LIBRARY_GROUP)
public static Typeface getFontSync(final Context context, final FontRequest request,
final TextView targetView, @FetchStrategy int strategy, int timeout, final int style) {
- final String id = request.getIdentifier();
+ final String id = request.getIdentifier() + "-" + style;
Typeface cached = sTypefaceCache.get(id);
if (cached != null) {
return cached;
@@ -211,13 +208,13 @@
if (isBlockingFetch && timeout == FontResourcesParserCompat.INFINITE_TIMEOUT_VALUE) {
// Wait forever. No need to post to the thread.
- return getFontInternal(context, request);
+ return getFontInternal(context, request, style);
}
final Callable<Typeface> fetcher = new Callable<Typeface>() {
@Override
public Typeface call() throws Exception {
- Typeface typeface = getFontInternal(context, request);
+ Typeface typeface = getFontInternal(context, request, style);
if (typeface != null) {
sTypefaceCache.put(id, typeface);
}
@@ -581,55 +578,6 @@
}
/**
- * A helper function to create a mapping from {@link Uri} to {@link ByteBuffer}.
- *
- * Skip if the file contents is not ready to be read.
- *
- * @param context A {@link Context} to be used for resolving content URI in
- * {@link FontInfo}.
- * @param fonts An array of {@link FontInfo}.
- * @return A map from {@link Uri} to {@link ByteBuffer}.
- */
- private static Map<Uri, ByteBuffer> prepareFontData(Context context, FontInfo[] fonts,
- CancellationSignal cancellationSignal) {
- final HashMap<Uri, ByteBuffer> out = new HashMap<>();
- final ContentResolver resolver = context.getContentResolver();
-
- for (FontInfo font : fonts) {
- if (font.getResultCode() != Columns.RESULT_CODE_OK) {
- continue;
- }
-
- final Uri uri = font.getUri();
- if (out.containsKey(uri)) {
- continue;
- }
-
- ByteBuffer buffer = null;
- ParcelFileDescriptor pfd = null;
- FileInputStream fis = null;
- try {
- if (Build.VERSION.SDK_INT > 19) {
- pfd = resolver.openFileDescriptor(uri, "r", cancellationSignal);
- } else {
- pfd = resolver.openFileDescriptor(uri, "r");
- }
- fis = new FileInputStream(pfd.getFileDescriptor());
- final FileChannel fileChannel = fis.getChannel();
- final long size = fileChannel.size();
- buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
- } catch (IOException e) {
- // ignore
- }
-
- // TODO: try other approach?, e.g. read all contents instead of mmap.
-
- out.put(uri, buffer);
- }
- return Collections.unmodifiableMap(out);
- }
-
- /**
* Build a Typeface from an array of {@link FontInfo}
*
* Results that are marked as not ready will be skipped.
@@ -643,9 +591,8 @@
*/
public static Typeface buildTypeface(@NonNull Context context,
@Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts) {
- final Map<Uri, ByteBuffer> uriBuffer =
- prepareFontData(context, fonts, cancellationSignal);
- return TypefaceCompat.createTypeface(context, fonts, uriBuffer);
+ return TypefaceCompat.createFromFontInfo(context, cancellationSignal, fonts,
+ Typeface.NORMAL);
}
/**
@@ -699,6 +646,8 @@
}
List<byte[]> signatures;
+ // We correctly check all signatures returned, as advised in the lint error.
+ @SuppressLint("PackageManagerGetSignatures")
PackageInfo packageInfo = packageManager.getPackageInfo(info.packageName,
PackageManager.GET_SIGNATURES);
signatures = convertToByteArrayList(packageInfo.signatures);
diff --git a/compat/java/android/support/v4/text/util/LinkifyCompat.java b/compat/java/android/support/v4/text/util/LinkifyCompat.java
index d242780..23b3e49 100644
--- a/compat/java/android/support/v4/text/util/LinkifyCompat.java
+++ b/compat/java/android/support/v4/text/util/LinkifyCompat.java
@@ -18,6 +18,7 @@
import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+import android.os.Build;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -96,6 +97,9 @@
* @return True if at least one link is found and applied.
*/
public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask) {
+ if (Build.VERSION.SDK_INT >= 26) {
+ return Linkify.addLinks(text, mask);
+ }
if (mask == 0) {
return false;
}
@@ -157,6 +161,9 @@
* @return True if at least one link is found and applied.
*/
public static final boolean addLinks(@NonNull TextView text, @LinkifyMask int mask) {
+ if (Build.VERSION.SDK_INT >= 26) {
+ return Linkify.addLinks(text, mask);
+ }
if (mask == 0) {
return false;
}
@@ -197,6 +204,10 @@
*/
public static final void addLinks(@NonNull TextView text, @NonNull Pattern pattern,
@Nullable String scheme) {
+ if (Build.VERSION.SDK_INT >= 26) {
+ Linkify.addLinks(text, pattern, scheme);
+ return;
+ }
addLinks(text, pattern, scheme, null, null, null);
}
@@ -217,6 +228,10 @@
public static final void addLinks(@NonNull TextView text, @NonNull Pattern pattern,
@Nullable String scheme, @Nullable MatchFilter matchFilter,
@Nullable TransformFilter transformFilter) {
+ if (Build.VERSION.SDK_INT >= 26) {
+ Linkify.addLinks(text, pattern, scheme, matchFilter, transformFilter);
+ return;
+ }
addLinks(text, pattern, scheme, null, matchFilter, transformFilter);
}
@@ -238,8 +253,12 @@
* @param transformFilter Filter to allow the client code to update the link found.
*/
public static final void addLinks(@NonNull TextView text, @NonNull Pattern pattern,
- @Nullable String defaultScheme, @Nullable String[] schemes,
+ @Nullable String defaultScheme, @Nullable String[] schemes,
@Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter) {
+ if (Build.VERSION.SDK_INT >= 26) {
+ Linkify.addLinks(text, pattern, defaultScheme, schemes, matchFilter, transformFilter);
+ return;
+ }
SpannableString spannable = SpannableString.valueOf(text.getText());
boolean linksAdded = addLinks(spannable, pattern, defaultScheme, schemes, matchFilter,
@@ -261,6 +280,9 @@
*/
public static final boolean addLinks(@NonNull Spannable text, @NonNull Pattern pattern,
@Nullable String scheme) {
+ if (Build.VERSION.SDK_INT >= 26) {
+ return Linkify.addLinks(text, pattern, scheme);
+ }
return addLinks(text, pattern, scheme, null, null, null);
}
@@ -282,6 +304,9 @@
public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
@Nullable String scheme, @Nullable MatchFilter matchFilter,
@Nullable TransformFilter transformFilter) {
+ if (Build.VERSION.SDK_INT >= 26) {
+ return Linkify.addLinks(spannable, pattern, scheme, matchFilter, transformFilter);
+ }
return addLinks(spannable, pattern, scheme, null, matchFilter,
transformFilter);
}
@@ -305,6 +330,10 @@
public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
@Nullable String defaultScheme, @Nullable String[] schemes,
@Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter) {
+ if (Build.VERSION.SDK_INT >= 26) {
+ return Linkify.addLinks(spannable, pattern, defaultScheme, schemes, matchFilter,
+ transformFilter);
+ }
final String[] schemesCopy;
if (defaultScheme == null) defaultScheme = "";
if (schemes == null || schemes.length < 1) {
diff --git a/compat/java/android/support/v4/view/MenuItemCompat.java b/compat/java/android/support/v4/view/MenuItemCompat.java
index 649c413..d7e96cc 100644
--- a/compat/java/android/support/v4/view/MenuItemCompat.java
+++ b/compat/java/android/support/v4/view/MenuItemCompat.java
@@ -19,9 +19,9 @@
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v4.internal.view.SupportMenuItem;
-import android.support.v4.os.BuildCompat;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
@@ -274,7 +274,7 @@
*/
static final MenuVersionImpl IMPL;
static {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
IMPL = new MenuItemCompatApi26Impl();
} else {
IMPL = new MenuItemCompatBaseImpl();
diff --git a/compat/java/android/support/v4/view/ViewCompat.java b/compat/java/android/support/v4/view/ViewCompat.java
index efbf848..a4035b2 100644
--- a/compat/java/android/support/v4/view/ViewCompat.java
+++ b/compat/java/android/support/v4/view/ViewCompat.java
@@ -36,7 +36,6 @@
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.annotation.RestrictTo;
-import android.support.v4.os.BuildCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
import android.util.Log;
@@ -1576,7 +1575,7 @@
static final ViewCompatBaseImpl IMPL;
static {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
IMPL = new ViewCompatApi26Impl();
} else if (Build.VERSION.SDK_INT >= 24) {
IMPL = new ViewCompatApi24Impl();
diff --git a/compat/java/android/support/v4/view/ViewConfigurationCompat.java b/compat/java/android/support/v4/view/ViewConfigurationCompat.java
index 683a380..4ae2260 100644
--- a/compat/java/android/support/v4/view/ViewConfigurationCompat.java
+++ b/compat/java/android/support/v4/view/ViewConfigurationCompat.java
@@ -17,8 +17,8 @@
package android.support.v4.view;
import android.content.Context;
+import android.os.Build;
import android.support.annotation.NonNull;
-import android.support.v4.os.BuildCompat;
import android.util.Log;
import android.util.TypedValue;
import android.view.ViewConfiguration;
@@ -37,7 +37,7 @@
private static Method sGetScaledScrollFactorMethod;
static {
- if (android.os.Build.VERSION.SDK_INT >= 25 && !BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT == 25) {
try {
sGetScaledScrollFactorMethod =
ViewConfiguration.class.getDeclaredMethod("getScaledScrollFactor");
@@ -79,7 +79,7 @@
*/
public static float getScaledHorizontalScrollFactor(@NonNull ViewConfiguration config,
@NonNull Context context) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return config.getScaledHorizontalScrollFactor();
} else {
return getLegacyScrollFactor(config, context);
@@ -96,7 +96,7 @@
*/
public static float getScaledVerticalScrollFactor(@NonNull ViewConfiguration config,
@NonNull Context context) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return config.getScaledVerticalScrollFactor();
} else {
return getLegacyScrollFactor(config, context);
diff --git a/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java b/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java
index bf313a0..426dad9 100644
--- a/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java
+++ b/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java
@@ -36,14 +36,7 @@
public static final String TAG = "NotificationCompat";
// Extras keys used for Jellybean SDK and above.
- static final String EXTRA_LOCAL_ONLY = "android.support.localOnly";
- static final String EXTRA_ACTION_EXTRAS = "android.support.actionExtras";
- static final String EXTRA_REMOTE_INPUTS = "android.support.remoteInputs";
static final String EXTRA_DATA_ONLY_REMOTE_INPUTS = "android.support.dataRemoteInputs";
- static final String EXTRA_GROUP_KEY = "android.support.groupKey";
- static final String EXTRA_GROUP_SUMMARY = "android.support.isGroupSummary";
- static final String EXTRA_SORT_KEY = "android.support.sortKey";
- static final String EXTRA_USE_SIDE_CHANNEL = "android.support.useSideChannel";
static final String EXTRA_ALLOW_GENERATED_REPLIES = "android.support.allowGeneratedReplies";
// Bundle keys for storing action fields in a bundle
@@ -112,18 +105,18 @@
mExtras.putAll(extras);
}
if (localOnly) {
- mExtras.putBoolean(EXTRA_LOCAL_ONLY, true);
+ mExtras.putBoolean(NotificationCompatExtras.EXTRA_LOCAL_ONLY, true);
}
if (groupKey != null) {
- mExtras.putString(EXTRA_GROUP_KEY, groupKey);
+ mExtras.putString(NotificationCompatExtras.EXTRA_GROUP_KEY, groupKey);
if (groupSummary) {
- mExtras.putBoolean(EXTRA_GROUP_SUMMARY, true);
+ mExtras.putBoolean(NotificationCompatExtras.EXTRA_GROUP_SUMMARY, true);
} else {
- mExtras.putBoolean(EXTRA_USE_SIDE_CHANNEL, true);
+ mExtras.putBoolean(NotificationManagerCompat.EXTRA_USE_SIDE_CHANNEL, true);
}
}
if (sortKey != null) {
- mExtras.putString(EXTRA_SORT_KEY, sortKey);
+ mExtras.putString(NotificationCompatExtras.EXTRA_SORT_KEY, sortKey);
}
mContentView = contentView;
mBigContentView = bigContentView;
@@ -155,7 +148,8 @@
SparseArray<Bundle> actionExtrasMap = buildActionExtrasMap(mActionExtrasList);
if (actionExtrasMap != null) {
// Add the action extras sparse array if any action was added with extras.
- getExtras(notif).putSparseParcelableArray(EXTRA_ACTION_EXTRAS, actionExtrasMap);
+ getExtras(notif).putSparseParcelableArray(
+ NotificationCompatExtras.EXTRA_ACTION_EXTRAS, actionExtrasMap);
}
if (mContentView != null) {
notif.contentView = mContentView;
@@ -266,7 +260,8 @@
boolean allowGeneratedReplies = false;
if (extras != null) {
remoteInputs = RemoteInputCompatJellybean.fromBundleArray(
- BundleUtil.getBundleArrayFromBundle(extras, EXTRA_REMOTE_INPUTS),
+ BundleUtil.getBundleArrayFromBundle(extras,
+ NotificationCompatExtras.EXTRA_REMOTE_INPUTS),
remoteInputFactory);
dataOnlyRemoteInputs = RemoteInputCompatJellybean.fromBundleArray(
BundleUtil.getBundleArrayFromBundle(extras, EXTRA_DATA_ONLY_REMOTE_INPUTS),
@@ -282,7 +277,7 @@
builder.addAction(action.getIcon(), action.getTitle(), action.getActionIntent());
Bundle actionExtras = new Bundle(action.getExtras());
if (action.getRemoteInputs() != null) {
- actionExtras.putParcelableArray(EXTRA_REMOTE_INPUTS,
+ actionExtras.putParcelableArray(NotificationCompatExtras.EXTRA_REMOTE_INPUTS,
RemoteInputCompatJellybean.toBundleArray(action.getRemoteInputs()));
}
if (action.getDataOnlyRemoteInputs() != null) {
@@ -313,7 +308,7 @@
Bundle extras = getExtras(notif);
if (extras != null) {
SparseArray<Bundle> actionExtrasMap = extras.getSparseParcelableArray(
- EXTRA_ACTION_EXTRAS);
+ NotificationCompatExtras.EXTRA_ACTION_EXTRAS);
if (actionExtrasMap != null) {
actionExtras = actionExtrasMap.get(actionIndex);
}
diff --git a/compat/jellybean/android/support/v4/app/RemoteInputCompatJellybean.java b/compat/jellybean/android/support/v4/app/RemoteInputCompatJellybean.java
index 558a42b..0402a91 100644
--- a/compat/jellybean/android/support/v4/app/RemoteInputCompatJellybean.java
+++ b/compat/jellybean/android/support/v4/app/RemoteInputCompatJellybean.java
@@ -31,12 +31,6 @@
@RequiresApi(16)
class RemoteInputCompatJellybean {
- /** Label used to denote the clip data type used for remote input transport */
- public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results";
-
- /** Extra added to a clip data intent object to hold the results bundle. */
- public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
-
/** Extra added to a clip data intent object to hold the data results bundle. */
private static final String EXTRA_DATA_TYPE_RESULTS_DATA =
"android.remoteinput.dataTypeResultsData";
@@ -112,7 +106,7 @@
if (clipDataIntent == null) {
return null;
}
- return clipDataIntent.getExtras().getParcelable(EXTRA_RESULTS_DATA);
+ return clipDataIntent.getExtras().getParcelable(RemoteInput.EXTRA_RESULTS_DATA);
}
static Map<String, Uri> getDataResultsFromIntent(Intent intent, String remoteInputResultKey) {
@@ -145,7 +139,7 @@
if (clipDataIntent == null) {
clipDataIntent = new Intent(); // First time we've added a result.
}
- Bundle resultsBundle = clipDataIntent.getBundleExtra(EXTRA_RESULTS_DATA);
+ Bundle resultsBundle = clipDataIntent.getBundleExtra(RemoteInput.EXTRA_RESULTS_DATA);
if (resultsBundle == null) {
resultsBundle = new Bundle();
}
@@ -155,8 +149,8 @@
resultsBundle.putCharSequence(remoteInput.getResultKey(), (CharSequence) result);
}
}
- clipDataIntent.putExtra(EXTRA_RESULTS_DATA, resultsBundle);
- intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipDataIntent));
+ clipDataIntent.putExtra(RemoteInput.EXTRA_RESULTS_DATA, resultsBundle);
+ intent.setClipData(ClipData.newIntent(RemoteInput.RESULTS_CLIP_LABEL, clipDataIntent));
}
/**
@@ -186,7 +180,7 @@
resultsBundle.putString(remoteInput.getResultKey(), uri.toString());
clipDataIntent.putExtra(getExtraResultsKeyForData(mimeType), resultsBundle);
}
- intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipDataIntent));
+ intent.setClipData(ClipData.newIntent(RemoteInput.RESULTS_CLIP_LABEL, clipDataIntent));
}
private static String getExtraResultsKeyForData(String mimeType) {
@@ -202,7 +196,7 @@
if (!clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT)) {
return null;
}
- if (!clipDescription.getLabel().equals(RESULTS_CLIP_LABEL)) {
+ if (!clipDescription.getLabel().equals(RemoteInput.RESULTS_CLIP_LABEL)) {
return null;
}
return clipData.getItemAt(0).getIntent();
diff --git a/compat/kitkat/android/support/v4/app/NotificationCompatKitKat.java b/compat/kitkat/android/support/v4/app/NotificationCompatKitKat.java
index 34de842..f40fd1b 100644
--- a/compat/kitkat/android/support/v4/app/NotificationCompatKitKat.java
+++ b/compat/kitkat/android/support/v4/app/NotificationCompatKitKat.java
@@ -81,18 +81,18 @@
people.toArray(new String[people.size()]));
}
if (localOnly) {
- mExtras.putBoolean(NotificationCompatJellybean.EXTRA_LOCAL_ONLY, true);
+ mExtras.putBoolean(NotificationCompatExtras.EXTRA_LOCAL_ONLY, true);
}
if (groupKey != null) {
- mExtras.putString(NotificationCompatJellybean.EXTRA_GROUP_KEY, groupKey);
+ mExtras.putString(NotificationCompatExtras.EXTRA_GROUP_KEY, groupKey);
if (groupSummary) {
- mExtras.putBoolean(NotificationCompatJellybean.EXTRA_GROUP_SUMMARY, true);
+ mExtras.putBoolean(NotificationCompatExtras.EXTRA_GROUP_SUMMARY, true);
} else {
- mExtras.putBoolean(NotificationCompatJellybean.EXTRA_USE_SIDE_CHANNEL, true);
+ mExtras.putBoolean(NotificationManagerCompat.EXTRA_USE_SIDE_CHANNEL, true);
}
}
if (sortKey != null) {
- mExtras.putString(NotificationCompatJellybean.EXTRA_SORT_KEY, sortKey);
+ mExtras.putString(NotificationCompatExtras.EXTRA_SORT_KEY, sortKey);
}
mContentView = contentView;
mBigContentView = bigContentView;
@@ -115,7 +115,7 @@
if (actionExtrasMap != null) {
// Add the action extras sparse array if any action was added with extras.
mExtras.putSparseParcelableArray(
- NotificationCompatJellybean.EXTRA_ACTION_EXTRAS, actionExtrasMap);
+ NotificationCompatExtras.EXTRA_ACTION_EXTRAS, actionExtrasMap);
}
b.setExtras(mExtras);
Notification notification = b.build();
@@ -135,7 +135,7 @@
Notification.Action action = notif.actions[actionIndex];
Bundle actionExtras = null;
SparseArray<Bundle> actionExtrasMap = notif.extras.getSparseParcelableArray(
- NotificationCompatJellybean.EXTRA_ACTION_EXTRAS);
+ NotificationCompatExtras.EXTRA_ACTION_EXTRAS);
if (actionExtrasMap != null) {
actionExtras = actionExtrasMap.get(actionIndex);
}
diff --git a/compat/tests/AndroidManifest.xml b/compat/tests/AndroidManifest.xml
index ca75941..124d877 100644
--- a/compat/tests/AndroidManifest.xml
+++ b/compat/tests/AndroidManifest.xml
@@ -45,7 +45,7 @@
<activity android:name="android.support.v4.app.TestSupportActivity" />
<provider android:name="android.support.v4.provider.MockFontProvider"
- android:authorities="android.provider.fonts.font"
+ android:authorities="android.support.provider.fonts.font"
android:exported="false"
android:multiprocess="true" />
diff --git a/compat/tests/assets/fonts/large_a.ttf b/compat/tests/assets/fonts/large_a.ttf
new file mode 100644
index 0000000..0e778b6
--- /dev/null
+++ b/compat/tests/assets/fonts/large_a.ttf
Binary files differ
diff --git a/compat/tests/assets/fonts/large_a.ttx b/compat/tests/assets/fonts/large_a.ttx
new file mode 100644
index 0000000..c453414
--- /dev/null
+++ b/compat/tests/assets/fonts/large_a.ttx
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+ <GlyphOrder>
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="1em"/>
+ <GlyphID id="2" name="3em"/>
+ </GlyphOrder>
+
+ <head>
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x640cdb2f"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Fri Mar 17 07:26:00 2017"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="7"/>
+ <fontDirectionHint value="2"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="1.0"/>
+ <ascent value="1000"/>
+ <descent value="-200"/>
+ <lineGap value="0"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ </hhea>
+
+ <maxp>
+ <tableVersion value="0x10000"/>
+ <maxZones value="0"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="0"/>
+ <maxSizeOfInstructions value="0"/>
+ <maxComponentElements value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="594"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00001000"/>
+ <ySubscriptXSize value="650"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="650"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="350"/>
+ <yStrikeoutSize value="50"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="5"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="UKWN"/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="32"/>
+ <usLastCharIndex value="122"/>
+ <sTypoAscender value="800"/>
+ <sTypoDescender value="-200"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="200"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="700"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="93"/>
+ <mtx name="1em" width="1000" lsb="93"/>
+ <mtx name="3em" width="3000" lsb="93"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="3" platEncID="10" language="0">
+ <map code="0x0061" name="3em" />
+ <map code="0x0062" name="1em" />
+ <map code="0x0063" name="1em" />
+ <map code="0x0064" name="1em" />
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+ <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+ <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+ <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+ </glyf>
+
+ <name>
+ <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+ Copyright (C) 2017 The Android Open Source Project
+ </namerecord>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ SampleFont-Regular
+ </namerecord>
+ <namerecord nameID="10" platformID="3" platEncID="1" langID="0x409">
+ Source code is available at platform/frameworks/support/compat/tests/assets/fonts/large_a.ttx.
+ </namerecord>
+ <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ </namerecord>
+ <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+ http://www.apache.org/licenses/LICENSE-2.0
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-75"/>
+ <underlineThickness value="50"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+</ttFont>
diff --git a/compat/tests/assets/fonts/large_b.ttf b/compat/tests/assets/fonts/large_b.ttf
new file mode 100644
index 0000000..b8ce6ce
--- /dev/null
+++ b/compat/tests/assets/fonts/large_b.ttf
Binary files differ
diff --git a/compat/tests/assets/fonts/large_b.ttx b/compat/tests/assets/fonts/large_b.ttx
new file mode 100644
index 0000000..0274e9c
--- /dev/null
+++ b/compat/tests/assets/fonts/large_b.ttx
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+ <GlyphOrder>
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="1em"/>
+ <GlyphID id="2" name="3em"/>
+ </GlyphOrder>
+
+ <head>
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x640cdb2f"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Fri Mar 17 07:26:00 2017"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="7"/>
+ <fontDirectionHint value="2"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="1.0"/>
+ <ascent value="1000"/>
+ <descent value="-200"/>
+ <lineGap value="0"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ </hhea>
+
+ <maxp>
+ <tableVersion value="0x10000"/>
+ <maxZones value="0"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="0"/>
+ <maxSizeOfInstructions value="0"/>
+ <maxComponentElements value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="594"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00001000"/>
+ <ySubscriptXSize value="650"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="650"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="350"/>
+ <yStrikeoutSize value="50"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="5"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="UKWN"/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="32"/>
+ <usLastCharIndex value="122"/>
+ <sTypoAscender value="800"/>
+ <sTypoDescender value="-200"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="200"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="700"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="93"/>
+ <mtx name="1em" width="1000" lsb="93"/>
+ <mtx name="3em" width="3000" lsb="93"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="3" platEncID="10" language="0">
+ <map code="0x0061" name="1em" />
+ <map code="0x0062" name="3em" />
+ <map code="0x0063" name="1em" />
+ <map code="0x0064" name="1em" />
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+ <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+ <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+ <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+ </glyf>
+
+ <name>
+ <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+ Copyright (C) 2017 The Android Open Source Project
+ </namerecord>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ SampleFont-Regular
+ </namerecord>
+ <namerecord nameID="10" platformID="3" platEncID="1" langID="0x409">
+ Source code is available at platform/frameworks/support/compat/tests/assets/fonts/large_b.ttx.
+ </namerecord>
+ <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ </namerecord>
+ <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+ http://www.apache.org/licenses/LICENSE-2.0
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-75"/>
+ <underlineThickness value="50"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+</ttFont>
diff --git a/compat/tests/assets/fonts/large_c.ttf b/compat/tests/assets/fonts/large_c.ttf
new file mode 100644
index 0000000..dd5fa50
--- /dev/null
+++ b/compat/tests/assets/fonts/large_c.ttf
Binary files differ
diff --git a/compat/tests/assets/fonts/large_c.ttx b/compat/tests/assets/fonts/large_c.ttx
new file mode 100644
index 0000000..d3657b1
--- /dev/null
+++ b/compat/tests/assets/fonts/large_c.ttx
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+ <GlyphOrder>
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="1em"/>
+ <GlyphID id="2" name="3em"/>
+ </GlyphOrder>
+
+ <head>
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x640cdb2f"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Fri Mar 17 07:26:00 2017"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="7"/>
+ <fontDirectionHint value="2"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="1.0"/>
+ <ascent value="1000"/>
+ <descent value="-200"/>
+ <lineGap value="0"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ </hhea>
+
+ <maxp>
+ <tableVersion value="0x10000"/>
+ <maxZones value="0"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="0"/>
+ <maxSizeOfInstructions value="0"/>
+ <maxComponentElements value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="594"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00001000"/>
+ <ySubscriptXSize value="650"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="650"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="350"/>
+ <yStrikeoutSize value="50"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="5"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="UKWN"/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="32"/>
+ <usLastCharIndex value="122"/>
+ <sTypoAscender value="800"/>
+ <sTypoDescender value="-200"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="200"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="700"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="93"/>
+ <mtx name="1em" width="1000" lsb="93"/>
+ <mtx name="3em" width="3000" lsb="93"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="3" platEncID="10" language="0">
+ <map code="0x0061" name="1em" />
+ <map code="0x0062" name="1em" />
+ <map code="0x0063" name="3em" />
+ <map code="0x0064" name="1em" />
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+ <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+ <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+ <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+ </glyf>
+
+ <name>
+ <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+ Copyright (C) 2017 The Android Open Source Project
+ </namerecord>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ SampleFont-Regular
+ </namerecord>
+ <namerecord nameID="10" platformID="3" platEncID="1" langID="0x409">
+ Source code is available at platform/frameworks/support/compat/tests/assets/fonts/large_c.ttx.
+ </namerecord>
+ <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ </namerecord>
+ <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+ http://www.apache.org/licenses/LICENSE-2.0
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-75"/>
+ <underlineThickness value="50"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+</ttFont>
diff --git a/compat/tests/assets/fonts/large_d.ttf b/compat/tests/assets/fonts/large_d.ttf
new file mode 100644
index 0000000..b791100
--- /dev/null
+++ b/compat/tests/assets/fonts/large_d.ttf
Binary files differ
diff --git a/compat/tests/assets/fonts/large_d.ttx b/compat/tests/assets/fonts/large_d.ttx
new file mode 100644
index 0000000..12f668c
--- /dev/null
+++ b/compat/tests/assets/fonts/large_d.ttx
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+ <GlyphOrder>
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="1em"/>
+ <GlyphID id="2" name="3em"/>
+ </GlyphOrder>
+
+ <head>
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x640cdb2f"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Fri Mar 17 07:26:00 2017"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="7"/>
+ <fontDirectionHint value="2"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="1.0"/>
+ <ascent value="1000"/>
+ <descent value="-200"/>
+ <lineGap value="0"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ </hhea>
+
+ <maxp>
+ <tableVersion value="0x10000"/>
+ <maxZones value="0"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="0"/>
+ <maxSizeOfInstructions value="0"/>
+ <maxComponentElements value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="594"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00001000"/>
+ <ySubscriptXSize value="650"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="650"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="350"/>
+ <yStrikeoutSize value="50"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="5"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="UKWN"/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="32"/>
+ <usLastCharIndex value="122"/>
+ <sTypoAscender value="800"/>
+ <sTypoDescender value="-200"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="200"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="700"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="93"/>
+ <mtx name="1em" width="1000" lsb="93"/>
+ <mtx name="3em" width="3000" lsb="93"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="3" platEncID="10" language="0">
+ <map code="0x0061" name="1em" />
+ <map code="0x0062" name="1em" />
+ <map code="0x0063" name="1em" />
+ <map code="0x0064" name="3em" />
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+ <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+ <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+ <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+ </glyf>
+
+ <name>
+ <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+ Copyright (C) 2017 The Android Open Source Project
+ </namerecord>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ SampleFont-Regular
+ </namerecord>
+ <namerecord nameID="10" platformID="3" platEncID="1" langID="0x409">
+ Source code is available at platform/frameworks/support/compat/tests/assets/fonts/large_d.ttx.
+ </namerecord>
+ <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ </namerecord>
+ <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+ http://www.apache.org/licenses/LICENSE-2.0
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-75"/>
+ <underlineThickness value="50"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+</ttFont>
diff --git a/compat/tests/assets/fonts/samplefont.ttf b/compat/tests/assets/fonts/samplefont.ttf
new file mode 100644
index 0000000..5fccad2
--- /dev/null
+++ b/compat/tests/assets/fonts/samplefont.ttf
Binary files differ
diff --git a/compat/tests/assets/fonts/samplefont.ttx b/compat/tests/assets/fonts/samplefont.ttx
new file mode 100644
index 0000000..f618123
--- /dev/null
+++ b/compat/tests/assets/fonts/samplefont.ttx
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+ <GlyphOrder>
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="a"/>
+ </GlyphOrder>
+
+ <head>
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x640cdb2f"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Fri Mar 17 07:26:00 2017"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="7"/>
+ <fontDirectionHint value="2"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="1.0"/>
+ <ascent value="1000"/>
+ <descent value="-200"/>
+ <lineGap value="0"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ </hhea>
+
+ <maxp>
+ <tableVersion value="0x10000"/>
+ <maxZones value="0"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="0"/>
+ <maxSizeOfInstructions value="0"/>
+ <maxComponentElements value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="594"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00001000"/>
+ <ySubscriptXSize value="650"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="650"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="350"/>
+ <yStrikeoutSize value="50"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="5"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="UKWN"/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="32"/>
+ <usLastCharIndex value="122"/>
+ <sTypoAscender value="800"/>
+ <sTypoDescender value="-200"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="200"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="700"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="0"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="500" lsb="93"/>
+ <mtx name="a" width="500" lsb="93"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="3" platEncID="10" language="0">
+ <map code="0x0061" name="a" />
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+ <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+ <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0" />
+ </glyf>
+
+ <name>
+ <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+ Copyright (C) 2017 The Android Open Source Project
+ </namerecord>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Sample Font
+ </namerecord>
+ <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+ SampleFont-Regular
+ </namerecord>
+ <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ </namerecord>
+ <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+ http://www.apache.org/licenses/LICENSE-2.0
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-75"/>
+ <underlineThickness value="50"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+</ttFont>
diff --git a/compat/tests/assets/fonts/samplefont1.ttf b/compat/tests/assets/fonts/samplefont1.ttf
deleted file mode 100644
index 020436a..0000000
--- a/compat/tests/assets/fonts/samplefont1.ttf
+++ /dev/null
Binary files differ
diff --git a/compat/tests/fonts_readme.txt b/compat/tests/fonts_readme.txt
new file mode 100644
index 0000000..f0de576
--- /dev/null
+++ b/compat/tests/fonts_readme.txt
@@ -0,0 +1,15 @@
+All fonts included in this project follow the below copyright and licensing:
+
+Copyright (C) 2017 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java b/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java
new file mode 100644
index 0000000..a2f2c7c
--- /dev/null
+++ b/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.graphics;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.content.res.Resources;
+import android.graphics.Paint;
+import android.graphics.Typeface;
+import android.support.compat.test.R;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SdkSuppress;
+import android.support.test.filters.SmallTest;
+import android.support.testutils.PollingCheck;
+import android.support.v4.content.res.FontResourcesParserCompat;
+import android.support.v4.content.res.FontResourcesParserCompat.FamilyResourceEntry;
+import android.support.v4.content.res.FontResourcesParserCompat.ProviderResourceEntry;
+import android.support.v4.provider.FontRequest;
+import android.support.v4.provider.MockFontProvider;
+import android.widget.TextView;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+@SdkSuppress(maxSdkVersion = 25) // on API 26, use platform implementation.
+@SmallTest
+public class TypefaceCompatTest {
+ private static final String AUTHORITY = "android.provider.fonts.font";
+ private static final String PACKAGE = "android.support.compat.test";
+
+ public Context mContext;
+ public Resources mResources;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mResources = mContext.getResources();
+ MockFontProvider.prepareFontFiles(mContext);
+ }
+
+ @After
+ public void tearDown() {
+ MockFontProvider.cleanUpFontFiles(mContext);
+ }
+
+ // Signature to be used for authentication to access content provider.
+ // In this test case, the content provider and consumer live in the same package, self package's
+ // signature works.
+ private static final List<List<byte[]>> SIGNATURE;
+ static {
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ try {
+ PackageManager manager = context.getPackageManager();
+ PackageInfo info = manager.getPackageInfo(
+ context.getPackageName(), PackageManager.GET_SIGNATURES);
+ ArrayList<byte[]> out = new ArrayList<>();
+ for (Signature sig : info.signatures) {
+ out.add(sig.toByteArray());
+ }
+ SIGNATURE = new ArrayList<>();
+ SIGNATURE.add(out);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Helper method to get the used font resource id by typeface.
+ *
+ * If the typeface is created from one of the R.font.large_a, R.font.large_b, R.font.large_c or
+ * R.font.large_d resource, this method returns the resource id used by the typeface.
+ */
+ private static int getSelectedFontResourceId(Typeface typeface) {
+ // The glyph for "a" in R.font.large_a font has a 3em width and glyph for "b", "c" and "d"
+ // have 1em width. Similarly, The glyph for "b" in R.font.large_b font, the glyph for "c"
+ // in R.font.large_c font, the glyph for "d" in R.font.large_d font has 3em width and the
+ // glyph for the rest characters have 1em. Thus we can get the resource id of the source
+ // font file by comparing width of "a", "b", "c" and "d".
+ Paint p = new Paint();
+ p.setTypeface(typeface);
+ final int[] ids = { R.font.large_a, R.font.large_b, R.font.large_c, R.font.large_d };
+ final float[] widths = {
+ p.measureText("a"), p.measureText("b"), p.measureText("c"), p.measureText("d")
+ };
+
+ int maxIndex = Integer.MIN_VALUE;
+ float maxValue = Float.MIN_VALUE;
+ for (int i = 0; i < widths.length; ++i) {
+ if (maxValue < widths[i]) {
+ maxIndex = i;
+ maxValue = widths[i];
+ }
+ }
+ return ids[maxIndex];
+ }
+
+ /**
+ * Helper method to obtain ProviderResourceEntry with overwriting correct signatures.
+ */
+ private ProviderResourceEntry getProviderResourceEntry(int id) {
+ final ProviderResourceEntry entry;
+ try {
+ entry = (ProviderResourceEntry) FontResourcesParserCompat.parse(
+ mResources.getXml(id), mResources);
+ } catch (XmlPullParserException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ final FontRequest parsedRequest = entry.getRequest();
+ final FontRequest request = new FontRequest(parsedRequest.getProviderAuthority(),
+ parsedRequest.getProviderPackage(), parsedRequest.getQuery(), SIGNATURE);
+ return new ProviderResourceEntry(request, entry.getFetchStrategy(), entry.getTimeout());
+ }
+
+ @Test
+ public void testCreateFromResourcesFamilyXml_resourceFont_syncloading() throws Exception {
+ Typeface typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext,
+ getProviderResourceEntry(R.font.styletest_sync_providerfont), mResources,
+ R.font.styletest_sync_providerfont, Typeface.NORMAL, null /* TextView */);
+ typeface = Typeface.create(typeface, Typeface.NORMAL);
+ assertEquals(R.font.large_a, getSelectedFontResourceId(typeface));
+
+ typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext,
+ getProviderResourceEntry(R.font.styletest_sync_providerfont), mResources,
+ R.font.styletest_sync_providerfont, Typeface.ITALIC, null /* TextView */);
+ typeface = Typeface.create(typeface, Typeface.ITALIC);
+ assertEquals(R.font.large_b, getSelectedFontResourceId(typeface));
+
+ typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext,
+ getProviderResourceEntry(R.font.styletest_sync_providerfont), mResources,
+ R.font.styletest_sync_providerfont, Typeface.BOLD, null /* TextView */);
+ typeface = Typeface.create(typeface, Typeface.BOLD);
+ assertEquals(R.font.large_c, getSelectedFontResourceId(typeface));
+
+ typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext,
+ getProviderResourceEntry(R.font.styletest_sync_providerfont), mResources,
+ R.font.styletest_sync_providerfont, Typeface.BOLD_ITALIC, null /* TextView */);
+ typeface = Typeface.create(typeface, Typeface.BOLD_ITALIC);
+ assertEquals(R.font.large_d, getSelectedFontResourceId(typeface));
+ }
+
+ @Test
+ public void testCreateFromResourcesFamilyXml_resourceFont_asyncloading() throws Exception {
+ Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ final TextView textView = new TextView(mContext);
+ PollingCheck.PollingCheckCondition condition = new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return textView.getTypeface() != null;
+ }
+ };
+
+ textView.setTypeface(null);
+ inst.runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ TypefaceCompat.createFromResourcesFamilyXml(mContext,
+ getProviderResourceEntry(R.font.styletest_async_providerfont), mResources,
+ R.font.styletest_async_providerfont, Typeface.NORMAL, textView);
+ }
+ });
+ PollingCheck.waitFor(condition);
+ assertEquals(R.font.large_a, getSelectedFontResourceId(textView.getTypeface()));
+
+ textView.setTypeface(null);
+ inst.runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ TypefaceCompat.createFromResourcesFamilyXml(mContext,
+ getProviderResourceEntry(R.font.styletest_async_providerfont), mResources,
+ R.font.styletest_async_providerfont, Typeface.ITALIC, textView);
+ }
+ });
+ PollingCheck.waitFor(condition);
+ assertEquals(R.font.large_b, getSelectedFontResourceId(textView.getTypeface()));
+
+ textView.setTypeface(null);
+ inst.runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ TypefaceCompat.createFromResourcesFamilyXml(mContext,
+ getProviderResourceEntry(R.font.styletest_async_providerfont), mResources,
+ R.font.styletest_async_providerfont, Typeface.BOLD, textView);
+ }
+ });
+ PollingCheck.waitFor(condition);
+ assertEquals(R.font.large_c, getSelectedFontResourceId(textView.getTypeface()));
+
+ textView.setTypeface(null);
+ inst.runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ TypefaceCompat.createFromResourcesFamilyXml(mContext,
+ getProviderResourceEntry(R.font.styletest_async_providerfont), mResources,
+ R.font.styletest_async_providerfont, Typeface.BOLD_ITALIC, textView);
+ }
+ });
+ PollingCheck.waitFor(condition);
+ assertEquals(R.font.large_d, getSelectedFontResourceId(textView.getTypeface()));
+ }
+
+ @Test
+ public void testCreateFromResourcesFamilyXml_resourceFont() throws Exception {
+ final FamilyResourceEntry entry = FontResourcesParserCompat.parse(
+ mResources.getXml(R.font.styletestfont), mResources);
+ Typeface typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry, mResources,
+ R.font.styletestfont, Typeface.NORMAL, null /* text view */);
+ assertEquals(typeface, TypefaceCompat.findFromCache(
+ mResources, R.font.styletestfont, Typeface.NORMAL));
+ typeface = Typeface.create(typeface, Typeface.NORMAL);
+ // styletestfont has a node of fontStyle="normal" fontWeight="400" font="@font/large_a".
+ assertEquals(R.font.large_a, getSelectedFontResourceId(typeface));
+
+ typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry, mResources,
+ R.font.styletestfont, Typeface.ITALIC, null);
+ assertEquals(typeface, TypefaceCompat.findFromCache(
+ mResources, R.font.styletestfont, Typeface.ITALIC));
+ typeface = Typeface.create(typeface, Typeface.ITALIC);
+ // styletestfont has a node of fontStyle="italic" fontWeight="400" font="@font/large_b".
+ assertEquals(R.font.large_b, getSelectedFontResourceId(typeface));
+
+ typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry, mResources,
+ R.font.styletestfont, Typeface.BOLD, null);
+ assertEquals(typeface, TypefaceCompat.findFromCache(
+ mResources, R.font.styletestfont, Typeface.BOLD));
+ typeface = Typeface.create(typeface, Typeface.BOLD);
+ // styletestfont has a node of fontStyle="normal" fontWeight="700" font="@font/large_c".
+ assertEquals(R.font.large_c, getSelectedFontResourceId(typeface));
+
+ typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry, mResources,
+ R.font.styletestfont, Typeface.BOLD_ITALIC, null);
+ assertEquals(typeface, TypefaceCompat.findFromCache(
+ mResources, R.font.styletestfont, Typeface.BOLD_ITALIC));
+ typeface = Typeface.create(typeface, Typeface.BOLD_ITALIC);
+ // styletestfont has a node of fontStyle="italic" fontWeight="700" font="@font/large_d".
+ assertEquals(R.font.large_d, getSelectedFontResourceId(typeface));
+ }
+
+ @Test
+ public void testCreateFromResourcesFontFile() {
+ Typeface typeface = TypefaceCompat.createFromResourcesFontFile(
+ mContext, mResources, R.font.large_a, Typeface.NORMAL);
+ assertEquals(typeface, TypefaceCompat.findFromCache(
+ mResources, R.font.large_a, Typeface.NORMAL));
+ assertEquals(R.font.large_a, getSelectedFontResourceId(typeface));
+
+ typeface = TypefaceCompat.createFromResourcesFontFile(
+ mContext, mResources, R.font.large_b, Typeface.NORMAL);
+ assertEquals(typeface, TypefaceCompat.findFromCache(
+ mResources, R.font.large_b, Typeface.NORMAL));
+ assertEquals(R.font.large_b, getSelectedFontResourceId(typeface));
+ }
+}
diff --git a/compat/tests/java/android/support/v4/provider/FontsContractCompatTest.java b/compat/tests/java/android/support/v4/provider/FontsContractCompatTest.java
index d63fe22..66bdd50 100644
--- a/compat/tests/java/android/support/v4/provider/FontsContractCompatTest.java
+++ b/compat/tests/java/android/support/v4/provider/FontsContractCompatTest.java
@@ -63,7 +63,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class FontsContractCompatTest {
- private static final String AUTHORITY = "android.provider.fonts.font";
+ private static final String AUTHORITY = "android.support.provider.fonts.font";
private static final String PACKAGE = "android.support.compat.test";
// Signature to be used for authentication to access content provider.
diff --git a/compat/tests/java/android/support/v4/provider/MockFontProvider.java b/compat/tests/java/android/support/v4/provider/MockFontProvider.java
index 9f4a8a1..f07d92d 100644
--- a/compat/tests/java/android/support/v4/provider/MockFontProvider.java
+++ b/compat/tests/java/android/support/v4/provider/MockFontProvider.java
@@ -41,9 +41,13 @@
*/
public class MockFontProvider extends ContentProvider {
static final String[] FONT_FILES = {
- "samplefont1.ttf",
+ "samplefont.ttf", "large_a.ttf", "large_b.ttf", "large_c.ttf", "large_d.ttf"
};
private static final int SAMPLE_FONT_FILE_0_ID = 0;
+ private static final int LARGE_A_FILE_ID = 1;
+ private static final int LARGE_B_FILE_ID = 2;
+ private static final int LARGE_C_FILE_ID = 3;
+ private static final int LARGE_D_FILE_ID = 4;
static final String SINGLE_FONT_FAMILY_QUERY = "singleFontFamily";
static final String SINGLE_FONT_FAMILY2_QUERY = "singleFontFamily2";
@@ -54,6 +58,7 @@
static final String NOT_FOUND_THIRD_QUERY = "notFoundThird";
static final String NEGATIVE_ERROR_CODE_QUERY = "negativeCode";
static final String MANDATORY_FIELDS_ONLY_QUERY = "mandatoryFields";
+ static final String STYLE_TEST_QUERY = "styleTest";
static class Font {
Font(int id, int fileId, int ttcIndex, String varSettings, int weight, int italic,
@@ -160,6 +165,17 @@
Columns.RESULT_CODE_OK, false),
});
+ map.put(STYLE_TEST_QUERY, new Font[] {
+ new Font(id++, LARGE_A_FILE_ID, 0, null, 400, 0 /* normal */,
+ Columns.RESULT_CODE_OK, true),
+ new Font(id++, LARGE_B_FILE_ID, 0, null, 400, 1 /* italic */,
+ Columns.RESULT_CODE_OK, true),
+ new Font(id++, LARGE_C_FILE_ID, 0, null, 700, 0 /* normal */,
+ Columns.RESULT_CODE_OK, true),
+ new Font(id++, LARGE_D_FILE_ID, 0, null, 700, 1 /* italic */,
+ Columns.RESULT_CODE_OK, true),
+ });
+
QUERY_MAP = Collections.unmodifiableMap(map);
}
@@ -188,7 +204,15 @@
InputStream is = null;
try {
is = mgr.open("fonts/" + file);
- copy(is, getCopiedFile(context, file));
+ File copied = getCopiedFile(context, file);
+ File parent = copied.getParentFile();
+ if (!parent.isDirectory()) {
+ parent.mkdirs();
+ parent.setReadable(true, false);
+ parent.setExecutable(true, false);
+ }
+ copy(is, copied);
+ copied.setReadable(true, false);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
@@ -229,7 +253,8 @@
}
public static File getCopiedFile(Context context, String path) {
- return new File(context.getFilesDir(), path);
+ final File cacheDir = new File(context.getFilesDir(), "fontCache");
+ return new File(cacheDir, path);
}
@Override
diff --git a/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java b/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java
index 51bb7d0..d79c789 100644
--- a/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java
+++ b/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java
@@ -245,12 +245,21 @@
assertTrue(LinkifyCompat.addLinks(spannable, Linkify.ALL));
URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
assertEquals(3, spans.length);
- assertEquals("tel:8005551233", spans[0].getURL());
- assertEquals("mailto:800-555-1211@gmail.com", spans[1].getURL());
- assertEquals("http://800-555-1222.com", spans[2].getURL());
+ assertTrue(containsUrl(spans, "tel:8005551233"));
+ assertTrue(containsUrl(spans, "mailto:800-555-1211@gmail.com"));
+ assertTrue(containsUrl(spans, "http://800-555-1222.com"));
}
}
+ private boolean containsUrl(URLSpan[] spans, String expectedValue) {
+ for (URLSpan span : spans) {
+ if (span.getURL().equals(expectedValue)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Test
public void testAddLinks_addsLinksWhenDefaultSchemeIsNull() {
Spannable spannable = new SpannableString("any https://android.com any android.com any");
diff --git a/compat/tests/res/font/dummyproviderfont.xml b/compat/tests/res/font/dummyproviderfont.xml
new file mode 100644
index 0000000..b0b41c3
--- /dev/null
+++ b/compat/tests/res/font/dummyproviderfont.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:fontProviderAuthority="android.provider.fonts.font"
+ android:fontProviderPackage="android.support.compat.test"
+ android:fontProviderQuery="styleTest"
+ app:fontProviderAuthority="android.provider.fonts.font"
+ app:fontProviderPackage="android.support.compat.test"
+ app:fontProviderQuery="styleTest" >
+</font-family>
diff --git a/compat/tests/res/font/large_a.ttf b/compat/tests/res/font/large_a.ttf
new file mode 100644
index 0000000..0e778b6
--- /dev/null
+++ b/compat/tests/res/font/large_a.ttf
Binary files differ
diff --git a/compat/tests/res/font/large_b.ttf b/compat/tests/res/font/large_b.ttf
new file mode 100644
index 0000000..b8ce6ce
--- /dev/null
+++ b/compat/tests/res/font/large_b.ttf
Binary files differ
diff --git a/compat/tests/res/font/large_c.ttf b/compat/tests/res/font/large_c.ttf
new file mode 100644
index 0000000..dd5fa50
--- /dev/null
+++ b/compat/tests/res/font/large_c.ttf
Binary files differ
diff --git a/compat/tests/res/font/large_d.ttf b/compat/tests/res/font/large_d.ttf
new file mode 100644
index 0000000..b791100
--- /dev/null
+++ b/compat/tests/res/font/large_d.ttf
Binary files differ
diff --git a/compat/tests/res/font/samplefont.ttf b/compat/tests/res/font/samplefont.ttf
index 2852302..5fccad2 100644
--- a/compat/tests/res/font/samplefont.ttf
+++ b/compat/tests/res/font/samplefont.ttf
Binary files differ
diff --git a/compat/tests/res/font/samplefont2.ttf b/compat/tests/res/font/samplefont2.ttf
index 2852302..f31b8a9 100644
--- a/compat/tests/res/font/samplefont2.ttf
+++ b/compat/tests/res/font/samplefont2.ttf
Binary files differ
diff --git a/compat/tests/res/font/samplefont3.ttf b/compat/tests/res/font/samplefont3.ttf
index 2852302..9c850ab 100644
--- a/compat/tests/res/font/samplefont3.ttf
+++ b/compat/tests/res/font/samplefont3.ttf
Binary files differ
diff --git a/compat/tests/res/font/samplefont4.ttf b/compat/tests/res/font/samplefont4.ttf
index 2852302..9c850ab 100644
--- a/compat/tests/res/font/samplefont4.ttf
+++ b/compat/tests/res/font/samplefont4.ttf
Binary files differ
diff --git a/compat/tests/res/font/styletest_async_providerfont.xml b/compat/tests/res/font/styletest_async_providerfont.xml
new file mode 100644
index 0000000..8d934cb
--- /dev/null
+++ b/compat/tests/res/font/styletest_async_providerfont.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:fontProviderAuthority="android.support.provider.fonts.font"
+ android:fontProviderPackage="android.support.compat.test"
+ android:fontProviderQuery="styleTest"
+ app:fontProviderAuthority="android.support.provider.fonts.font"
+ app:fontProviderPackage="android.support.compat.test"
+ app:fontProviderQuery="styleTest"
+ app:fontProviderFetchStrategy="async">
+</font-family>
diff --git a/compat/tests/res/font/styletest_sync_providerfont.xml b/compat/tests/res/font/styletest_sync_providerfont.xml
new file mode 100644
index 0000000..4e9c7d6
--- /dev/null
+++ b/compat/tests/res/font/styletest_sync_providerfont.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:fontProviderAuthority="android.support.provider.fonts.font"
+ android:fontProviderPackage="android.support.compat.test"
+ android:fontProviderQuery="styleTest"
+ app:fontProviderAuthority="android.support.provider.fonts.font"
+ app:fontProviderPackage="android.support.compat.test"
+ app:fontProviderQuery="styleTest"
+ app:fontProviderFetchStrategy="blocking"
+ app:fontProviderFetchTimeout="forever">
+</font-family>
diff --git a/compat/tests/res/font/styletestfont.xml b/compat/tests/res/font/styletestfont.xml
new file mode 100644
index 0000000..f1326d5
--- /dev/null
+++ b/compat/tests/res/font/styletestfont.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <font app:fontStyle="normal" app:fontWeight="400" app:font="@font/large_a"
+ android:fontStyle="normal" android:fontWeight="400" android:font="@font/large_a" />
+ <font app:fontStyle="italic" app:fontWeight="400" app:font="@font/large_b"
+ android:fontStyle="italic" android:fontWeight="400" android:font="@font/large_b" />
+ <font app:fontStyle="normal" app:fontWeight="700" app:font="@font/large_c"
+ android:fontStyle="normal" android:fontWeight="700" android:font="@font/large_c" />
+ <font app:fontStyle="italic" app:fontWeight="700" app:font="@font/large_d"
+ android:fontStyle="italic" android:fontWeight="700" android:font="@font/large_d" />
+</font-family>
diff --git a/core-ui/ics/android/support/v4/app/ActionBarDrawerToggleIcs.java b/core-ui/ics/android/support/v4/app/ActionBarDrawerToggleIcs.java
index 7826f86..a332b8a 100644
--- a/core-ui/ics/android/support/v4/app/ActionBarDrawerToggleIcs.java
+++ b/core-ui/ics/android/support/v4/app/ActionBarDrawerToggleIcs.java
@@ -39,7 +39,7 @@
*/
@RequiresApi(14)
class ActionBarDrawerToggleIcs {
- private static final String TAG = "ActionBarDrawerToggleHoneycomb";
+ private static final String TAG = "ActionBarDrawerToggle";
private static final int[] THEME_ATTRS = new int[] {
R.attr.homeAsUpIndicator
diff --git a/core-ui/java/android/support/v4/widget/ExploreByTouchHelper.java b/core-ui/java/android/support/v4/widget/ExploreByTouchHelper.java
index 7ca0054..8a29eff 100644
--- a/core-ui/java/android/support/v4/widget/ExploreByTouchHelper.java
+++ b/core-ui/java/android/support/v4/widget/ExploreByTouchHelper.java
@@ -28,7 +28,6 @@
import android.support.v4.view.ViewCompat.FocusRealDirection;
import android.support.v4.view.ViewParentCompat;
import android.support.v4.view.accessibility.AccessibilityEventCompat;
-import android.support.v4.view.accessibility.AccessibilityManagerCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
import android.support.v4.view.accessibility.AccessibilityRecordCompat;
@@ -177,8 +176,7 @@
* @return Whether the hover event was handled.
*/
public final boolean dispatchHoverEvent(@NonNull MotionEvent event) {
- if (!mManager.isEnabled()
- || !AccessibilityManagerCompat.isTouchExplorationEnabled(mManager)) {
+ if (!mManager.isEnabled() || !mManager.isTouchExplorationEnabled()) {
return false;
}
@@ -650,7 +648,7 @@
*/
private AccessibilityEvent createEventForHost(int eventType) {
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
- ViewCompat.onInitializeAccessibilityEvent(mHost, event);
+ mHost.onInitializeAccessibilityEvent(event);
return event;
}
@@ -877,11 +875,13 @@
if (mHost.getLocalVisibleRect(mTempVisibleRect)) {
mTempVisibleRect.offset(mTempGlobalRect[0] - mHost.getScrollX(),
mTempGlobalRect[1] - mHost.getScrollY());
- mTempScreenRect.intersect(mTempVisibleRect);
- node.setBoundsInScreen(mTempScreenRect);
+ final boolean intersects = mTempScreenRect.intersect(mTempVisibleRect);
+ if (intersects) {
+ node.setBoundsInScreen(mTempScreenRect);
- if (isVisibleToUser(mTempScreenRect)) {
- node.setVisibleToUser(true);
+ if (isVisibleToUser(mTempScreenRect)) {
+ node.setVisibleToUser(true);
+ }
}
}
@@ -939,7 +939,7 @@
ViewParent viewParent = mHost.getParent();
while (viewParent instanceof View) {
final View view = (View) viewParent;
- if ((ViewCompat.getAlpha(view) <= 0) || (view.getVisibility() != View.VISIBLE)) {
+ if ((view.getAlpha() <= 0) || (view.getVisibility() != View.VISIBLE)) {
return false;
}
viewParent = view.getParent();
@@ -962,8 +962,7 @@
* @return whether this virtual view actually took accessibility focus
*/
private boolean requestAccessibilityFocus(int virtualViewId) {
- if (!mManager.isEnabled()
- || !AccessibilityManagerCompat.isTouchExplorationEnabled(mManager)) {
+ if (!mManager.isEnabled() || !mManager.isTouchExplorationEnabled()) {
return false;
}
// TODO: Check virtual view visibility.
diff --git a/core-ui/java/android/support/v4/widget/Space.java b/core-ui/java/android/support/v4/widget/Space.java
index 4857479..77a2d2e 100644
--- a/core-ui/java/android/support/v4/widget/Space.java
+++ b/core-ui/java/android/support/v4/widget/Space.java
@@ -16,6 +16,7 @@
package android.support.v4.widget;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
@@ -48,6 +49,7 @@
* @param canvas an unused parameter.
*/
@Override
+ @SuppressLint("MissingSuperCall")
public void draw(Canvas canvas) {
}
diff --git a/core-ui/java/android/support/v4/widget/SwipeRefreshLayout.java b/core-ui/java/android/support/v4/widget/SwipeRefreshLayout.java
index 983683f..25231aa 100644
--- a/core-ui/java/android/support/v4/widget/SwipeRefreshLayout.java
+++ b/core-ui/java/android/support/v4/widget/SwipeRefreshLayout.java
@@ -527,7 +527,7 @@
* @deprecated Use {@link #setColorSchemeResources(int...)}
*/
@Deprecated
- public void setColorScheme(@ColorInt int... colors) {
+ public void setColorScheme(@ColorRes int... colors) {
setColorSchemeResources(colors);
}
diff --git a/core-ui/tests/java/android/support/v4/view/BaseViewPagerTest.java b/core-ui/tests/java/android/support/v4/view/BaseViewPagerTest.java
index 1544e76..855d01d 100644
--- a/core-ui/tests/java/android/support/v4/view/BaseViewPagerTest.java
+++ b/core-ui/tests/java/android/support/v4/view/BaseViewPagerTest.java
@@ -1076,7 +1076,7 @@
}
@Test
- @MediumTest
+ @LargeTest
public void testKeyboardNavigation() {
ButtonPagerAdapter adapter = new ButtonPagerAdapter();
adapter.add("Red", Color.RED);
diff --git a/design/src/android/support/design/widget/AppBarLayout.java b/design/src/android/support/design/widget/AppBarLayout.java
index 89fcf7c..d0e7027 100644
--- a/design/src/android/support/design/widget/AppBarLayout.java
+++ b/design/src/android/support/design/widget/AppBarLayout.java
@@ -34,7 +34,6 @@
import android.support.annotation.VisibleForTesting;
import android.support.design.R;
import android.support.v4.math.MathUtils;
-import android.support.v4.os.BuildCompat;
import android.support.v4.view.AbsSavedState;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.WindowInsetsCompat;
@@ -179,7 +178,7 @@
ViewUtilsLollipop.setDefaultAppBarLayoutStateListAnimator(
this, a.getDimensionPixelSize(R.styleable.AppBarLayout_elevation, 0));
}
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
// In O+, we have these values set in the style. Since there is no defStyleAttr for
// AppBarLayout at the AppCompat level, check for these attributes here.
if (a.hasValue(R.styleable.AppBarLayout_android_keyboardNavigationCluster)) {
diff --git a/development/refaster/IsAtLeastO.java b/development/refaster/IsAtLeastO.java
new file mode 100644
index 0000000..9198441
--- /dev/null
+++ b/development/refaster/IsAtLeastO.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import android.os.Build.VERSION;
+import android.support.v4.os.BuildCompat;
+
+import com.google.errorprone.refaster.annotation.AfterTemplate;
+import com.google.errorprone.refaster.annotation.AlsoNegation;
+import com.google.errorprone.refaster.annotation.BeforeTemplate;
+
+/**
+ * Replace usages of BuildCompat.isAtLeastO() with SDK_INT check.
+ */
+public class IsAtLeastO {
+ @BeforeTemplate
+ boolean usingAtLeastO() {
+ return BuildCompat.isAtLeastO();
+ }
+
+ @AfterTemplate
+ @AlsoNegation
+ boolean optimizedMethod() {
+ return VERSION.SDK_INT >= 26;
+ }
+}
diff --git a/development/refaster/README b/development/refaster/README
new file mode 100644
index 0000000..daf8f0d
--- /dev/null
+++ b/development/refaster/README
@@ -0,0 +1,25 @@
+Author: aurimas@google.com
+Updated: 6/6/2017
+
+Instructions on how to compile and apply refaster rules to support library
+
+0. Download error-prone and refaster jars
+http://errorprone.info/docs/refaster will have up to date instructions
+
+1. Compile the refaster rule (in this example IsAtLeastO.java)
+java -cp /path/to/android.jar:/path/to/support-compat.jar:javac-9-dev-r3297-4.jar:error_prone_refaster-2.0.18.jar com.google.errorprone.refaster.RefasterRuleCompiler IsAtLeastO.java --out `pwd`/myrule.refaster
+
+2. Update build to use the refaster rule
+Add compiler args to error-prone in SupportLibraryPlugin.groovy
+'-XepPatchChecks:refaster:/path/to/refaster/myrule.refaster',
+'-XepPatchLocation:' + project.projectDir
+
+3. Compile support library using the refaster rule
+./gradlew assembleErrorProne
+
+4. Apply patches
+error-prone will produce patch files like "design/error-prone.patch" and to apply them, cd into the
+directory e.g. "design" and then run:
+patch -p0 -u -i error-prone.patch
+
+5. Rules have been applied! Celebrate!
\ No newline at end of file
diff --git a/droiddoc.mk b/droiddoc.mk
index 4bd194a..0913f5f 100644
--- a/droiddoc.mk
+++ b/droiddoc.mk
@@ -36,4 +36,7 @@
-since $(SUPPORT_PATH)/api/25.1.0.txt 25.1.0 \
-since $(SUPPORT_PATH)/api/25.2.0.txt 25.2.0 \
-since $(SUPPORT_PATH)/api/25.3.0.txt 25.3.0 \
- -since $(SUPPORT_PATH)/api/26.0.0-alpha1.txt 26.0.0-alpha1
+ -since $(SUPPORT_PATH)/api/25.4.0.txt 25.4.0 \
+ -since $(SUPPORT_PATH)/api/26.0.0-alpha1.txt 26.0.0-alpha1 \
+ -since $(SUPPORT_PATH)/api/26.0.0-beta1.txt 26.0.0-beta1 \
+ -since $(SUPPORT_PATH)/api/26.0.0-beta2.txt 26.0.0-beta2
diff --git a/emoji/bundled/src/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java b/emoji/bundled/src/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java
index 37fc444..97ea363 100644
--- a/emoji/bundled/src/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java
+++ b/emoji/bundled/src/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java
@@ -43,7 +43,7 @@
super(new BundledMetadataLoader(context));
}
- private static class BundledMetadataLoader implements EmojiCompat.MetadataLoader {
+ private static class BundledMetadataLoader implements EmojiCompat.MetadataRepoLoader {
private final Context mContext;
private BundledMetadataLoader(@NonNull Context context) {
@@ -52,7 +52,7 @@
@Override
@RequiresApi(19)
- public void load(@NonNull EmojiCompat.LoaderCallback loaderCallback) {
+ public void load(@NonNull EmojiCompat.MetadataRepoLoaderCallback loaderCallback) {
Preconditions.checkNotNull(loaderCallback, "loaderCallback cannot be null");
final InitRunnable runnable = new InitRunnable(mContext, loaderCallback);
final Thread thread = new Thread(runnable);
@@ -64,11 +64,11 @@
@RequiresApi(19)
private static class InitRunnable implements Runnable {
private static final String FONT_NAME = "NotoColorEmojiCompat.ttf";
- private final EmojiCompat.LoaderCallback mLoaderCallback;
+ private final EmojiCompat.MetadataRepoLoaderCallback mLoaderCallback;
private final Context mContext;
private InitRunnable(final Context context,
- final EmojiCompat.LoaderCallback loaderCallback) {
+ final EmojiCompat.MetadataRepoLoaderCallback loaderCallback) {
mContext = context;
mLoaderCallback = loaderCallback;
}
diff --git a/emoji/core/src/android/support/text/emoji/EmojiCompat.java b/emoji/core/src/android/support/text/emoji/EmojiCompat.java
index b5db6f6..26efbba 100644
--- a/emoji/core/src/android/support/text/emoji/EmojiCompat.java
+++ b/emoji/core/src/android/support/text/emoji/EmojiCompat.java
@@ -22,6 +22,7 @@
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.AnyThread;
+import android.support.annotation.CheckResult;
import android.support.annotation.ColorInt;
import android.support.annotation.GuardedBy;
import android.support.annotation.IntDef;
@@ -101,19 +102,31 @@
/**
* EmojiCompat successfully initialized.
*/
+ public static final int LOAD_STATE_SUCCEEDED = 1;
+
+ /**
+ * @deprecated Use {@link #LOAD_STATE_SUCCEEDED} instead.
+ */
+ @Deprecated
public static final int LOAD_STATE_SUCCESS = 1;
/**
* An unrecoverable error occurred during initialization of EmojiCompat. Calls to functions
* such as {@link #process(CharSequence)} will fail.
*/
+ public static final int LOAD_STATE_FAILED = 2;
+
+ /**
+ * @deprecated Use {@link #LOAD_STATE_FAILED} instead.
+ */
+ @Deprecated
public static final int LOAD_STATE_FAILURE = 2;
/**
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
- @IntDef({LOAD_STATE_LOADING, LOAD_STATE_SUCCESS, LOAD_STATE_FAILURE})
+ @IntDef({LOAD_STATE_LOADING, LOAD_STATE_SUCCEEDED, LOAD_STATE_FAILED})
@Retention(RetentionPolicy.SOURCE)
public @interface LoadState {
}
@@ -167,9 +180,16 @@
private final CompatInternal mHelper;
/**
- * MetadataLoader instance given in the Config instance.
+ * Metadata loader instance given in the Config instance.
*/
- private final MetadataLoader mMetadataLoader;
+ private final MetadataRepoLoader mMetadataLoader;
+
+ /**
+ * Old metadata loader instance given in the Config instance.
+ * @deprecated Will be removed soon.
+ */
+ @Deprecated
+ private final MetadataLoader mLegacyMetadataLoader;
/**
* @see Config#setReplaceAll(boolean)
@@ -197,6 +217,7 @@
mEmojiSpanIndicatorEnabled = config.mEmojiSpanIndicatorEnabled;
mEmojiSpanIndicatorColor = config.mEmojiSpanIndicatorColor;
mMetadataLoader = config.mMetadataLoader;
+ mLegacyMetadataLoader = config.mLegacyMetadataLoader;
mMainHandler = new Handler(Looper.getMainLooper());
mInitCallbacks = new ArraySet<>();
if (config.mInitCallbacks != null && !config.mInitCallbacks.isEmpty()) {
@@ -209,8 +230,8 @@
/**
* Initialize the singleton instance with a configuration. When used on devices running API 18
- * or below, the singleton instance is immediately moved into {@link #LOAD_STATE_SUCCESS} state
- * without loading any metadata.
+ * or below, the singleton instance is immediately moved into {@link #LOAD_STATE_SUCCEEDED}
+ * state without loading any metadata.
*
* @see EmojiCompat.Config
*/
@@ -296,7 +317,7 @@
final Collection<InitCallback> initCallbacks = new ArrayList<>();
mInitLock.writeLock().lock();
try {
- mLoadState = LOAD_STATE_SUCCESS;
+ mLoadState = LOAD_STATE_SUCCEEDED;
initCallbacks.addAll(mInitCallbacks);
mInitCallbacks.clear();
} finally {
@@ -310,7 +331,7 @@
final Collection<InitCallback> initCallbacks = new ArrayList<>();
mInitLock.writeLock().lock();
try {
- mLoadState = LOAD_STATE_FAILURE;
+ mLoadState = LOAD_STATE_FAILED;
initCallbacks.addAll(mInitCallbacks);
mInitCallbacks.clear();
} finally {
@@ -337,7 +358,7 @@
mInitLock.writeLock().lock();
try {
- if (mLoadState == LOAD_STATE_SUCCESS || mLoadState == LOAD_STATE_FAILURE) {
+ if (mLoadState == LOAD_STATE_SUCCEEDED || mLoadState == LOAD_STATE_FAILED) {
mMainHandler.post(new ListenerDispatcher(initCallback, mLoadState));
} else {
mInitCallbacks.add(initCallback);
@@ -364,10 +385,10 @@
/**
* Returns loading state of the EmojiCompat instance. When used on devices running API 18 or
- * below always returns {@link #LOAD_STATE_SUCCESS}.
+ * below always returns {@link #LOAD_STATE_SUCCEEDED}.
*
- * @return one of {@link #LOAD_STATE_LOADING}, {@link #LOAD_STATE_SUCCESS},
- * {@link #LOAD_STATE_FAILURE}
+ * @return one of {@link #LOAD_STATE_LOADING}, {@link #LOAD_STATE_SUCCEEDED},
+ * {@link #LOAD_STATE_FAILED}
*/
public @LoadState int getLoadState() {
mInitLock.readLock().lock();
@@ -382,7 +403,7 @@
* @return {@code true} if EmojiCompat is successfully initialized
*/
private boolean isInitialized() {
- return getLoadState() == LOAD_STATE_SUCCESS;
+ return getLoadState() == LOAD_STATE_SUCCEEDED;
}
/**
@@ -507,6 +528,7 @@
* @throws IllegalStateException if not initialized yet
* @see #process(CharSequence, int, int)
*/
+ @CheckResult
public CharSequence process(@NonNull final CharSequence charSequence) {
// since charSequence might be null here we have to check it. Passing through here to the
// main function so that it can do all the checks including isInitialized. It will also
@@ -541,6 +563,7 @@
* {@code start > charSequence.length()},
* {@code end > charSequence.length()}
*/
+ @CheckResult
public CharSequence process(@NonNull final CharSequence charSequence,
@IntRange(from = 0) final int start, @IntRange(from = 0) final int end) {
return process(charSequence, start, end, EmojiProcessor.EMOJI_COUNT_UNLIMITED);
@@ -575,6 +598,7 @@
* {@code end > charSequence.length()}
* {@code maxEmojiCount < 0}
*/
+ @CheckResult
public CharSequence process(@NonNull final CharSequence charSequence,
@IntRange(from = 0) final int start, @IntRange(from = 0) final int end,
@IntRange(from = 0) final int maxEmojiCount) {
@@ -614,6 +638,7 @@
* {@code end > charSequence.length()}
* {@code maxEmojiCount < 0}
*/
+ @CheckResult
public CharSequence process(@NonNull final CharSequence charSequence,
@IntRange(from = 0) final int start, @IntRange(from = 0) final int end,
@IntRange(from = 0) final int maxEmojiCount, @ReplaceStrategy int replaceStrategy) {
@@ -716,6 +741,44 @@
/**
* Interface to load emoji metadata.
*/
+ public interface MetadataRepoLoader {
+ /**
+ * Start loading the metadata. When the loading operation is finished {@link
+ * MetadataRepoLoaderCallback#onLoaded(MetadataRepo)} or
+ * {@link MetadataRepoLoaderCallback#onFailed(Throwable)} should be called. When used on
+ * devices running API 18 or below, this function is never called.
+ *
+ * @param loaderCallback callback to signal the loading state
+ */
+ void load(@NonNull MetadataRepoLoaderCallback loaderCallback);
+ }
+
+ /**
+ * Callback to inform EmojiCompat about the state of the metadata load. Passed to
+ * MetadataRepoLoader during {@link MetadataRepoLoader#load(MetadataRepoLoaderCallback)} call.
+ */
+ public abstract static class MetadataRepoLoaderCallback {
+ /**
+ * Called by {@link MetadataRepoLoader} when metadata is loaded successfully.
+ *
+ * @param metadataRepo MetadataRepo instance, cannot be {@code null}
+ */
+ public abstract void onLoaded(@NonNull MetadataRepo metadataRepo);
+
+ /**
+ * Called by {@link MetadataRepoLoader} if an error occurs while loading the metadata.
+ *
+ * @param throwable the exception that caused the failure, {@code nullable}
+ */
+ public abstract void onFailed(@Nullable Throwable throwable);
+ }
+
+ /**
+ * Interface to load emoji metadata.
+ *
+ * @deprecated Use {@link MetadataRepoLoader} instead.
+ */
+ @Deprecated
public interface MetadataLoader {
/**
* Start loading the metadata. When the loading operation is finished {@link
@@ -731,7 +794,10 @@
/**
* Callback to inform EmojiCompat about the state of the metadata load. Passed to MetadataLoader
* during {@link MetadataLoader#load(LoaderCallback)} call.
+ *
+ * @deprecated Use {@link MetadataRepoLoaderCallback} instead.
*/
+ @Deprecated
public abstract static class LoaderCallback {
/**
* Called by {@link MetadataLoader} when metadata is loaded successfully.
@@ -755,7 +821,8 @@
* @see #init(EmojiCompat.Config)
*/
public abstract static class Config {
- private final MetadataLoader mMetadataLoader;
+ private final MetadataRepoLoader mMetadataLoader;
+ private final MetadataLoader mLegacyMetadataLoader;
private boolean mReplaceAll;
private Set<InitCallback> mInitCallbacks;
private boolean mEmojiSpanIndicatorEnabled;
@@ -764,11 +831,25 @@
/**
* Default constructor.
*
+ * @param metadataLoader MetadataRepoLoader instance, cannot be {@code null}
+ */
+ protected Config(@NonNull final MetadataRepoLoader metadataLoader) {
+ Preconditions.checkNotNull(metadataLoader, "metadataLoader cannot be null.");
+ mMetadataLoader = metadataLoader;
+ mLegacyMetadataLoader = null;
+ }
+
+ /**
+ * Default constructor.
+ *
* @param metadataLoader MetadataLoader instance, cannot be {@code null}
+ *
+ * @deprecated Use constructor with MetadataRepoLoader instead.
*/
protected Config(@NonNull final MetadataLoader metadataLoader) {
Preconditions.checkNotNull(metadataLoader, "metadataLoader cannot be null.");
- mMetadataLoader = metadataLoader;
+ mLegacyMetadataLoader = metadataLoader;
+ mMetadataLoader = null;
}
/**
@@ -843,11 +924,11 @@
}
/**
- * Returns the {@link MetadataLoader}.
+ * Returns the {@link MetadataRepoLoader}.
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
- public final MetadataLoader getMetadataLoader() {
+ public final MetadataRepoLoader getMetadataLoader() {
return mMetadataLoader;
}
}
@@ -884,12 +965,12 @@
public void run() {
final int size = mInitCallbacks.size();
switch (mLoadState) {
- case LOAD_STATE_SUCCESS:
+ case LOAD_STATE_SUCCEEDED:
for (int i = 0; i < size; i++) {
mInitCallbacks.get(i).onInitialized();
}
break;
- case LOAD_STATE_FAILURE:
+ case LOAD_STATE_FAILED:
default:
for (int i = 0; i < size; i++) {
mInitCallbacks.get(i).onFailed(mThrowable);
@@ -961,17 +1042,34 @@
@Override
void loadMetadata() {
try {
- mEmojiCompat.mMetadataLoader.load(new LoaderCallback() {
- @Override
- public void onLoaded(@NonNull MetadataRepo metadataRepo) {
- onMetadataLoadSuccess(metadataRepo);
- }
+ if (mEmojiCompat.mMetadataLoader != null) {
+ final MetadataRepoLoaderCallback callback = new MetadataRepoLoaderCallback() {
+ @Override
+ public void onLoaded(@NonNull MetadataRepo metadataRepo) {
+ onMetadataLoadSuccess(metadataRepo);
+ }
- @Override
- public void onFailed(@Nullable Throwable throwable) {
- mEmojiCompat.onMetadataLoadFailed(throwable);
- }
- });
+ @Override
+ public void onFailed(@Nullable Throwable throwable) {
+ mEmojiCompat.onMetadataLoadFailed(throwable);
+ }
+ };
+ mEmojiCompat.mMetadataLoader.load(callback);
+ } else {
+ final LoaderCallback callback = new LoaderCallback() {
+ @Override
+ public void onLoaded(@NonNull MetadataRepo metadataRepo) {
+ onMetadataLoadSuccess(metadataRepo);
+ }
+
+ @Override
+ public void onFailed(@Nullable Throwable throwable) {
+ mEmojiCompat.onMetadataLoadFailed(throwable);
+ }
+ };
+ mEmojiCompat.mLegacyMetadataLoader.load(callback);
+ }
+
} catch (Throwable t) {
mEmojiCompat.onMetadataLoadFailed(t);
}
diff --git a/emoji/core/src/android/support/text/emoji/FontRequestEmojiCompatConfig.java b/emoji/core/src/android/support/text/emoji/FontRequestEmojiCompatConfig.java
index ae7cd14..f5d7b82 100644
--- a/emoji/core/src/android/support/text/emoji/FontRequestEmojiCompatConfig.java
+++ b/emoji/core/src/android/support/text/emoji/FontRequestEmojiCompatConfig.java
@@ -20,17 +20,14 @@
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Typeface;
-import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.annotation.RestrictTo;
-import android.support.v4.graphics.TypefaceCompat;
import android.support.v4.provider.FontRequest;
import android.support.v4.provider.FontsContractCompat;
import android.support.v4.provider.FontsContractCompat.FontFamilyResult;
import android.support.v4.provider.FontsContractCompat.FontInfo;
-import android.support.v4.util.ArrayMap;
import android.support.v4.util.Preconditions;
import java.io.FileInputStream;
@@ -64,10 +61,10 @@
/**
- * MetadataLoader implementation that uses FontsContractCompat and TypefaceCompat to load a
+ * MetadataRepoLoader implementation that uses FontsContractCompat and TypefaceCompat to load a
* given FontRequest.
*/
- private static class FontRequestMetadataLoader implements EmojiCompat.MetadataLoader {
+ private static class FontRequestMetadataLoader implements EmojiCompat.MetadataRepoLoader {
private final Context mContext;
private final FontRequest mRequest;
private final FontsContractDelegate mFontsContract;
@@ -83,7 +80,7 @@
@Override
@RequiresApi(19)
- public void load(@NonNull final EmojiCompat.LoaderCallback loaderCallback) {
+ public void load(@NonNull final EmojiCompat.MetadataRepoLoaderCallback loaderCallback) {
Preconditions.checkNotNull(loaderCallback, "LoaderCallback cannot be null");
final InitRunnable runnable =
new InitRunnable(mContext, mRequest, mFontsContract, loaderCallback);
@@ -98,7 +95,7 @@
*/
@RequiresApi(19)
private static class InitRunnable implements Runnable {
- private final EmojiCompat.LoaderCallback mLoaderCallback;
+ private final EmojiCompat.MetadataRepoLoaderCallback mLoaderCallback;
private final Context mContext;
private final FontsContractDelegate mFontsContract;
private final FontRequest mFontRequest;
@@ -106,7 +103,7 @@
private InitRunnable(final Context context,
final FontRequest fontRequest,
final FontsContractDelegate fontsContract,
- final EmojiCompat.LoaderCallback loaderCallback) {
+ final EmojiCompat.MetadataRepoLoaderCallback loaderCallback) {
mContext = context;
mFontRequest = fontRequest;
mFontsContract = fontsContract;
@@ -145,12 +142,10 @@
throwException("Unable to open file.");
}
- // TypefaceCompat.buildTypeface opens file descriptor again, so bypass the
- // FontsContract.prepareFontData and create FontInfo and ByteBuffer directly.
- final ArrayMap<Uri, ByteBuffer> bufferMap = new ArrayMap<>();
- bufferMap.put(font.getUri(), buffer.duplicate());
- final Typeface typeface = TypefaceCompat.createTypeface(mContext,
- new FontInfo[] { font }, bufferMap);
+ // TODO(nona): Introduce public API to make Typeface from filedescriptor so that we
+ // can stop opening file descriptor twice.
+ final Typeface typeface = FontsContractCompat.buildTypeface(mContext,
+ null /* cancellation signal */, fonts);
if (typeface == null) {
throwException("Failed to create Typeface.");
}
diff --git a/emoji/core/src/android/support/text/emoji/widget/EditTextAttributeHelper.java b/emoji/core/src/android/support/text/emoji/widget/EditTextAttributeHelper.java
index 49cd7c8..3ee7546 100644
--- a/emoji/core/src/android/support/text/emoji/widget/EditTextAttributeHelper.java
+++ b/emoji/core/src/android/support/text/emoji/widget/EditTextAttributeHelper.java
@@ -33,7 +33,7 @@
*/
@RestrictTo(LIBRARY_GROUP)
public class EditTextAttributeHelper {
-
+ static final int MAX_EMOJI_COUNT = Integer.MAX_VALUE;
private int mMaxEmojiCount;
public EditTextAttributeHelper(@NonNull View view, AttributeSet attrs, int defStyleAttr) {
@@ -41,8 +41,7 @@
final Context context = view.getContext();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.EmojiEditText,
defStyleAttr, 0);
- mMaxEmojiCount = a.getInteger(R.styleable.EmojiEditText_maxEmojiCount,
- EmojiTextWatcher.MAX_EMOJI_COUNT);
+ mMaxEmojiCount = a.getInteger(R.styleable.EmojiEditText_maxEmojiCount, MAX_EMOJI_COUNT);
a.recycle();
}
}
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiInputFilter.java b/emoji/core/src/android/support/text/emoji/widget/EmojiInputFilter.java
index a1a6fc8..4dec230 100644
--- a/emoji/core/src/android/support/text/emoji/widget/EmojiInputFilter.java
+++ b/emoji/core/src/android/support/text/emoji/widget/EmojiInputFilter.java
@@ -58,7 +58,7 @@
switch (EmojiCompat.get().getLoadState()){
- case EmojiCompat.LOAD_STATE_SUCCESS:
+ case EmojiCompat.LOAD_STATE_SUCCEEDED:
boolean process = true;
if (destEnd == 0 && destStart == 0 && dest.length() == 0) {
final CharSequence oldText = mTextView.getText();
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiTextWatcher.java b/emoji/core/src/android/support/text/emoji/widget/EmojiTextWatcher.java
index d261c0c..8c224fe 100644
--- a/emoji/core/src/android/support/text/emoji/widget/EmojiTextWatcher.java
+++ b/emoji/core/src/android/support/text/emoji/widget/EmojiTextWatcher.java
@@ -37,10 +37,9 @@
@RestrictTo(LIBRARY_GROUP)
@RequiresApi(19)
final class EmojiTextWatcher implements android.text.TextWatcher {
- static final int MAX_EMOJI_COUNT = Integer.MAX_VALUE;
private final EditText mEditText;
private InitCallback mInitCallback;
- private int mMaxEmojiCount = MAX_EMOJI_COUNT;
+ private int mMaxEmojiCount = EditTextAttributeHelper.MAX_EMOJI_COUNT;
EmojiTextWatcher(EditText editText) {
mEditText = editText;
@@ -64,7 +63,7 @@
//before > after --> a deletion occured
if (before <= after && charSequence instanceof Spannable) {
switch (EmojiCompat.get().getLoadState()){
- case EmojiCompat.LOAD_STATE_SUCCESS:
+ case EmojiCompat.LOAD_STATE_SUCCEEDED:
final Spannable s = (Spannable) charSequence;
EmojiCompat.get().process(s, start, start + after, mMaxEmojiCount);
break;
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiTransformationMethod.java b/emoji/core/src/android/support/text/emoji/widget/EmojiTransformationMethod.java
index b7e7531..6e66462 100644
--- a/emoji/core/src/android/support/text/emoji/widget/EmojiTransformationMethod.java
+++ b/emoji/core/src/android/support/text/emoji/widget/EmojiTransformationMethod.java
@@ -52,7 +52,7 @@
if (source != null) {
switch (EmojiCompat.get().getLoadState()){
- case EmojiCompat.LOAD_STATE_SUCCESS:
+ case EmojiCompat.LOAD_STATE_SUCCEEDED:
return EmojiCompat.get().process(source);
}
}
diff --git a/emoji/core/tests/java/android/support/text/emoji/ConfigTest.java b/emoji/core/tests/java/android/support/text/emoji/ConfigTest.java
index 75692af..538ce99 100644
--- a/emoji/core/tests/java/android/support/text/emoji/ConfigTest.java
+++ b/emoji/core/tests/java/android/support/text/emoji/ConfigTest.java
@@ -102,9 +102,9 @@
public void testInitCallback_callsFailCallback() {
final EmojiCompat.InitCallback initCallback1 = mock(EmojiCompat.InitCallback.class);
final EmojiCompat.InitCallback initCallback2 = mock(EmojiCompat.InitCallback.class);
- final EmojiCompat.MetadataLoader loader = mock(EmojiCompat.MetadataLoader.class);
- doThrow(new RuntimeException("")).when(loader).load(any(EmojiCompat.LoaderCallback
- .class));
+ final EmojiCompat.MetadataRepoLoader loader = mock(EmojiCompat.MetadataRepoLoader.class);
+ doThrow(new RuntimeException("")).when(loader)
+ .load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
final EmojiCompat.Config config = new TestConfigBuilder.TestConfig(loader)
.registerInitCallback(initCallback1)
diff --git a/emoji/core/tests/java/android/support/text/emoji/EmojiCompatTest.java b/emoji/core/tests/java/android/support/text/emoji/EmojiCompatTest.java
index 29964ce..eb4ce2e 100644
--- a/emoji/core/tests/java/android/support/text/emoji/EmojiCompatTest.java
+++ b/emoji/core/tests/java/android/support/text/emoji/EmojiCompatTest.java
@@ -589,7 +589,7 @@
@Test
@SdkSuppress(maxSdkVersion = 18)
public void testGetLoadState_returnsSuccess_pre19() {
- assertEquals(EmojiCompat.get().getLoadState(), EmojiCompat.LOAD_STATE_SUCCESS);
+ assertEquals(EmojiCompat.get().getLoadState(), EmojiCompat.LOAD_STATE_SUCCEEDED);
}
@Test
@@ -605,7 +605,7 @@
metadataLoader.getTestLatch().await();
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
- assertEquals(EmojiCompat.get().getLoadState(), EmojiCompat.LOAD_STATE_SUCCESS);
+ assertEquals(EmojiCompat.get().getLoadState(), EmojiCompat.LOAD_STATE_SUCCEEDED);
}
@Test
@@ -621,7 +621,7 @@
metadataLoader.getTestLatch().await();
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
- assertEquals(EmojiCompat.get().getLoadState(), EmojiCompat.LOAD_STATE_FAILURE);
+ assertEquals(EmojiCompat.get().getLoadState(), EmojiCompat.LOAD_STATE_FAILED);
}
@Test
diff --git a/emoji/core/tests/java/android/support/text/emoji/FontRequestEmojiCompatConfigTest.java b/emoji/core/tests/java/android/support/text/emoji/FontRequestEmojiCompatConfigTest.java
index 72602c5..8201e96 100644
--- a/emoji/core/tests/java/android/support/text/emoji/FontRequestEmojiCompatConfigTest.java
+++ b/emoji/core/tests/java/android/support/text/emoji/FontRequestEmojiCompatConfigTest.java
@@ -203,7 +203,7 @@
assertThat(argumentCaptor.getValue().getMessage(), containsString(exceptionMessage));
}
- public static class WaitingLoaderCallback extends EmojiCompat.LoaderCallback {
+ public static class WaitingLoaderCallback extends EmojiCompat.MetadataRepoLoaderCallback {
final CountDownLatch mLatch;
public WaitingLoaderCallback() {
diff --git a/emoji/core/tests/java/android/support/text/emoji/InitCallbackTest.java b/emoji/core/tests/java/android/support/text/emoji/InitCallbackTest.java
index e11f4da..10abb01 100644
--- a/emoji/core/tests/java/android/support/text/emoji/InitCallbackTest.java
+++ b/emoji/core/tests/java/android/support/text/emoji/InitCallbackTest.java
@@ -57,9 +57,9 @@
public void testRegisterInitCallback_callsFailCallback() {
final EmojiCompat.InitCallback initCallback1 = mock(EmojiCompat.InitCallback.class);
final EmojiCompat.InitCallback initCallback2 = mock(EmojiCompat.InitCallback.class);
- final EmojiCompat.MetadataLoader loader = mock(EmojiCompat.MetadataLoader.class);
- doThrow(new RuntimeException("")).when(loader).load(any(EmojiCompat.LoaderCallback
- .class));
+ final EmojiCompat.MetadataRepoLoader loader = mock(EmojiCompat.MetadataRepoLoader.class);
+ doThrow(new RuntimeException("")).when(loader)
+ .load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
final EmojiCompat.Config config = new TestConfig(loader);
final EmojiCompat emojiCompat = EmojiCompat.reset(config);
@@ -76,9 +76,9 @@
@SdkSuppress(minSdkVersion = 19)
public void testRegisterInitCallback_callsFailCallback_whenOnFailCalledByLoader() {
final EmojiCompat.InitCallback initCallback = mock(EmojiCompat.InitCallback.class);
- final EmojiCompat.MetadataLoader loader = new EmojiCompat.MetadataLoader() {
+ final EmojiCompat.MetadataRepoLoader loader = new EmojiCompat.MetadataRepoLoader() {
@Override
- public void load(@NonNull EmojiCompat.LoaderCallback loaderCallback) {
+ public void load(@NonNull EmojiCompat.MetadataRepoLoaderCallback loaderCallback) {
loaderCallback.onFailed(new RuntimeException(""));
}
};
@@ -95,9 +95,9 @@
@SdkSuppress(minSdkVersion = 19)
public void testRegisterInitCallback_callsFailCallback_whenMetadataRepoIsNull() {
final EmojiCompat.InitCallback initCallback = mock(EmojiCompat.InitCallback.class);
- final EmojiCompat.MetadataLoader loader = new EmojiCompat.MetadataLoader() {
+ final EmojiCompat.MetadataRepoLoader loader = new EmojiCompat.MetadataRepoLoader() {
@Override
- public void load(@NonNull EmojiCompat.LoaderCallback loaderCallback) {
+ public void load(@NonNull EmojiCompat.MetadataRepoLoaderCallback loaderCallback) {
loaderCallback.onLoaded(null);
}
};
diff --git a/emoji/core/tests/java/android/support/text/emoji/TestConfigBuilder.java b/emoji/core/tests/java/android/support/text/emoji/TestConfigBuilder.java
index 202b2e4..242d62b 100644
--- a/emoji/core/tests/java/android/support/text/emoji/TestConfigBuilder.java
+++ b/emoji/core/tests/java/android/support/text/emoji/TestConfigBuilder.java
@@ -34,12 +34,12 @@
super(new TestEmojiDataLoader());
}
- TestConfig(final EmojiCompat.MetadataLoader metadataLoader) {
+ TestConfig(final EmojiCompat.MetadataRepoLoader metadataLoader) {
super(metadataLoader);
}
}
- public static class WaitingDataLoader implements EmojiCompat.MetadataLoader {
+ public static class WaitingDataLoader implements EmojiCompat.MetadataRepoLoader {
private final CountDownLatch mLoaderLatch;
private final CountDownLatch mTestLatch;
private final boolean mSuccess;
@@ -63,7 +63,7 @@
}
@Override
- public void load(@NonNull final EmojiCompat.LoaderCallback loaderCallback) {
+ public void load(@NonNull final EmojiCompat.MetadataRepoLoaderCallback loaderCallback) {
new Thread(new Runnable() {
@Override
public void run() {
@@ -84,7 +84,7 @@
}
}
- public static class TestEmojiDataLoader implements EmojiCompat.MetadataLoader {
+ public static class TestEmojiDataLoader implements EmojiCompat.MetadataRepoLoader {
static final Object sMetadataRepoLock = new Object();
// keep a static instance to in order not to slow down the tests
@GuardedBy("sMetadataRepoLock")
@@ -94,7 +94,7 @@
}
@Override
- public void load(@NonNull EmojiCompat.LoaderCallback loaderCallback) {
+ public void load(@NonNull EmojiCompat.MetadataRepoLoaderCallback loaderCallback) {
if (sMetadataRepo == null) {
synchronized (sMetadataRepoLock) {
if (sMetadataRepo == null) {
diff --git a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiInputFilterTest.java b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiInputFilterTest.java
index e9c9418..ca594cf 100644
--- a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiInputFilterTest.java
+++ b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiInputFilterTest.java
@@ -54,7 +54,7 @@
final TextView textView = mock(TextView.class);
mEmojiCompat = mock(EmojiCompat.class);
EmojiCompat.reset(mEmojiCompat);
- when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_SUCCESS);
+ when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_SUCCEEDED);
mInputFilter = new EmojiInputFilter(textView);
}
@@ -106,7 +106,7 @@
@Test
public void testFilter_whenEmojiCompatLoadFailed() {
final Spannable testString = new SpannableString("abc");
- when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_FAILURE);
+ when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_FAILED);
final CharSequence result = mInputFilter.filter(testString, 0, 1, null, 0, 1);
diff --git a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiTextWatcherTest.java b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiTextWatcherTest.java
index 6fc7347..728947c 100644
--- a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiTextWatcherTest.java
+++ b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiTextWatcherTest.java
@@ -55,7 +55,7 @@
@Test
public void testOnTextChanged_callsProcess() {
final Spannable testString = new SpannableString("abc");
- when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_SUCCESS);
+ when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_SUCCEEDED);
mTextWatcher.onTextChanged(testString, 0, 0, 1);
@@ -78,7 +78,7 @@
@Test
public void testOnTextChanged_whenEmojiCompatLoadFailed() {
final Spannable testString = new SpannableString("abc");
- when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_FAILURE);
+ when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_FAILED);
mTextWatcher.onTextChanged(testString, 0, 0, 1);
diff --git a/exifinterface/src/android/support/media/ExifInterface.java b/exifinterface/src/android/support/media/ExifInterface.java
index ec59c63..dac55bd 100644
--- a/exifinterface/src/android/support/media/ExifInterface.java
+++ b/exifinterface/src/android/support/media/ExifInterface.java
@@ -2603,9 +2603,9 @@
}
private void addDefaultValuesForCompatibility() {
- // The value of DATETIME tag has the same value of DATETIME_ORIGINAL tag.
+ // If DATETIME tag has no value, then set the value to DATETIME_ORIGINAL tag's.
String valueOfDateTimeOriginal = getAttribute(TAG_DATETIME_ORIGINAL);
- if (valueOfDateTimeOriginal != null) {
+ if (valueOfDateTimeOriginal != null && getAttribute(TAG_DATETIME) == null) {
mAttributes[IFD_TYPE_PRIMARY].put(TAG_DATETIME,
ExifAttribute.createString(valueOfDateTimeOriginal));
}
diff --git a/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java b/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
index ee9e38e..4af8a4a 100644
--- a/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
+++ b/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
@@ -82,7 +82,7 @@
ExifInterface.TAG_MAKE,
ExifInterface.TAG_MODEL,
ExifInterface.TAG_F_NUMBER,
- ExifInterface.TAG_DATETIME,
+ ExifInterface.TAG_DATETIME_ORIGINAL,
ExifInterface.TAG_EXPOSURE_TIME,
ExifInterface.TAG_FLASH,
ExifInterface.TAG_FOCAL_LENGTH,
@@ -118,7 +118,7 @@
public final String make;
public final String model;
public final float aperture;
- public final String datetime;
+ public final String dateTimeOriginal;
public final float exposureTime;
public final float flash;
public final String focalLength;
@@ -161,7 +161,7 @@
make = getString(typedArray, 7);
model = getString(typedArray, 8);
aperture = typedArray.getFloat(9, 0f);
- datetime = getString(typedArray, 10);
+ dateTimeOriginal = getString(typedArray, 10);
exposureTime = typedArray.getFloat(11, 0f);
flash = typedArray.getFloat(12, 0f);
focalLength = getString(typedArray, 13);
@@ -295,6 +295,33 @@
}
}
+ @Test
+ @SmallTest
+ public void testSetDateTime() throws IOException {
+ final String dateTimeValue = "2017:02:02 22:22:22";
+ final String dateTimeOriginalValue = "2017:01:01 11:11:11";
+
+ File imageFile = new File(
+ Environment.getExternalStorageDirectory(), EXIF_BYTE_ORDER_II_JPEG);
+ ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
+ exif.setAttribute(ExifInterface.TAG_DATETIME, dateTimeValue);
+ exif.setAttribute(ExifInterface.TAG_DATETIME_ORIGINAL, dateTimeOriginalValue);
+ exif.saveAttributes();
+
+ // Check that the DATETIME value is not overwritten by DATETIME_ORIGINAL's value.
+ exif = new ExifInterface(imageFile.getAbsolutePath());
+ assertEquals(dateTimeValue, exif.getAttribute(ExifInterface.TAG_DATETIME));
+ assertEquals(dateTimeOriginalValue, exif.getAttribute(ExifInterface.TAG_DATETIME_ORIGINAL));
+
+ // Now remove the DATETIME value.
+ exif.setAttribute(ExifInterface.TAG_DATETIME, null);
+ exif.saveAttributes();
+
+ // When the DATETIME has no value, then it should be set to DATETIME_ORIGINAL's value.
+ exif = new ExifInterface(imageFile.getAbsolutePath());
+ assertEquals(dateTimeOriginalValue, exif.getAttribute(ExifInterface.TAG_DATETIME));
+ }
+
private void printExifTagsAndValues(String fileName, ExifInterface exifInterface) {
// Prints thumbnail information.
if (exifInterface.hasThumbnail()) {
@@ -390,7 +417,8 @@
assertStringTag(exifInterface, ExifInterface.TAG_MAKE, expectedValue.make);
assertStringTag(exifInterface, ExifInterface.TAG_MODEL, expectedValue.model);
assertFloatTag(exifInterface, ExifInterface.TAG_F_NUMBER, expectedValue.aperture);
- assertStringTag(exifInterface, ExifInterface.TAG_DATETIME, expectedValue.datetime);
+ assertStringTag(exifInterface, ExifInterface.TAG_DATETIME_ORIGINAL,
+ expectedValue.dateTimeOriginal);
assertFloatTag(exifInterface, ExifInterface.TAG_EXPOSURE_TIME, expectedValue.exposureTime);
assertFloatTag(exifInterface, ExifInterface.TAG_FLASH, expectedValue.flash);
assertStringTag(exifInterface, ExifInterface.TAG_FOCAL_LENGTH, expectedValue.focalLength);
diff --git a/fragment/java/android/support/v4/app/FragmentManager.java b/fragment/java/android/support/v4/app/FragmentManager.java
index c49b69b..460d474 100644
--- a/fragment/java/android/support/v4/app/FragmentManager.java
+++ b/fragment/java/android/support/v4/app/FragmentManager.java
@@ -662,7 +662,8 @@
ArrayList<Integer> mAvailBackStackIndices;
ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
- private CopyOnWriteArrayList<Pair<FragmentLifecycleCallbacks, Boolean>> mLifecycleCallbacks;
+ private final CopyOnWriteArrayList<Pair<FragmentLifecycleCallbacks, Boolean>>
+ mLifecycleCallbacks = new CopyOnWriteArrayList<>();
int mCurState = Fragment.INITIALIZING;
FragmentHostCallback mHost;
@@ -3350,18 +3351,11 @@
@Override
public void registerFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb,
boolean recursive) {
- if (mLifecycleCallbacks == null) {
- mLifecycleCallbacks = new CopyOnWriteArrayList<>();
- }
mLifecycleCallbacks.add(new Pair<>(cb, recursive));
}
@Override
public void unregisterFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb) {
- if (mLifecycleCallbacks == null) {
- return;
- }
-
synchronized (mLifecycleCallbacks) {
for (int i = 0, N = mLifecycleCallbacks.size(); i < N; i++) {
if (mLifecycleCallbacks.get(i).first == cb) {
@@ -3380,9 +3374,6 @@
.dispatchOnFragmentPreAttached(f, context, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentPreAttached(this, f, context);
@@ -3398,9 +3389,6 @@
.dispatchOnFragmentAttached(f, context, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentAttached(this, f, context);
@@ -3417,9 +3405,6 @@
.dispatchOnFragmentPreCreated(f, savedInstanceState, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentPreCreated(this, f, savedInstanceState);
@@ -3435,9 +3420,6 @@
.dispatchOnFragmentCreated(f, savedInstanceState, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentCreated(this, f, savedInstanceState);
@@ -3454,9 +3436,6 @@
.dispatchOnFragmentActivityCreated(f, savedInstanceState, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentActivityCreated(this, f, savedInstanceState);
@@ -3473,9 +3452,6 @@
.dispatchOnFragmentViewCreated(f, v, savedInstanceState, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentViewCreated(this, f, v, savedInstanceState);
@@ -3491,9 +3467,6 @@
.dispatchOnFragmentStarted(f, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentStarted(this, f);
@@ -3509,9 +3482,6 @@
.dispatchOnFragmentResumed(f, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentResumed(this, f);
@@ -3527,9 +3497,6 @@
.dispatchOnFragmentPaused(f, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentPaused(this, f);
@@ -3545,9 +3512,6 @@
.dispatchOnFragmentStopped(f, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentStopped(this, f);
@@ -3563,9 +3527,6 @@
.dispatchOnFragmentSaveInstanceState(f, outState, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentSaveInstanceState(this, f, outState);
@@ -3581,9 +3542,6 @@
.dispatchOnFragmentViewDestroyed(f, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentViewDestroyed(this, f);
@@ -3599,9 +3557,6 @@
.dispatchOnFragmentDestroyed(f, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentDestroyed(this, f);
@@ -3617,9 +3572,6 @@
.dispatchOnFragmentDetached(f, true);
}
}
- if (mLifecycleCallbacks == null) {
- return;
- }
for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
if (!onlyRecursive || p.second) {
p.first.onFragmentDetached(this, f);
diff --git a/media-compat/java/android/support/v4/media/MediaBrowserCompat.java b/media-compat/java/android/support/v4/media/MediaBrowserCompat.java
index 98d6452..93ee3e0 100644
--- a/media-compat/java/android/support/v4/media/MediaBrowserCompat.java
+++ b/media-compat/java/android/support/v4/media/MediaBrowserCompat.java
@@ -24,7 +24,8 @@
import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_REMOVE_SUBSCRIPTION;
import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_SEARCH;
import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_SEND_CUSTOM_ACTION;
-import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
+import static android.support.v4.media.MediaBrowserProtocol
+ .CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
import static android.support.v4.media.MediaBrowserProtocol.CLIENT_VERSION_CURRENT;
import static android.support.v4.media.MediaBrowserProtocol.DATA_CALLBACK_TOKEN;
import static android.support.v4.media.MediaBrowserProtocol.DATA_CUSTOM_ACTION;
@@ -69,7 +70,6 @@
import android.support.v4.media.session.IMediaSession;
import android.support.v4.media.session.MediaControllerCompat.TransportControls;
import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v4.os.BuildCompat;
import android.support.v4.os.ResultReceiver;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;
@@ -181,7 +181,7 @@
ConnectionCallback callback, Bundle rootHints) {
// To workaround an issue of {@link #unsubscribe(String, SubscriptionCallback)} on API 24
// and 25 devices, use the support library version of implementation on those devices.
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
mImpl = new MediaBrowserImplApi24(context, serviceComponent, callback, rootHints);
} else if (Build.VERSION.SDK_INT >= 23) {
mImpl = new MediaBrowserImplApi23(context, serviceComponent, callback, rootHints);
@@ -676,7 +676,7 @@
WeakReference<Subscription> mSubscriptionRef;
public SubscriptionCallback() {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
mSubscriptionCallbackObj =
MediaBrowserCompatApi24.createSubscriptionCallback(new StubApi24());
mToken = null;
diff --git a/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java b/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java
index 12617b7..7c4c761 100644
--- a/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java
+++ b/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java
@@ -25,7 +25,8 @@
import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_REMOVE_SUBSCRIPTION;
import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_SEARCH;
import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_SEND_CUSTOM_ACTION;
-import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
+import static android.support.v4.media.MediaBrowserProtocol
+ .CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
import static android.support.v4.media.MediaBrowserProtocol.DATA_CALLBACK_TOKEN;
import static android.support.v4.media.MediaBrowserProtocol.DATA_CALLING_UID;
import static android.support.v4.media.MediaBrowserProtocol.DATA_CUSTOM_ACTION;
@@ -68,7 +69,6 @@
import android.support.v4.app.BundleCompat;
import android.support.v4.media.session.IMediaSession;
import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v4.os.BuildCompat;
import android.support.v4.os.ResultReceiver;
import android.support.v4.util.ArrayMap;
import android.support.v4.util.Pair;
@@ -977,7 +977,7 @@
@Override
public void onCreate() {
super.onCreate();
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
mImpl = new MediaBrowserServiceImplApi24();
} else if (Build.VERSION.SDK_INT >= 23) {
mImpl = new MediaBrowserServiceImplApi23();
diff --git a/media-compat/java/android/support/v4/media/session/MediaButtonReceiver.java b/media-compat/java/android/support/v4/media/session/MediaButtonReceiver.java
index afb72945..d411131 100644
--- a/media-compat/java/android/support/v4/media/session/MediaButtonReceiver.java
+++ b/media-compat/java/android/support/v4/media/session/MediaButtonReceiver.java
@@ -24,11 +24,11 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.Build;
import android.os.RemoteException;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaBrowserServiceCompat;
import android.support.v4.media.session.PlaybackStateCompat.MediaKeyAction;
-import android.support.v4.os.BuildCompat;
import android.util.Log;
import android.view.KeyEvent;
@@ -284,7 +284,7 @@
}
private static void startForegroundService(Context context, Intent intent) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
context.startForegroundService(intent);
} else {
context.startService(intent);
diff --git a/media-compat/proguard-rules.pro b/media-compat/proguard-rules.pro
index 38a9966..416b2e8 100644
--- a/media-compat/proguard-rules.pro
+++ b/media-compat/proguard-rules.pro
@@ -13,6 +13,6 @@
# limitations under the License.
# Prevent Parcelable objects from being removed or renamed.
--keep class * implements android.os.Parcelable {
+-keep class android.support.v4.media.** implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
\ No newline at end of file
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/accessibility/AccessibilityManagerSupportActivity.java b/samples/Support4Demos/src/com/example/android/supportv4/accessibility/AccessibilityManagerSupportActivity.java
index 4ffc0ef..061ed21 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/accessibility/AccessibilityManagerSupportActivity.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/accessibility/AccessibilityManagerSupportActivity.java
@@ -22,7 +22,6 @@
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat;
-import android.support.v4.view.accessibility.AccessibilityManagerCompat;
import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;
import android.widget.Toast;
@@ -79,20 +78,16 @@
* when the global accessibility state on the device changes.
*/
private void registerAccessibilityStateChangeListener() {
- // The AccessibilityStateChange listener APIs were added in ICS. Therefore to be
- // backwards compatible we use the APIs in the support library. Note that if the
- // platform API version is lower and the called API is not available no listener
- // is added and you will not receive a call of onAccessibilityStateChanged.
- AccessibilityManagerCompat.addAccessibilityStateChangeListener(mAccessibilityManager,
- new AccessibilityManagerCompat.AccessibilityStateChangeListener() {
- @Override
- public void onAccessibilityStateChanged(boolean enabled) {
- Toast.makeText(AccessibilityManagerSupportActivity.this,
- getString(R.string.accessibility_manager_accessibility_state,
- Boolean.toString(enabled)),
- Toast.LENGTH_SHORT).show();
- }
- });
+ mAccessibilityManager.addAccessibilityStateChangeListener(
+ new AccessibilityManager.AccessibilityStateChangeListener() {
+ @Override
+ public void onAccessibilityStateChanged(boolean enabled) {
+ Toast.makeText(AccessibilityManagerSupportActivity.this,
+ getString(R.string.accessibility_manager_accessibility_state,
+ Boolean.toString(enabled)),
+ Toast.LENGTH_SHORT).show();
+ }
+ });
}
/**
@@ -100,13 +95,9 @@
* accessibility services.
*/
private void updateAccessibilityStateView() {
- // The API for getting the enabled accessibility services based on feedback
- // type was added in ICS. Therefore to be backwards compatible we use the
- // APIs in the support library. Note that if the platform API version is lower
- // and the called API is not available an empty list of services is returned.
List<AccessibilityServiceInfo> enabledServices =
- AccessibilityManagerCompat.getEnabledAccessibilityServiceList(mAccessibilityManager,
- AccessibilityServiceInfo.FEEDBACK_SPOKEN);
+ mAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_SPOKEN);
if (!enabledServices.isEmpty()) {
StringBuilder builder = new StringBuilder();
final int enabledServiceCount = enabledServices.size();
diff --git a/samples/SupportTransitionDemos/res/layout/change_transform.xml b/samples/SupportTransitionDemos/res/layout/change_transform.xml
index 35909e3..c9559ab 100644
--- a/samples/SupportTransitionDemos/res/layout/change_transform.xml
+++ b/samples/SupportTransitionDemos/res/layout/change_transform.xml
@@ -32,6 +32,8 @@
android:id="@+id/container_1"
android:layout_width="match_parent"
android:layout_height="0dp"
+ android:layout_marginEnd="128dp"
+ android:layout_marginRight="128dp"
android:layout_weight="1"
android:background="#BBDEFB"/>
@@ -39,6 +41,8 @@
android:id="@+id/container_2"
android:layout_width="match_parent"
android:layout_height="0dp"
+ android:layout_marginLeft="128dp"
+ android:layout_marginStart="128dp"
android:layout_weight="1"
android:background="#FFCC80"/>
diff --git a/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ChangeTransformUsage.java b/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ChangeTransformUsage.java
index 67aa409..af1bafd 100644
--- a/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ChangeTransformUsage.java
+++ b/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ChangeTransformUsage.java
@@ -17,8 +17,10 @@
package com.example.android.support.transition.widget;
import android.os.Bundle;
+import android.support.transition.ArcMotion;
import android.support.transition.ChangeTransform;
import android.support.transition.TransitionManager;
+import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
@@ -45,6 +47,8 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mChangeTransform = new ChangeTransform();
+ mChangeTransform.setInterpolator(new FastOutSlowInInterpolator());
+ mChangeTransform.setPathMotion(new ArcMotion());
mRoot = findViewById(R.id.root);
mContainer1 = findViewById(R.id.container_1);
mContainer2 = findViewById(R.id.container_2);
diff --git a/samples/SupportWearDemos/AndroidManifest.xml b/samples/SupportWearDemos/AndroidManifest.xml
index df77ef7..eb10f0a 100644
--- a/samples/SupportWearDemos/AndroidManifest.xml
+++ b/samples/SupportWearDemos/AndroidManifest.xml
@@ -18,9 +18,12 @@
package="com.example.android.support.wear" >
<uses-feature android:name="android.hardware.type.watch" />
- <application android:icon="@drawable/app_sample_code" android:label="SupportWearDemos" >
+ <application android:icon="@drawable/app_sample_code" android:label="SupportWearDemos"
+ android:theme="@android:style/Theme.DeviceDefault">
<activity android:name="com.example.android.support.wear.app.SimpleWearableRecyclerViewDemo">
</activity>
+ <activity android:name="com.example.android.support.wear.app.WearableSwitchDemo">
+ </activity>
<activity android:name="com.example.android.support.wear.app.MainDemoActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/samples/SupportWearDemos/build.gradle b/samples/SupportWearDemos/build.gradle
index 2819768..0eac8a1 100644
--- a/samples/SupportWearDemos/build.gradle
+++ b/samples/SupportWearDemos/build.gradle
@@ -24,7 +24,7 @@
compileSdkVersion project.ext.currentSdk
defaultConfig {
- minSdkVersion 23
+ minSdkVersion 24
targetSdkVersion project.ext.currentSdk
}
diff --git a/samples/SupportWearDemos/res/layout/switch_demo.xml b/samples/SupportWearDemos/res/layout/switch_demo.xml
new file mode 100644
index 0000000..921568c
--- /dev/null
+++ b/samples/SupportWearDemos/res/layout/switch_demo.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ <Switch
+ style="@style/Widget.Wear.RoundSwitch"
+ android:layout_gravity="center"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+</merge>
diff --git a/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java b/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java
index 26dbef7..c9512a2 100644
--- a/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java
+++ b/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java
@@ -50,9 +50,10 @@
private Map<String, Intent> createContentMap() {
Map<String, Intent> contentMap = new HashMap<>();
- Intent intent = new Intent();
- intent.setClass(MainDemoActivity.this, SimpleWearableRecyclerViewDemo.class);
- contentMap.put("Wearable Recycler View", intent);
+ contentMap.put("Wearable Recycler View", new Intent(
+ this, SimpleWearableRecyclerViewDemo.class));
+ contentMap.put("Wearable Switch", new Intent(
+ this, WearableSwitchDemo.class));
return contentMap;
}
diff --git a/samples/SupportWearDemos/src/com/example/android/support/wear/app/WearableSwitchDemo.java b/samples/SupportWearDemos/src/com/example/android/support/wear/app/WearableSwitchDemo.java
new file mode 100644
index 0000000..774021b
--- /dev/null
+++ b/samples/SupportWearDemos/src/com/example/android/support/wear/app/WearableSwitchDemo.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.support.wear.app;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.example.android.support.wear.R;
+
+/** Main activity for the Switch demo. */
+public class WearableSwitchDemo extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.switch_demo);
+ }
+}
diff --git a/transition/api14/android/support/transition/GhostViewApi14.java b/transition/api14/android/support/transition/GhostViewApi14.java
index 9c91c99..c918651 100644
--- a/transition/api14/android/support/transition/GhostViewApi14.java
+++ b/transition/api14/android/support/transition/GhostViewApi14.java
@@ -150,6 +150,8 @@
final int[] viewLocation = new int[2];
getLocationOnScreen(location);
mView.getLocationOnScreen(viewLocation);
+ viewLocation[0] -= mView.getTranslationX();
+ viewLocation[1] -= mView.getTranslationY();
mDeltaX = viewLocation[0] - location[0];
mDeltaY = viewLocation[1] - location[1];
// Monitor invalidation of the target view.
diff --git a/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java b/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java
index a51c4d6..a1038de 100644
--- a/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java
+++ b/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java
@@ -18,7 +18,6 @@
import android.animation.ObjectAnimator;
import android.graphics.Path;
-import android.graphics.PathMeasure;
import android.graphics.PointF;
import android.support.annotation.RequiresApi;
import android.util.Property;
@@ -31,47 +30,4 @@
return ObjectAnimator.ofFloat(target, new PathProperty<>(property, path), 0f, 1f);
}
- /**
- * A special {@link Property} that can animate a pair of properties bi-dimensionally along the
- * specified path.
- * <p>
- * This property should always be used with Animator that sets float fractions between
- * {@code 0.f} and {@code 1.f}. For example, setting {@code 0.5f} to this property sets the
- * values right in the middle of the specified path to the underlying properties.
- * <p>
- * Unlike many of the platform built-in properties, instances of this class cannot be reused
- * for later animations.
- */
- private static class PathProperty<T> extends Property<T, Float> {
-
- private final Property<T, PointF> mProperty;
- private final PathMeasure mPathMeasure;
- private final float mPathLength;
- private final float[] mPosition = new float[2];
- private final PointF mPointF = new PointF();
- private float mCurrentFraction;
-
- PathProperty(Property<T, PointF> property, Path path) {
- super(Float.class, property.getName());
- mProperty = property;
- mPathMeasure = new PathMeasure(path, false);
- mPathLength = mPathMeasure.getLength();
- }
-
- @Override
- public Float get(T object) {
- return mCurrentFraction;
- }
-
- @Override
- public void set(T target, Float fraction) {
- mCurrentFraction = fraction;
- mPathMeasure.getPosTan(mPathLength * fraction, mPosition, null);
- mPointF.x = mPosition[0];
- mPointF.y = mPosition[1];
- mProperty.set(target, mPointF);
- }
-
- }
-
}
diff --git a/transition/api14/android/support/transition/PathProperty.java b/transition/api14/android/support/transition/PathProperty.java
new file mode 100644
index 0000000..c5e7429
--- /dev/null
+++ b/transition/api14/android/support/transition/PathProperty.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.transition;
+
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.PointF;
+import android.util.Property;
+
+/**
+ * A special {@link Property} that can animate a pair of properties bi-dimensionally along the
+ * specified path.
+ * <p>
+ * This property should always be used with Animator that sets float fractions between
+ * {@code 0.f} and {@code 1.f}. For example, setting {@code 0.5f} to this property sets the
+ * values right in the middle of the specified path to the underlying properties.
+ * <p>
+ * Unlike many of the platform built-in properties, instances of this class cannot be reused
+ * for later animations.
+ */
+class PathProperty<T> extends Property<T, Float> {
+
+ private final Property<T, PointF> mProperty;
+ private final PathMeasure mPathMeasure;
+ private final float mPathLength;
+ private final float[] mPosition = new float[2];
+ private final PointF mPointF = new PointF();
+ private float mCurrentFraction;
+
+ PathProperty(Property<T, PointF> property, Path path) {
+ super(Float.class, property.getName());
+ mProperty = property;
+ mPathMeasure = new PathMeasure(path, false);
+ mPathLength = mPathMeasure.getLength();
+ }
+
+ @Override
+ public Float get(T object) {
+ return mCurrentFraction;
+ }
+
+ @Override
+ public void set(T target, Float fraction) {
+ mCurrentFraction = fraction;
+ mPathMeasure.getPosTan(mPathLength * fraction, mPosition, null);
+ mPointF.x = mPosition[0];
+ mPointF.y = mPosition[1];
+ mProperty.set(target, mPointF);
+ }
+
+}
diff --git a/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java b/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java
index 7bcd36e..072178b 100644
--- a/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java
+++ b/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java
@@ -17,9 +17,7 @@
package android.support.transition;
import android.animation.PropertyValuesHolder;
-import android.animation.TypeEvaluator;
import android.graphics.Path;
-import android.graphics.PathMeasure;
import android.graphics.PointF;
import android.support.annotation.RequiresApi;
import android.util.Property;
@@ -29,28 +27,7 @@
@Override
public PropertyValuesHolder ofPointF(Property<?, PointF> property, Path path) {
- return PropertyValuesHolder.ofObject(property, new PathEvaluator(path));
- }
-
- private static class PathEvaluator implements TypeEvaluator<PointF> {
-
- private final PointF mPointF = new PointF();
- private final PathMeasure mPathMeasure;
- private final float mPathLength;
- private final float[] mPosition = new float[2];
-
- PathEvaluator(Path path) {
- mPathMeasure = new PathMeasure(path, false);
- mPathLength = mPathMeasure.getLength();
- }
-
- @Override
- public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
- mPathMeasure.getPosTan(mPathLength * fraction, mPosition, null);
- mPointF.set(mPosition[0], mPosition[1]);
- return mPointF;
- }
-
+ return PropertyValuesHolder.ofFloat(new PathProperty<>(property, path), 0f, 1f);
}
}
diff --git a/transition/src/android/support/transition/ArcMotion.java b/transition/src/android/support/transition/ArcMotion.java
index a89ce4c..42f667c 100644
--- a/transition/src/android/support/transition/ArcMotion.java
+++ b/transition/src/android/support/transition/ArcMotion.java
@@ -37,6 +37,14 @@
* {@link #setMinimumVerticalAngle(float)} may be used to set the minimum angle of the
* arc between two points.
* </p>
+ * <p>This may be used in XML as an element inside a transition.</p>
+ * <pre>{@code
+ * <changeBounds>
+ * <arcMotion android:minimumHorizontalAngle="15"
+ * android:minimumVerticalAngle="0"
+ * android:maximumAngle="90"/>
+ * </changeBounds>}
+ * </pre>
*/
public class ArcMotion extends PathMotion {
diff --git a/transition/src/android/support/transition/ChangeTransform.java b/transition/src/android/support/transition/ChangeTransform.java
index 539a89e..f0adc08 100644
--- a/transition/src/android/support/transition/ChangeTransform.java
+++ b/transition/src/android/support/transition/ChangeTransform.java
@@ -19,10 +19,12 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
+import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Matrix;
+import android.graphics.Path;
+import android.graphics.PointF;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.content.res.TypedArrayUtils;
@@ -59,16 +61,35 @@
PROPNAME_PARENT_MATRIX,
};
- private static final Property<View, Matrix> ANIMATION_MATRIX_PROPERTY =
- new Property<View, Matrix>(Matrix.class, "animationMatrix") {
+ /**
+ * This property sets the animation matrix properties that are not translations.
+ */
+ private static final Property<PathAnimatorMatrix, float[]> NON_TRANSLATIONS_PROPERTY =
+ new Property<PathAnimatorMatrix, float[]>(float[].class, "nonTranslations") {
@Override
- public Matrix get(View view) {
+ public float[] get(PathAnimatorMatrix object) {
return null;
}
@Override
- public void set(View view, Matrix matrix) {
- ViewUtils.setAnimationMatrix(view, matrix);
+ public void set(PathAnimatorMatrix object, float[] value) {
+ object.setValues(value);
+ }
+ };
+
+ /**
+ * This property sets the translation animation matrix properties.
+ */
+ private static final Property<PathAnimatorMatrix, PointF> TRANSLATIONS_PROPERTY =
+ new Property<PathAnimatorMatrix, PointF>(PointF.class, "translations") {
+ @Override
+ public PointF get(PathAnimatorMatrix object) {
+ return null;
+ }
+
+ @Override
+ public void set(PathAnimatorMatrix object, PointF value) {
+ object.setTranslation(value);
}
};
@@ -278,8 +299,23 @@
final View view = endValues.view;
setIdentityTransforms(view);
- ObjectAnimator animator = ObjectAnimator.ofObject(view, ANIMATION_MATRIX_PROPERTY,
- new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix);
+ final float[] startMatrixValues = new float[9];
+ startMatrix.getValues(startMatrixValues);
+ final float[] endMatrixValues = new float[9];
+ endMatrix.getValues(endMatrixValues);
+ final PathAnimatorMatrix pathAnimatorMatrix =
+ new PathAnimatorMatrix(view, startMatrixValues);
+
+ PropertyValuesHolder valuesProperty = PropertyValuesHolder.ofObject(
+ NON_TRANSLATIONS_PROPERTY, new FloatArrayEvaluator(new float[9]),
+ startMatrixValues, endMatrixValues);
+ Path path = getPathMotion().getPath(startMatrixValues[Matrix.MTRANS_X],
+ startMatrixValues[Matrix.MTRANS_Y], endMatrixValues[Matrix.MTRANS_X],
+ endMatrixValues[Matrix.MTRANS_Y]);
+ PropertyValuesHolder translationProperty = PropertyValuesHolderUtils.ofPointF(
+ TRANSLATIONS_PROPERTY, path);
+ ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(pathAnimatorMatrix,
+ valuesProperty, translationProperty);
final Matrix finalEndMatrix = endMatrix;
@@ -302,14 +338,13 @@
view.setTag(R.id.parent_matrix, null);
}
}
- ANIMATION_MATRIX_PROPERTY.set(view, null);
+ ViewUtils.setAnimationMatrix(view, null);
transforms.restore(view);
}
@Override
public void onAnimationPause(Animator animation) {
- ValueAnimator animator = (ValueAnimator) animation;
- Matrix currentMatrix = (Matrix) animator.getAnimatedValue();
+ Matrix currentMatrix = pathAnimatorMatrix.getMatrix();
setCurrentMatrix(currentMatrix);
}
@@ -471,7 +506,7 @@
}
- private static class GhostListener extends Transition.TransitionListenerAdapter {
+ private static class GhostListener extends TransitionListenerAdapter {
private View mView;
private GhostViewImpl mGhostView;
@@ -501,4 +536,48 @@
}
+ /**
+ * PathAnimatorMatrix allows the translations and the rest of the matrix to be set
+ * separately. This allows the PathMotion to affect the translations while scale
+ * and rotation are evaluated separately.
+ */
+ private static class PathAnimatorMatrix {
+
+ private final Matrix mMatrix = new Matrix();
+ private final View mView;
+ private final float[] mValues;
+ private float mTranslationX;
+ private float mTranslationY;
+
+ PathAnimatorMatrix(View view, float[] values) {
+ mView = view;
+ mValues = values.clone();
+ mTranslationX = mValues[Matrix.MTRANS_X];
+ mTranslationY = mValues[Matrix.MTRANS_Y];
+ setAnimationMatrix();
+ }
+
+ void setValues(float[] values) {
+ System.arraycopy(values, 0, mValues, 0, values.length);
+ setAnimationMatrix();
+ }
+
+ void setTranslation(PointF translation) {
+ mTranslationX = translation.x;
+ mTranslationY = translation.y;
+ setAnimationMatrix();
+ }
+
+ private void setAnimationMatrix() {
+ mValues[Matrix.MTRANS_X] = mTranslationX;
+ mValues[Matrix.MTRANS_Y] = mTranslationY;
+ mMatrix.setValues(mValues);
+ ViewUtils.setAnimationMatrix(mView, mMatrix);
+ }
+
+ Matrix getMatrix() {
+ return mMatrix;
+ }
+ }
+
}
diff --git a/transition/src/android/support/transition/FloatArrayEvaluator.java b/transition/src/android/support/transition/FloatArrayEvaluator.java
new file mode 100644
index 0000000..81b97b7
--- /dev/null
+++ b/transition/src/android/support/transition/FloatArrayEvaluator.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.transition;
+
+import android.animation.TypeEvaluator;
+
+/**
+ * This evaluator can be used to perform type interpolation between <code>float[]</code> values.
+ * Each index into the array is treated as a separate value to interpolate. For example,
+ * evaluating <code>{100, 200}</code> and <code>{300, 400}</code> will interpolate the value at
+ * the first index between 100 and 300 and the value at the second index value between 200 and 400.
+ */
+class FloatArrayEvaluator implements TypeEvaluator<float[]> {
+
+ private float[] mArray;
+
+ /**
+ * Create a FloatArrayEvaluator that reuses <code>reuseArray</code> for every evaluate() call.
+ * Caution must be taken to ensure that the value returned from
+ * {@link android.animation.ValueAnimator#getAnimatedValue()} is not cached, modified, or
+ * used across threads. The value will be modified on each <code>evaluate()</code> call.
+ *
+ * @param reuseArray The array to modify and return from <code>evaluate</code>.
+ */
+ FloatArrayEvaluator(float[] reuseArray) {
+ mArray = reuseArray;
+ }
+
+ /**
+ * Interpolates the value at each index by the fraction. If
+ * {@link #FloatArrayEvaluator(float[])} was used to construct this object,
+ * <code>reuseArray</code> will be returned, otherwise a new <code>float[]</code>
+ * will be returned.
+ *
+ * @param fraction The fraction from the starting to the ending values
+ * @param startValue The start value.
+ * @param endValue The end value.
+ * @return A <code>float[]</code> where each element is an interpolation between
+ * the same index in startValue and endValue.
+ */
+ @Override
+ public float[] evaluate(float fraction, float[] startValue, float[] endValue) {
+ float[] array = mArray;
+ if (array == null) {
+ array = new float[startValue.length];
+ }
+
+ for (int i = 0; i < array.length; i++) {
+ float start = startValue[i];
+ float end = endValue[i];
+ array[i] = start + (fraction * (end - start));
+ }
+ return array;
+ }
+
+}
diff --git a/transition/src/android/support/transition/PathMotion.java b/transition/src/android/support/transition/PathMotion.java
index 513b61e..d270a08 100644
--- a/transition/src/android/support/transition/PathMotion.java
+++ b/transition/src/android/support/transition/PathMotion.java
@@ -29,6 +29,14 @@
* have these motions move in a curve can change how Views interpolate in two dimensions
* by extending PathMotion and implementing {@link #getPath(float, float, float, float)}.
* </p>
+ * <p>This may be used in XML as an element inside a transition.</p>
+ * <pre>
+ * {@code
+ * <changeBounds>
+ * <pathMotion class="my.app.transition.MyPathMotion"/>
+ * </changeBounds>
+ * }
+ * </pre>
*/
public abstract class PathMotion {
diff --git a/transition/src/android/support/transition/PatternPathMotion.java b/transition/src/android/support/transition/PatternPathMotion.java
index a8c6078..2ac6e72 100644
--- a/transition/src/android/support/transition/PatternPathMotion.java
+++ b/transition/src/android/support/transition/PatternPathMotion.java
@@ -31,6 +31,12 @@
* A PathMotion that takes a Path pattern and applies it to the separation between two points.
* The starting point of the Path will be moved to the origin and the end point will be scaled
* and rotated so that it matches with the target end point.
+ * <p>This may be used in XML as an element inside a transition.</p>
+ * <pre>{@code
+ * <changeBounds>
+ * <patternPathMotion android:patternPathData="M0 0 L0 100 L100 100"/>
+ * </changeBounds>}
+ * </pre>
*/
public class PatternPathMotion extends PathMotion {
diff --git a/transition/src/android/support/transition/Transition.java b/transition/src/android/support/transition/Transition.java
index a2b38bc..04cc57b 100644
--- a/transition/src/android/support/transition/Transition.java
+++ b/transition/src/android/support/transition/Transition.java
@@ -2087,7 +2087,7 @@
* @see PatternPathMotion
* @see android.transition.PathMotion
*/
- @Nullable
+ @NonNull
public PathMotion getPathMotion() {
return mPathMotion;
}
@@ -2335,36 +2335,6 @@
}
/**
- * Utility adapter class to avoid having to override all three methods
- * whenever someone just wants to listen for a single event.
- *
- * @hide
- */
- @RestrictTo(LIBRARY_GROUP)
- public static class TransitionListenerAdapter implements TransitionListener {
-
- @Override
- public void onTransitionStart(@NonNull Transition transition) {
- }
-
- @Override
- public void onTransitionEnd(@NonNull Transition transition) {
- }
-
- @Override
- public void onTransitionCancel(@NonNull Transition transition) {
- }
-
- @Override
- public void onTransitionPause(@NonNull Transition transition) {
- }
-
- @Override
- public void onTransitionResume(@NonNull Transition transition) {
- }
- }
-
- /**
* Holds information about each animator used when a new transition starts
* while other transitions are still running to determine whether a running
* animation should be canceled or a new animation noop'd. The structure holds
diff --git a/transition/src/android/support/transition/TransitionListenerAdapter.java b/transition/src/android/support/transition/TransitionListenerAdapter.java
new file mode 100644
index 0000000..333fbfb
--- /dev/null
+++ b/transition/src/android/support/transition/TransitionListenerAdapter.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.transition;
+
+import android.support.annotation.NonNull;
+
+/**
+ * This adapter class provides empty implementations of the methods from {@link
+ * Transition.TransitionListener}.
+ * Any custom listener that cares only about a subset of the methods of this listener can
+ * simply subclass this adapter class instead of implementing the interface directly.
+ */
+public class TransitionListenerAdapter implements Transition.TransitionListener {
+
+ @Override
+ public void onTransitionStart(@NonNull Transition transition) {
+ }
+
+ @Override
+ public void onTransitionEnd(@NonNull Transition transition) {
+ }
+
+ @Override
+ public void onTransitionCancel(@NonNull Transition transition) {
+ }
+
+ @Override
+ public void onTransitionPause(@NonNull Transition transition) {
+ }
+
+ @Override
+ public void onTransitionResume(@NonNull Transition transition) {
+ }
+
+}
diff --git a/transition/src/android/support/transition/TransitionManager.java b/transition/src/android/support/transition/TransitionManager.java
index f65a464..d5f46ab 100644
--- a/transition/src/android/support/transition/TransitionManager.java
+++ b/transition/src/android/support/transition/TransitionManager.java
@@ -273,7 +273,7 @@
previousRunningTransitions = new ArrayList<>(currentTransitions);
}
currentTransitions.add(mTransition);
- mTransition.addListener(new Transition.TransitionListenerAdapter() {
+ mTransition.addListener(new TransitionListenerAdapter() {
@Override
public void onTransitionEnd(@NonNull Transition transition) {
ArrayList<Transition> currentTransitions = runningTransitions.get(mSceneRoot);
diff --git a/transition/src/android/support/transition/ViewUtils.java b/transition/src/android/support/transition/ViewUtils.java
index bf671d0..66c3076 100644
--- a/transition/src/android/support/transition/ViewUtils.java
+++ b/transition/src/android/support/transition/ViewUtils.java
@@ -20,6 +20,7 @@
import android.graphics.Rect;
import android.os.Build;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.util.Log;
import android.util.Property;
@@ -188,7 +189,7 @@
* @param v The view
* @param m The matrix
*/
- static void setAnimationMatrix(@NonNull View v, @NonNull Matrix m) {
+ static void setAnimationMatrix(@NonNull View v, @Nullable Matrix m) {
IMPL.setAnimationMatrix(v, m);
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java b/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
index 65d2c44..262a5a6 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
@@ -37,7 +37,6 @@
import android.support.v17.leanback.widget.BackgroundHelper;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
-import android.support.v4.os.BuildCompat;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.util.Log;
import android.view.View;
@@ -674,7 +673,7 @@
// Activity transition below O has ghost effect for null window background where we
// need set a transparent background to force redraw the whole window.
mContext.getWindow().getDecorView().setBackground(
- BuildCompat.isAtLeastO() ? null : new ColorDrawable(Color.TRANSPARENT));
+ Build.VERSION.SDK_INT >= 26 ? null : new ColorDrawable(Color.TRANSPARENT));
}
void attachToViewInternal(View sceneRoot) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
index 35238cf..ff2d999 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
@@ -1882,7 +1882,9 @@
View view = getChildAt(index);
position = getAdapterPositionByView(view);
Grid.Location location = mGrid.getLocation(position);
- if (location == null) {
+ // position could be NO_POSITION for the views off the screen that were cached. For
+ // these views markKnownViewsInvalid invalidates them.
+ if (location == null || (position == NO_POSITION)) {
if (DEBUG) Log.w(getTag(), "fastRelayout(): no Location at " + position);
invalidateAfter = true;
break;
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetTest.java
index 5bc5af4..a6f005d 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetTest.java
@@ -778,6 +778,39 @@
verifyEdgesSame(endEdges, endEdges2);
}
+
+ @Test
+ public void testLayoutWhenAViewIsInvalidated() throws Throwable {
+ Intent intent = new Intent();
+ intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID, R.layout.vertical_linear);
+ intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10);
+ mNumRows = 1;
+ initActivity(intent);
+ mOrientation = BaseGridView.VERTICAL;
+ waitOneUiCycle();
+
+ mActivityTestRule.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ RecyclerView.ViewHolder vh = mGridView.findViewHolderForAdapterPosition(3);
+ // The following is nowhere ideal since we can't override GridLayoutManager to
+ // obtain a reference to Recycler. Ideally, this test should call
+ // addFlags(ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID) on the ViewHolder to
+ // simulate markKnownViewsInvalid on the cached views in RecyclerView.
+ mLayoutManager.stopIgnoringView(vh.itemView);
+ }
+ });
+
+ mActivityTestRule.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mGridView.requestLayout();
+ }
+ });
+ waitForScrollIdle();
+ }
+
+
void preparePredictiveLayout() throws Throwable {
Intent intent = new Intent();
intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java b/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
index 78136e2..c8d7b0a 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
@@ -31,7 +31,6 @@
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.NavUtils;
import android.support.v4.app.TaskStackBuilder;
-import android.support.v4.os.BuildCompat;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.Toolbar;
import android.support.v7.widget.VectorEnabledTintResources;
@@ -549,7 +548,7 @@
* and perform the corresponding action.
*/
private boolean performMenuItemShortcut(int keycode, KeyEvent event) {
- if (!BuildCompat.isAtLeastO() && !event.isCtrlPressed()
+ if (!(Build.VERSION.SDK_INT >= 26) && !event.isCtrlPressed()
&& !KeyEvent.metaStateHasNoModifiers(event.getMetaState())
&& event.getRepeatCount() == 0
&& !KeyEvent.isModifierKey(event.getKeyCode())) {
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java
index e79a906..2a4022c 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java
@@ -26,11 +26,11 @@
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.annotation.VisibleForTesting;
-import android.support.v4.os.BuildCompat;
import android.support.v7.view.SupportActionModeWrapper;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -217,7 +217,7 @@
res.updateConfiguration(config, metrics);
// We may need to flush the Resources' drawable cache due to framework bugs.
- if (!BuildCompat.isAtLeastO()) {
+ if (!(Build.VERSION.SDK_INT >= 26)) {
ResourcesFlusher.flush(res);
}
}
diff --git a/v7/appcompat/src/android/support/v7/view/menu/CascadingMenuPopup.java b/v7/appcompat/src/android/support/v7/view/menu/CascadingMenuPopup.java
index fda1a97..73499cf 100644
--- a/v7/appcompat/src/android/support/v7/view/menu/CascadingMenuPopup.java
+++ b/v7/appcompat/src/android/support/v7/view/menu/CascadingMenuPopup.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Handler;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -28,7 +29,6 @@
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.support.v4.internal.view.SupportMenu;
-import android.support.v4.os.BuildCompat;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewCompat;
import android.support.v7.appcompat.R;
@@ -406,7 +406,7 @@
final int parentOffsetLeft;
final int parentOffsetTop;
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
// Anchor the submenu directly to the parent menu item view. This allows for
// accurate submenu positioning when the parent menu is being moved.
popupWindow.setAnchorView(parentView);
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
index c5f6e17..afd59bd 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
@@ -27,7 +27,6 @@
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.annotation.RestrictTo;
-import android.support.v4.os.BuildCompat;
import android.support.v4.widget.TextViewCompat;
import android.support.v7.appcompat.R;
import android.text.method.PasswordTransformationMethod;
@@ -171,7 +170,7 @@
mAutoSizeTextHelper.loadFromAttributes(attrs, defStyleAttr);
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
// Delegate auto-size functionality to the framework implementation.
if (mAutoSizeTextHelper.getAutoSizeTextType()
!= TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE) {
@@ -200,6 +199,7 @@
if (a.hasValue(R.styleable.TextAppearance_android_fontFamily)
|| a.hasValue(R.styleable.TextAppearance_fontFamily)) {
+ mFontTypeface = null;
int fontFamilyId = a.hasValue(R.styleable.TextAppearance_android_fontFamily)
? R.styleable.TextAppearance_android_fontFamily
: R.styleable.TextAppearance_fontFamily;
@@ -283,45 +283,33 @@
@RestrictTo(LIBRARY_GROUP)
void onLayout(boolean changed, int left, int top, int right, int bottom) {
// Auto-size is supported by the framework starting from Android O.
- if (!BuildCompat.isAtLeastO()) {
- if (isAutoSizeEnabled()) {
- if (getNeedsAutoSizeText()) {
- // Call auto-size after the width and height have been calculated.
- autoSizeText();
- }
- // Always try to auto-size if enabled. Functions that do not want to trigger
- // auto-sizing after the next layout round should set this to false.
- setNeedsAutoSizeText(true);
- }
+ if (!(Build.VERSION.SDK_INT >= 26)) {
+ autoSizeText();
}
}
/** @hide */
@RestrictTo(LIBRARY_GROUP)
void setTextSize(int unit, float size) {
- if (!BuildCompat.isAtLeastO()) {
+ if (!(Build.VERSION.SDK_INT >= 26)) {
if (!isAutoSizeEnabled()) {
setTextSizeInternal(unit, size);
}
}
}
- private boolean isAutoSizeEnabled() {
- return mAutoSizeTextHelper.isAutoSizeEnabled();
- }
-
- private boolean getNeedsAutoSizeText() {
- return mAutoSizeTextHelper.getNeedsAutoSizeText();
- }
-
- private void setNeedsAutoSizeText(boolean needsAutoSizeText) {
- mAutoSizeTextHelper.setNeedsAutoSizeText(needsAutoSizeText);
- }
-
- private void autoSizeText() {
+ /** @hide */
+ @RestrictTo(LIBRARY_GROUP)
+ void autoSizeText() {
mAutoSizeTextHelper.autoSizeText();
}
+ /** @hide */
+ @RestrictTo(LIBRARY_GROUP)
+ boolean isAutoSizeEnabled() {
+ return mAutoSizeTextHelper.isAutoSizeEnabled();
+ }
+
private void setTextSizeInternal(int unit, float size) {
mAutoSizeTextHelper.setTextSizeInternal(unit, size);
}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java b/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
index 992ddc6..39f8c1f 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
@@ -22,11 +22,11 @@
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
-import android.support.v4.os.BuildCompat;
import android.support.v4.view.TintableBackgroundView;
import android.support.v4.widget.AutoSizeableTextView;
import android.support.v4.widget.TextViewCompat;
@@ -183,7 +183,7 @@
@Override
public void setTextSize(int unit, float size) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
super.setTextSize(unit, size);
} else {
if (mTextHelper != null) {
@@ -192,6 +192,14 @@
}
}
+ @Override
+ protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
+ super.onTextChanged(text, start, lengthBefore, lengthAfter);
+ if (mTextHelper != null && Build.VERSION.SDK_INT < 26 && mTextHelper.isAutoSizeEnabled()) {
+ mTextHelper.autoSizeText();
+ }
+ }
+
/**
* This should be accessed via
* {@link android.support.v4.widget.TextViewCompat#setAutoSizeTextTypeWithDefaults(
@@ -203,7 +211,7 @@
@Override
public void setAutoSizeTextTypeWithDefaults(
@TextViewCompat.AutoSizeTextType int autoSizeTextType) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
super.setAutoSizeTextTypeWithDefaults(autoSizeTextType);
} else {
if (mTextHelper != null) {
@@ -226,7 +234,7 @@
int autoSizeMaxTextSize,
int autoSizeStepGranularity,
int unit) throws IllegalArgumentException {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
super.setAutoSizeTextTypeUniformWithConfiguration(
autoSizeMinTextSize, autoSizeMaxTextSize, autoSizeStepGranularity, unit);
} else {
@@ -248,7 +256,7 @@
@Override
public void setAutoSizeTextTypeUniformWithPresetSizes(@NonNull int[] presetSizes, int unit)
throws IllegalArgumentException {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
super.setAutoSizeTextTypeUniformWithPresetSizes(presetSizes, unit);
} else {
if (mTextHelper != null) {
@@ -267,7 +275,7 @@
@Override
@TextViewCompat.AutoSizeTextType
public int getAutoSizeTextType() {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return super.getAutoSizeTextType() == TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM
? TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM
: TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE;
@@ -288,7 +296,7 @@
@RestrictTo(LIBRARY_GROUP)
@Override
public int getAutoSizeStepGranularity() {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return super.getAutoSizeStepGranularity();
} else {
if (mTextHelper != null) {
@@ -307,7 +315,7 @@
@RestrictTo(LIBRARY_GROUP)
@Override
public int getAutoSizeMinTextSize() {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return super.getAutoSizeMinTextSize();
} else {
if (mTextHelper != null) {
@@ -326,7 +334,7 @@
@RestrictTo(LIBRARY_GROUP)
@Override
public int getAutoSizeMaxTextSize() {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return super.getAutoSizeMaxTextSize();
} else {
if (mTextHelper != null) {
@@ -345,7 +353,7 @@
@RestrictTo(LIBRARY_GROUP)
@Override
public int[] getAutoSizeTextAvailableSizes() {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return super.getAutoSizeTextAvailableSizes();
} else {
if (mTextHelper != null) {
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java
index 068366a..a648aaf 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java
@@ -26,7 +26,6 @@
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.RestrictTo;
-import android.support.v4.os.BuildCompat;
import android.support.v4.widget.TextViewCompat;
import android.support.v7.appcompat.R;
import android.text.Layout;
@@ -210,7 +209,9 @@
autoSizeMinTextSizeInPx,
autoSizeMaxTextSizeInPx,
DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX);
- setupAutoSizeText();
+ if (setupAutoSizeText()) {
+ autoSizeText();
+ }
break;
default:
throw new IllegalArgumentException(
@@ -266,7 +267,9 @@
validateAndSetAutoSizeTextTypeUniformConfiguration(autoSizeMinTextSizeInPx,
autoSizeMaxTextSizeInPx,
autoSizeStepGranularityInPx);
- setupAutoSizeText();
+ if (setupAutoSizeText()) {
+ autoSizeText();
+ }
}
}
@@ -320,7 +323,10 @@
} else {
mHasPresetAutoSizeValues = false;
}
- setupAutoSizeText();
+
+ if (setupAutoSizeText()) {
+ autoSizeText();
+ }
}
}
@@ -493,20 +499,19 @@
mHasPresetAutoSizeValues = false;
}
- private void setupAutoSizeText() {
+ private boolean setupAutoSizeText() {
if (supportsAutoSizeText()
&& mAutoSizeTextType == TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM) {
// Calculate the sizes set based on minimum size, maximum size and step size if we do
// not have a predefined set of sizes or if the current sizes array is empty.
if (!mHasPresetAutoSizeValues || mAutoSizeTextSizesInPx.length == 0) {
// Calculate sizes to choose from based on the current auto-size configuration.
- int autoSizeValuesLength = (int) Math.ceil(
- (mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
- / mAutoSizeStepGranularityInPx);
- // Also reserve a slot for the max size if it fits.
- if ((mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
- % mAutoSizeStepGranularityInPx == 0) {
+ int autoSizeValuesLength = 1;
+ float currentSize = Math.round(mAutoSizeMinTextSizeInPx);
+ while (Math.round(currentSize + mAutoSizeStepGranularityInPx)
+ <= Math.round(mAutoSizeMaxTextSizeInPx)) {
autoSizeValuesLength++;
+ currentSize += mAutoSizeStepGranularityInPx;
}
int[] autoSizeTextSizesInPx = new int[autoSizeValuesLength];
float sizeToAdd = mAutoSizeMinTextSizeInPx;
@@ -518,17 +523,11 @@
}
mNeedsAutoSizeText = true;
-
- // If the build version is at least 26 there is no need to auto-size using this
- // helper because the job has been delegated to the actual TextView but the
- // configuration still needs to be done for the case where this function is called
- // from {@link #loadFromAttributes}, in which case the auto-size configuration
- // attributes set up in this function will be read by {@link AppCompatTextHelper}
- // and after passed on to the actual TextView which will take care of auto-sizing.
- if (!BuildCompat.isAtLeastO()) {
- autoSizeText();
- }
+ } else {
+ mNeedsAutoSizeText = false;
}
+
+ return mNeedsAutoSizeText;
}
/**
@@ -538,31 +537,44 @@
*/
@RestrictTo(LIBRARY_GROUP)
void autoSizeText() {
- if (mTextView.getMeasuredHeight() <= 0 || mTextView.getMeasuredWidth() <= 0) {
+ if (!isAutoSizeEnabled()) {
return;
}
- final int maxWidth = mTextView.getWidth() - mTextView.getTotalPaddingLeft()
- - mTextView.getTotalPaddingRight();
- final int maxHeight = Build.VERSION.SDK_INT >= 21
- ? mTextView.getHeight() - mTextView.getExtendedPaddingBottom()
- - mTextView.getExtendedPaddingBottom()
- : mTextView.getHeight() - mTextView.getCompoundPaddingBottom()
- - mTextView.getCompoundPaddingTop();
+ if (mNeedsAutoSizeText) {
+ if (mTextView.getMeasuredHeight() <= 0 || mTextView.getMeasuredWidth() <= 0) {
+ return;
+ }
- if (maxWidth <= 0 || maxHeight <= 0) {
- return;
- }
+ final boolean horizontallyScrolling = invokeAndReturnWithDefault(
+ mTextView, "getHorizontallyScrolling", false);
+ final int availableWidth = horizontallyScrolling
+ ? VERY_WIDE
+ : mTextView.getMeasuredWidth() - mTextView.getTotalPaddingLeft()
+ - mTextView.getTotalPaddingRight();
+ final int availableHeight = Build.VERSION.SDK_INT >= 21
+ ? mTextView.getHeight() - mTextView.getExtendedPaddingBottom()
+ - mTextView.getExtendedPaddingBottom()
+ : mTextView.getHeight() - mTextView.getCompoundPaddingBottom()
+ - mTextView.getCompoundPaddingTop();
- synchronized (TEMP_RECTF) {
- TEMP_RECTF.setEmpty();
- TEMP_RECTF.right = maxWidth;
- TEMP_RECTF.bottom = maxHeight;
- final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF);
- if (optimalTextSize != mTextView.getTextSize()) {
- setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize);
+ if (availableWidth <= 0 || availableHeight <= 0) {
+ return;
+ }
+
+ synchronized (TEMP_RECTF) {
+ TEMP_RECTF.setEmpty();
+ TEMP_RECTF.right = availableWidth;
+ TEMP_RECTF.bottom = availableHeight;
+ final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF);
+ if (optimalTextSize != mTextView.getTextSize()) {
+ setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize);
+ }
}
}
+ // Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing
+ // after the next layout pass should set this to false.
+ mNeedsAutoSizeText = true;
}
private void clearAutoSizeConfiguration() {
@@ -588,6 +600,11 @@
if (size != mTextView.getPaint().getTextSize()) {
mTextView.getPaint().setTextSize(size);
+ boolean isInLayout = false;
+ if (Build.VERSION.SDK_INT >= 18) {
+ isInLayout = mTextView.isInLayout();
+ }
+
if (mTextView.getLayout() != null) {
// Do not auto-size right after setting the text size.
mNeedsAutoSizeText = false;
@@ -611,7 +628,12 @@
// Nothing to do.
}
- mTextView.requestLayout();
+ if (!isInLayout) {
+ mTextView.requestLayout();
+ } else {
+ mTextView.forceLayout();
+ }
+
mTextView.invalidate();
}
}
@@ -648,12 +670,6 @@
private boolean suggestedSizeFitsInSpace(int suggestedSizeInPx, RectF availableSpace) {
final CharSequence text = mTextView.getText();
final int maxLines = Build.VERSION.SDK_INT >= 16 ? mTextView.getMaxLines() : -1;
- final boolean horizontallyScrolling = invokeAndReturnWithDefault(
- mTextView, "getHorizontallyScrolling", false);
- final int availableWidth = horizontallyScrolling
- ? VERY_WIDE
- : mTextView.getMeasuredWidth() - mTextView.getTotalPaddingLeft()
- - mTextView.getTotalPaddingRight();
if (mTempTextPaint == null) {
mTempTextPaint = new TextPaint();
} else {
@@ -666,8 +682,10 @@
Layout.Alignment alignment = invokeAndReturnWithDefault(
mTextView, "getLayoutAlignment", Layout.Alignment.ALIGN_NORMAL);
final StaticLayout layout = Build.VERSION.SDK_INT >= 23
- ? createStaticLayoutForMeasuring(text, alignment, availableWidth, maxLines)
- : createStaticLayoutForMeasuringPre23(text, alignment, availableWidth);
+ ? createStaticLayoutForMeasuring(
+ text, alignment, Math.round(availableSpace.right), maxLines)
+ : createStaticLayoutForMeasuringPre23(
+ text, alignment, Math.round(availableSpace.right));
// Lines overflow.
if (maxLines != -1 && layout.getLineCount() > maxLines) {
@@ -779,18 +797,6 @@
&& mAutoSizeTextType != TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE;
}
- /** @hide */
- @RestrictTo(LIBRARY_GROUP)
- boolean getNeedsAutoSizeText() {
- return mNeedsAutoSizeText;
- }
-
- /** @hide */
- @RestrictTo(LIBRARY_GROUP)
- void setNeedsAutoSizeText(boolean needsAutoSizeText) {
- mNeedsAutoSizeText = needsAutoSizeText;
- }
-
/**
* @return {@code true} if this TextView supports auto-sizing text to fit within its container.
*/
diff --git a/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java b/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java
index 6abdb75..bb400f1 100644
--- a/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java
+++ b/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java
@@ -1054,8 +1054,7 @@
final int margin = lp.topMargin + lp.bottomMargin;
final int childHeight = child.getMeasuredHeight() + margin;
- childState = ViewUtils.combineMeasuredStates(childState,
- child.getMeasuredState());
+ childState = View.combineMeasuredStates(childState, child.getMeasuredState());
if (baselineAligned) {
final int childBaseline = child.getBaseline();
diff --git a/v7/appcompat/src/android/support/v7/widget/SuggestionsAdapter.java b/v7/appcompat/src/android/support/v7/widget/SuggestionsAdapter.java
index 24dafb3..d6f0099 100644
--- a/v7/appcompat/src/android/support/v7/widget/SuggestionsAdapter.java
+++ b/v7/appcompat/src/android/support/v7/widget/SuggestionsAdapter.java
@@ -503,7 +503,7 @@
* @return a Drawable, or null if none found
*/
private Drawable getDrawableFromResourceValue(String drawableId) {
- if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) {
+ if (drawableId == null || drawableId.isEmpty() || "0".equals(drawableId)) {
return null;
}
try {
diff --git a/v7/appcompat/src/android/support/v7/widget/TintTypedArray.java b/v7/appcompat/src/android/support/v7/widget/TintTypedArray.java
index b920505..0a86600 100644
--- a/v7/appcompat/src/android/support/v7/widget/TintTypedArray.java
+++ b/v7/appcompat/src/android/support/v7/widget/TintTypedArray.java
@@ -31,7 +31,6 @@
import android.support.annotation.RestrictTo;
import android.support.annotation.StyleableRes;
import android.support.v4.content.res.ResourcesCompat;
-import android.support.v4.os.BuildCompat;
import android.support.v7.content.res.AppCompatResources;
import android.util.AttributeSet;
import android.util.TypedValue;
@@ -110,7 +109,7 @@
*/
@Nullable
public Typeface getFont(@StyleableRes int index, int style, @NonNull TextView targetView) {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
return mWrapped.getFont(index);
}
final int resourceId = mWrapped.getResourceId(index, 0);
diff --git a/v7/appcompat/src/android/support/v7/widget/TooltipCompat.java b/v7/appcompat/src/android/support/v7/widget/TooltipCompat.java
index f7466bc..470c3b2 100644
--- a/v7/appcompat/src/android/support/v7/widget/TooltipCompat.java
+++ b/v7/appcompat/src/android/support/v7/widget/TooltipCompat.java
@@ -17,9 +17,9 @@
package android.support.v7.widget;
import android.annotation.TargetApi;
+import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.v4.os.BuildCompat;
import android.view.View;
/**
@@ -49,7 +49,7 @@
private static final ViewCompatImpl IMPL;
static {
- if (BuildCompat.isAtLeastO()) {
+ if (Build.VERSION.SDK_INT >= 26) {
IMPL = new Api26ViewCompatImpl();
} else {
IMPL = new BaseViewCompatImpl();
diff --git a/v7/appcompat/src/android/support/v7/widget/TooltipCompatHandler.java b/v7/appcompat/src/android/support/v7/widget/TooltipCompatHandler.java
index 4670534..b7f0c2c 100644
--- a/v7/appcompat/src/android/support/v7/widget/TooltipCompatHandler.java
+++ b/v7/appcompat/src/android/support/v7/widget/TooltipCompatHandler.java
@@ -22,7 +22,6 @@
import android.content.Context;
import android.support.annotation.RestrictTo;
import android.support.v4.view.ViewCompat;
-import android.support.v4.view.accessibility.AccessibilityManagerCompat;
import android.text.TextUtils;
import android.util.Log;
import android.view.MotionEvent;
@@ -116,8 +115,7 @@
}
AccessibilityManager manager = (AccessibilityManager)
mAnchor.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
- if (manager.isEnabled()
- && AccessibilityManagerCompat.isTouchExplorationEnabled(manager)) {
+ if (manager.isEnabled() && manager.isTouchExplorationEnabled()) {
return false;
}
switch (event.getAction()) {
diff --git a/v7/appcompat/src/android/support/v7/widget/ViewUtils.java b/v7/appcompat/src/android/support/v7/widget/ViewUtils.java
index 58acb03..0f910c3 100644
--- a/v7/appcompat/src/android/support/v7/widget/ViewUtils.java
+++ b/v7/appcompat/src/android/support/v7/widget/ViewUtils.java
@@ -58,21 +58,6 @@
}
/**
- * Merge two states as returned by {@link View#getMeasuredState()} ()}.
- * @param curState The current state as returned from a view or the result
- * of combining multiple views.
- * @param newState The new view state to combine.
- * @return Returns a new integer reflecting the combination of the two
- * states.
- *
- * @deprecated Use {@link View#combineMeasuredStates(int, int)} directly.
- */
- @Deprecated
- public static int combineMeasuredStates(int curState, int newState) {
- return View.combineMeasuredStates(curState, newState);
- }
-
- /**
* Allow calling the hidden method {@code computeFitSystemWindows(Rect, Rect)} through
* reflection on {@code view}.
*/
diff --git a/v7/appcompat/tests/fonts_readme.txt b/v7/appcompat/tests/fonts_readme.txt
new file mode 100644
index 0000000..f0de576
--- /dev/null
+++ b/v7/appcompat/tests/fonts_readme.txt
@@ -0,0 +1,15 @@
+All fonts included in this project follow the below copyright and licensing:
+
+Copyright (C) 2017 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/v7/appcompat/tests/res/font/samplefont.ttf b/v7/appcompat/tests/res/font/samplefont.ttf
index 2852302..5fccad2 100644
--- a/v7/appcompat/tests/res/font/samplefont.ttf
+++ b/v7/appcompat/tests/res/font/samplefont.ttf
Binary files differ
diff --git a/v7/appcompat/tests/res/font/samplefont2.ttf b/v7/appcompat/tests/res/font/samplefont2.ttf
index 2852302..f31b8a9 100644
--- a/v7/appcompat/tests/res/font/samplefont2.ttf
+++ b/v7/appcompat/tests/res/font/samplefont2.ttf
Binary files differ
diff --git a/v7/appcompat/tests/res/font/samplefont3.ttf b/v7/appcompat/tests/res/font/samplefont3.ttf
index 2852302..9c850ab 100644
--- a/v7/appcompat/tests/res/font/samplefont3.ttf
+++ b/v7/appcompat/tests/res/font/samplefont3.ttf
Binary files differ
diff --git a/v7/appcompat/tests/res/font/samplefont4.ttf b/v7/appcompat/tests/res/font/samplefont4.ttf
index 2852302..9c850ab 100644
--- a/v7/appcompat/tests/res/font/samplefont4.ttf
+++ b/v7/appcompat/tests/res/font/samplefont4.ttf
Binary files differ
diff --git a/v7/appcompat/tests/res/values/strings.xml b/v7/appcompat/tests/res/values/strings.xml
index 8a1746b..86386e2 100644
--- a/v7/appcompat/tests/res/values/strings.xml
+++ b/v7/appcompat/tests/res/values/strings.xml
@@ -95,4 +95,5 @@
<string name="menu6">menu six</string>
<string name="font_sans_serif">sans-serif</string>
+ <string name="font_serif">serif</string>
</resources>
diff --git a/v7/appcompat/tests/res/values/styles.xml b/v7/appcompat/tests/res/values/styles.xml
index 81f8493..c08930a 100644
--- a/v7/appcompat/tests/res/values/styles.xml
+++ b/v7/appcompat/tests/res/values/styles.xml
@@ -70,4 +70,12 @@
<item name="fontFamily">@font/samplexmlfont</item>
<item name="android:textStyle">italic</item>
</style>
+
+ <style name="TextView_SansSerif">
+ <item name="android:fontFamily">@string/font_sans_serif</item>
+ </style>
+
+ <style name="TextView_Serif">
+ <item name="android:fontFamily">@string/font_serif</item>
+ </style>
</resources>
diff --git a/v7/appcompat/tests/src/android/support/v7/app/AlertDialogCursorTest.java b/v7/appcompat/tests/src/android/support/v7/app/AlertDialogCursorTest.java
index 8afd231..690cc26 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/AlertDialogCursorTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/AlertDialogCursorTest.java
@@ -45,6 +45,8 @@
import android.database.sqlite.SQLiteDatabase;
import android.support.test.espresso.DataInteraction;
import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v7.appcompat.test.R;
import android.support.v7.testutils.TestUtilsMatchers;
import android.view.View;
@@ -56,13 +58,17 @@
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.io.File;
@MediumTest
-public class AlertDialogCursorTest
- extends BaseInstrumentationTestCase<AlertDialogTestActivity> {
+@RunWith(AndroidJUnit4.class)
+public class AlertDialogCursorTest {
+ @Rule
+ public final ActivityTestRule<AlertDialogTestActivity> mActivityTestRule;
private Button mButton;
@@ -82,7 +88,7 @@
private AlertDialog mAlertDialog;
public AlertDialogCursorTest() {
- super(AlertDialogTestActivity.class);
+ mActivityTestRule = new ActivityTestRule<>(AlertDialogTestActivity.class);
}
@Before
diff --git a/v7/appcompat/tests/src/android/support/v7/app/AlertDialogTest.java b/v7/appcompat/tests/src/android/support/v7/app/AlertDialogTest.java
index 1d4b244..53cc4b5 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/AlertDialogTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/AlertDialogTest.java
@@ -60,6 +60,7 @@
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
import android.support.v7.appcompat.test.R;
import android.support.v7.testutils.TestUtilsMatchers;
import android.text.TextUtils;
@@ -76,6 +77,7 @@
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -95,13 +97,16 @@
* is rendered by a single <code>CheckedTextView</code>.</li>
* </ul>
*/
-public class AlertDialogTest extends BaseInstrumentationTestCase<AlertDialogTestActivity> {
+public class AlertDialogTest {
+ @Rule
+ public final ActivityTestRule<AlertDialogTestActivity> mActivityTestRule;
+
private Button mButton;
private AlertDialog mAlertDialog;
public AlertDialogTest() {
- super(AlertDialogTestActivity.class);
+ mActivityTestRule = new ActivityTestRule<>(AlertDialogTestActivity.class);
}
@Before
diff --git a/v7/appcompat/tests/src/android/support/v7/app/AppCompatVectorDrawableIntegrationTest.java b/v7/appcompat/tests/src/android/support/v7/app/AppCompatVectorDrawableIntegrationTest.java
index 905521d..84816ae 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/AppCompatVectorDrawableIntegrationTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/AppCompatVectorDrawableIntegrationTest.java
@@ -24,17 +24,23 @@
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.test.annotation.UiThreadTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v7.appcompat.test.R;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.View;
import android.widget.ImageView;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
@SmallTest
-public class AppCompatVectorDrawableIntegrationTest
- extends BaseInstrumentationTestCase<AppCompatVectorDrawableIntegrationActivity> {
+@RunWith(AndroidJUnit4.class)
+public class AppCompatVectorDrawableIntegrationTest {
+ @Rule
+ public final ActivityTestRule<AppCompatVectorDrawableIntegrationActivity> mActivityTestRule;
private Bitmap mBitmap;
private Canvas mCanvas;
@@ -46,7 +52,8 @@
private static final int CENTER_Y = HEIGHT / 2;
public AppCompatVectorDrawableIntegrationTest() {
- super(AppCompatVectorDrawableIntegrationActivity.class);
+ mActivityTestRule =
+ new ActivityTestRule<>(AppCompatVectorDrawableIntegrationActivity.class);
}
@Before
diff --git a/v7/appcompat/tests/src/android/support/v7/app/BaseBasicsTestCase.java b/v7/appcompat/tests/src/android/support/v7/app/BaseBasicsTestCase.java
index 6112d34..c634097 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/BaseBasicsTestCase.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/BaseBasicsTestCase.java
@@ -42,6 +42,8 @@
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SdkSuppress;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v7.appcompat.test.R;
import android.support.v7.custom.FitWindowsContentLayout;
import android.support.v7.testutils.BaseTestActivity;
@@ -50,24 +52,31 @@
import android.view.View;
import android.view.WindowInsets;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
@SmallTest
-public abstract class BaseBasicsTestCase<A extends BaseTestActivity>
- extends BaseInstrumentationTestCase<A> {
+@RunWith(AndroidJUnit4.class)
+public abstract class BaseBasicsTestCase<A extends BaseTestActivity> {
+ @Rule
+ public final ActivityTestRule<A> mActivityTestRule;
+
protected BaseBasicsTestCase(Class<A> activityClass) {
- super(activityClass);
+ mActivityTestRule = new ActivityTestRule<>(activityClass);
}
@Test
public void testActionBarExists() {
- assertNotNull("ActionBar is not null", getActivity().getSupportActionBar());
+ assertNotNull("ActionBar is not null",
+ mActivityTestRule.getActivity().getSupportActionBar());
}
@Test
public void testDefaultActionBarTitle() {
- assertEquals(getActivity().getTitle(), getActivity().getSupportActionBar().getTitle());
+ assertEquals(mActivityTestRule.getActivity().getTitle(),
+ mActivityTestRule.getActivity().getSupportActionBar().getTitle());
}
@UiThreadTest
@@ -84,10 +93,10 @@
@RequiresApi(16)
public void testFitSystemWindowsReachesContent() {
final FitWindowsContentLayout content =
- (FitWindowsContentLayout) getActivity().findViewById(R.id.test_content);
+ mActivityTestRule.getActivity().findViewById(R.id.test_content);
assertNotNull(content);
- if (!canShowSystemUi(getActivity())) {
+ if (!canShowSystemUi(mActivityTestRule.getActivity())) {
// Device cannot show system UI so setSystemUiVisibility will do nothing.
return;
}
@@ -103,10 +112,10 @@
@SdkSuppress(minSdkVersion = 21)
@RequiresApi(21)
public void testOnApplyWindowInsetsReachesContent() {
- final View content = getActivity().findViewById(R.id.test_content);
+ final View content = mActivityTestRule.getActivity().findViewById(R.id.test_content);
assertNotNull(content);
- if (!canShowSystemUi(getActivity())) {
+ if (!canShowSystemUi(mActivityTestRule.getActivity())) {
// Device cannot show system UI so setSystemUiVisibility will do nothing.
return;
}
@@ -128,7 +137,7 @@
@Test
@UiThreadTest
public void testSupportActionModeCallbacks() {
- final A activity = getActivity();
+ final A activity = mActivityTestRule.getActivity();
// Create a mock action mode callback which returns true from onCreateActionMode
final ActionMode.Callback callback = mock(ActionMode.Callback.class);
@@ -152,7 +161,7 @@
@Test
@UiThreadTest
public void testSupportActionModeCallbacksInvalidate() {
- final A activity = getActivity();
+ final A activity = mActivityTestRule.getActivity();
// Create a mock action mode callback which returns true from onCreateActionMode
final ActionMode.Callback callback = mock(ActionMode.Callback.class);
@@ -176,7 +185,7 @@
@Test
@UiThreadTest
public void testSupportActionModeCallbacksWithFalseOnCreate() {
- final A activity = getActivity();
+ final A activity = mActivityTestRule.getActivity();
// Create a mock action mode callback which returns true from onCreateActionMode
final ActionMode.Callback callback = mock(ActionMode.Callback.class);
@@ -206,7 +215,7 @@
}
protected void testSupportActionModeAppCompatCallbacks(final boolean fromWindow) {
- final A activity = getActivity();
+ final A activity = mActivityTestRule.getActivity();
// Create a mock action mode callback which returns true from onCreateActionMode
final ActionMode.Callback amCallback = mock(ActionMode.Callback.class);
diff --git a/v7/appcompat/tests/src/android/support/v7/app/BaseInstrumentationTestCase.java b/v7/appcompat/tests/src/android/support/v7/app/BaseInstrumentationTestCase.java
deleted file mode 100644
index c98df27..0000000
--- a/v7/appcompat/tests/src/android/support/v7/app/BaseInstrumentationTestCase.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v7.app;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Rule;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public abstract class BaseInstrumentationTestCase<A extends Activity> {
-
- @Rule
- public final ActivityTestRule<A> mActivityTestRule;
-
- protected BaseInstrumentationTestCase(Class<A> activityClass) {
- mActivityTestRule = new ActivityTestRule<A>(activityClass);
- }
-
- @Deprecated
- public A getActivity() {
- return mActivityTestRule.getActivity();
- }
-
- @Deprecated
- public Instrumentation getInstrumentation() {
- return InstrumentationRegistry.getInstrumentation();
- }
-}
diff --git a/v7/appcompat/tests/src/android/support/v7/app/BaseKeyEventsTestCase.java b/v7/appcompat/tests/src/android/support/v7/app/BaseKeyEventsTestCase.java
index 5e10e97..135f65d 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/BaseKeyEventsTestCase.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/BaseKeyEventsTestCase.java
@@ -30,8 +30,12 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import android.app.Instrumentation;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.appcompat.test.R;
import android.support.v7.testutils.BaseTestActivity;
@@ -41,15 +45,29 @@
import android.view.MenuItem;
import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.concurrent.atomic.AtomicBoolean;
-public abstract class BaseKeyEventsTestCase<A extends BaseTestActivity>
- extends BaseInstrumentationTestCase<A> {
+@RunWith(AndroidJUnit4.class)
+public abstract class BaseKeyEventsTestCase<A extends BaseTestActivity> {
+ @Rule
+ public final ActivityTestRule<A> mActivityTestRule;
+
+ private Instrumentation mInstrumentation;
+ private A mActivity;
protected BaseKeyEventsTestCase(Class<A> activityClass) {
- super(activityClass);
+ mActivityTestRule = new ActivityTestRule<>(activityClass);
+ }
+
+ @Before
+ public void setup() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mActivity = mActivityTestRule.getActivity();
}
@Test
@@ -57,10 +75,10 @@
public void testBackDismissesActionMode() {
final AtomicBoolean destroyed = new AtomicBoolean();
- getActivity().runOnUiThread(new Runnable() {
+ mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
- getActivity().startSupportActionMode(new ActionMode.Callback() {
+ mActivity.startSupportActionMode(new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.sample_actions, menu);
@@ -85,11 +103,11 @@
}
});
- getInstrumentation().waitForIdleSync();
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ mInstrumentation.waitForIdleSync();
- assertFalse("Activity was not finished", getActivity().isFinishing());
+ assertFalse("Activity was not finished", mActivity.isFinishing());
assertTrue("ActionMode was destroyed", destroyed.get());
}
@@ -103,14 +121,14 @@
.check(matches(isDisplayed()));
// Let things settle
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
// Now send a back event to collapse the custom action view
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ mInstrumentation.waitForIdleSync();
// Check that the Activity is still running
- assertFalse(getActivity().isFinishing());
- assertFalse(getActivity().isDestroyed());
+ assertFalse(mActivity.isFinishing());
+ assertFalse(mActivity.isDestroyed());
// ... and that our action view is not attached
onView(withClassName(Matchers.is(CustomCollapsibleView.class.getName())))
.check(doesNotExist());
@@ -119,24 +137,24 @@
@Test
@SmallTest
public void testMenuPressInvokesPanelCallbacks() throws InterruptedException {
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
- getInstrumentation().waitForIdleSync();
- assertTrue("onMenuOpened called", getActivity().wasOnMenuOpenedCalled());
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
+ mInstrumentation.waitForIdleSync();
+ assertTrue("onMenuOpened called", mActivity.wasOnMenuOpenedCalled());
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
- getInstrumentation().waitForIdleSync();
- assertTrue("onPanelClosed called", getActivity().wasOnPanelClosedCalled());
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
+ mInstrumentation.waitForIdleSync();
+ assertTrue("onPanelClosed called", mActivity.wasOnPanelClosedCalled());
}
@Test
@SmallTest
public void testBackPressWithMenuInvokesOnPanelClosed() throws InterruptedException {
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
+ mInstrumentation.waitForIdleSync();
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- getInstrumentation().waitForIdleSync();
- assertTrue("onPanelClosed called", getActivity().wasOnPanelClosedCalled());
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ mInstrumentation.waitForIdleSync();
+ assertTrue("onPanelClosed called", mActivity.wasOnPanelClosedCalled());
}
@Test
@@ -144,25 +162,25 @@
public void testBackPressWithEmptyMenuFinishesActivity() throws InterruptedException {
repopulateWithEmptyMenu();
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
+ mInstrumentation.waitForIdleSync();
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- assertTrue(getActivity().isFinishing());
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ assertTrue(mActivity.isFinishing());
}
@Test
@SmallTest
public void testDelKeyEventReachesActivity() {
// First send the event
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DEL);
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DEL);
+ mInstrumentation.waitForIdleSync();
- KeyEvent downEvent = getActivity().getInvokedKeyDownEvent();
+ KeyEvent downEvent = mActivity.getInvokedKeyDownEvent();
assertNotNull("onKeyDown called", downEvent);
assertEquals("onKeyDown event matches", KeyEvent.KEYCODE_DEL, downEvent.getKeyCode());
- KeyEvent upEvent = getActivity().getInvokedKeyUpEvent();
+ KeyEvent upEvent = mActivity.getInvokedKeyUpEvent();
assertNotNull("onKeyUp called", upEvent);
assertEquals("onKeyUp event matches", KeyEvent.KEYCODE_DEL, upEvent.getKeyCode());
}
@@ -170,14 +188,14 @@
@Test
@SmallTest
public void testMenuKeyEventReachesActivity() throws InterruptedException {
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
+ mInstrumentation.waitForIdleSync();
- KeyEvent downEvent = getActivity().getInvokedKeyDownEvent();
+ KeyEvent downEvent = mActivity.getInvokedKeyDownEvent();
assertNotNull("onKeyDown called", downEvent);
assertEquals("onKeyDown event matches", KeyEvent.KEYCODE_MENU, downEvent.getKeyCode());
- KeyEvent upEvent = getActivity().getInvokedKeyUpEvent();
+ KeyEvent upEvent = mActivity.getInvokedKeyUpEvent();
assertNotNull("onKeyUp called", upEvent);
assertEquals("onKeyDown event matches", KeyEvent.KEYCODE_MENU, upEvent.getKeyCode());
}
@@ -193,7 +211,7 @@
.check(matches(isDisplayed()))
.check(matches(withContentDescription((String) null)));
- Menu menu = getActivity().getMenu();
+ Menu menu = mActivity.getMenu();
final MenuItem alphaItem = menu.findItem(R.id.action_alpha_shortcut);
assertNotNull(alphaItem);
@@ -201,9 +219,9 @@
@Override
public void run() {
MenuItemCompat.setContentDescription(alphaItem,
- getActivity().getString(R.string.alpha_menu_description));
+ mActivity.getString(R.string.alpha_menu_description));
MenuItemCompat.setTooltipText(alphaItem,
- getActivity().getString(R.string.alpha_menu_tooltip));
+ mActivity.getString(R.string.alpha_menu_tooltip));
}
});
@@ -214,9 +232,9 @@
private void repopulateWithEmptyMenu() throws InterruptedException {
int count = 0;
- getActivity().setShouldPopulateOptionsMenu(false);
+ mActivity.setShouldPopulateOptionsMenu(false);
while (count++ < 10) {
- Menu menu = getActivity().getMenu();
+ Menu menu = mActivity.getMenu();
if (menu == null || menu.size() != 0) {
Thread.sleep(100);
} else {
diff --git a/v7/appcompat/tests/src/android/support/v7/app/BaseKeyboardShortcutsTestCase.java b/v7/appcompat/tests/src/android/support/v7/app/BaseKeyboardShortcutsTestCase.java
index cb21347..88216d1 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/BaseKeyboardShortcutsTestCase.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/BaseKeyboardShortcutsTestCase.java
@@ -19,21 +19,29 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import android.app.Instrumentation;
import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v7.appcompat.test.R;
import android.support.v7.testutils.BaseTestActivity;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MenuItem;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
-public abstract class BaseKeyboardShortcutsTestCase<A extends BaseTestActivity>
- extends BaseInstrumentationTestCase<A> {
+@RunWith(AndroidJUnit4.class)
+public abstract class BaseKeyboardShortcutsTestCase<A extends BaseTestActivity> {
+ @Rule
+ public final ActivityTestRule<A> mActivityTestRule;
protected BaseKeyboardShortcutsTestCase(Class<A> activityClass) {
- super(activityClass);
+ mActivityTestRule = new ActivityTestRule<>(activityClass);
}
@Test
@@ -45,18 +53,19 @@
}
private void testKeyboardShortcut(final int keyCode, final int meta, final int expectedId) {
+ final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
final long downTime = SystemClock.uptimeMillis();
final KeyEvent downEvent = new KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN,
keyCode, 0, meta, KeyCharacterMap.VIRTUAL_KEYBOARD, 0);
- getInstrumentation().sendKeySync(downEvent);
- getInstrumentation().waitForIdleSync();
+ instrumentation.sendKeySync(downEvent);
+ instrumentation.waitForIdleSync();
final KeyEvent upEvent = new KeyEvent(downTime, downTime + 500, KeyEvent.ACTION_UP,
keyCode, 0, meta, KeyCharacterMap.VIRTUAL_KEYBOARD, 0);
- getInstrumentation().sendKeySync(upEvent);
- getInstrumentation().waitForIdleSync();
+ instrumentation.sendKeySync(upEvent);
+ instrumentation.waitForIdleSync();
- MenuItem selectedItem = getActivity().getOptionsItemSelected();
+ MenuItem selectedItem = mActivityTestRule.getActivity().getOptionsItemSelected();
assertNotNull("Options item selected", selectedItem);
assertEquals("Correct options item selected", selectedItem.getItemId(), expectedId);
}
diff --git a/v7/appcompat/tests/src/android/support/v7/app/DialogTestCase.java b/v7/appcompat/tests/src/android/support/v7/app/DialogTestCase.java
index 8230cbc..ce9c157 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/DialogTestCase.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/DialogTestCase.java
@@ -21,25 +21,30 @@
import android.app.Dialog;
import android.os.Bundle;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
-public class DialogTestCase extends BaseInstrumentationTestCase<WindowDecorAppCompatActivity> {
-
- public DialogTestCase() {
- super(WindowDecorAppCompatActivity.class);
- }
+@RunWith(AndroidJUnit4.class)
+public class DialogTestCase {
+ @Rule
+ public final ActivityTestRule<WindowDecorAppCompatActivity> mActivityTestRule =
+ new ActivityTestRule<>(WindowDecorAppCompatActivity.class);
@Test
public void testDialogFragmentShows() {
- getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
TestDialogFragment fragment = new TestDialogFragment();
- fragment.show(getActivity().getSupportFragmentManager(), null);
+ fragment.show(mActivityTestRule.getActivity().getSupportFragmentManager(), null);
- getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
assertNotNull("Dialog was null", fragment.getDialog());
assertTrue("Dialog was not being shown", fragment.getDialog().isShowing());
diff --git a/v7/appcompat/tests/src/android/support/v7/app/DrawerDynamicLayoutTest.java b/v7/appcompat/tests/src/android/support/v7/app/DrawerDynamicLayoutTest.java
index 198c63a..54597c0 100755
--- a/v7/appcompat/tests/src/android/support/v7/app/DrawerDynamicLayoutTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/DrawerDynamicLayoutTest.java
@@ -28,6 +28,8 @@
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.appcompat.test.R;
import android.view.View;
@@ -37,18 +39,20 @@
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.After;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Test cases to verify that <code>DrawerLayout</code> only supports configurations
* with at most one drawer child along each vertical (left / right) edge.
*/
@SmallTest
-public class DrawerDynamicLayoutTest
- extends BaseInstrumentationTestCase<DrawerDynamicLayoutActivity> {
- public DrawerDynamicLayoutTest() {
- super(DrawerDynamicLayoutActivity.class);
- }
+@RunWith(AndroidJUnit4.class)
+public class DrawerDynamicLayoutTest {
+ @Rule
+ public final ActivityTestRule<DrawerDynamicLayoutActivity> mActivityTestRule =
+ new ActivityTestRule<>(DrawerDynamicLayoutActivity.class);
@UiThreadTest
@After
diff --git a/v7/appcompat/tests/src/android/support/v7/app/DrawerLayoutDoubleTest.java b/v7/appcompat/tests/src/android/support/v7/app/DrawerLayoutDoubleTest.java
index 2f43430..8578798 100755
--- a/v7/appcompat/tests/src/android/support/v7/app/DrawerLayoutDoubleTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/DrawerLayoutDoubleTest.java
@@ -28,6 +28,8 @@
import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.appcompat.test.R;
@@ -35,10 +37,16 @@
import android.view.View;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
-public class DrawerLayoutDoubleTest
- extends BaseInstrumentationTestCase<DrawerLayoutDoubleActivity> {
+@RunWith(AndroidJUnit4.class)
+public class DrawerLayoutDoubleTest {
+ @Rule
+ public final ActivityTestRule<DrawerLayoutDoubleActivity> mActivityTestRule =
+ new ActivityTestRule<>(DrawerLayoutDoubleActivity.class);
+
private CustomDrawerLayout mDrawerLayout;
private View mStartDrawer;
@@ -47,10 +55,6 @@
private View mContentView;
- public DrawerLayoutDoubleTest() {
- super(DrawerLayoutDoubleActivity.class);
- }
-
@Before
public void setUp() {
final DrawerLayoutDoubleActivity activity = mActivityTestRule.getActivity();
diff --git a/v7/appcompat/tests/src/android/support/v7/app/DrawerLayoutTest.java b/v7/appcompat/tests/src/android/support/v7/app/DrawerLayoutTest.java
index 34c5d64..f43c909 100755
--- a/v7/appcompat/tests/src/android/support/v7/app/DrawerLayoutTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/DrawerLayoutTest.java
@@ -49,6 +49,8 @@
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import android.support.test.filters.Suppress;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.appcompat.test.R;
@@ -56,21 +58,24 @@
import android.view.View;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
-public class DrawerLayoutTest extends BaseInstrumentationTestCase<DrawerLayoutActivity> {
+@RunWith(AndroidJUnit4.class)
+public class DrawerLayoutTest {
+ @Rule
+ public final ActivityTestRule<DrawerLayoutActivity> mActivityTestRule =
+ new ActivityTestRule<DrawerLayoutActivity>(DrawerLayoutActivity.class);
+
private CustomDrawerLayout mDrawerLayout;
private View mStartDrawer;
private View mContentView;
- public DrawerLayoutTest() {
- super(DrawerLayoutActivity.class);
- }
-
@Before
public void setUp() {
final DrawerLayoutActivity activity = mActivityTestRule.getActivity();
diff --git a/v7/appcompat/tests/src/android/support/v7/app/FragmentContentIdTest.java b/v7/appcompat/tests/src/android/support/v7/app/FragmentContentIdTest.java
index c2e2d16..c316e29 100755
--- a/v7/appcompat/tests/src/android/support/v7/app/FragmentContentIdTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/FragmentContentIdTest.java
@@ -23,15 +23,19 @@
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v7.appcompat.test.R;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
-public class FragmentContentIdTest extends BaseInstrumentationTestCase<FragmentContentIdActivity> {
-
- public FragmentContentIdTest() {
- super(FragmentContentIdActivity.class);
- }
+@RunWith(AndroidJUnit4.class)
+public class FragmentContentIdTest {
+ @Rule
+ public final ActivityTestRule<FragmentContentIdActivity> mActivityTestRule =
+ new ActivityTestRule<>(FragmentContentIdActivity.class);
@SmallTest
@Test
@@ -48,5 +52,4 @@
// And that fragment_b is displayed
onView(withId(R.id.fragment_b)).check(matches(isDisplayed()));
}
-
}
diff --git a/v7/appcompat/tests/src/android/support/v7/app/KeyEventsTestCaseWithToolbar.java b/v7/appcompat/tests/src/android/support/v7/app/KeyEventsTestCaseWithToolbar.java
index 80cfcaa..e7d485b 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/KeyEventsTestCaseWithToolbar.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/KeyEventsTestCaseWithToolbar.java
@@ -16,14 +16,15 @@
package android.support.v7.app;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.v7.widget.Toolbar;
import android.view.KeyEvent;
import android.view.Window;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
import org.junit.Test;
public class KeyEventsTestCaseWithToolbar extends BaseKeyEventsTestCase<ToolbarAppCompatActivity> {
@@ -46,12 +47,12 @@
Toolbar toolbar = mActivityTestRule.getActivity().getToolbar();
assertFalse(toolbar.isOverflowMenuShowing());
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
- getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
assertTrue(toolbar.isOverflowMenuShowing());
- getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
- getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
assertFalse(toolbar.isOverflowMenuShowing());
}
@@ -70,7 +71,7 @@
mActivityTestRule.getActivity().openOptionsMenu();
}
});
- getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
assertTrue(toolbar.isOverflowMenuShowing());
mActivityTestRule.runOnUiThread(new Runnable() {
@@ -79,7 +80,7 @@
mActivityTestRule.getActivity().closeOptionsMenu();
}
});
- getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
assertFalse(toolbar.isOverflowMenuShowing());
}
}
diff --git a/v7/appcompat/tests/src/android/support/v7/app/KeyboardShortcutsTestCaseWithToolbar.java b/v7/appcompat/tests/src/android/support/v7/app/KeyboardShortcutsTestCaseWithToolbar.java
index fc2b2ae..4f450ff 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/KeyboardShortcutsTestCaseWithToolbar.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/KeyboardShortcutsTestCaseWithToolbar.java
@@ -22,7 +22,10 @@
import android.os.Build;
import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v7.testutils.BaseTestActivity;
import android.support.v7.widget.Toolbar;
import android.view.KeyEvent;
@@ -30,13 +33,15 @@
import android.view.View;
import android.view.Window;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
-public class KeyboardShortcutsTestCaseWithToolbar
- extends BaseKeyboardShortcutsTestCase<ToolbarAppCompatActivity> {
- public KeyboardShortcutsTestCaseWithToolbar() {
- super(ToolbarAppCompatActivity.class);
- }
+@RunWith(AndroidJUnit4.class)
+public class KeyboardShortcutsTestCaseWithToolbar {
+ @Rule
+ public final ActivityTestRule<ToolbarAppCompatActivity> mActivityTestRule =
+ new ActivityTestRule<>(ToolbarAppCompatActivity.class);
@Test
@SmallTest
@@ -45,7 +50,7 @@
if (Build.VERSION.SDK_INT <= 25) {
return;
}
- final BaseTestActivity activity = getActivity();
+ final BaseTestActivity activity = mActivityTestRule.getActivity();
final View editText = activity.findViewById(android.support.v7.appcompat.test.R.id.editText);
mActivityTestRule.runOnUiThread(new Runnable() {
@@ -55,9 +60,9 @@
}
});
- getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
sendMetaKey(KeyEvent.KEYCODE_TAB);
- getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
@@ -71,7 +76,7 @@
// navigation won't leaves it.
sendMetaKey(KeyEvent.KEYCODE_TAB);
- getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
// Should jump to the first view again.
mActivityTestRule.runOnUiThread(new Runnable() {
@@ -85,10 +90,10 @@
@Test
@SmallTest
public void testKeyShortcuts() throws Throwable {
- final ToolbarAppCompatActivity activity = getActivity();
+ final ToolbarAppCompatActivity activity = mActivityTestRule.getActivity();
final Toolbar toolbar =
- (Toolbar) activity.findViewById(android.support.v7.appcompat.test.R.id.toolbar);
+ activity.findViewById(android.support.v7.appcompat.test.R.id.toolbar);
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
@@ -135,7 +140,7 @@
activity.resetCounters();
// Make sure that unhandled shortcuts don't prepare menus (since toolbar is handling that).
- getInstrumentation().sendKeySync(unhandledShortcutKey);
+ InstrumentationRegistry.getInstrumentation().sendKeySync(unhandledShortcutKey);
assertEquals(1, activity.mKeyShortcutCount);
assertEquals(0, activity.mPrepareMenuCount);
assertEquals(0, activity.mCreateMenuCount);
@@ -145,10 +150,10 @@
long time = SystemClock.uptimeMillis();
KeyEvent keyDown = new KeyEvent(time, time, KeyEvent.ACTION_DOWN, keyCode,
0, KeyEvent.META_META_ON);
- getInstrumentation().sendKeySync(keyDown);
+ InstrumentationRegistry.getInstrumentation().sendKeySync(keyDown);
time = SystemClock.uptimeMillis();
KeyEvent keyUp = new KeyEvent(time, time, KeyEvent.ACTION_UP, keyCode,
0, KeyEvent.META_META_ON);
- getInstrumentation().sendKeySync(keyUp);
+ InstrumentationRegistry.getInstrumentation().sendKeySync(keyUp);
}
}
diff --git a/v7/appcompat/tests/src/android/support/v7/app/LayoutInflaterFactoryTestCase.java b/v7/appcompat/tests/src/android/support/v7/app/LayoutInflaterFactoryTestCase.java
index 64c63a0..892a554 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/LayoutInflaterFactoryTestCase.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/LayoutInflaterFactoryTestCase.java
@@ -20,12 +20,14 @@
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
-import android.support.annotation.RequiresApi;
import android.content.Context;
import android.content.res.Resources;
+import android.support.annotation.RequiresApi;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SdkSuppress;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v7.appcompat.test.R;
import android.support.v7.custom.ContextWrapperFrameLayout;
import android.support.v7.widget.AppCompatAutoCompleteTextView;
@@ -45,14 +47,15 @@
import android.widget.LinearLayout;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
-public class LayoutInflaterFactoryTestCase
- extends BaseInstrumentationTestCase<LayoutInflaterFactoryTestActivity> {
-
- public LayoutInflaterFactoryTestCase() {
- super(LayoutInflaterFactoryTestActivity.class);
- }
+@RunWith(AndroidJUnit4.class)
+public class LayoutInflaterFactoryTestCase {
+ @Rule
+ public final ActivityTestRule<LayoutInflaterFactoryTestActivity> mActivityTestRule =
+ new ActivityTestRule<>(LayoutInflaterFactoryTestActivity.class);
@Before
public void setup() {
@@ -64,7 +67,7 @@
@Test
@SmallTest
public void testAndroidThemeInflation() {
- final LayoutInflater inflater = LayoutInflater.from(getActivity());
+ final LayoutInflater inflater = LayoutInflater.from(mActivityTestRule.getActivity());
assertThemedContext(inflater.inflate(R.layout.layout_android_theme, null));
}
@@ -72,7 +75,7 @@
@Test
@SmallTest
public void testAppThemeInflation() {
- final LayoutInflater inflater = LayoutInflater.from(getActivity());
+ final LayoutInflater inflater = LayoutInflater.from(mActivityTestRule.getActivity());
assertThemedContext(inflater.inflate(R.layout.layout_app_theme, null));
}
@@ -83,7 +86,7 @@
@Test
@SmallTest
public void testAndroidThemeWithChildrenInflation() {
- LayoutInflater inflater = LayoutInflater.from(getActivity());
+ LayoutInflater inflater = LayoutInflater.from(mActivityTestRule.getActivity());
final ViewGroup root = (ViewGroup) inflater.inflate(
R.layout.layout_android_theme_children, null);
assertThemedContext(root);
@@ -93,7 +96,7 @@
@Test
@SmallTest
public void testThemedInflationWithUnattachedParent() {
- final Context activity = getActivity();
+ final Context activity = mActivityTestRule.getActivity();
// Create a parent but not attached
final LinearLayout parent = new LinearLayout(activity);
@@ -195,15 +198,15 @@
@Test
@SmallTest
public void testDeclarativeOnClickWithContextWrapper() {
- LayoutInflater inflater = LayoutInflater.from(getActivity());
+ LayoutInflater inflater = LayoutInflater.from(mActivityTestRule.getActivity());
View view = inflater.inflate(R.layout.layout_button_themed_onclick, null);
assertTrue(view.performClick());
- assertTrue(getActivity().wasDeclarativeOnClickCalled());
+ assertTrue(mActivityTestRule.getActivity().wasDeclarativeOnClickCalled());
}
private void verifyAppCompatWidgetInflation(final int layout, final Class<?> expectedClass) {
- LayoutInflater inflater = LayoutInflater.from(getActivity());
+ LayoutInflater inflater = LayoutInflater.from(mActivityTestRule.getActivity());
View view = inflater.inflate(layout, null);
assertSame("View is " + expectedClass.getSimpleName(), expectedClass,
view.getClass());
diff --git a/v7/appcompat/tests/src/android/support/v7/app/NightModeTestCase.java b/v7/appcompat/tests/src/android/support/v7/app/NightModeTestCase.java
index 2168069..2981ad4 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/NightModeTestCase.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/NightModeTestCase.java
@@ -28,22 +28,27 @@
import android.app.Instrumentation;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
-import android.support.test.filters.SdkSuppress;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v4.content.ContextCompat;
import android.support.v7.appcompat.test.R;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
@LargeTest
-@SdkSuppress(minSdkVersion = 14)
-public class NightModeTestCase extends BaseInstrumentationTestCase<NightModeActivity> {
+@RunWith(AndroidJUnit4.class)
+public class NightModeTestCase {
+ @Rule
+ public final ActivityTestRule<NightModeActivity> mActivityTestRule;
private static final String STRING_DAY = "DAY";
private static final String STRING_NIGHT = "NIGHT";
public NightModeTestCase() {
- super(NightModeActivity.class);
+ mActivityTestRule = new ActivityTestRule<>(NightModeActivity.class);
}
@Before
@@ -116,7 +121,7 @@
});
// Now wait for the recreate
- getInstrumentation().waitForIdleSync();
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
// Now check that the text has changed, signifying that night resources are being used
onView(withId(R.id.text_night_mode)).check(matches(withText(STRING_NIGHT)));
@@ -128,7 +133,7 @@
final FakeTwilightManager twilightManager = new FakeTwilightManager();
TwilightManager.setInstance(twilightManager);
- final NightModeActivity activity = getActivity();
+ final NightModeActivity activity = mActivityTestRule.getActivity();
// Set MODE_NIGHT_AUTO so that we will change to night mode automatically
setLocalNightModeAndWaitForRecreate(activity, AppCompatDelegate.MODE_NIGHT_AUTO);
@@ -138,7 +143,8 @@
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
public void run() {
- final Instrumentation instrumentation = getInstrumentation();
+ final Instrumentation instrumentation =
+ InstrumentationRegistry.getInstrumentation();
// Now fool the Activity into thinking that it has gone into the background
instrumentation.callActivityOnPause(activity);
instrumentation.callActivityOnStop(activity);
diff --git a/v7/appcompat/tests/src/android/support/v7/res/content/AppCompatResourcesTestCase.java b/v7/appcompat/tests/src/android/support/v7/res/content/AppCompatResourcesTestCase.java
index bfb456a..d6b9f83 100644
--- a/v7/appcompat/tests/src/android/support/v7/res/content/AppCompatResourcesTestCase.java
+++ b/v7/appcompat/tests/src/android/support/v7/res/content/AppCompatResourcesTestCase.java
@@ -23,25 +23,31 @@
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v4.graphics.ColorUtils;
import android.support.v7.app.AppCompatActivity;
-import android.support.v7.app.BaseInstrumentationTestCase;
import android.support.v7.appcompat.test.R;
import android.support.v7.content.res.AppCompatResources;
import android.support.v7.testutils.TestUtils;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
@SmallTest
-public class AppCompatResourcesTestCase extends BaseInstrumentationTestCase<AppCompatActivity> {
+@RunWith(AndroidJUnit4.class)
+public class AppCompatResourcesTestCase {
+ @Rule
+ public final ActivityTestRule<AppCompatActivity> mActivityTestRule;
public AppCompatResourcesTestCase() {
- super(AppCompatActivity.class);
+ mActivityTestRule = new ActivityTestRule<>(AppCompatActivity.class);
}
@Test
public void testGetColorStateListWithThemedAttributes() {
- final Activity context = getActivity();
+ final Activity context = mActivityTestRule.getActivity();
final int colorForegound = TestUtils.getThemeAttrColor(
context, android.R.attr.colorForeground);
@@ -65,7 +71,7 @@
@Test
public void testGetDrawableVectorResource() {
- final Activity context = getActivity();
+ final Activity context = mActivityTestRule.getActivity();
assertNotNull(AppCompatResources.getDrawable(context, R.drawable.test_vector_off));
}
diff --git a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatBaseImageViewTest.java b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatBaseImageViewTest.java
index c8398ed..431dc0e 100755
--- a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatBaseImageViewTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatBaseImageViewTest.java
@@ -66,7 +66,7 @@
@SmallTest
public void testImageTintingAcrossStateChange() {
final @IdRes int viewId = R.id.view_tinted_source;
- final Resources res = getActivity().getResources();
+ final Resources res = mActivity.getResources();
final T view = (T) mContainer.findViewById(viewId);
@ColorInt int lilacDefault = ResourcesCompat.getColor(res, R.color.lilac_default, null);
@@ -144,7 +144,7 @@
@SmallTest
public void testImageTintingAcrossModeChange() {
final @IdRes int viewId = R.id.view_untinted_source;
- final Resources res = getActivity().getResources();
+ final Resources res = mActivity.getResources();
final T view = (T) mContainer.findViewById(viewId);
@ColorInt int emeraldDefault = ResourcesCompat.getColor(
@@ -216,7 +216,7 @@
@SmallTest
public void testImageOpaqueTintingAcrossImageChange() {
final @IdRes int viewId = R.id.view_tinted_no_source;
- final Resources res = getActivity().getResources();
+ final Resources res = mActivity.getResources();
final T view = (T) mContainer.findViewById(viewId);
@ColorInt int lilacDefault = ResourcesCompat.getColor(res, R.color.lilac_default, null);
@@ -271,7 +271,7 @@
@SmallTest
public void testImageTranslucentTintingAcrossImageChange() {
final @IdRes int viewId = R.id.view_untinted_no_source;
- final Resources res = getActivity().getResources();
+ final Resources res = mActivity.getResources();
final T view = (T) mContainer.findViewById(viewId);
@ColorInt int emeraldDefault = ResourcesCompat.getColor(
@@ -361,7 +361,7 @@
@SmallTest
public void testImageTintingAcrossBackgroundTintingChange() {
final @IdRes int viewId = R.id.view_untinted_source;
- final Resources res = getActivity().getResources();
+ final Resources res = mActivity.getResources();
final T view = (T) mContainer.findViewById(viewId);
@ColorInt int lilacDefault = ResourcesCompat.getColor(res, R.color.lilac_default, null);
diff --git a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatBaseViewTest.java b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatBaseViewTest.java
index 74a73d3..cafe2cf 100644
--- a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatBaseViewTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatBaseViewTest.java
@@ -36,9 +36,10 @@
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v4.graphics.ColorUtils;
-import android.support.v7.app.BaseInstrumentationTestCase;
import android.support.v7.appcompat.test.R;
import android.support.v7.testutils.AppCompatTintableViewActions;
import android.support.v7.testutils.BaseTestActivity;
@@ -47,7 +48,9 @@
import android.view.ViewGroup;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Base class for testing custom view extensions in appcompat-v7 that implement the
@@ -55,15 +58,18 @@
* from here and add test cases specific to the functionality they add to the relevant
* base view class (such as <code>AppCompatTextView</code>'s all-caps support).
*/
-public abstract class AppCompatBaseViewTest<A extends BaseTestActivity, T extends View>
- extends BaseInstrumentationTestCase<A> {
+@RunWith(AndroidJUnit4.class)
+public abstract class AppCompatBaseViewTest<A extends BaseTestActivity, T extends View> {
+ @Rule
+ public final ActivityTestRule<A> mActivityTestRule;
+
protected ViewGroup mContainer;
protected A mActivity;
protected Resources mResources;
public AppCompatBaseViewTest(Class clazz) {
- super(clazz);
+ mActivityTestRule = new ActivityTestRule<A>(clazz);
}
@Before
diff --git a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewAutoSizeTest.java b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewAutoSizeTest.java
index f05f8f8..78f7524 100644
--- a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewAutoSizeTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewAutoSizeTest.java
@@ -22,15 +22,18 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.Nullable;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v4.widget.TextViewCompat;
-import android.support.v7.app.BaseInstrumentationTestCase;
import android.support.v7.appcompat.test.R;
import android.text.TextUtils;
import android.text.method.SingleLineTransformationMethod;
@@ -41,29 +44,123 @@
import android.widget.TextView;
import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
-public class AppCompatTextViewAutoSizeTest extends
- BaseInstrumentationTestCase<AppCompatTextViewAutoSizeActivity> {
+@RunWith(AndroidJUnit4.class)
+public class AppCompatTextViewAutoSizeTest {
+ @Rule
+ public final ActivityTestRule<AppCompatTextViewAutoSizeActivity> mActivityTestRule;
+
+ private Instrumentation mInstrumentation;
+ private AppCompatTextViewAutoSizeActivity mActivity;
public AppCompatTextViewAutoSizeTest() {
- super(AppCompatTextViewAutoSizeActivity.class);
+ mActivityTestRule = new ActivityTestRule<>(AppCompatTextViewAutoSizeActivity.class);
+ }
+
+ @Before
+ public void setup() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mActivity = mActivityTestRule.getActivity();
+ }
+
+ @Test
+ public void testAutoSizeCallers_setText() throws Throwable {
+ final AppCompatTextView autoSizeTextView = prepareAndRetrieveAutoSizeTestData(
+ R.id.textview_autosize_uniform, false);
+
+ // Configure layout params and auto-size both in pixels to dodge flakiness on different
+ // devices.
+ final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+ 500, 500);
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ autoSizeTextView.setLayoutParams(layoutParams);
+ autoSizeTextView.setAutoSizeTextTypeUniformWithConfiguration(
+ 1, 5000, 1, TypedValue.COMPLEX_UNIT_PX);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ final String initialText = "13characters ";
+ final StringBuilder textToSet = new StringBuilder().append(initialText);
+ float initialSize = 0;
+
+ // As we add characters the text size shrinks.
+ for (int i = 0; i < 10; i++) {
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ autoSizeTextView.setText(textToSet.toString());
+ }
+ });
+
+ mInstrumentation.waitForIdleSync();
+ float expectedLargerSize = autoSizeTextView.getTextSize();
+ if (i == 0) {
+ initialSize = expectedLargerSize;
+ }
+
+ textToSet.append(initialText);
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ autoSizeTextView.setText(textToSet.toString());
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertTrue(expectedLargerSize >= autoSizeTextView.getTextSize());
+ }
+ assertTrue(initialSize > autoSizeTextView.getTextSize());
+
+ initialSize = 9999999;
+ // As we remove characters the text size expands.
+ for (int i = 9; i >= 0; i--) {
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ autoSizeTextView.setText(textToSet.toString());
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ float expectedSmallerSize = autoSizeTextView.getTextSize();
+ if (i == 0) {
+ initialSize = expectedSmallerSize;
+ }
+
+ textToSet.replace((textToSet.length() - initialText.length()),
+ textToSet.length(), "");
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ autoSizeTextView.setText(textToSet.toString());
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(autoSizeTextView.getTextSize() >= expectedSmallerSize);
+ }
+ assertTrue(autoSizeTextView.getTextSize() > initialSize);
}
@Test
public void testAutoSizeUniform_equivalentConfigurations() throws Throwable {
- final DisplayMetrics dm = getActivity().getResources().getDisplayMetrics();
+ final DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
final int minTextSize = 10;
final int maxTextSize = 20;
final int granularity = 2;
final int unit = TypedValue.COMPLEX_UNIT_SP;
- final AppCompatTextView granularityTextView = new AppCompatTextView(getActivity());
+ final AppCompatTextView granularityTextView = new AppCompatTextView(mActivity);
granularityTextView.setAutoSizeTextTypeUniformWithConfiguration(
minTextSize, maxTextSize, granularity, unit);
- final AppCompatTextView presetTextView = new AppCompatTextView(getActivity());
+ final AppCompatTextView presetTextView = new AppCompatTextView(mActivity);
presetTextView.setAutoSizeTextTypeUniformWithPresetSizes(
new int[]{minTextSize, 12, 14, 16, 18, maxTextSize}, unit);
@@ -95,33 +192,32 @@
presetTextView.getAutoSizeTextAvailableSizes());
final String someText = "This is a string";
- final int widthHeight = 600;
+ final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+ 500, 500);
// Configure identically and attach to layout.
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
public void run() {
- LinearLayout ll = getActivity().findViewById(R.id.layout_textviewtest);
+ granularityTextView.setLayoutParams(layoutParams);
+ presetTextView.setLayoutParams(layoutParams);
+
+ LinearLayout ll = mActivity.findViewById(R.id.layout_textviewtest);
ll.removeAllViews();
ll.addView(granularityTextView);
ll.addView(presetTextView);
granularityTextView.setText(someText);
- granularityTextView.setWidth(widthHeight);
- granularityTextView.setHeight(widthHeight);
-
presetTextView.setText(someText);
- presetTextView.setWidth(widthHeight);
- presetTextView.setHeight(widthHeight);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertEquals(granularityTextView.getTextSize(), presetTextView.getTextSize(), 0f);
}
@Test
public void testAutoSize_notSupportedByEditText() throws Throwable {
- final AppCompatEditText autoSizeEditText = (AppCompatEditText) getActivity().findViewById(
+ final AppCompatEditText autoSizeEditText = (AppCompatEditText) mActivity.findViewById(
R.id.edittext_autosize_uniform);
// Do not force exact height only.
final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
@@ -133,7 +229,7 @@
autoSizeEditText.setLayoutParams(layoutParams);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final float initialTextSize = autoSizeEditText.getTextSize();
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
@@ -141,7 +237,7 @@
autoSizeEditText.setHeight(autoSizeEditText.getHeight() / 4);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertEquals(initialTextSize, autoSizeEditText.getTextSize(), 0f);
}
@@ -160,7 +256,7 @@
autoSizeTextView.setLayoutParams(layoutParams);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final float initialTextSize = autoSizeTextView.getTextSize();
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
@@ -168,7 +264,7 @@
autoSizeTextView.setHeight(autoSizeTextView.getHeight() / 4);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertTrue(autoSizeTextView.getTextSize() < initialTextSize);
}
@@ -178,7 +274,7 @@
final AppCompatTextView autoSizeTextView = prepareAndRetrieveAutoSizeTestData(
R.id.textview_autosize_uniform, false);
final float initialTextSize = autoSizeTextView.getTextSize();
- final Drawable drawable = ResourcesCompat.getDrawable(getActivity().getResources(),
+ final Drawable drawable = ResourcesCompat.getDrawable(mActivity.getResources(),
R.drawable.test_drawable_red, null);
drawable.setBounds(0, 0, autoSizeTextView.getWidth() / 3, autoSizeTextView.getHeight() / 3);
mActivityTestRule.runOnUiThread(new Runnable() {
@@ -187,7 +283,7 @@
autoSizeTextView.setCompoundDrawables(drawable, drawable, drawable, drawable);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertTrue(autoSizeTextView.getTextSize() < initialTextSize);
}
@@ -198,7 +294,7 @@
final AppCompatTextView autoSizeTextView = prepareAndRetrieveAutoSizeTestData(
R.id.textview_autosize_uniform, false);
final float initialTextSize = autoSizeTextView.getTextSize();
- final Drawable drawable = ResourcesCompat.getDrawable(getActivity().getResources(),
+ final Drawable drawable = ResourcesCompat.getDrawable(mActivity.getResources(),
R.drawable.test_drawable_red, null);
drawable.setBounds(0, 0, autoSizeTextView.getWidth() / 3,
autoSizeTextView.getHeight() / 3);
@@ -211,7 +307,7 @@
}
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertTrue(autoSizeTextView.getTextSize() < initialTextSize);
}
@@ -229,10 +325,10 @@
autoSizeTextView.setHeight(autoSizeTextView.getHeight() * 2);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
// Setup the drawables before setting their padding in order to modify the available
// space and trigger a resize.
- final Drawable drawable = ResourcesCompat.getDrawable(getActivity().getResources(),
+ final Drawable drawable = ResourcesCompat.getDrawable(mActivity.getResources(),
R.drawable.test_drawable_red, null);
drawable.setBounds(0, 0, autoSizeTextView.getWidth() / 4, autoSizeTextView.getHeight() / 4);
mActivityTestRule.runOnUiThread(new Runnable() {
@@ -242,7 +338,7 @@
drawable, drawable, drawable, drawable);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final float initialTextSize = autoSizeTextView.getTextSize();
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
@@ -251,7 +347,7 @@
autoSizeTextView.getCompoundDrawablePadding() + 10);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertTrue(autoSizeTextView.getTextSize() < initialTextSize);
}
@@ -269,7 +365,7 @@
autoSizeTextView.getWidth() / 3, autoSizeTextView.getHeight() / 3);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertTrue(autoSizeTextView.getTextSize() < initialTextSize);
}
@@ -291,7 +387,7 @@
}
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertTrue(autoSizeTextView.getTextSize() < initialTextSize);
}
@@ -312,7 +408,7 @@
+ "sentence to make sure this test is not flaky. Not flaky at all.");
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final float initialTextSize = autoSizeTextView.getTextSize();
mActivityTestRule.runOnUiThread(new Runnable() {
@@ -325,7 +421,7 @@
autoSizeTextView.setTypeface(differentTypeface);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final float changedTextSize = autoSizeTextView.getTextSize();
// Don't really know if it is larger or smaller (depends on the typeface chosen above),
@@ -338,7 +434,7 @@
autoSizeTextView.setTypeface(autoSizeTextView.getTypeface());
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertEquals(changedTextSize, autoSizeTextView.getTextSize(), 0f);
}
@@ -359,7 +455,7 @@
}
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final float changedTextSize = autoSizeTextView.getTextSize();
assertTrue(changedTextSize < initialTextSize);
@@ -372,7 +468,7 @@
}
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertEquals(changedTextSize, autoSizeTextView.getTextSize(), 0f);
}
@@ -392,7 +488,7 @@
autoSizeTextView.setLayoutParams(layoutParams);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final float initialTextSize = autoSizeTextView.getTextSize();
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
@@ -401,7 +497,7 @@
autoSizeTextView.getHeight() / 4);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertTrue(autoSizeTextView.getTextSize() < initialTextSize);
}
@@ -420,7 +516,7 @@
autoSizeTextView.setLayoutParams(layoutParams);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final float initialTextSize = autoSizeTextView.getTextSize();
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
@@ -429,7 +525,7 @@
autoSizeTextView.getWidth() / 4);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertTrue(autoSizeTextView.getTextSize() != initialTextSize);
}
@@ -448,7 +544,7 @@
autoSizeTextView.setLayoutParams(layoutParams);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final float initialTextSize = autoSizeTextView.getTextSize();
mActivityTestRule.runOnUiThread(new Runnable() {
@@ -458,7 +554,7 @@
autoSizeTextView.getWidth() / 4);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertTrue(autoSizeTextView.getTextSize() != initialTextSize);
}
@@ -475,7 +571,7 @@
autoSizeTextView.setTextSize(initialTextSize + 123f);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertEquals(initialTextSize, autoSizeTextView.getTextSize(), 0f);
}
@@ -492,7 +588,7 @@
autoSizeTextView.setHorizontallyScrolling(true);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertTrue(autoSizeTextView.getTextSize() > initialTextSize);
mActivityTestRule.runOnUiThread(new Runnable() {
@@ -501,13 +597,13 @@
autoSizeTextView.setHorizontallyScrolling(false);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
Assert.assertEquals(initialTextSize, autoSizeTextView.getTextSize(), 0f);
}
@Test
public void testAutoSize_setEllipsize() throws Throwable {
- final AppCompatTextView textView = (AppCompatTextView) getActivity().findViewById(
+ final AppCompatTextView textView = (AppCompatTextView) mActivity.findViewById(
R.id.textview_autosize_uniform_predef_sizes);
final int initialAutoSizeType = textView.getAutoSizeTextType();
final int initialMinTextSize = textView.getAutoSizeMinTextSize();
@@ -531,7 +627,7 @@
textView.setEllipsize(newEllipsizeValue);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
Assert.assertEquals(newEllipsizeValue, textView.getEllipsize());
// Beside the ellipsis no auto-size attribute has changed.
Assert.assertEquals(initialAutoSizeType, textView.getAutoSizeTextType());
@@ -544,7 +640,7 @@
@Test
public void testEllipsize_setAutoSize() throws Throwable {
final AppCompatTextView textView =
- (AppCompatTextView) getActivity().findViewById(R.id.textview_text);
+ (AppCompatTextView) mActivity.findViewById(R.id.textview_text);
final TextUtils.TruncateAt newEllipsizeValue = TextUtils.TruncateAt.END;
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
@@ -552,7 +648,7 @@
textView.setEllipsize(newEllipsizeValue);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
Assert.assertEquals(newEllipsizeValue, textView.getEllipsize());
Assert.assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
textView.getAutoSizeTextType());
@@ -568,7 +664,7 @@
TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
Assert.assertEquals(newEllipsizeValue, textView.getEllipsize());
Assert.assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM,
textView.getAutoSizeTextType());
@@ -581,9 +677,9 @@
@Test
public void testAutoSizeUniform_obtainStyledAttributesUsingPredefinedSizes() {
- DisplayMetrics m = getActivity().getResources().getDisplayMetrics();
+ DisplayMetrics m = mActivity.getResources().getDisplayMetrics();
final AppCompatTextView autoSizeTextViewUniform =
- (AppCompatTextView) getActivity().findViewById(
+ (AppCompatTextView) mActivity.findViewById(
R.id.textview_autosize_uniform_predef_sizes);
// In arrays.xml predefined the step sizes as: 5px, 11dip, 19sp, 29pt, 43mm and 53in.
@@ -610,7 +706,7 @@
@Test
public void testAutoSizeUniform_obtainStyledAttributesPredefinedSizesFiltering() {
- AppCompatTextView autoSizeTextViewUniform = (AppCompatTextView) getActivity().findViewById(
+ AppCompatTextView autoSizeTextViewUniform = (AppCompatTextView) mActivity.findViewById(
R.id.textview_autosize_uniform_predef_sizes_redundant_values);
// In arrays.xml predefined the step sizes as: 40px, 10px, 10px, 10px, 0dp.
@@ -620,7 +716,7 @@
@Test
public void testAutoSizeUniform_predefinedSizesFilteringAndSorting() throws Throwable {
- final AppCompatTextView textView = (AppCompatTextView) getActivity().findViewById(
+ final AppCompatTextView textView = (AppCompatTextView) mActivity.findViewById(
R.id.textview_text);
Assert.assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
textView.getAutoSizeTextType());
@@ -633,13 +729,13 @@
predefinedSizes, TypedValue.COMPLEX_UNIT_PX);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertArrayEquals(new int[] {10, 40, 400}, textView.getAutoSizeTextAvailableSizes());
}
@Test(expected = NullPointerException.class)
public void testAutoSizeUniform_predefinedSizesNullArray() throws Throwable {
- final AppCompatTextView textView = (AppCompatTextView) getActivity().findViewById(
+ final AppCompatTextView textView = (AppCompatTextView) mActivity.findViewById(
R.id.textview_text);
Assert.assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
textView.getAutoSizeTextType());
@@ -652,12 +748,12 @@
predefinedSizes, TypedValue.COMPLEX_UNIT_PX);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
}
@Test
public void testAutoSizeUniform_predefinedSizesEmptyArray() throws Throwable {
- final AppCompatTextView textView = (AppCompatTextView) getActivity().findViewById(
+ final AppCompatTextView textView = (AppCompatTextView) mActivity.findViewById(
R.id.textview_text);
Assert.assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
textView.getAutoSizeTextType());
@@ -669,7 +765,7 @@
TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final int[] defaultSizes = textView.getAutoSizeTextAvailableSizes();
assertNotNull(defaultSizes);
@@ -683,7 +779,7 @@
predefinedSizes, TypedValue.COMPLEX_UNIT_PX);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final int[] newSizes = textView.getAutoSizeTextAvailableSizes();
assertNotNull(defaultSizes);
@@ -693,7 +789,7 @@
@Test
public void testAutoSizeUniform_buildsSizes() throws Throwable {
final AppCompatTextView autoSizeTextViewUniform =
- (AppCompatTextView) getActivity().findViewById(
+ (AppCompatTextView) mActivity.findViewById(
R.id.textview_autosize_uniform);
// Verify that the interval limits are both included.
@@ -705,7 +801,7 @@
TypedValue.COMPLEX_UNIT_PX);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertArrayEquals(
new int[] {10, 12, 14, 16, 18, 20},
autoSizeTextViewUniform.getAutoSizeTextAvailableSizes());
@@ -721,7 +817,7 @@
TypedValue.COMPLEX_UNIT_PX);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertArrayEquals(
new int[] {10, 12, 14, 16, 18},
autoSizeTextViewUniform.getAutoSizeTextAvailableSizes());
@@ -737,7 +833,7 @@
TypedValue.COMPLEX_UNIT_PX);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertArrayEquals(
new int[] {10, 12, 14, 16, 18, 20},
autoSizeTextViewUniform.getAutoSizeTextAvailableSizes());
@@ -745,7 +841,7 @@
@Test
public void testAutoSizeUniform_getSetAutoSizeTextDefaults() {
- final AppCompatTextView textView = new AppCompatTextView(getActivity());
+ final AppCompatTextView textView = new AppCompatTextView(mActivity);
Assert.assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
textView.getAutoSizeTextType());
// Min/Max/Granularity values for auto-sizing are 0 because they are not used.
@@ -774,7 +870,7 @@
@Test
public void testAutoSizeUniform_getSetAutoSizeStepGranularity() {
- final AppCompatTextView textView = new AppCompatTextView(getActivity());
+ final AppCompatTextView textView = new AppCompatTextView(mActivity);
Assert.assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
textView.getAutoSizeTextType());
final int initialValue = -1;
@@ -799,7 +895,7 @@
@Test
public void testAutoSizeUniform_getSetAutoSizeMinTextSize() {
- final AppCompatTextView textView = new AppCompatTextView(getActivity());
+ final AppCompatTextView textView = new AppCompatTextView(mActivity);
textView.setAutoSizeTextTypeWithDefaults(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
Assert.assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM,
textView.getAutoSizeTextType());
@@ -831,41 +927,41 @@
// It does not matter which unit has been used to set the min size, the getter always
// returns it in pixels.
Assert.assertEquals(Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
- newMinSize, getActivity().getResources().getDisplayMetrics())),
+ newMinSize, mActivity.getResources().getDisplayMetrics())),
textView.getAutoSizeMinTextSize());
}
@Test(expected = IllegalArgumentException.class)
public void testAutoSizeUniform_throwsException_whenMaxLessThanMin() {
- final AppCompatTextView textView = new AppCompatTextView(getActivity());
+ final AppCompatTextView textView = new AppCompatTextView(mActivity);
textView.setAutoSizeTextTypeUniformWithConfiguration(
10, 9, 1, TypedValue.COMPLEX_UNIT_SP);
}
@Test(expected = IllegalArgumentException.class)
public void testAutoSizeUniform_throwsException_minLessThanZero() {
- final AppCompatTextView textView = new AppCompatTextView(getActivity());
+ final AppCompatTextView textView = new AppCompatTextView(mActivity);
textView.setAutoSizeTextTypeUniformWithConfiguration(
-1, 9, 1, TypedValue.COMPLEX_UNIT_SP);
}
@Test(expected = IllegalArgumentException.class)
public void testAutoSizeUniform_throwsException_maxLessThanZero() {
- final AppCompatTextView textView = new AppCompatTextView(getActivity());
+ final AppCompatTextView textView = new AppCompatTextView(mActivity);
textView.setAutoSizeTextTypeUniformWithConfiguration(
10, -1, 1, TypedValue.COMPLEX_UNIT_SP);
}
@Test(expected = IllegalArgumentException.class)
public void testAutoSizeUniform_throwsException_granularityLessThanZero() {
- final AppCompatTextView textView = new AppCompatTextView(getActivity());
+ final AppCompatTextView textView = new AppCompatTextView(mActivity);
textView.setAutoSizeTextTypeUniformWithConfiguration(
10, 20, -1, TypedValue.COMPLEX_UNIT_SP);
}
@Test
public void testAutoSizeUniform_getSetAutoSizeMaxTextSize() {
- final AppCompatTextView textView = new AppCompatTextView(getActivity());
+ final AppCompatTextView textView = new AppCompatTextView(mActivity);
textView.setAutoSizeTextTypeWithDefaults(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
Assert.assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM,
textView.getAutoSizeTextType());
@@ -892,13 +988,13 @@
// It does not matter which unit has been used to set the max size, the getter always
// returns it in pixels.
Assert.assertEquals(Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
- newMaxSize, getActivity().getResources().getDisplayMetrics())),
+ newMaxSize, mActivity.getResources().getDisplayMetrics())),
textView.getAutoSizeMaxTextSize());
}
@Test
public void testAutoSizeUniform_autoSizeCalledWhenTypeChanged() throws Throwable {
- final AppCompatTextView textView = (AppCompatTextView) getActivity().findViewById(
+ final AppCompatTextView textView = (AppCompatTextView) mActivity.findViewById(
R.id.textview_text);
// Make sure we pick an already inflated non auto-sized text view.
Assert.assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
@@ -911,7 +1007,7 @@
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, customTextSize);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
Assert.assertEquals(customTextSize, textView.getTextSize(), 0f);
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
@@ -920,7 +1016,7 @@
TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
// The size of the text should have changed.
assertNotEquals(customTextSize, textView.getTextSize(), 0f);
}
@@ -936,7 +1032,7 @@
textView.setAutoSizeTextTypeWithDefaults(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
final float newTextSizeInPx = 123f;
assertNotEquals(newTextSizeInPx, textView.getTextSize(), 0f);
@@ -946,7 +1042,7 @@
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newTextSizeInPx);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertEquals(newTextSizeInPx, textView.getTextSize(), 0f);
}
@@ -966,17 +1062,17 @@
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
public void run() {
- LinearLayout ll = (LinearLayout) getActivity().findViewById(
+ LinearLayout ll = (LinearLayout) mActivity.findViewById(
android.support.v7.appcompat.test.R.id.layout_textviewtest);
AppCompatTextView targetedTextView =
- (AppCompatTextView) getActivity().findViewById(viewId);
+ (AppCompatTextView) mActivity.findViewById(viewId);
ll.removeAllViews();
ll.addView(targetedTextView);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
- final AppCompatTextView textView = getActivity().findViewById(viewId);
+ final AppCompatTextView textView = mActivity.findViewById(viewId);
if (shouldWrapLayoutContent) {
// Do not force exact width or height.
final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
@@ -988,19 +1084,22 @@
textView.setLayoutParams(layoutParams);
}
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
}
return textView;
}
@Test
- public void testAutosizeWithMaxLines_shouldNotThrowException() throws Throwable {
+ public void testAutoSizeWithMaxLines_shouldNotThrowException() throws Throwable {
// the layout contains an instance of CustomTextViewWithTransformationMethod
- final AppCompatTextView textView = (AppCompatTextView) mActivityTestRule.getActivity()
+ final AppCompatTextView textView = (AppCompatTextView) mActivity
.getLayoutInflater().inflate(R.layout.textview_autosize_maxlines, null);
assertTrue(textView instanceof CustomTextViewWithTransformationMethod);
- assertEquals(1, textView.getMaxLines());
+ // Method added in API 16.
+ if (Build.VERSION.SDK_INT >= 16) {
+ assertEquals(1, textView.getMaxLines());
+ }
assertEquals(TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM, textView.getAutoSizeTextType());
assertTrue(textView.getTransformationMethod() instanceof SingleLineTransformationMethod);
}
diff --git a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java
index d1b00ad..5470329 100644
--- a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatTextViewTest.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.Typeface;
@@ -244,4 +245,17 @@
assertNotEquals(Typeface.DEFAULT, textView.getTypeface());
}
+
+ @Test
+ @UiThreadTest
+ public void testSetTextAppearance_resetTypeface() throws PackageManager.NameNotFoundException {
+ TextView textView = mContainer.findViewById(R.id.textview_simple);
+
+ TextViewCompat.setTextAppearance(textView, R.style.TextView_SansSerif);
+ Typeface firstTypeface = textView.getTypeface();
+
+ TextViewCompat.setTextAppearance(textView, R.style.TextView_Serif);
+ Typeface secondTypeface = textView.getTypeface();
+ assertNotEquals(firstTypeface, secondTypeface);
+ }
}
diff --git a/v7/appcompat/tests/src/android/support/v7/widget/ListPopupWindowTest.java b/v7/appcompat/tests/src/android/support/v7/widget/ListPopupWindowTest.java
index 907e653..3b01e4b 100644
--- a/v7/appcompat/tests/src/android/support/v7/widget/ListPopupWindowTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/widget/ListPopupWindowTest.java
@@ -46,7 +46,8 @@
import android.support.test.filters.FlakyTest;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
-import android.support.v7.app.BaseInstrumentationTestCase;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v7.appcompat.test.R;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -60,9 +61,16 @@
import android.widget.TextView;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
-public class ListPopupWindowTest extends BaseInstrumentationTestCase<PopupTestActivity> {
+@RunWith(AndroidJUnit4.class)
+public class ListPopupWindowTest {
+ @Rule
+ public final ActivityTestRule<PopupTestActivity> mActivityTestRule =
+ new ActivityTestRule<>(PopupTestActivity.class);
+
private FrameLayout mContainer;
private Button mButton;
@@ -86,15 +94,11 @@
}
}
- public ListPopupWindowTest() {
- super(PopupTestActivity.class);
- }
-
@Before
public void setUp() throws Exception {
final PopupTestActivity activity = mActivityTestRule.getActivity();
- mContainer = (FrameLayout) activity.findViewById(R.id.container);
- mButton = (Button) mContainer.findViewById(R.id.test_button);
+ mContainer = activity.findViewById(R.id.container);
+ mButton = mContainer.findViewById(R.id.test_button);
mItemClickListener = new PopupItemClickListener();
}
diff --git a/v7/appcompat/tests/src/android/support/v7/widget/PopupMenuTest.java b/v7/appcompat/tests/src/android/support/v7/widget/PopupMenuTest.java
index 8186e3a..7be67a6 100644
--- a/v7/appcompat/tests/src/android/support/v7/widget/PopupMenuTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/widget/PopupMenuTest.java
@@ -51,8 +51,9 @@
import android.support.test.filters.FlakyTest;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v4.view.MenuItemCompat;
-import android.support.v7.app.BaseInstrumentationTestCase;
import android.support.v7.appcompat.test.R;
import android.text.TextUtils;
import android.view.MenuInflater;
@@ -69,9 +70,16 @@
import org.hamcrest.TypeSafeMatcher;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
-public class PopupMenuTest extends BaseInstrumentationTestCase<PopupTestActivity> {
+@RunWith(AndroidJUnit4.class)
+public class PopupMenuTest {
+ @Rule
+ public final ActivityTestRule<PopupTestActivity> mActivityTestRule =
+ new ActivityTestRule<>(PopupTestActivity.class);
+
// Since PopupMenu doesn't expose any access to the underlying
// implementation (like ListPopupWindow.getListView), we're relying on the
// class name of the list view from MenuPopupWindow that is being used
@@ -89,15 +97,11 @@
private View mMainDecorView;
- public PopupMenuTest() {
- super(PopupTestActivity.class);
- }
-
@Before
public void setUp() throws Exception {
final PopupTestActivity activity = mActivityTestRule.getActivity();
- mContainer = (FrameLayout) activity.findViewById(R.id.container);
- mButton = (Button) mContainer.findViewById(R.id.test_button);
+ mContainer = activity.findViewById(R.id.container);
+ mButton = mContainer.findViewById(R.id.test_button);
mResources = mActivityTestRule.getActivity().getResources();
mMainDecorView = mActivityTestRule.getActivity().getWindow().getDecorView();
}
diff --git a/v7/appcompat/tests/src/android/support/v7/widget/TintResourcesTest.java b/v7/appcompat/tests/src/android/support/v7/widget/TintResourcesTest.java
index eb2d462..700fe26 100644
--- a/v7/appcompat/tests/src/android/support/v7/widget/TintResourcesTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/widget/TintResourcesTest.java
@@ -22,26 +22,31 @@
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v7.app.AppCompatActivity;
-import android.support.v7.app.BaseInstrumentationTestCase;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
@SmallTest
-public class TintResourcesTest extends BaseInstrumentationTestCase<AppCompatActivity> {
-
- public TintResourcesTest() {
- super(AppCompatActivity.class);
- }
+@RunWith(AndroidJUnit4.class)
+public class TintResourcesTest {
+ @Rule
+ public final ActivityTestRule<AppCompatActivity> mActivityTestRule =
+ new ActivityTestRule<>(AppCompatActivity.class);
@Test
public void testTintResourcesDelegateBackToOriginalResources() {
- final TestResources testResources = new TestResources(getActivity().getResources());
+ final TestResources testResources =
+ new TestResources(mActivityTestRule.getActivity().getResources());
// First make sure that the flag is false
assertFalse(testResources.wasGetDrawableCalled());
// Now wrap in a TintResources instance and get a Drawable
- final Resources tintResources = new TintResources(getActivity(), testResources);
+ final Resources tintResources =
+ new TintResources(mActivityTestRule.getActivity(), testResources);
tintResources.getDrawable(android.R.drawable.ic_delete);
// ...and assert that the flag was flipped
diff --git a/v7/cardview/src/android/support/v7/widget/CardView.java b/v7/cardview/src/android/support/v7/widget/CardView.java
index fab9453..3df45d9 100644
--- a/v7/cardview/src/android/support/v7/widget/CardView.java
+++ b/v7/cardview/src/android/support/v7/widget/CardView.java
@@ -196,6 +196,9 @@
widthMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(minWidth,
MeasureSpec.getSize(widthMeasureSpec)), widthMode);
break;
+ case MeasureSpec.UNSPECIFIED:
+ // Do nothing
+ break;
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
@@ -206,6 +209,9 @@
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(minHeight,
MeasureSpec.getSize(heightMeasureSpec)), heightMode);
break;
+ case MeasureSpec.UNSPECIFIED:
+ // Do nothing
+ break;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} else {
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
index a7e8cb5..00d15c9 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
@@ -489,7 +489,8 @@
setEnabled(mRouter.isRouteAvailable(mSelector,
MediaRouter.AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE));
}
- if (mRemoteIndicator.getCurrent() instanceof AnimationDrawable) {
+ if (mRemoteIndicator != null
+ && mRemoteIndicator.getCurrent() instanceof AnimationDrawable) {
AnimationDrawable curDrawable = (AnimationDrawable) mRemoteIndicator.getCurrent();
if (mAttachedToWindow) {
if ((needsRefresh || isConnecting) && !curDrawable.isRunning()) {
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
index e2c9b87..e052035 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
@@ -2560,6 +2560,20 @@
}
private void setSelectedRouteInternal(RouteInfo route, int unselectReason) {
+ // TODO: Remove the following logging when no longer needed.
+ if (mBluetoothRoute != null && route.isDefault()) {
+ final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+ StringBuffer sb = new StringBuffer();
+ // callStack[3] is the caller of this method.
+ for (int i = 3; i < callStack.length; i++) {
+ StackTraceElement caller = callStack[i];
+ sb.append(caller.getClassName() + "." + caller.getMethodName()
+ + ":" + caller.getLineNumber()).append(" ");
+ }
+ Log.w(TAG, "Default route is selected while a BT route is available: pkgName="
+ + mApplicationContext.getPackageName() + ", callers=" + sb.toString());
+ }
+
if (mSelectedRoute != route) {
if (mSelectedRoute != null) {
if (DEBUG) {
diff --git a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
index e01cd83..e452009 100644
--- a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
+++ b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
@@ -677,7 +677,7 @@
int defStyleAttr, int defStyleRes) {
if (className != null) {
className = className.trim();
- if (className.length() != 0) { // Can't use isEmpty since it was added in API 9.
+ if (!className.isEmpty()) {
className = getFullClassName(context, className);
try {
ClassLoader classLoader;
diff --git a/wear/AndroidManifest.xml b/wear/AndroidManifest.xml
index fda54e2..5fa5a83 100644
--- a/wear/AndroidManifest.xml
+++ b/wear/AndroidManifest.xml
@@ -15,7 +15,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.support.wear">
- <uses-sdk android:minSdkVersion="22"/>
<application>
<meta-data android:name="android.support.VERSION" android:value="${support-version}" />
</application>
diff --git a/wear/build.gradle b/wear/build.gradle
index b320ab7..07e579e 100644
--- a/wear/build.gradle
+++ b/wear/build.gradle
@@ -19,7 +19,7 @@
android {
defaultConfig {
- minSdkVersion 23
+ minSdkVersion 24
}
sourceSets {
diff --git a/wear/res/layout-v23/action_drawer_title_view.xml b/wear/res-public/values/public_styles.xml
similarity index 64%
copy from wear/res/layout-v23/action_drawer_title_view.xml
copy to wear/res-public/values/public_styles.xml
index a2be3e1..d4575e4 100644
--- a/wear/res/layout-v23/action_drawer_title_view.xml
+++ b/wear/res-public/values/public_styles.xml
@@ -13,11 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/wearable_support_action_drawer_title"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/action_drawer_item_icon_size"
- android:layout_gravity="center"
- android:gravity="center"
- style="@style/WearableActionDrawerTitleText" />
+<!-- Definitions of styles to be exposed as public -->
+<resources>
+ <public type="style" name="Widget.Wear.RoundSwitch"/>
+</resources>
diff --git a/wear/res/layout-v23/action_drawer_title_view.xml b/wear/res/color/ws_switch_thumb_color_material.xml
similarity index 63%
copy from wear/res/layout-v23/action_drawer_title_view.xml
copy to wear/res/color/ws_switch_thumb_color_material.xml
index a2be3e1..0707d69 100644
--- a/wear/res/layout-v23/action_drawer_title_view.xml
+++ b/wear/res/color/ws_switch_thumb_color_material.xml
@@ -13,11 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/wearable_support_action_drawer_title"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/action_drawer_item_icon_size"
- android:layout_gravity="center"
- android:gravity="center"
- style="@style/WearableActionDrawerTitleText" />
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?android:attr/colorButtonNormal"
+ android:alpha="?android:attr/disabledAlpha" android:state_enabled="false" />
+ <item android:color="?android:attr/colorControlActivated" android:state_checked="true" />
+ <item android:color="?android:attr/colorButtonNormal" />
+</selector>
diff --git a/wear/res/layout-v23/action_drawer_title_view.xml b/wear/res/color/ws_switch_track_color_material.xml
similarity index 65%
copy from wear/res/layout-v23/action_drawer_title_view.xml
copy to wear/res/color/ws_switch_track_color_material.xml
index a2be3e1..214bf4a 100644
--- a/wear/res/layout-v23/action_drawer_title_view.xml
+++ b/wear/res/color/ws_switch_track_color_material.xml
@@ -13,11 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/wearable_support_action_drawer_title"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/action_drawer_item_icon_size"
- android:layout_gravity="center"
- android:gravity="center"
- style="@style/WearableActionDrawerTitleText" />
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:alpha="?android:attr/disabledAlpha"
+ android:color="?android:attr/colorPrimary" />
+ <item android:color="?android:attr/colorPrimary" />
+</selector>
diff --git a/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_14w.png b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..371469c
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_15w.png b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..e477260
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_16w.png b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..19a1bd3
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_17w.png b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..79dc733
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_18w.png b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..6d921c0
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/ws_switch_track_mtrl.png b/wear/res/drawable-hdpi/ws_switch_track_mtrl.png
new file mode 100644
index 0000000..ecee3e1
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_track_mtrl.png
Binary files differ
diff --git a/wear/res/drawable-v21/ic_expand_more_white_22.xml b/wear/res/drawable-v21/ws_ic_expand_more_white_22.xml
similarity index 100%
rename from wear/res/drawable-v21/ic_expand_more_white_22.xml
rename to wear/res/drawable-v21/ws_ic_expand_more_white_22.xml
diff --git a/wear/res/drawable-v21/ws_switch_thumb_material_anim.xml b/wear/res/drawable-v21/ws_switch_thumb_material_anim.xml
new file mode 100644
index 0000000..15423e5
--- /dev/null
+++ b/wear/res/drawable-v21/ws_switch_thumb_material_anim.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:constantSize="true">
+ <item
+ android:id="@+id/off"
+ android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+ android:state_enabled="false" />
+ <item
+ android:id="@+id/on"
+ android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+ android:state_checked="true" />
+ <item
+ android:id="@+id/off"
+ android:drawable="@drawable/ws_switch_thumb_mtrl_14w" />
+ <transition
+ android:fromId="@id/off"
+ android:toId="@id/on">
+ <animation-list>
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+ android:duration="30" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_15w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_16w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_17w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_18w"
+ android:duration="75" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_17w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_16w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_15w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+ android:duration="30" />
+ </animation-list>
+ </transition>
+ <transition
+ android:fromId="@id/on"
+ android:toId="@id/off">
+ <animation-list>
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+ android:duration="30" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_15w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_16w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_17w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_18w"
+ android:duration="75" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_17w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_16w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_15w"
+ android:duration="15" />
+ <item
+ android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+ android:duration="30" />
+ </animation-list>
+ </transition>
+</animated-selector>
diff --git a/wear/res/drawable-v23/action_item_background.xml b/wear/res/drawable-v23/ws_action_item_background.xml
similarity index 100%
rename from wear/res/drawable-v23/action_item_background.xml
rename to wear/res/drawable-v23/ws_action_item_background.xml
diff --git a/wear/res/drawable-v23/action_item_icon_background.xml b/wear/res/drawable-v23/ws_action_item_icon_background.xml
similarity index 100%
rename from wear/res/drawable-v23/action_item_icon_background.xml
rename to wear/res/drawable-v23/ws_action_item_icon_background.xml
diff --git a/wear/res/drawable-v23/ic_expand_less_white_22.xml b/wear/res/drawable-v23/ws_ic_expand_less_white_22.xml
similarity index 100%
rename from wear/res/drawable-v23/ic_expand_less_white_22.xml
rename to wear/res/drawable-v23/ws_ic_expand_less_white_22.xml
diff --git a/wear/res/drawable-v23/ic_more_horiz_24dp_wht.xml b/wear/res/drawable-v23/ws_ic_more_horiz_24dp_wht.xml
similarity index 100%
rename from wear/res/drawable-v23/ic_more_horiz_24dp_wht.xml
rename to wear/res/drawable-v23/ws_ic_more_horiz_24dp_wht.xml
diff --git a/wear/res/drawable-v23/ic_more_vert_24dp_wht.xml b/wear/res/drawable-v23/ws_ic_more_vert_24dp_wht.xml
similarity index 100%
rename from wear/res/drawable-v23/ic_more_vert_24dp_wht.xml
rename to wear/res/drawable-v23/ws_ic_more_vert_24dp_wht.xml
diff --git a/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_14w.png b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..7f7ca14
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_15w.png b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..52120b8
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_16w.png b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..d6e9be9
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_17w.png b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..8d76393
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_18w.png b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..ca9c66e
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/ws_switch_track_mtrl.png b/wear/res/drawable-xhdpi/ws_switch_track_mtrl.png
new file mode 100644
index 0000000..1aa5442
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_track_mtrl.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_14w.png b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..c0d72d7
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_15w.png b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..d7c0ec0
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_16w.png b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..5815ba9
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_17w.png b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..41da8c0
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_18w.png b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..975eb01
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_track_mtrl.png b/wear/res/drawable-xxhdpi/ws_switch_track_mtrl.png
new file mode 100644
index 0000000..af2042b
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_track_mtrl.png
Binary files differ
diff --git a/wear/res/layout-v23/action_drawer_item_view.xml b/wear/res/layout-v23/ws_action_drawer_item_view.xml
similarity index 70%
rename from wear/res/layout-v23/action_drawer_item_view.xml
rename to wear/res/layout-v23/ws_action_drawer_item_view.xml
index 068e364..fc84862 100644
--- a/wear/res/layout-v23/action_drawer_item_view.xml
+++ b/wear/res/layout-v23/ws_action_drawer_item_view.xml
@@ -18,24 +18,24 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@drawable/action_item_background"
+ android:background="@drawable/ws_action_item_background"
android:orientation="horizontal">
<ImageView
- android:id="@+id/wearable_support_action_drawer_item_icon"
- android:layout_width="@dimen/action_drawer_item_icon_size"
- android:layout_height="@dimen/action_drawer_item_icon_size"
+ android:id="@+id/ws_action_drawer_item_icon"
+ android:layout_width="@dimen/ws_action_drawer_item_icon_size"
+ android:layout_height="@dimen/ws_action_drawer_item_icon_size"
android:layout_gravity="center_vertical"
- android:background="@drawable/action_item_icon_background"
+ android:background="@drawable/ws_action_item_icon_background"
android:tint="?android:attr/colorBackground"
- android:padding="@dimen/action_drawer_item_icon_padding"
+ android:padding="@dimen/ws_action_drawer_item_icon_padding"
android:scaleType="fitCenter"
tools:ignore="ContentDescription" />
<TextView
- android:id="@+id/wearable_support_action_drawer_item_text"
+ android:id="@+id/ws_action_drawer_item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/WearableActionDrawerItemText"/>
+ style="@style/WsWearableActionDrawerItemText"/>
</LinearLayout>
diff --git a/wear/res/layout-v23/action_drawer_peek_view.xml b/wear/res/layout-v23/ws_action_drawer_peek_view.xml
similarity index 66%
rename from wear/res/layout-v23/action_drawer_peek_view.xml
rename to wear/res/layout-v23/ws_action_drawer_peek_view.xml
index 88946cb..ce66d73 100644
--- a/wear/res/layout-v23/action_drawer_peek_view.xml
+++ b/wear/res/layout-v23/ws_action_drawer_peek_view.xml
@@ -17,25 +17,25 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
- android:layout_height="@dimen/action_drawer_peek_view_height"
+ android:layout_height="@dimen/ws_action_drawer_peek_view_height"
android:layout_gravity="center"
android:gravity="center_vertical"
android:orientation="vertical"
- android:paddingTop="@dimen/action_drawer_peek_top_padding">
+ android:paddingTop="@dimen/ws_action_drawer_peek_top_padding">
<ImageView
- android:id="@+id/wearable_support_action_drawer_peek_action_icon"
- android:layout_width="@dimen/peek_view_icon_size"
- android:layout_height="@dimen/peek_view_icon_size"
+ android:id="@+id/ws_action_drawer_peek_action_icon"
+ android:layout_width="@dimen/ws_peek_view_icon_size"
+ android:layout_height="@dimen/ws_peek_view_icon_size"
android:tint="?android:attr/colorForeground"
tools:ignore="ContentDescription" />
<ImageView
- android:id="@+id/wearable_support_action_drawer_expand_icon"
- android:layout_width="@dimen/peek_view_icon_size"
- android:layout_height="@dimen/peek_view_icon_size"
- android:layout_marginTop="@dimen/action_drawer_expand_icon_top_margin"
- android:src="@drawable/ic_expand_less_white_22"
+ android:id="@+id/ws_action_drawer_expand_icon"
+ android:layout_width="@dimen/ws_peek_view_icon_size"
+ android:layout_height="@dimen/ws_peek_view_icon_size"
+ android:layout_marginTop="@dimen/ws_action_drawer_expand_icon_top_margin"
+ android:src="@drawable/ws_ic_expand_less_white_22"
android:alpha="0.5"
android:tint="?android:attr/colorForeground"
tools:ignore="NegativeMargin,ContentDescription" />
diff --git a/wear/res/layout-v23/action_drawer_title_view.xml b/wear/res/layout-v23/ws_action_drawer_title_view.xml
similarity index 83%
rename from wear/res/layout-v23/action_drawer_title_view.xml
rename to wear/res/layout-v23/ws_action_drawer_title_view.xml
index a2be3e1..e5535c4 100644
--- a/wear/res/layout-v23/action_drawer_title_view.xml
+++ b/wear/res/layout-v23/ws_action_drawer_title_view.xml
@@ -15,9 +15,9 @@
-->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/wearable_support_action_drawer_title"
+ android:id="@+id/ws_action_drawer_title"
android:layout_width="wrap_content"
- android:layout_height="@dimen/action_drawer_item_icon_size"
+ android:layout_height="@dimen/ws_action_drawer_item_icon_size"
android:layout_gravity="center"
android:gravity="center"
- style="@style/WearableActionDrawerTitleText" />
+ style="@style/WsWearableActionDrawerTitleText" />
diff --git a/wear/res/layout-v23/wearable_drawer_view.xml b/wear/res/layout-v23/ws_wearable_drawer_view.xml
similarity index 74%
rename from wear/res/layout-v23/wearable_drawer_view.xml
rename to wear/res/layout-v23/ws_wearable_drawer_view.xml
index 8659aac..c7c5907 100644
--- a/wear/res/layout-v23/wearable_drawer_view.xml
+++ b/wear/res/layout-v23/ws_wearable_drawer_view.xml
@@ -19,16 +19,16 @@
<!-- Layout gravity for peek is set in code by WearableDrawerView. -->
<FrameLayout
- android:id="@+id/wearable_support_drawer_view_peek_container"
+ android:id="@+id/ws_drawer_view_peek_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
- android:id="@+id/wearable_support_drawer_view_peek_icon"
- android:layout_width="@dimen/peek_view_icon_size"
- android:layout_height="@dimen/peek_view_icon_size"
- android:layout_marginTop="@dimen/peek_view_top_padding"
- android:layout_marginBottom="@dimen/peek_view_bottom_padding"
+ android:id="@+id/ws_drawer_view_peek_icon"
+ android:layout_width="@dimen/ws_peek_view_icon_size"
+ android:layout_height="@dimen/ws_peek_view_icon_size"
+ android:layout_marginTop="@dimen/ws_peek_view_top_padding"
+ android:layout_marginBottom="@dimen/ws_peek_view_bottom_padding"
android:layout_gravity="center"
android:tint="?android:attr/colorForeground"
tools:ignore="ContentDescription" />
diff --git a/wear/res/layout/single_page_nav_drawer_5_item.xml b/wear/res/layout/single_page_nav_drawer_5_item.xml
deleted file mode 100644
index 2a8c3af..0000000
--- a/wear/res/layout/single_page_nav_drawer_5_item.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="false">
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_0"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- app:layout_marginStartPercent="@fraction/nav_drawer_margin_5_items_horizontal_outer_rows"
- app:layout_marginTopPercent="@fraction/nav_drawer_margin_5_items_vertical"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle"/>
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_1"
- android:layout_alignParentEnd="true"
- android:layout_alignParentTop="true"
- app:layout_marginEndPercent="@fraction/nav_drawer_margin_5_items_horizontal_outer_rows"
- app:layout_marginTopPercent="@fraction/nav_drawer_margin_5_items_vertical"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_2"
- android:layout_alignParentStart="true"
- android:layout_centerVertical="true"
- app:layout_marginStartPercent="@fraction/nav_drawer_margin_5_items_horizontal_middle_row"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_3"
- android:layout_centerInParent="true"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_4"
- android:layout_alignParentEnd="true"
- android:layout_centerVertical="true"
- app:layout_marginEndPercent="@fraction/nav_drawer_margin_5_items_horizontal_middle_row"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
- <TextView
- android:id="@+id/wearable_support_nav_drawer_text"
- android:layout_below="@id/wearable_support_nav_drawer_icon_4"
- style="@style/SinglePageNavDrawerTextStyle"/>
-
-</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_7_item.xml b/wear/res/layout/single_page_nav_drawer_7_item.xml
deleted file mode 100644
index 45e0c24..0000000
--- a/wear/res/layout/single_page_nav_drawer_7_item.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="false">
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_0"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- app:layout_marginStartPercent="@fraction/nav_drawer_margin_7_items_horizontal_outer_rows"
- app:layout_marginTopPercent="@fraction/nav_drawer_margin_7_items_vertical"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_1"
- android:layout_alignParentEnd="true"
- android:layout_alignParentTop="true"
- app:layout_marginEndPercent="@fraction/nav_drawer_margin_7_items_horizontal_outer_rows"
- app:layout_marginTopPercent="@fraction/nav_drawer_margin_7_items_vertical"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_2"
- android:layout_alignParentStart="true"
- android:layout_centerVertical="true"
- app:layout_marginStartPercent="@fraction/nav_drawer_margin_7_items_horizontal_middle_row"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_3"
- android:layout_centerInParent="true"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_4"
- android:layout_alignParentEnd="true"
- android:layout_centerVertical="true"
- app:layout_marginEndPercent="@fraction/nav_drawer_margin_7_items_horizontal_middle_row"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_5"
- android:layout_alignParentStart="true"
- android:layout_alignParentBottom="true"
- app:layout_marginStartPercent="@fraction/nav_drawer_margin_7_items_horizontal_outer_rows"
- app:layout_marginBottomPercent="@fraction/nav_drawer_margin_7_items_vertical"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
- <android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_6"
- android:layout_alignParentEnd="true"
- android:layout_alignParentBottom="true"
- app:layout_marginEndPercent="@fraction/nav_drawer_margin_7_items_horizontal_outer_rows"
- app:layout_marginBottomPercent="@fraction/nav_drawer_margin_7_items_vertical"
- tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
-
-</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/navigation_drawer_item_view.xml b/wear/res/layout/ws_navigation_drawer_item_view.xml
similarity index 86%
rename from wear/res/layout/navigation_drawer_item_view.xml
rename to wear/res/layout/ws_navigation_drawer_item_view.xml
index 9e4d86a..dcd5e41 100644
--- a/wear/res/layout/navigation_drawer_item_view.xml
+++ b/wear/res/layout/ws_navigation_drawer_item_view.xml
@@ -19,17 +19,17 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
- android:id="@+id/wearable_support_navigation_drawer_item_icon"
+ android:id="@+id/ws_navigation_drawer_item_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerInParent="true"
android:scaleType="fitCenter"
tools:ignore="ContentDescription" />
<TextView
- android:id="@+id/wearable_support_navigation_drawer_item_text"
+ android:id="@+id/ws_navigation_drawer_item_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@id/wearable_support_navigation_drawer_item_icon"
+ android:layout_below="@id/ws_navigation_drawer_item_icon"
android:layout_marginTop="6dp"
android:gravity="center_horizontal"
android:textColor="?android:attr/textColorPrimary"/>
diff --git a/wear/res/layout/navigation_drawer_view.xml b/wear/res/layout/ws_navigation_drawer_view.xml
similarity index 78%
rename from wear/res/layout/navigation_drawer_view.xml
rename to wear/res/layout/ws_navigation_drawer_view.xml
index 9824bbf..92855eb 100644
--- a/wear/res/layout/navigation_drawer_view.xml
+++ b/wear/res/layout/ws_navigation_drawer_view.xml
@@ -20,15 +20,15 @@
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
- android:id="@+id/wearable_support_navigation_drawer_view_pager"
+ android:id="@+id/ws_navigation_drawer_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.wear.widget.drawer.PageIndicatorView
- android:id="@+id/wearable_support_navigation_drawer_page_indicator"
+ android:id="@+id/ws_navigation_drawer_page_indicator"
android:layout_width="wrap_content"
- android:layout_height="@dimen/peek_view_icon_size"
- android:layout_marginBottom="@dimen/peek_view_bottom_padding"
+ android:layout_height="@dimen/ws_peek_view_icon_size"
+ android:layout_marginBottom="@dimen/ws_peek_view_bottom_padding"
android:layout_gravity="bottom|center_horizontal"
- app:pageIndicatorDotFadeWhenIdle="false" />
+ app:dotFadeWhenIdle="false" />
</FrameLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_1_item.xml b/wear/res/layout/ws_single_page_nav_drawer_1_item.xml
similarity index 79%
rename from wear/res/layout/single_page_nav_drawer_1_item.xml
rename to wear/res/layout/ws_single_page_nav_drawer_1_item.xml
index 2911f43..550d737 100644
--- a/wear/res/layout/single_page_nav_drawer_1_item.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_1_item.xml
@@ -20,14 +20,14 @@
android:clipChildren="false">
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_0"
+ android:id="@+id/ws_nav_drawer_icon_0"
android:layout_centerInParent="true"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<TextView
- android:id="@+id/wearable_support_nav_drawer_text"
- android:layout_below="@id/wearable_support_nav_drawer_icon_0"
- style="@style/SinglePageNavDrawerTextStyle"/>
+ android:id="@+id/ws_nav_drawer_text"
+ android:layout_below="@id/ws_nav_drawer_icon_0"
+ style="@style/WsSinglePageNavDrawerTextStyle"/>
</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_2_item.xml b/wear/res/layout/ws_single_page_nav_drawer_2_item.xml
similarity index 71%
rename from wear/res/layout/single_page_nav_drawer_2_item.xml
rename to wear/res/layout/ws_single_page_nav_drawer_2_item.xml
index cbdbb24..63dbbe6 100644
--- a/wear/res/layout/single_page_nav_drawer_2_item.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_2_item.xml
@@ -21,24 +21,24 @@
android:clipChildren="false">
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_0"
+ android:id="@+id/ws_nav_drawer_icon_0"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
- app:layout_marginStartPercent="@fraction/nav_drawer_margin_2_items"
+ app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_2_items"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_1"
+ android:id="@+id/ws_nav_drawer_icon_1"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
- app:layout_marginEndPercent="@fraction/nav_drawer_margin_2_items"
+ app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_2_items"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<TextView
- android:id="@+id/wearable_support_nav_drawer_text"
- android:layout_below="@id/wearable_support_nav_drawer_icon_1"
- style="@style/SinglePageNavDrawerTextStyle"/>
+ android:id="@+id/ws_nav_drawer_text"
+ android:layout_below="@id/ws_nav_drawer_icon_1"
+ style="@style/WsSinglePageNavDrawerTextStyle"/>
</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_3_item.xml b/wear/res/layout/ws_single_page_nav_drawer_3_item.xml
similarity index 69%
rename from wear/res/layout/single_page_nav_drawer_3_item.xml
rename to wear/res/layout/ws_single_page_nav_drawer_3_item.xml
index 5e4fc52..209ec16 100644
--- a/wear/res/layout/single_page_nav_drawer_3_item.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_3_item.xml
@@ -21,30 +21,30 @@
android:clipChildren="false">
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_0"
+ android:id="@+id/ws_nav_drawer_icon_0"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
- app:layout_marginStartPercent="@fraction/nav_drawer_margin_3_items"
+ app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_3_items"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_1"
+ android:id="@+id/ws_nav_drawer_icon_1"
android:layout_centerInParent="true"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_2"
+ android:id="@+id/ws_nav_drawer_icon_2"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
- app:layout_marginEndPercent="@fraction/nav_drawer_margin_3_items"
+ app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_3_items"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<TextView
- android:id="@+id/wearable_support_nav_drawer_text"
- android:layout_below="@id/wearable_support_nav_drawer_icon_2"
- style="@style/SinglePageNavDrawerTextStyle"/>
+ android:id="@+id/ws_nav_drawer_text"
+ android:layout_below="@id/ws_nav_drawer_icon_2"
+ style="@style/WsSinglePageNavDrawerTextStyle"/>
</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_4_item.xml b/wear/res/layout/ws_single_page_nav_drawer_4_item.xml
similarity index 66%
rename from wear/res/layout/single_page_nav_drawer_4_item.xml
rename to wear/res/layout/ws_single_page_nav_drawer_4_item.xml
index 4acfdab..1b2c163 100644
--- a/wear/res/layout/single_page_nav_drawer_4_item.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_4_item.xml
@@ -21,38 +21,38 @@
android:clipChildren="false">
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_0"
+ android:id="@+id/ws_nav_drawer_icon_0"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
- app:layout_marginTopPercent="@fraction/nav_drawer_margin_4_items_vertical"
+ app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_4_items_vertical"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_1"
+ android:id="@+id/ws_nav_drawer_icon_1"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
- app:layout_marginStartPercent="@fraction/nav_drawer_margin_4_items_horizontal"
+ app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_4_items_horizontal"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_2"
+ android:id="@+id/ws_nav_drawer_icon_2"
android:layout_centerInParent="true"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_3"
+ android:id="@+id/ws_nav_drawer_icon_3"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
- app:layout_marginEndPercent="@fraction/nav_drawer_margin_4_items_horizontal"
+ app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_4_items_horizontal"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<TextView
- android:id="@+id/wearable_support_nav_drawer_text"
- android:layout_below="@id/wearable_support_nav_drawer_icon_3"
- style="@style/SinglePageNavDrawerTextStyle"/>
+ android:id="@+id/ws_nav_drawer_text"
+ android:layout_below="@id/ws_nav_drawer_icon_3"
+ style="@style/WsSinglePageNavDrawerTextStyle"/>
</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/ws_single_page_nav_drawer_5_item.xml b/wear/res/layout/ws_single_page_nav_drawer_5_item.xml
new file mode 100644
index 0000000..699533d
--- /dev/null
+++ b/wear/res/layout/ws_single_page_nav_drawer_5_item.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false">
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_0"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_5_items_horizontal_outer_rows"
+ app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_5_items_vertical"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle"/>
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_1"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_5_items_horizontal_outer_rows"
+ app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_5_items_vertical"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_2"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"
+ app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_5_items_horizontal_middle_row"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_3"
+ android:layout_centerInParent="true"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_4"
+ android:layout_alignParentEnd="true"
+ android:layout_centerVertical="true"
+ app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_5_items_horizontal_middle_row"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+ <TextView
+ android:id="@+id/ws_nav_drawer_text"
+ android:layout_below="@id/ws_nav_drawer_icon_4"
+ style="@style/WsSinglePageNavDrawerTextStyle"/>
+
+</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_6_item.xml b/wear/res/layout/ws_single_page_nav_drawer_6_item.xml
similarity index 60%
rename from wear/res/layout/single_page_nav_drawer_6_item.xml
rename to wear/res/layout/ws_single_page_nav_drawer_6_item.xml
index fd6cd65..00625a1 100644
--- a/wear/res/layout/single_page_nav_drawer_6_item.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_6_item.xml
@@ -21,56 +21,56 @@
android:clipChildren="false">
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_0"
+ android:id="@+id/ws_nav_drawer_icon_0"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
- app:layout_marginStartPercent="@fraction/nav_drawer_margin_6_items_horizontal"
- app:layout_marginTopPercent="@fraction/nav_drawer_margin_6_items_vertical"
+ app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_6_items_horizontal"
+ app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_1"
+ android:id="@+id/ws_nav_drawer_icon_1"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
- app:layout_marginTopPercent="@fraction/nav_drawer_margin_6_items_vertical"
+ app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_2"
+ android:id="@+id/ws_nav_drawer_icon_2"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
- app:layout_marginEndPercent="@fraction/nav_drawer_margin_6_items_horizontal"
- app:layout_marginTopPercent="@fraction/nav_drawer_margin_6_items_vertical"
+ app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_6_items_horizontal"
+ app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_3"
+ android:id="@+id/ws_nav_drawer_icon_3"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
- app:layout_marginStartPercent="@fraction/nav_drawer_margin_6_items_horizontal"
- app:layout_marginBottomPercent="@fraction/nav_drawer_margin_6_items_vertical"
+ app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_6_items_horizontal"
+ app:layout_marginBottomPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_4"
+ android:id="@+id/ws_nav_drawer_icon_4"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
- app:layout_marginBottomPercent="@fraction/nav_drawer_margin_6_items_vertical"
+ app:layout_marginBottomPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
<android.support.wear.widget.CircledImageView
- android:id="@+id/wearable_support_nav_drawer_icon_5"
+ android:id="@+id/ws_nav_drawer_icon_5"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
- app:layout_marginEndPercent="@fraction/nav_drawer_margin_6_items_horizontal"
- app:layout_marginBottomPercent="@fraction/nav_drawer_margin_6_items_vertical"
+ app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_6_items_horizontal"
+ app:layout_marginBottomPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
tools:ignore="ContentDescription"
- style="@style/SinglePageNavDrawerIconStyle" />
+ style="@style/WsSinglePageNavDrawerIconStyle" />
</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/ws_single_page_nav_drawer_7_item.xml b/wear/res/layout/ws_single_page_nav_drawer_7_item.xml
new file mode 100644
index 0000000..5daef22
--- /dev/null
+++ b/wear/res/layout/ws_single_page_nav_drawer_7_item.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false">
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_0"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_outer_rows"
+ app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_7_items_vertical"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_1"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_outer_rows"
+ app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_7_items_vertical"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_2"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"
+ app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_middle_row"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_3"
+ android:layout_centerInParent="true"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_4"
+ android:layout_alignParentEnd="true"
+ android:layout_centerVertical="true"
+ app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_middle_row"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_5"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentBottom="true"
+ app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_outer_rows"
+ app:layout_marginBottomPercent="@fraction/ws_nav_drawer_margin_7_items_vertical"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+ <android.support.wear.widget.CircledImageView
+ android:id="@+id/ws_nav_drawer_icon_6"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentBottom="true"
+ app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_outer_rows"
+ app:layout_marginBottomPercent="@fraction/ws_nav_drawer_margin_7_items_vertical"
+ tools:ignore="ContentDescription"
+ style="@style/WsSinglePageNavDrawerIconStyle" />
+
+</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_peek_view.xml b/wear/res/layout/ws_single_page_nav_drawer_peek_view.xml
similarity index 78%
rename from wear/res/layout/single_page_nav_drawer_peek_view.xml
rename to wear/res/layout/ws_single_page_nav_drawer_peek_view.xml
index e0ed880..8b11554 100644
--- a/wear/res/layout/single_page_nav_drawer_peek_view.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_peek_view.xml
@@ -20,13 +20,13 @@
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
- android:paddingTop="@dimen/peek_view_top_padding"
- android:paddingBottom="@dimen/peek_view_bottom_padding">
+ android:paddingTop="@dimen/ws_peek_view_top_padding"
+ android:paddingBottom="@dimen/ws_peek_view_bottom_padding">
<ImageView
- android:layout_width="@dimen/peek_view_icon_size"
- android:layout_height="@dimen/peek_view_icon_size"
- android:src="@drawable/ic_expand_more_white_22"
+ android:layout_width="@dimen/ws_peek_view_icon_size"
+ android:layout_height="@dimen/ws_peek_view_icon_size"
+ android:src="@drawable/ws_ic_expand_more_white_22"
android:tint="?android:attr/colorForeground"
tools:ignore="ContentDescription"/>
diff --git a/wear/res/values-sw180dp-notround/dimens.xml b/wear/res/values-sw180dp-notround/dimens.xml
index 87938e5..f6395d3 100644
--- a/wear/res/values-sw180dp-notround/dimens.xml
+++ b/wear/res/values-sw180dp-notround/dimens.xml
@@ -15,11 +15,11 @@
-->
<resources>
- <dimen name="action_drawer_item_top_padding">10dp</dimen>
- <dimen name="action_drawer_item_bottom_padding">10dp</dimen>
- <dimen name="action_drawer_item_icon_right_margin">12dp</dimen>
- <dimen name="action_drawer_item_icon_size">40dp</dimen>
- <dimen name="action_drawer_item_icon_padding">8dp</dimen>
- <dimen name="action_drawer_item_text_size">16sp</dimen>
+ <dimen name="ws_action_drawer_item_top_padding">10dp</dimen>
+ <dimen name="ws_action_drawer_item_bottom_padding">10dp</dimen>
+ <dimen name="ws_action_drawer_item_icon_right_margin">12dp</dimen>
+ <dimen name="ws_action_drawer_item_icon_size">40dp</dimen>
+ <dimen name="ws_action_drawer_item_icon_padding">8dp</dimen>
+ <dimen name="ws_action_drawer_item_text_size">16sp</dimen>
</resources>
diff --git a/wear/res/values-sw210dp-round/dimens.xml b/wear/res/values-sw210dp-round/dimens.xml
index d6d4ed0..1a2581e 100644
--- a/wear/res/values-sw210dp-round/dimens.xml
+++ b/wear/res/values-sw210dp-round/dimens.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<resources>
- <dimen name="action_drawer_item_top_padding">10dp</dimen>
- <dimen name="action_drawer_item_bottom_padding">10dp</dimen>
- <dimen name="action_drawer_item_icon_right_margin">12dp</dimen>
- <dimen name="action_drawer_item_icon_size">40dp</dimen>
- <dimen name="action_drawer_item_icon_padding">8dp</dimen>
- <dimen name="action_drawer_item_text_size">16sp</dimen>
+ <dimen name="ws_action_drawer_item_top_padding">10dp</dimen>
+ <dimen name="ws_action_drawer_item_bottom_padding">10dp</dimen>
+ <dimen name="ws_action_drawer_item_icon_right_margin">12dp</dimen>
+ <dimen name="ws_action_drawer_item_icon_size">40dp</dimen>
+ <dimen name="ws_action_drawer_item_icon_padding">8dp</dimen>
+ <dimen name="ws_action_drawer_item_text_size">16sp</dimen>
</resources>
diff --git a/wear/res/values-sw210dp/dimens.xml b/wear/res/values-sw210dp/dimens.xml
index e8d7afc..8f69e0b 100644
--- a/wear/res/values-sw210dp/dimens.xml
+++ b/wear/res/values-sw210dp/dimens.xml
@@ -15,8 +15,8 @@
-->
<resources>
- <dimen name="nav_drawer_text_size">14sp</dimen>
- <dimen name="nav_drawer_single_page_icon_size">32dp</dimen>
- <dimen name="nav_drawer_single_page_circle_radius">27dp</dimen>
+ <dimen name="ws_nav_drawer_text_size">14sp</dimen>
+ <dimen name="ws_nav_drawer_single_page_icon_size">32dp</dimen>
+ <dimen name="ws_nav_drawer_single_page_circle_radius">27dp</dimen>
</resources>
diff --git a/wear/res/values-v20/styles.xml b/wear/res/values-v20/styles.xml
index aa442f7..2104f6d 100644
--- a/wear/res/values-v20/styles.xml
+++ b/wear/res/values-v20/styles.xml
@@ -15,20 +15,20 @@
-->
<resources>
- <style name="PageIndicatorViewStyle">
- <item name="pageIndicatorDotSpacing">7.8dp</item>
- <item name="pageIndicatorDotRadius">2.1dp</item>
- <item name="pageIndicatorDotRadiusSelected">3.1dp</item>
- <item name="pageIndicatorDotColor">?android:attr/colorForeground</item>
- <item name="pageIndicatorDotColorSelected">?android:attr/colorForeground</item>
- <item name="pageIndicatorDotFadeOutDelay">1000</item>
- <item name="pageIndicatorDotFadeOutDuration">250</item>
- <item name="pageIndicatorDotFadeInDuration">100</item>
- <item name="pageIndicatorDotFadeWhenIdle">true</item>
- <item name="pageIndicatorDotShadowColor">#66000000</item>
- <item name="pageIndicatorDotShadowRadius">1dp</item>
- <item name="pageIndicatorDotShadowDx">0.5dp</item>
- <item name="pageIndicatorDotShadowDy">0.5dp</item>
+ <style name="WsPageIndicatorViewStyle">
+ <item name="dotSpacing">7.8dp</item>
+ <item name="dotRadius">2.1dp</item>
+ <item name="dotRadiusSelected">3.1dp</item>
+ <item name="dotColor">?android:attr/colorForeground</item>
+ <item name="dotColorSelected">?android:attr/colorForeground</item>
+ <item name="dotFadeOutDelay">1000</item>
+ <item name="dotFadeOutDuration">250</item>
+ <item name="dotFadeInDuration">100</item>
+ <item name="dotFadeWhenIdle">true</item>
+ <item name="dotShadowColor">#66000000</item>
+ <item name="dotShadowRadius">1dp</item>
+ <item name="dotShadowDx">0.5dp</item>
+ <item name="dotShadowDy">0.5dp</item>
</style>
</resources>
diff --git a/wear/res/values-v23/styles.xml b/wear/res/values-v23/styles.xml
index 49a94eb..6bb1a51 100644
--- a/wear/res/values-v23/styles.xml
+++ b/wear/res/values-v23/styles.xml
@@ -14,15 +14,15 @@
limitations under the License.
-->
<resources>
- <style name="WearableActionDrawerItemText">
+ <style name="WsWearableActionDrawerItemText">
<item name="android:layout_gravity">center_vertical</item>
<item name="android:ellipsize">end</item>
<item name="android:fontFamily">sans-serif-condensed-light</item>
<item name="android:maxLines">3</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:textSize">@dimen/action_drawer_item_text_size</item>
+ <item name="android:textSize">@dimen/ws_action_drawer_item_text_size</item>
</style>
- <style name="WearableActionDrawerTitleText" parent="android:TextAppearance.Material.Subhead">
+ <style name="WsWearableActionDrawerTitleText" parent="android:TextAppearance.Material.Subhead">
<item name="android:alpha">0.7</item>
</style>
</resources>
diff --git a/wear/res/values/attrs.xml b/wear/res/values/attrs.xml
index 673fda5..8688a52 100644
--- a/wear/res/values/attrs.xml
+++ b/wear/res/values/attrs.xml
@@ -101,70 +101,70 @@
<declare-styleable name="PageIndicatorView">
<!-- Sets the distance between dots. -->
- <attr name="pageIndicatorDotSpacing" format="dimension" />
+ <attr name="dotSpacing" format="dimension" />
<!-- Sets the radius of a dot when it is not selected. -->
- <attr name="pageIndicatorDotRadius" format="dimension" />
+ <attr name="dotRadius" format="dimension" />
<!-- Sets the radius of a dot when it is selected. -->
- <attr name="pageIndicatorDotRadiusSelected" format="dimension" />
+ <attr name="dotRadiusSelected" format="dimension" />
<!-- Sets the color of a dot when it is not selected. -->
- <attr name="pageIndicatorDotColor" format="color" />
+ <attr name="dotColor" format="color" />
<!-- Sets the color of a dot when it is selected. -->
- <attr name="pageIndicatorDotColorSelected" format="color" />
+ <attr name="dotColorSelected" format="color" />
<!-- Sets whether the dots should fade out after inactivity. -->
- <attr name="pageIndicatorDotFadeWhenIdle" format="boolean" />
+ <attr name="dotFadeWhenIdle" format="boolean" />
<!-- Sets the delay between the pager arriving at an idle state, and the fade out animation
beginning, in milliseconds. -->
- <attr name="pageIndicatorDotFadeOutDelay" format="integer" />
+ <attr name="dotFadeOutDelay" format="integer" />
<!-- Sets the duration of the fade out animation. -->
- <attr name="pageIndicatorDotFadeOutDuration" format="integer" />
+ <attr name="dotFadeOutDuration" format="integer" />
<!-- Sets the duration of the fade in animation. -->
- <attr name="pageIndicatorDotFadeInDuration" format="integer" />
+ <attr name="dotFadeInDuration" format="integer" />
<!-- Sets the shadow color. -->
- <attr name="pageIndicatorDotShadowColor" format="color" />
+ <attr name="dotShadowColor" format="color" />
<!-- Sets the shadow radius. -->
- <attr name="pageIndicatorDotShadowRadius" format="dimension" />
+ <attr name="dotShadowRadius" format="dimension" />
<!-- Sets the horizontal shadow offset. -->
- <attr name="pageIndicatorDotShadowDx" format="dimension" />
+ <attr name="dotShadowDx" format="dimension" />
<!-- Sets the vertical shadow offset. -->
- <attr name="pageIndicatorDotShadowDy" format="dimension" />
+ <attr name="dotShadowDy" format="dimension" />
</declare-styleable>
<declare-styleable name="CircledImageView">
<attr name="android:src" />
<!-- Sets the color of the circle. -->
- <attr name="circle_color" format="color" />
+ <attr name="background_color" format="color" />
<!-- Sets the radius of the circle. -->
- <attr name="circle_radius" format="dimension" />
+ <attr name="background_radius" format="dimension" />
<!-- Sets the radius of the circle while the circle is being pressed. -->
- <attr name="circle_radius_pressed" format="dimension" />
+ <attr name="background_radius_pressed" format="dimension" />
<!-- Sets the width of the border. -->
- <attr name="circle_border_width" format="dimension" />
+ <attr name="background_border_width" format="dimension" />
<!-- Sets the color of the border. -->
- <attr name="circle_border_color" format="color" />
+ <attr name="background_border_color" format="color" />
<!-- Sets the stroke cap for the border around the circle. -->
- <attr name="circle_border_cap" format="enum">
+ <attr name="background_border_cap" format="enum">
<enum name="butt" value="0" />
<enum name="round" value="1" />
<enum name="square" value="2" />
</attr>
<!-- Sets the padding between the edge of the circle and the start of the image. -->
- <attr name="circle_padding" format="dimension" />
+ <attr name="img_padding" format="dimension" />
<!-- Sets the width of the shadow. -->
- <attr name="shadow_width" format="dimension" />
+ <attr name="background_shadow_width" format="dimension" />
<!-- Sets the percentage of the circle which the image should occupy. -->
- <attr name="image_circle_percentage" format="dimension" />
+ <attr name="img_circle_percentage" format="dimension" />
<!-- Sets the percentage of the circle which the image should should be offset
horizontally. -->
- <attr name="image_horizontal_offcenter_percentage" format="dimension" />
+ <attr name="img_horizontal_offset_percentage" format="dimension" />
<!-- Sets the tint color of the image. -->
- <attr name="image_tint" format="color" />
+ <attr name="img_tint" format="color" />
<!-- Sets the radius of the circle to be a percentage of the largest dimension of the
view. -->
- <attr name="circle_radius_percent" format="fraction" />
+ <attr name="background_radius_percent" format="fraction" />
<!-- Sets the circle radius when pressed. -->
- <attr name="circle_radius_pressed_percent" format="fraction" />
+ <attr name="background_radius_pressed_percent" format="fraction" />
<!-- Sets which dimension to use if the image isn't square. -->
- <attr name="square_dimen" format="enum">
+ <attr name="clip_dimen" format="enum">
<enum name="none" value="0" />
<enum name="height" value="1" />
<enum name="width" value="2" />
diff --git a/wear/res/values/dimens.xml b/wear/res/values/dimens.xml
index c39fc77..4e5496d 100644
--- a/wear/res/values/dimens.xml
+++ b/wear/res/values/dimens.xml
@@ -15,50 +15,52 @@
-->
<resources>
<!-- Values for the WearableRecyclerView. -->
- <dimen name="wrv_curve_default_x_offset">24dp</dimen>
+ <dimen name="ws_wrv_curve_default_x_offset">24dp</dimen>
<!-- Values for WearableDrawerView. -->
- <dimen name="wearable_drawer_view_elevation">12dp</dimen>
+ <dimen name="ws_wearable_drawer_view_elevation">12dp</dimen>
<!-- Values for WearableActionDrawerView. -->
- <item name="action_drawer_item_first_item_top_padding" type="fraction">15%</item>
- <item name="action_drawer_item_last_item_bottom_padding" type="fraction">15%</item>
- <item name="action_drawer_item_left_padding" type="fraction">15%</item>
- <item name="action_drawer_item_right_padding" type="fraction">10%</item>
- <dimen name="action_drawer_item_top_padding">8dp</dimen>
- <dimen name="action_drawer_item_bottom_padding">8dp</dimen>
- <dimen name="action_drawer_item_icon_right_margin">8dp</dimen>
- <dimen name="action_drawer_item_icon_size">36dp</dimen>
- <dimen name="action_drawer_item_icon_padding">7dp</dimen>
- <dimen name="action_drawer_item_text_size">14sp</dimen>
- <dimen name="action_drawer_peek_view_height">43dp</dimen>
- <dimen name="action_drawer_peek_top_padding">2dp</dimen>
- <dimen name="action_drawer_expand_icon_top_margin">-3dp</dimen>
+ <item name="ws_action_drawer_item_first_item_top_padding" type="fraction">15%</item>
+ <item name="ws_action_drawer_item_last_item_bottom_padding" type="fraction">15%</item>
+ <item name="ws_action_drawer_item_left_padding" type="fraction">15%</item>
+ <item name="ws_action_drawer_item_right_padding" type="fraction">10%</item>
+ <dimen name="ws_action_drawer_item_top_padding">8dp</dimen>
+ <dimen name="ws_action_drawer_item_bottom_padding">8dp</dimen>
+ <dimen name="ws_action_drawer_item_icon_right_margin">8dp</dimen>
+ <dimen name="ws_action_drawer_item_icon_size">36dp</dimen>
+ <dimen name="ws_action_drawer_item_icon_padding">7dp</dimen>
+ <dimen name="ws_action_drawer_item_text_size">14sp</dimen>
+ <dimen name="ws_action_drawer_peek_view_height">43dp</dimen>
+ <dimen name="ws_action_drawer_peek_top_padding">2dp</dimen>
+ <dimen name="ws_action_drawer_expand_icon_top_margin">-3dp</dimen>
<!-- Dimensions for the single page WearableNavigationDrawerView. -->
- <dimen name="nav_drawer_single_page_icon_size">28dp</dimen>
- <dimen name="nav_drawer_single_page_icon_padding">6dp</dimen>
- <dimen name="nav_drawer_single_page_circle_radius">24dp</dimen>
- <dimen name="nav_drawer_text_size">12sp</dimen>
- <fraction name="nav_drawer_text_margin">13%</fraction>
- <fraction name="nav_drawer_margin_2_items">20%</fraction>
- <fraction name="nav_drawer_margin_3_items">16%</fraction>
- <fraction name="nav_drawer_margin_4_items_vertical">16.9%</fraction>
- <fraction name="nav_drawer_margin_4_items_horizontal">13%</fraction>
- <fraction name="nav_drawer_margin_5_items_horizontal_outer_rows">27.4%</fraction>
- <fraction name="nav_drawer_margin_5_items_horizontal_middle_row">13%</fraction>
- <fraction name="nav_drawer_margin_5_items_vertical">16.9%</fraction>
- <fraction name="nav_drawer_margin_6_items_horizontal">16%</fraction>
- <fraction name="nav_drawer_margin_6_items_vertical">26.8%</fraction>
- <fraction name="nav_drawer_margin_7_items_horizontal_outer_rows">27.4%</fraction>
- <fraction name="nav_drawer_margin_7_items_horizontal_middle_row">13%</fraction>
- <fraction name="nav_drawer_margin_7_items_vertical">16.9%</fraction>
+ <dimen name="ws_nav_drawer_single_page_icon_size">28dp</dimen>
+ <dimen name="ws_nav_drawer_single_page_icon_padding">6dp</dimen>
+ <dimen name="ws_nav_drawer_single_page_circle_radius">24dp</dimen>
+ <dimen name="ws_nav_drawer_text_size">12sp</dimen>
+ <fraction name="ws_nav_drawer_text_margin">13%</fraction>
+ <fraction name="ws_nav_drawer_margin_2_items">20%</fraction>
+ <fraction name="ws_nav_drawer_margin_3_items">16%</fraction>
+ <fraction name="ws_nav_drawer_margin_4_items_vertical">16.9%</fraction>
+ <fraction name="ws_nav_drawer_margin_4_items_horizontal">13%</fraction>
+ <fraction name="ws_nav_drawer_margin_5_items_horizontal_outer_rows">27.4%</fraction>
+ <fraction name="ws_nav_drawer_margin_5_items_horizontal_middle_row">13%</fraction>
+ <fraction name="ws_nav_drawer_margin_5_items_vertical">16.9%</fraction>
+ <fraction name="ws_nav_drawer_margin_6_items_horizontal">16%</fraction>
+ <fraction name="ws_nav_drawer_margin_6_items_vertical">26.8%</fraction>
+ <fraction name="ws_nav_drawer_margin_7_items_horizontal_outer_rows">27.4%</fraction>
+ <fraction name="ws_nav_drawer_margin_7_items_horizontal_middle_row">13%</fraction>
+ <fraction name="ws_nav_drawer_margin_7_items_vertical">16.9%</fraction>
- <dimen name="peek_view_top_padding">8dp</dimen>
- <dimen name="peek_view_bottom_padding">8dp</dimen>
- <dimen name="peek_view_icon_size">22dp</dimen>
+ <dimen name="ws_peek_view_top_padding">8dp</dimen>
+ <dimen name="ws_peek_view_bottom_padding">8dp</dimen>
+ <dimen name="ws_peek_view_icon_size">22dp</dimen>
<!-- Maximum distance from edge to consider an edge drag. This should be the sum of the peek
view's top padding, bottom padding, and icon size. -->
- <dimen name="drawer_view_edge_size">38dp</dimen>
+ <dimen name="ws_drawer_view_edge_size">38dp</dimen>
+ <!-- Dimensions for the wearable switch. -->
+ <dimen name="ws_switch_size">40dp</dimen>
</resources>
diff --git a/wear/res/values/ids.xml b/wear/res/values/ids.xml
index 881e52a..8a7324e 100644
--- a/wear/res/values/ids.xml
+++ b/wear/res/values/ids.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<resources>
- <item name="wearable_support_navigation_drawer_view_pager" type="id" />
+ <item name="ws_navigation_drawer_view_pager" type="id" />
</resources>
diff --git a/wear/res/values/strings.xml b/wear/res/values/strings.xml
index 4d50ddf..3bbb78c 100644
--- a/wear/res/values/strings.xml
+++ b/wear/res/values/strings.xml
@@ -15,8 +15,8 @@
-->
<resources>
<!-- String describing the navigation drawer which is read aloud when focused using accessibility gestures [CHAR LIMIT=35] -->
- <string name="navigation_drawer_content_description">Navigation drawer</string>
+ <string name="ws_navigation_drawer_content_description">Navigation drawer</string>
<!-- String describing the action drawer which is read aloud when focused using accessibility gestures [CHAR LIMIT=35] -->
- <string name="action_drawer_content_description">Action drawer</string>
+ <string name="ws_action_drawer_content_description">Action drawer</string>
</resources>
diff --git a/wear/res/values/styles.xml b/wear/res/values/styles.xml
index 706df13..c0036f1 100644
--- a/wear/res/values/styles.xml
+++ b/wear/res/values/styles.xml
@@ -14,27 +14,41 @@
limitations under the License.
-->
<resources>
- <style name="SinglePageNavDrawerIconStyle">
- <item name="android:layout_height">@dimen/nav_drawer_single_page_icon_size</item>
- <item name="android:layout_width">@dimen/nav_drawer_single_page_icon_size</item>
- <item name="android:padding">@dimen/nav_drawer_single_page_icon_padding</item>
+ <style name="WsSinglePageNavDrawerIconStyle">
+ <item name="android:layout_height">@dimen/ws_nav_drawer_single_page_icon_size</item>
+ <item name="android:layout_width">@dimen/ws_nav_drawer_single_page_icon_size</item>
+ <item name="android:padding">@dimen/ws_nav_drawer_single_page_icon_padding</item>
<item name="android:clipToPadding">false</item>
- <item name="circle_radius">@dimen/nav_drawer_single_page_circle_radius</item>
- <item name="circle_color">#33ffffff</item>
+ <item name="background_radius">@dimen/ws_nav_drawer_single_page_circle_radius</item>
+ <item name="background_color">#33ffffff</item>
</style>
- <style name="SinglePageNavDrawerTextStyle">
+ <style name="WsSinglePageNavDrawerTextStyle">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">match_parent</item>
<item name="android:fontFamily">sans-serif-condensed</item>
- <item name="android:textSize">@dimen/nav_drawer_text_size</item>
+ <item name="android:textSize">@dimen/ws_nav_drawer_text_size</item>
<item name="android:gravity">center</item>
<item name="android:maxLines">2</item>
- <item name="layout_marginTopPercent">@fraction/nav_drawer_text_margin</item>
- <item name="layout_marginStartPercent">@fraction/nav_drawer_text_margin</item>
- <item name="layout_marginEndPercent">@fraction/nav_drawer_text_margin</item>
+ <item name="layout_marginTopPercent">@fraction/ws_nav_drawer_text_margin</item>
+ <item name="layout_marginStartPercent">@fraction/ws_nav_drawer_text_margin</item>
+ <item name="layout_marginEndPercent">@fraction/ws_nav_drawer_text_margin</item>
</style>
- <style name="Widget.Wearable.WearableDrawerView" parent="">
- <item name="android:elevation">@dimen/wearable_drawer_view_elevation</item>
+ <style name="Widget.Wear.WearableDrawerView" parent="">
+ <item name="android:elevation">@dimen/ws_wearable_drawer_view_elevation</item>
<item name="android:background">?android:attr/colorBackgroundFloating</item>
</style>
+ <style name="Widget.Wear.RoundSwitch"
+ parent="@android:style/Widget.Material.CompoundButton.Switch">
+ <item name="android:layout_width">@dimen/ws_switch_size</item>
+ <item name="android:layout_height">@dimen/ws_switch_size</item>
+ <item name="android:switchMinWidth">@dimen/ws_switch_size</item>
+ <item name="android:layout_gravity">center</item>
+ <item name="android:thumb">@drawable/ws_switch_thumb_material_anim</item>
+ <item name="android:thumbTint">@color/ws_switch_thumb_color_material</item>
+ <item name="android:thumbTintMode">multiply</item>
+ <item name="android:track">@drawable/ws_switch_track_mtrl</item>
+ <item name="android:trackTint">@color/ws_switch_track_color_material</item>
+ <item name="android:background">@empty</item>
+ <item name="android:showText">false</item>
+ </style>
</resources>
diff --git a/wear/src/android/support/wear/internal/widget/drawer/MultiPageUi.java b/wear/src/android/support/wear/internal/widget/drawer/MultiPageUi.java
index 8a65b57..9056845 100644
--- a/wear/src/android/support/wear/internal/widget/drawer/MultiPageUi.java
+++ b/wear/src/android/support/wear/internal/widget/drawer/MultiPageUi.java
@@ -59,16 +59,16 @@
mPresenter = presenter;
LayoutInflater inflater = LayoutInflater.from(drawer.getContext());
- final View content =
- inflater.inflate(R.layout.navigation_drawer_view, drawer, false /* attachToRoot */);
+ final View content = inflater.inflate(R.layout.ws_navigation_drawer_view, drawer,
+ false /* attachToRoot */);
mNavigationPager =
(ViewPager) content
- .findViewById(R.id.wearable_support_navigation_drawer_view_pager);
+ .findViewById(R.id.ws_navigation_drawer_view_pager);
mPageIndicatorView =
(PageIndicatorView)
content.findViewById(
- R.id.wearable_support_navigation_drawer_page_indicator);
+ R.id.ws_navigation_drawer_page_indicator);
drawer.setDrawerContent(content);
}
@@ -138,13 +138,13 @@
// of this method. Attaching to root will cause view to point to container instead.
final View view =
LayoutInflater.from(container.getContext())
- .inflate(R.layout.navigation_drawer_item_view, container, false);
+ .inflate(R.layout.ws_navigation_drawer_item_view, container, false);
container.addView(view);
final ImageView iconView =
(ImageView) view
- .findViewById(R.id.wearable_support_navigation_drawer_item_icon);
+ .findViewById(R.id.ws_navigation_drawer_item_icon);
final TextView textView =
- (TextView) view.findViewById(R.id.wearable_support_navigation_drawer_item_text);
+ (TextView) view.findViewById(R.id.ws_navigation_drawer_item_text);
iconView.setImageDrawable(mAdapter.getItemDrawable(position));
textView.setText(mAdapter.getItemText(position));
return view;
diff --git a/wear/src/android/support/wear/internal/widget/drawer/SinglePageUi.java b/wear/src/android/support/wear/internal/widget/drawer/SinglePageUi.java
index 9a834eb..f3a4290 100644
--- a/wear/src/android/support/wear/internal/widget/drawer/SinglePageUi.java
+++ b/wear/src/android/support/wear/internal/widget/drawer/SinglePageUi.java
@@ -44,26 +44,26 @@
@IdRes
private static final int[] SINGLE_PAGE_BUTTON_IDS =
new int[]{
- R.id.wearable_support_nav_drawer_icon_0,
- R.id.wearable_support_nav_drawer_icon_1,
- R.id.wearable_support_nav_drawer_icon_2,
- R.id.wearable_support_nav_drawer_icon_3,
- R.id.wearable_support_nav_drawer_icon_4,
- R.id.wearable_support_nav_drawer_icon_5,
- R.id.wearable_support_nav_drawer_icon_6,
+ R.id.ws_nav_drawer_icon_0,
+ R.id.ws_nav_drawer_icon_1,
+ R.id.ws_nav_drawer_icon_2,
+ R.id.ws_nav_drawer_icon_3,
+ R.id.ws_nav_drawer_icon_4,
+ R.id.ws_nav_drawer_icon_5,
+ R.id.ws_nav_drawer_icon_6,
};
@LayoutRes
private static final int[] SINGLE_PAGE_LAYOUT_RES =
new int[]{
0,
- R.layout.single_page_nav_drawer_1_item,
- R.layout.single_page_nav_drawer_2_item,
- R.layout.single_page_nav_drawer_3_item,
- R.layout.single_page_nav_drawer_4_item,
- R.layout.single_page_nav_drawer_5_item,
- R.layout.single_page_nav_drawer_6_item,
- R.layout.single_page_nav_drawer_7_item,
+ R.layout.ws_single_page_nav_drawer_1_item,
+ R.layout.ws_single_page_nav_drawer_2_item,
+ R.layout.ws_single_page_nav_drawer_3_item,
+ R.layout.ws_single_page_nav_drawer_4_item,
+ R.layout.ws_single_page_nav_drawer_5_item,
+ R.layout.ws_single_page_nav_drawer_6_item,
+ R.layout.ws_single_page_nav_drawer_7_item,
};
private final WearableNavigationDrawerView mDrawer;
@@ -108,10 +108,10 @@
View content = inflater.inflate(layoutRes, mDrawer, false /* attachToRoot */);
final View peek =
inflater.inflate(
- R.layout.single_page_nav_drawer_peek_view, mDrawer,
+ R.layout.ws_single_page_nav_drawer_peek_view, mDrawer,
false /* attachToRoot */);
- mTextView = (TextView) content.findViewById(R.id.wearable_support_nav_drawer_text);
+ mTextView = (TextView) content.findViewById(R.id.ws_nav_drawer_text);
mSinglePageImageViews = new CircledImageView[count];
for (int i = 0; i < count; i++) {
mSinglePageImageViews[i] = (CircledImageView) content
diff --git a/wear/src/android/support/wear/widget/CircledImageView.java b/wear/src/android/support/wear/widget/CircledImageView.java
index 413b913..e21a1ab 100644
--- a/wear/src/android/support/wear/widget/CircledImageView.java
+++ b/wear/src/android/support/wear/widget/CircledImageView.java
@@ -143,54 +143,55 @@
mDrawable = mDrawable.mutate();
}
- mCircleColor = a.getColorStateList(R.styleable.CircledImageView_circle_color);
+ mCircleColor = a.getColorStateList(R.styleable.CircledImageView_background_color);
if (mCircleColor == null) {
mCircleColor = ColorStateList.valueOf(android.R.color.darker_gray);
}
- mCircleRadius = a.getDimension(R.styleable.CircledImageView_circle_radius, 0);
+ mCircleRadius = a.getDimension(R.styleable.CircledImageView_background_radius, 0);
mInitialCircleRadius = mCircleRadius;
- mCircleRadiusPressed =
- a.getDimension(R.styleable.CircledImageView_circle_radius_pressed, mCircleRadius);
+ mCircleRadiusPressed = a.getDimension(
+ R.styleable.CircledImageView_background_radius_pressed, mCircleRadius);
mCircleBorderColor = a
- .getColor(R.styleable.CircledImageView_circle_border_color, Color.BLACK);
+ .getColor(R.styleable.CircledImageView_background_border_color, Color.BLACK);
mCircleBorderCap =
- Paint.Cap.values()[a.getInt(R.styleable.CircledImageView_circle_border_cap, 0)];
- mCircleBorderWidth = a.getDimension(R.styleable.CircledImageView_circle_border_width, 0);
+ Paint.Cap.values()[a.getInt(R.styleable.CircledImageView_background_border_cap, 0)];
+ mCircleBorderWidth = a.getDimension(
+ R.styleable.CircledImageView_background_border_width, 0);
if (mCircleBorderWidth > 0) {
// The border arc is drawn from the middle of the arc - take that into account.
mRadiusInset += mCircleBorderWidth / 2;
}
- float circlePadding = a.getDimension(R.styleable.CircledImageView_circle_padding, 0);
+ float circlePadding = a.getDimension(R.styleable.CircledImageView_img_padding, 0);
if (circlePadding > 0) {
mRadiusInset += circlePadding;
}
mImageCirclePercentage = a
- .getFloat(R.styleable.CircledImageView_image_circle_percentage, 0f);
+ .getFloat(R.styleable.CircledImageView_img_circle_percentage, 0f);
mImageHorizontalOffcenterPercentage =
- a.getFloat(R.styleable.CircledImageView_image_horizontal_offcenter_percentage, 0f);
+ a.getFloat(R.styleable.CircledImageView_img_horizontal_offset_percentage, 0f);
- if (a.hasValue(R.styleable.CircledImageView_image_tint)) {
- mImageTint = a.getColor(R.styleable.CircledImageView_image_tint, 0);
+ if (a.hasValue(R.styleable.CircledImageView_img_tint)) {
+ mImageTint = a.getColor(R.styleable.CircledImageView_img_tint, 0);
}
- if (a.hasValue(R.styleable.CircledImageView_square_dimen)) {
- mSquareDimen = a.getInt(R.styleable.CircledImageView_square_dimen, SQUARE_DIMEN_NONE);
+ if (a.hasValue(R.styleable.CircledImageView_clip_dimen)) {
+ mSquareDimen = a.getInt(R.styleable.CircledImageView_clip_dimen, SQUARE_DIMEN_NONE);
}
mCircleRadiusPercent =
- a.getFraction(R.styleable.CircledImageView_circle_radius_percent, 1, 1, 0f);
+ a.getFraction(R.styleable.CircledImageView_background_radius_percent, 1, 1, 0f);
mCircleRadiusPressedPercent =
a.getFraction(
- R.styleable.CircledImageView_circle_radius_pressed_percent, 1, 1,
+ R.styleable.CircledImageView_background_radius_pressed_percent, 1, 1,
mCircleRadiusPercent);
- float shadowWidth = a.getDimension(R.styleable.CircledImageView_shadow_width, 0);
+ float shadowWidth = a.getDimension(R.styleable.CircledImageView_background_shadow_width, 0);
a.recycle();
diff --git a/wear/src/android/support/wear/widget/CurvingLayoutCallback.java b/wear/src/android/support/wear/widget/CurvingLayoutCallback.java
index f6eed46..275f1f8 100644
--- a/wear/src/android/support/wear/widget/CurvingLayoutCallback.java
+++ b/wear/src/android/support/wear/widget/CurvingLayoutCallback.java
@@ -53,7 +53,7 @@
mPathMeasure = new PathMeasure();
mIsScreenRound = context.getResources().getConfiguration().isScreenRound();
mXCurveOffset = context.getResources().getDimensionPixelSize(
- R.dimen.wrv_curve_default_x_offset);
+ R.dimen.ws_wrv_curve_default_x_offset);
}
@Override
diff --git a/wear/src/android/support/wear/widget/drawer/PageIndicatorView.java b/wear/src/android/support/wear/widget/drawer/PageIndicatorView.java
index 7317c21..bd2dded 100644
--- a/wear/src/android/support/wear/widget/drawer/PageIndicatorView.java
+++ b/wear/src/android/support/wear/widget/drawer/PageIndicatorView.java
@@ -96,28 +96,28 @@
getContext()
.obtainStyledAttributes(
attrs, R.styleable.PageIndicatorView, defStyleAttr,
- R.style.PageIndicatorViewStyle);
+ R.style.WsPageIndicatorViewStyle);
mDotSpacing =
- a.getDimensionPixelOffset(R.styleable.PageIndicatorView_pageIndicatorDotSpacing, 0);
- mDotRadius = a.getDimension(R.styleable.PageIndicatorView_pageIndicatorDotRadius, 0);
+ a.getDimensionPixelOffset(R.styleable.PageIndicatorView_dotSpacing, 0);
+ mDotRadius = a.getDimension(R.styleable.PageIndicatorView_dotRadius, 0);
mDotRadiusSelected =
- a.getDimension(R.styleable.PageIndicatorView_pageIndicatorDotRadiusSelected, 0);
- mDotColor = a.getColor(R.styleable.PageIndicatorView_pageIndicatorDotColor, 0);
+ a.getDimension(R.styleable.PageIndicatorView_dotRadiusSelected, 0);
+ mDotColor = a.getColor(R.styleable.PageIndicatorView_dotColor, 0);
mDotColorSelected = a
- .getColor(R.styleable.PageIndicatorView_pageIndicatorDotColorSelected, 0);
- mDotFadeOutDelay = a.getInt(R.styleable.PageIndicatorView_pageIndicatorDotFadeOutDelay, 0);
+ .getColor(R.styleable.PageIndicatorView_dotColorSelected, 0);
+ mDotFadeOutDelay = a.getInt(R.styleable.PageIndicatorView_dotFadeOutDelay, 0);
mDotFadeOutDuration =
- a.getInt(R.styleable.PageIndicatorView_pageIndicatorDotFadeOutDuration, 0);
+ a.getInt(R.styleable.PageIndicatorView_dotFadeOutDuration, 0);
mDotFadeInDuration = a
- .getInt(R.styleable.PageIndicatorView_pageIndicatorDotFadeInDuration, 0);
+ .getInt(R.styleable.PageIndicatorView_dotFadeInDuration, 0);
mDotFadeWhenIdle =
- a.getBoolean(R.styleable.PageIndicatorView_pageIndicatorDotFadeWhenIdle, false);
- mDotShadowDx = a.getDimension(R.styleable.PageIndicatorView_pageIndicatorDotShadowDx, 0);
- mDotShadowDy = a.getDimension(R.styleable.PageIndicatorView_pageIndicatorDotShadowDy, 0);
+ a.getBoolean(R.styleable.PageIndicatorView_dotFadeWhenIdle, false);
+ mDotShadowDx = a.getDimension(R.styleable.PageIndicatorView_dotShadowDx, 0);
+ mDotShadowDy = a.getDimension(R.styleable.PageIndicatorView_dotShadowDy, 0);
mDotShadowRadius =
- a.getDimension(R.styleable.PageIndicatorView_pageIndicatorDotShadowRadius, 0);
- mDotShadowColor = a.getColor(R.styleable.PageIndicatorView_pageIndicatorDotShadowColor, 0);
+ a.getDimension(R.styleable.PageIndicatorView_dotShadowRadius, 0);
+ mDotShadowColor = a.getColor(R.styleable.PageIndicatorView_dotShadowColor, 0);
a.recycle();
mDotPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
diff --git a/wear/src/android/support/wear/widget/drawer/WearableActionDrawerView.java b/wear/src/android/support/wear/widget/drawer/WearableActionDrawerView.java
index a663cc2..3074865 100644
--- a/wear/src/android/support/wear/widget/drawer/WearableActionDrawerView.java
+++ b/wear/src/android/support/wear/widget/drawer/WearableActionDrawerView.java
@@ -137,20 +137,20 @@
if (!mShowOverflowInPeek) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
- View peekView = layoutInflater.inflate(
- R.layout.action_drawer_peek_view, getPeekContainer(), false /* attachToRoot */);
+ View peekView = layoutInflater.inflate(R.layout.ws_action_drawer_peek_view,
+ getPeekContainer(), false /* attachToRoot */);
setPeekContent(peekView);
mPeekActionIcon =
(ImageView) peekView
- .findViewById(R.id.wearable_support_action_drawer_peek_action_icon);
+ .findViewById(R.id.ws_action_drawer_peek_action_icon);
mPeekExpandIcon =
(ImageView) peekView
- .findViewById(R.id.wearable_support_action_drawer_expand_icon);
+ .findViewById(R.id.ws_action_drawer_expand_icon);
} else {
mPeekActionIcon = null;
mPeekExpandIcon = null;
getPeekContainer().setContentDescription(
- context.getString(R.string.action_drawer_content_description));
+ context.getString(R.string.ws_action_drawer_content_description));
}
if (menuRes != 0) {
@@ -164,26 +164,26 @@
int screenHeightPx = ResourcesUtil.getScreenHeightPx(context);
Resources res = getResources();
- mTopPadding = res.getDimensionPixelOffset(R.dimen.action_drawer_item_top_padding);
- mBottomPadding = res.getDimensionPixelOffset(R.dimen.action_drawer_item_bottom_padding);
+ mTopPadding = res.getDimensionPixelOffset(R.dimen.ws_action_drawer_item_top_padding);
+ mBottomPadding = res.getDimensionPixelOffset(R.dimen.ws_action_drawer_item_bottom_padding);
mLeftPadding =
ResourcesUtil.getFractionOfScreenPx(
- context, screenWidthPx, R.fraction.action_drawer_item_left_padding);
+ context, screenWidthPx, R.fraction.ws_action_drawer_item_left_padding);
mRightPadding =
ResourcesUtil.getFractionOfScreenPx(
- context, screenWidthPx, R.fraction.action_drawer_item_right_padding);
+ context, screenWidthPx, R.fraction.ws_action_drawer_item_right_padding);
mFirstItemTopPadding =
ResourcesUtil.getFractionOfScreenPx(
context, screenHeightPx,
- R.fraction.action_drawer_item_first_item_top_padding);
+ R.fraction.ws_action_drawer_item_first_item_top_padding);
mLastItemBottomPadding =
ResourcesUtil.getFractionOfScreenPx(
context, screenHeightPx,
- R.fraction.action_drawer_item_last_item_bottom_padding);
+ R.fraction.ws_action_drawer_item_last_item_bottom_padding);
mIconRightMargin = res
- .getDimensionPixelOffset(R.dimen.action_drawer_item_icon_right_margin);
+ .getDimensionPixelOffset(R.dimen.ws_action_drawer_item_icon_right_margin);
mActionList = new RecyclerView(context);
mActionList.setLayoutManager(new LinearLayoutManager(context));
@@ -359,7 +359,7 @@
TitleViewHolder(View view) {
super(view);
this.view = view;
- textView = (TextView) view.findViewById(R.id.wearable_support_action_drawer_title);
+ textView = (TextView) view.findViewById(R.id.ws_action_drawer_title);
}
}
@@ -425,14 +425,14 @@
case TYPE_TITLE:
View titleView =
LayoutInflater.from(parent.getContext())
- .inflate(R.layout.action_drawer_title_view, parent, false);
+ .inflate(R.layout.ws_action_drawer_title_view, parent, false);
return new TitleViewHolder(titleView);
case TYPE_ACTION:
default:
View actionView =
LayoutInflater.from(parent.getContext())
- .inflate(R.layout.action_drawer_item_view, parent, false);
+ .inflate(R.layout.ws_action_drawer_item_view, parent, false);
actionView.setOnClickListener(mItemClickListener);
return new ActionItemViewHolder(actionView);
}
@@ -453,9 +453,9 @@
ActionItemViewHolder(View view) {
super(view);
this.view = view;
- iconView = (ImageView) view.findViewById(R.id.wearable_support_action_drawer_item_icon);
+ iconView = (ImageView) view.findViewById(R.id.ws_action_drawer_item_icon);
((LinearLayout.LayoutParams) iconView.getLayoutParams()).setMarginEnd(mIconRightMargin);
- textView = (TextView) view.findViewById(R.id.wearable_support_action_drawer_item_text);
+ textView = (TextView) view.findViewById(R.id.ws_action_drawer_item_text);
}
}
}
diff --git a/wear/src/android/support/wear/widget/drawer/WearableDrawerView.java b/wear/src/android/support/wear/widget/drawer/WearableDrawerView.java
index 97aa9f5..0203860 100644
--- a/wear/src/android/support/wear/widget/drawer/WearableDrawerView.java
+++ b/wear/src/android/support/wear/widget/drawer/WearableDrawerView.java
@@ -149,13 +149,14 @@
public WearableDrawerView(
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- LayoutInflater.from(context).inflate(R.layout.wearable_drawer_view, this, true);
+ LayoutInflater.from(context).inflate(R.layout.ws_wearable_drawer_view, this, true);
setClickable(true);
- setElevation(context.getResources().getDimension(R.dimen.wearable_drawer_view_elevation));
+ setElevation(context.getResources()
+ .getDimension(R.dimen.ws_wearable_drawer_view_elevation));
- mPeekContainer = (ViewGroup) findViewById(R.id.wearable_support_drawer_view_peek_container);
- mPeekIcon = (ImageView) findViewById(R.id.wearable_support_drawer_view_peek_icon);
+ mPeekContainer = (ViewGroup) findViewById(R.id.ws_drawer_view_peek_container);
+ mPeekIcon = (ImageView) findViewById(R.id.ws_drawer_view_peek_icon);
mPeekContainer.setOnClickListener(
new OnClickListener() {
@@ -215,10 +216,10 @@
== Gravity.TOP;
if (isTopDrawer) {
peekParams.gravity = Gravity.BOTTOM;
- mPeekIcon.setImageResource(R.drawable.ic_more_horiz_24dp_wht);
+ mPeekIcon.setImageResource(R.drawable.ws_ic_more_horiz_24dp_wht);
} else {
peekParams.gravity = Gravity.TOP;
- mPeekIcon.setImageResource(R.drawable.ic_more_vert_24dp_wht);
+ mPeekIcon.setImageResource(R.drawable.ws_ic_more_vert_24dp_wht);
}
mPeekContainer.setLayoutParams(peekParams);
}
@@ -466,7 +467,7 @@
TypedArray typedArray =
context.obtainStyledAttributes(
attrs, R.styleable.WearableDrawerView, defStyleAttr,
- R.style.Widget_Wearable_WearableDrawerView);
+ R.style.Widget_Wear_WearableDrawerView);
Drawable background =
getDrawable(context, typedArray, R.styleable.WearableDrawerView_android_background);
diff --git a/wear/src/android/support/wear/widget/drawer/WearableNavigationDrawerView.java b/wear/src/android/support/wear/widget/drawer/WearableNavigationDrawerView.java
index 5a17c5c..31cbdd0 100644
--- a/wear/src/android/support/wear/widget/drawer/WearableNavigationDrawerView.java
+++ b/wear/src/android/support/wear/widget/drawer/WearableNavigationDrawerView.java
@@ -163,7 +163,7 @@
getPeekContainer()
.setContentDescription(
- context.getString(R.string.navigation_drawer_content_description));
+ context.getString(R.string.ws_navigation_drawer_content_description));
setOpenOnlyAtTopEnabled(true);
}
diff --git a/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java b/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
index 88c89c7..07eaa87 100644
--- a/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
+++ b/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
@@ -136,7 +136,7 @@
MAX_WAIT_MS));
// THEN the text should display "0".
- onView(withId(R.id.wearable_support_nav_drawer_text)).check(matches(withText("0")));
+ onView(withId(R.id.ws_nav_drawer_text)).check(matches(withText("0")));
}
@Test
@@ -151,13 +151,13 @@
MAX_WAIT_MS));
// WHEN the second item is selected
- onView(withId(R.id.wearable_support_nav_drawer_icon_1)).perform(click());
+ onView(withId(R.id.ws_nav_drawer_icon_1)).perform(click());
// THEN the text should display "1" and it should close.
- onView(withId(R.id.wearable_support_nav_drawer_text))
+ onView(withId(R.id.ws_nav_drawer_text))
.perform(
waitForMatchingView(
- allOf(withId(R.id.wearable_support_nav_drawer_text), withText("1")),
+ allOf(withId(R.id.ws_nav_drawer_text), withText("1")),
MAX_WAIT_MS));
onView(withId(R.id.navigation_drawer))
.perform(
@@ -181,7 +181,7 @@
selectNavItem(navDrawer, 1);
// THEN the text should display "1" and the listener should be notified.
- onView(withId(R.id.wearable_support_nav_drawer_text))
+ onView(withId(R.id.ws_nav_drawer_text))
.check(matches(withText("1")));
verify(mNavDrawerItemSelectedListener).onItemSelected(1);
}
@@ -201,7 +201,7 @@
selectNavItem(navDrawer, 1);
// THEN the text should display "1" and the listener should be notified.
- onView(allOf(withId(R.id.wearable_support_navigation_drawer_item_text), isDisplayed()))
+ onView(allOf(withId(R.id.ws_navigation_drawer_item_text), isDisplayed()))
.check(matches(withText("1")));
verify(mNavDrawerItemSelectedListener).onItemSelected(1);
}
@@ -319,7 +319,7 @@
DrawerTestActivity activity = activityRule.getActivity();
ImageView peekIconView =
(ImageView) activity
- .findViewById(R.id.wearable_support_action_drawer_peek_action_icon);
+ .findViewById(R.id.ws_action_drawer_peek_action_icon);
// THEN its peek icon should not be null
assertNotNull(peekIconView.getDrawable());
}
@@ -340,7 +340,7 @@
onView(
allOf(
withParent(withId(R.id.action_drawer)),
- withId(R.id.wearable_support_drawer_view_peek_container)))
+ withId(R.id.ws_drawer_view_peek_container)))
.perform(click());
// THEN its click listener should be notified
verify(mockClickListener).onMenuItemClick(any(MenuItem.class));