Merge "Add @GuardedBy annotation to PersistentDataBlockService#mIsWritable."
diff --git a/Android.bp b/Android.bp
index 010b2b4..9088315 100644
--- a/Android.bp
+++ b/Android.bp
@@ -13,6 +13,11 @@
// limitations under the License.
subdirs = [
+ "libs/*",
"native/android",
"native/graphics/jni",
]
+
+optional_subdirs = [
+ "core/tests/utiltests/jni",
+]
diff --git a/Android.mk b/Android.mk
index 5d902c2..e17fd0b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -45,6 +45,7 @@
core/java/android/app/admin/SecurityLogTags.logtags \
core/java/android/content/EventLogTags.logtags \
core/java/android/speech/tts/EventLogTags.logtags \
+ core/java/android/net/EventLogTags.logtags \
core/java/android/webkit/EventLogTags.logtags \
core/java/com/android/internal/logging/EventLogTags.logtags \
@@ -212,6 +213,7 @@
core/java/android/net/INetworkManagementEventObserver.aidl \
core/java/android/net/INetworkPolicyListener.aidl \
core/java/android/net/INetworkPolicyManager.aidl \
+ core/java/android/net/INetworkRecommendationProvider.aidl \
core/java/android/net/INetworkScoreCache.aidl \
core/java/android/net/INetworkScoreService.aidl \
core/java/android/net/INetworkStatsService.aidl \
@@ -492,6 +494,7 @@
LOCAL_SRC_FILES += \
../../system/netd/server/binder/android/net/INetd.aidl \
+ ../native/cmds/installd/binder/android/os/IInstalld.aidl \
LOCAL_AIDL_INCLUDES += system/update_engine/binder_bindings
@@ -517,7 +520,7 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(framework_res_R_stamp)
LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt okhttp legacy-test bouncycastle ext
+LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt okhttp bouncycastle ext
LOCAL_STATIC_JAVA_LIBRARIES := \
framework-protos \
@@ -666,6 +669,9 @@
frameworks/base/core/java/android/view/textservice/SuggestionsInfo.aidl \
frameworks/base/core/java/android/service/carrier/CarrierIdentifier.aidl \
frameworks/base/core/java/android/service/carrier/MessagePdu.aidl \
+ frameworks/base/core/java/android/service/notification/Adjustment.aidl \
+ frameworks/base/core/java/android/service/notification/Condition.aidl \
+ frameworks/base/core/java/android/service/notification/SnoozeCriterion.aidl \
frameworks/base/core/java/android/service/notification/StatusBarNotification.aidl \
frameworks/base/core/java/android/service/chooser/ChooserTarget.aidl \
frameworks/base/core/java/android/speech/tts/Voice.aidl \
@@ -755,6 +761,7 @@
# Search through the base framework dirs for these packages.
# The result will be relative to frameworks/base.
fwbase_dirs_to_document := \
+ legacy-test/src \
test-runner/src \
$(patsubst $(LOCAL_PATH)/%,%, \
$(wildcard \
diff --git a/api/current.txt b/api/current.txt
index 304ccf8..c294d8a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2804,9 +2804,14 @@
public static class GestureDescription.StrokeDescription {
ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long);
+ ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long, int, boolean);
+ method public int getContinuedStrokeId();
method public long getDuration();
+ method public int getId();
method public android.graphics.Path getPath();
method public long getStartTime();
+ method public boolean isContinued();
+ field public static final int INVALID_STROKE_ID = -1; // 0xffffffff
}
}
@@ -3474,6 +3479,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public void enterPictureInPictureMode(float);
+ method public void enterPictureInPictureModeOnMoveToBackground(boolean);
method public android.view.View findViewById(int);
method public void finish();
method public void finishActivity(int);
@@ -5941,6 +5947,13 @@
package android.app.admin {
+ public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getIpAddress();
+ method public int getPort();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR;
+ }
+
public final class DeviceAdminInfo implements android.os.Parcelable {
ctor public DeviceAdminInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -5981,6 +5994,7 @@
method public void onEnabled(android.content.Context, android.content.Intent);
method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, java.lang.String);
method public void onLockTaskModeExiting(android.content.Context, android.content.Intent);
+ method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
method public void onPasswordChanged(android.content.Context, android.content.Intent);
method public void onPasswordExpiring(android.content.Context, android.content.Intent);
method public void onPasswordFailed(android.content.Context, android.content.Intent);
@@ -6085,6 +6099,7 @@
method public boolean isLockTaskPermitted(java.lang.String);
method public boolean isManagedProfile(android.content.ComponentName);
method public boolean isMasterVolumeMuted(android.content.ComponentName);
+ method public boolean isNetworkLoggingEnabled(android.content.ComponentName);
method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public boolean isProfileOwnerApp(java.lang.String);
method public boolean isProvisioningAllowed(java.lang.String);
@@ -6098,6 +6113,7 @@
method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
method public boolean requestBugreport(android.content.ComponentName);
method public boolean resetPassword(java.lang.String, int);
+ method public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(android.content.ComponentName, long);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
@@ -6121,6 +6137,7 @@
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
+ method public void setNetworkLoggingEnabled(android.content.ComponentName, boolean);
method public void setOrganizationColor(android.content.ComponentName, int);
method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
@@ -6185,6 +6202,7 @@
field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
+ field public static final java.lang.String EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION = "android.app.extra.PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION";
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
@@ -6234,6 +6252,22 @@
field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
}
+ public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getHostname();
+ method public java.lang.String[] getIpAddresses();
+ method public int getIpAddressesCount();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
+ }
+
+ public abstract class NetworkEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getPackageName();
+ method public long getTimestamp();
+ method public abstract void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.NetworkEvent> CREATOR;
+ }
+
public class SecurityLog {
ctor public SecurityLog();
field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
@@ -7944,6 +7978,7 @@
method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method protected final void setPathPermissions(android.content.pm.PathPermission[]);
method protected final void setReadPermission(java.lang.String);
@@ -7976,6 +8011,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal) throws android.os.RemoteException;
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal) throws android.os.RemoteException;
method public deprecated boolean release();
method public final android.net.Uri uncanonicalize(android.net.Uri) throws android.os.RemoteException;
method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
@@ -8078,6 +8114,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public final android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public final boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method public final void registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver);
method public void releasePersistableUriPermission(android.net.Uri, int);
@@ -8100,6 +8137,9 @@
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
+ field public static final java.lang.String QUERY_ARG_SELECTION = "android:query-selection";
+ field public static final java.lang.String QUERY_ARG_SELECTION_ARGS = "android:query-selection-args";
+ field public static final java.lang.String QUERY_ARG_SORT_ORDER = "android:query-sort-order";
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";
@@ -8816,6 +8856,7 @@
field public static final java.lang.String CATEGORY_SELECTED_ALTERNATIVE = "android.intent.category.SELECTED_ALTERNATIVE";
field public static final java.lang.String CATEGORY_TAB = "android.intent.category.TAB";
field public static final java.lang.String CATEGORY_TEST = "android.intent.category.TEST";
+ field public static final java.lang.String CATEGORY_TYPED_OPENABLE = "android.intent.category.TYPED_OPENABLE";
field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
field public static final java.lang.String CATEGORY_VOICE = "android.intent.category.VOICE";
field public static final android.os.Parcelable.Creator<android.content.Intent> CREATOR;
@@ -20199,8 +20240,8 @@
}
public class AudioTrack implements android.media.AudioRouting {
- ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
- ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
@@ -21489,7 +21530,7 @@
method public void selectTrack(int) throws java.lang.IllegalStateException;
method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
- method public void setAudioStreamType(int);
+ method public deprecated void setAudioStreamType(int);
method public void setAuxEffectSendLevel(float);
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
@@ -29681,6 +29722,7 @@
field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps";
+ field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
@@ -35056,18 +35098,19 @@
package android.service.notification {
public final class Adjustment implements android.os.Parcelable {
- ctor public Adjustment(java.lang.String, java.lang.String, int, android.os.Bundle, java.lang.CharSequence, android.net.Uri, int);
+ ctor public Adjustment(java.lang.String, java.lang.String, android.os.Bundle, java.lang.CharSequence, int);
ctor protected Adjustment(android.os.Parcel);
method public int describeContents();
method public java.lang.CharSequence getExplanation();
- method public int getImportance();
method public java.lang.String getKey();
method public java.lang.String getPackage();
- method public android.net.Uri getReference();
method public android.os.Bundle getSignals();
method public int getUser();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+ field public static final java.lang.String KEY_CHANNEL_ID = "key_channel_id";
+ field public static final java.lang.String KEY_PEOPLE = "key_people";
+ field public static final java.lang.String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
}
public final class Condition implements android.os.Parcelable {
@@ -35189,11 +35232,14 @@
public static class NotificationListenerService.Ranking {
ctor public NotificationListenerService.Ranking();
+ method public java.util.List<java.lang.String> getAdditionalPeople();
+ method public android.app.NotificationChannel getChannel();
method public int getImportance();
method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
method public java.lang.String getOverrideGroupKey();
method public int getRank();
+ method public java.util.List<android.service.notification.SnoozeCriterion> getSnoozeCriteria();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
@@ -35207,6 +35253,17 @@
field public static final android.os.Parcelable.Creator<android.service.notification.NotificationListenerService.RankingMap> CREATOR;
}
+ public final class SnoozeCriterion implements android.os.Parcelable {
+ ctor public SnoozeCriterion(java.lang.String, java.lang.CharSequence, java.lang.CharSequence);
+ ctor protected SnoozeCriterion(android.os.Parcel);
+ method public int describeContents();
+ method public java.lang.CharSequence getConfirmation();
+ method public java.lang.CharSequence getExplanation();
+ method public java.lang.String getId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.notification.SnoozeCriterion> CREATOR;
+ }
+
public class StatusBarNotification implements android.os.Parcelable {
ctor public deprecated StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
ctor public StatusBarNotification(android.os.Parcel);
@@ -37259,7 +37316,10 @@
field public static final java.lang.String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
field public static final java.lang.String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
+ field public static final java.lang.String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
field public static final java.lang.String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
+ field public static final java.lang.String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+ field public static final java.lang.String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL = "mdn_is_additional_voicemail_number_bool";
field public static final java.lang.String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
field public static final java.lang.String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
field public static final java.lang.String KEY_MMS_ALIAS_MIN_CHARS_INT = "aliasMinChars";
@@ -37642,6 +37702,7 @@
}
public final class SmsManager {
+ method public java.lang.String createAppSpecificSmsToken(android.app.PendingIntent);
method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
method public void downloadMultimediaMessage(android.content.Context, java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
method public android.os.Bundle getCarrierConfigValues();
@@ -43467,6 +43528,7 @@
field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
+ field public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 16; // 0x10
field public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192; // 0x2000
field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
@@ -44384,7 +44446,7 @@
field public static final int FLAG_ALT_FOCUSABLE_IM = 131072; // 0x20000
field public static final deprecated int FLAG_BLUR_BEHIND = 4; // 0x4
field public static final int FLAG_DIM_BEHIND = 2; // 0x2
- field public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
+ field public static final deprecated int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
field public static final deprecated int FLAG_DITHER = 4096; // 0x1000
field public static final int FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = -2147483648; // 0x80000000
field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
@@ -62569,13 +62631,13 @@
ctor public Attributes.Name(java.lang.String);
field public static final java.util.jar.Attributes.Name CLASS_PATH;
field public static final java.util.jar.Attributes.Name CONTENT_TYPE;
- field public static final java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
+ field public static final deprecated java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
field public static final java.util.jar.Attributes.Name EXTENSION_LIST;
field public static final java.util.jar.Attributes.Name EXTENSION_NAME;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_TITLE;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_URL;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_URL;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VERSION;
field public static final java.util.jar.Attributes.Name MAIN_CLASS;
field public static final java.util.jar.Attributes.Name MANIFEST_VERSION;
@@ -62642,11 +62704,11 @@
}
public static abstract interface Pack200.Packer {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void pack(java.util.jar.JarFile, java.io.OutputStream) throws java.io.IOException;
method public abstract void pack(java.util.jar.JarInputStream, java.io.OutputStream) throws java.io.IOException;
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
field public static final java.lang.String CLASS_ATTRIBUTE_PFX = "pack.class.attribute.";
field public static final java.lang.String CODE_ATTRIBUTE_PFX = "pack.code.attribute.";
field public static final java.lang.String DEFLATE_HINT = "pack.deflate.hint";
@@ -62669,9 +62731,9 @@
}
public static abstract interface Pack200.Unpacker {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void unpack(java.io.InputStream, java.util.jar.JarOutputStream) throws java.io.IOException;
method public abstract void unpack(java.io.File, java.util.jar.JarOutputStream) throws java.io.IOException;
field public static final java.lang.String DEFLATE_HINT = "unpack.deflate.hint";
diff --git a/api/system-current.txt b/api/system-current.txt
index d54e6a9..a3672b3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2918,9 +2918,14 @@
public static class GestureDescription.StrokeDescription {
ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long);
+ ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long, int, boolean);
+ method public int getContinuedStrokeId();
method public long getDuration();
+ method public int getId();
method public android.graphics.Path getPath();
method public long getStartTime();
+ method public boolean isContinued();
+ field public static final int INVALID_STROKE_ID = -1; // 0xffffffff
}
}
@@ -3591,6 +3596,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public void enterPictureInPictureMode(float);
+ method public void enterPictureInPictureModeOnMoveToBackground(boolean);
method public android.view.View findViewById(int);
method public void finish();
method public void finishActivity(int);
@@ -6113,6 +6119,13 @@
package android.app.admin {
+ public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getIpAddress();
+ method public int getPort();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR;
+ }
+
public final class DeviceAdminInfo implements android.os.Parcelable {
ctor public DeviceAdminInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -6153,6 +6166,7 @@
method public void onEnabled(android.content.Context, android.content.Intent);
method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, java.lang.String);
method public void onLockTaskModeExiting(android.content.Context, android.content.Intent);
+ method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
method public void onPasswordChanged(android.content.Context, android.content.Intent);
method public void onPasswordExpiring(android.content.Context, android.content.Intent);
method public void onPasswordFailed(android.content.Context, android.content.Intent);
@@ -6268,6 +6282,7 @@
method public boolean isLockTaskPermitted(java.lang.String);
method public boolean isManagedProfile(android.content.ComponentName);
method public boolean isMasterVolumeMuted(android.content.ComponentName);
+ method public boolean isNetworkLoggingEnabled(android.content.ComponentName);
method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public boolean isProfileOwnerApp(java.lang.String);
method public boolean isProvisioningAllowed(java.lang.String);
@@ -6282,6 +6297,7 @@
method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
method public boolean requestBugreport(android.content.ComponentName);
method public boolean resetPassword(java.lang.String, int);
+ method public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(android.content.ComponentName, long);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
@@ -6306,6 +6322,7 @@
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
+ method public void setNetworkLoggingEnabled(android.content.ComponentName, boolean);
method public void setOrganizationColor(android.content.ComponentName, int);
method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
@@ -6374,6 +6391,7 @@
field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
+ field public static final java.lang.String EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION = "android.app.extra.PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION";
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
@@ -6428,6 +6446,22 @@
field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
}
+ public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getHostname();
+ method public java.lang.String[] getIpAddresses();
+ method public int getIpAddressesCount();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
+ }
+
+ public abstract class NetworkEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getPackageName();
+ method public long getTimestamp();
+ method public abstract void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.NetworkEvent> CREATOR;
+ }
+
public class SecurityLog {
ctor public SecurityLog();
field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
@@ -8279,6 +8313,7 @@
method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method protected final void setPathPermissions(android.content.pm.PathPermission[]);
method protected final void setReadPermission(java.lang.String);
@@ -8311,6 +8346,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal) throws android.os.RemoteException;
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal) throws android.os.RemoteException;
method public deprecated boolean release();
method public final android.net.Uri uncanonicalize(android.net.Uri) throws android.os.RemoteException;
method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
@@ -8413,6 +8449,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public final android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public final boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method public final void registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver);
method public void releasePersistableUriPermission(android.net.Uri, int);
@@ -8435,6 +8472,9 @@
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
+ field public static final java.lang.String QUERY_ARG_SELECTION = "android:query-selection";
+ field public static final java.lang.String QUERY_ARG_SELECTION_ARGS = "android:query-selection-args";
+ field public static final java.lang.String QUERY_ARG_SORT_ORDER = "android:query-sort-order";
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";
@@ -9176,6 +9216,7 @@
field public static final java.lang.String CATEGORY_SELECTED_ALTERNATIVE = "android.intent.category.SELECTED_ALTERNATIVE";
field public static final java.lang.String CATEGORY_TAB = "android.intent.category.TAB";
field public static final java.lang.String CATEGORY_TEST = "android.intent.category.TEST";
+ field public static final java.lang.String CATEGORY_TYPED_OPENABLE = "android.intent.category.TYPED_OPENABLE";
field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
field public static final java.lang.String CATEGORY_VOICE = "android.intent.category.VOICE";
field public static final android.os.Parcelable.Creator<android.content.Intent> CREATOR;
@@ -10201,6 +10242,7 @@
method public void setAppPackageName(java.lang.String);
method public void setDontKillApp(boolean);
method public void setGrantedRuntimePermissions(java.lang.String[]);
+ method public void setInstallAsInstantApp(boolean);
method public void setInstallLocation(int);
method public void setOriginatingUid(int);
method public void setOriginatingUri(android.net.Uri);
@@ -10493,6 +10535,7 @@
field public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1
field public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
field public static final int MATCH_ALL = 131072; // 0x20000
+ field public static final int MATCH_ANY_USER = 4194304; // 0x400000
field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000
@@ -21766,8 +21809,8 @@
}
public class AudioTrack implements android.media.AudioRouting {
- ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
- ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
@@ -23056,7 +23099,7 @@
method public void selectTrack(int) throws java.lang.IllegalStateException;
method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
- method public void setAudioStreamType(int);
+ method public deprecated void setAudioStreamType(int);
method public void setAuxEffectSendLevel(float);
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
@@ -25950,6 +25993,14 @@
field public final android.net.WifiKey wifiKey;
}
+ public abstract class NetworkRecommendationProvider {
+ ctor public NetworkRecommendationProvider(android.os.Handler);
+ method public final android.os.IBinder getBinder();
+ method public abstract android.net.RecommendationResult onRequestRecommendation(android.net.RecommendationRequest);
+ field public static final java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
+ field public static final java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
+ }
+
public class NetworkRequest implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
@@ -25970,10 +26021,12 @@
method public boolean clearScores() throws java.lang.SecurityException;
method public void disableScoring() throws java.lang.SecurityException;
method public java.lang.String getActiveScorerPackage();
+ method public android.net.RecommendationResult requestRecommendation(android.net.RecommendationRequest) throws java.lang.SecurityException;
method public boolean setActiveScorer(java.lang.String) throws java.lang.SecurityException;
method public boolean updateScores(android.net.ScoredNetwork[]) throws java.lang.SecurityException;
field public static final java.lang.String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
field public static final java.lang.String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
+ field public static final java.lang.String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
field public static final java.lang.String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
field public static final java.lang.String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
field public static final java.lang.String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
@@ -26008,6 +26061,24 @@
field public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
}
+ public final class RecommendationRequest implements android.os.Parcelable {
+ ctor protected RecommendationRequest(android.os.Parcel);
+ method public int describeContents();
+ method public android.net.wifi.WifiConfiguration getCurrentSelectedConfig();
+ method public android.net.NetworkCapabilities getRequiredCapabilities();
+ method public android.net.wifi.ScanResult[] getScanResults();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
+ }
+
+ public final class RecommendationResult implements android.os.Parcelable {
+ ctor public RecommendationResult(android.net.wifi.WifiConfiguration);
+ method public int describeContents();
+ method public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
+ }
+
public final class RouteInfo implements android.os.Parcelable {
method public int describeContents();
method public android.net.IpPrefix getDestination();
@@ -26061,9 +26132,12 @@
public class ScoredNetwork implements android.os.Parcelable {
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
+ ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean, android.os.Bundle);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
+ field public static final java.lang.String EXTRA_HAS_CAPTIVE_PORTAL = "android.net.extra.HAS_CAPTIVE_PORTAL";
+ field public final android.os.Bundle attributes;
field public final boolean meteredHint;
field public final android.net.NetworkKey networkKey;
field public final android.net.RssiCurve rssiCurve;
@@ -32296,6 +32370,7 @@
field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps";
+ field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
@@ -35524,6 +35599,7 @@
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
+ field public static final java.lang.String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
field public static final java.lang.String ACTION_HARD_KEYBOARD_SETTINGS = "android.settings.HARD_KEYBOARD_SETTINGS";
field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
field public static final java.lang.String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
@@ -35614,6 +35690,7 @@
field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
field public static final java.lang.String MODE_RINGER = "mode_ringer";
field public static final java.lang.String NETWORK_PREFERENCE = "network_preference";
+ field public static final java.lang.String NETWORK_RECOMMENDATIONS_ENABLED = "network_recommendations_enabled";
field public static final java.lang.String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
field public static final java.lang.String RADIO_BLUETOOTH = "bluetooth";
field public static final java.lang.String RADIO_CELL = "cell";
@@ -35638,6 +35715,7 @@
field public static final int WIFI_SLEEP_POLICY_DEFAULT = 0; // 0x0
field public static final int WIFI_SLEEP_POLICY_NEVER = 2; // 0x2
field public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1; // 0x1
+ field public static final java.lang.String WIFI_WAKEUP_ENABLED = "wifi_wakeup_enabled";
field public static final java.lang.String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
field public static final java.lang.String WINDOW_ANIMATION_SCALE = "window_animation_scale";
}
@@ -37853,18 +37931,19 @@
package android.service.notification {
public final class Adjustment implements android.os.Parcelable {
- ctor public Adjustment(java.lang.String, java.lang.String, int, android.os.Bundle, java.lang.CharSequence, android.net.Uri, int);
+ ctor public Adjustment(java.lang.String, java.lang.String, android.os.Bundle, java.lang.CharSequence, int);
ctor protected Adjustment(android.os.Parcel);
method public int describeContents();
method public java.lang.CharSequence getExplanation();
- method public int getImportance();
method public java.lang.String getKey();
method public java.lang.String getPackage();
- method public android.net.Uri getReference();
method public android.os.Bundle getSignals();
method public int getUser();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+ field public static final java.lang.String KEY_CHANNEL_ID = "key_channel_id";
+ field public static final java.lang.String KEY_PEOPLE = "key_people";
+ field public static final java.lang.String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
}
public final class Condition implements android.os.Parcelable {
@@ -37993,11 +38072,14 @@
public static class NotificationListenerService.Ranking {
ctor public NotificationListenerService.Ranking();
+ method public java.util.List<java.lang.String> getAdditionalPeople();
+ method public android.app.NotificationChannel getChannel();
method public int getImportance();
method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
method public java.lang.String getOverrideGroupKey();
method public int getRank();
+ method public java.util.List<android.service.notification.SnoozeCriterion> getSnoozeCriteria();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
@@ -38011,6 +38093,17 @@
field public static final android.os.Parcelable.Creator<android.service.notification.NotificationListenerService.RankingMap> CREATOR;
}
+ public final class SnoozeCriterion implements android.os.Parcelable {
+ ctor public SnoozeCriterion(java.lang.String, java.lang.CharSequence, java.lang.CharSequence);
+ ctor protected SnoozeCriterion(android.os.Parcel);
+ method public int describeContents();
+ method public java.lang.CharSequence getConfirmation();
+ method public java.lang.CharSequence getExplanation();
+ method public java.lang.String getId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.notification.SnoozeCriterion> CREATOR;
+ }
+
public class StatusBarNotification implements android.os.Parcelable {
ctor public deprecated StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
ctor public StatusBarNotification(android.os.Parcel);
@@ -40329,7 +40422,10 @@
field public static final java.lang.String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
field public static final java.lang.String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
+ field public static final java.lang.String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
field public static final java.lang.String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
+ field public static final java.lang.String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+ field public static final java.lang.String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL = "mdn_is_additional_voicemail_number_bool";
field public static final java.lang.String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
field public static final java.lang.String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
field public static final java.lang.String KEY_MMS_ALIAS_MIN_CHARS_INT = "aliasMinChars";
@@ -40712,6 +40808,7 @@
}
public final class SmsManager {
+ method public java.lang.String createAppSpecificSmsToken(android.app.PendingIntent);
method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
method public void downloadMultimediaMessage(android.content.Context, java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
method public android.os.Bundle getCarrierConfigValues();
@@ -46619,6 +46716,7 @@
field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
+ field public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 16; // 0x10
field public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192; // 0x2000
field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
@@ -47539,7 +47637,7 @@
field public static final int FLAG_ALT_FOCUSABLE_IM = 131072; // 0x20000
field public static final deprecated int FLAG_BLUR_BEHIND = 4; // 0x4
field public static final int FLAG_DIM_BEHIND = 2; // 0x2
- field public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
+ field public static final deprecated int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
field public static final deprecated int FLAG_DITHER = 4096; // 0x1000
field public static final int FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = -2147483648; // 0x80000000
field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
@@ -66080,13 +66178,13 @@
ctor public Attributes.Name(java.lang.String);
field public static final java.util.jar.Attributes.Name CLASS_PATH;
field public static final java.util.jar.Attributes.Name CONTENT_TYPE;
- field public static final java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
+ field public static final deprecated java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
field public static final java.util.jar.Attributes.Name EXTENSION_LIST;
field public static final java.util.jar.Attributes.Name EXTENSION_NAME;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_TITLE;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_URL;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_URL;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VERSION;
field public static final java.util.jar.Attributes.Name MAIN_CLASS;
field public static final java.util.jar.Attributes.Name MANIFEST_VERSION;
@@ -66153,11 +66251,11 @@
}
public static abstract interface Pack200.Packer {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void pack(java.util.jar.JarFile, java.io.OutputStream) throws java.io.IOException;
method public abstract void pack(java.util.jar.JarInputStream, java.io.OutputStream) throws java.io.IOException;
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
field public static final java.lang.String CLASS_ATTRIBUTE_PFX = "pack.class.attribute.";
field public static final java.lang.String CODE_ATTRIBUTE_PFX = "pack.code.attribute.";
field public static final java.lang.String DEFLATE_HINT = "pack.deflate.hint";
@@ -66180,9 +66278,9 @@
}
public static abstract interface Pack200.Unpacker {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void unpack(java.io.InputStream, java.util.jar.JarOutputStream) throws java.io.IOException;
method public abstract void unpack(java.io.File, java.util.jar.JarOutputStream) throws java.io.IOException;
field public static final java.lang.String DEFLATE_HINT = "unpack.deflate.hint";
diff --git a/api/test-current.txt b/api/test-current.txt
index f269479..11f1c5c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2804,9 +2804,14 @@
public static class GestureDescription.StrokeDescription {
ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long);
+ ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long, int, boolean);
+ method public int getContinuedStrokeId();
method public long getDuration();
+ method public int getId();
method public android.graphics.Path getPath();
method public long getStartTime();
+ method public boolean isContinued();
+ field public static final int INVALID_STROKE_ID = -1; // 0xffffffff
}
}
@@ -3476,6 +3481,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public void enterPictureInPictureMode(float);
+ method public void enterPictureInPictureModeOnMoveToBackground(boolean);
method public android.view.View findViewById(int);
method public void finish();
method public void finishActivity(int);
@@ -5958,6 +5964,13 @@
package android.app.admin {
+ public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getIpAddress();
+ method public int getPort();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR;
+ }
+
public final class DeviceAdminInfo implements android.os.Parcelable {
ctor public DeviceAdminInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -5998,6 +6011,7 @@
method public void onEnabled(android.content.Context, android.content.Intent);
method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, java.lang.String);
method public void onLockTaskModeExiting(android.content.Context, android.content.Intent);
+ method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
method public void onPasswordChanged(android.content.Context, android.content.Intent);
method public void onPasswordExpiring(android.content.Context, android.content.Intent);
method public void onPasswordFailed(android.content.Context, android.content.Intent);
@@ -6107,6 +6121,7 @@
method public boolean isLockTaskPermitted(java.lang.String);
method public boolean isManagedProfile(android.content.ComponentName);
method public boolean isMasterVolumeMuted(android.content.ComponentName);
+ method public boolean isNetworkLoggingEnabled(android.content.ComponentName);
method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public boolean isProfileOwnerApp(java.lang.String);
method public boolean isProvisioningAllowed(java.lang.String);
@@ -6120,6 +6135,7 @@
method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
method public boolean requestBugreport(android.content.ComponentName);
method public boolean resetPassword(java.lang.String, int);
+ method public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(android.content.ComponentName, long);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
@@ -6143,6 +6159,7 @@
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
+ method public void setNetworkLoggingEnabled(android.content.ComponentName, boolean);
method public void setOrganizationColor(android.content.ComponentName, int);
method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
@@ -6207,6 +6224,7 @@
field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
+ field public static final java.lang.String EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION = "android.app.extra.PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION";
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
@@ -6256,6 +6274,22 @@
field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
}
+ public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getHostname();
+ method public java.lang.String[] getIpAddresses();
+ method public int getIpAddressesCount();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
+ }
+
+ public abstract class NetworkEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getPackageName();
+ method public long getTimestamp();
+ method public abstract void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.NetworkEvent> CREATOR;
+ }
+
public class SecurityLog {
ctor public SecurityLog();
field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
@@ -7966,6 +8000,7 @@
method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method protected final void setPathPermissions(android.content.pm.PathPermission[]);
method protected final void setReadPermission(java.lang.String);
@@ -7998,6 +8033,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal) throws android.os.RemoteException;
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal) throws android.os.RemoteException;
method public deprecated boolean release();
method public final android.net.Uri uncanonicalize(android.net.Uri) throws android.os.RemoteException;
method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
@@ -8101,6 +8137,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public final android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public final boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method public final void registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver);
method public void releasePersistableUriPermission(android.net.Uri, int);
@@ -8123,6 +8160,9 @@
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
+ field public static final java.lang.String QUERY_ARG_SELECTION = "android:query-selection";
+ field public static final java.lang.String QUERY_ARG_SELECTION_ARGS = "android:query-selection-args";
+ field public static final java.lang.String QUERY_ARG_SORT_ORDER = "android:query-sort-order";
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";
@@ -8841,6 +8881,7 @@
field public static final java.lang.String CATEGORY_SELECTED_ALTERNATIVE = "android.intent.category.SELECTED_ALTERNATIVE";
field public static final java.lang.String CATEGORY_TAB = "android.intent.category.TAB";
field public static final java.lang.String CATEGORY_TEST = "android.intent.category.TEST";
+ field public static final java.lang.String CATEGORY_TYPED_OPENABLE = "android.intent.category.TYPED_OPENABLE";
field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
field public static final java.lang.String CATEGORY_VOICE = "android.intent.category.VOICE";
field public static final android.os.Parcelable.Creator<android.content.Intent> CREATOR;
@@ -20286,8 +20327,8 @@
}
public class AudioTrack implements android.media.AudioRouting {
- ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
- ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
@@ -21576,7 +21617,7 @@
method public void selectTrack(int) throws java.lang.IllegalStateException;
method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
- method public void setAudioStreamType(int);
+ method public deprecated void setAudioStreamType(int);
method public void setAuxEffectSendLevel(float);
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
@@ -29770,6 +29811,7 @@
field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps";
+ field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
@@ -32823,6 +32865,7 @@
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
+ field public static final java.lang.String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
field public static final java.lang.String ACTION_HARD_KEYBOARD_SETTINGS = "android.settings.HARD_KEYBOARD_SETTINGS";
field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
field public static final java.lang.String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
@@ -35152,18 +35195,19 @@
package android.service.notification {
public final class Adjustment implements android.os.Parcelable {
- ctor public Adjustment(java.lang.String, java.lang.String, int, android.os.Bundle, java.lang.CharSequence, android.net.Uri, int);
+ ctor public Adjustment(java.lang.String, java.lang.String, android.os.Bundle, java.lang.CharSequence, int);
ctor protected Adjustment(android.os.Parcel);
method public int describeContents();
method public java.lang.CharSequence getExplanation();
- method public int getImportance();
method public java.lang.String getKey();
method public java.lang.String getPackage();
- method public android.net.Uri getReference();
method public android.os.Bundle getSignals();
method public int getUser();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+ field public static final java.lang.String KEY_CHANNEL_ID = "key_channel_id";
+ field public static final java.lang.String KEY_PEOPLE = "key_people";
+ field public static final java.lang.String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
}
public final class Condition implements android.os.Parcelable {
@@ -35285,11 +35329,14 @@
public static class NotificationListenerService.Ranking {
ctor public NotificationListenerService.Ranking();
+ method public java.util.List<java.lang.String> getAdditionalPeople();
+ method public android.app.NotificationChannel getChannel();
method public int getImportance();
method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
method public java.lang.String getOverrideGroupKey();
method public int getRank();
+ method public java.util.List<android.service.notification.SnoozeCriterion> getSnoozeCriteria();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
@@ -35303,6 +35350,17 @@
field public static final android.os.Parcelable.Creator<android.service.notification.NotificationListenerService.RankingMap> CREATOR;
}
+ public final class SnoozeCriterion implements android.os.Parcelable {
+ ctor public SnoozeCriterion(java.lang.String, java.lang.CharSequence, java.lang.CharSequence);
+ ctor protected SnoozeCriterion(android.os.Parcel);
+ method public int describeContents();
+ method public java.lang.CharSequence getConfirmation();
+ method public java.lang.CharSequence getExplanation();
+ method public java.lang.String getId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.notification.SnoozeCriterion> CREATOR;
+ }
+
public class StatusBarNotification implements android.os.Parcelable {
ctor public deprecated StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
ctor public StatusBarNotification(android.os.Parcel);
@@ -37355,7 +37413,10 @@
field public static final java.lang.String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
field public static final java.lang.String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
+ field public static final java.lang.String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
field public static final java.lang.String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
+ field public static final java.lang.String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+ field public static final java.lang.String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL = "mdn_is_additional_voicemail_number_bool";
field public static final java.lang.String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
field public static final java.lang.String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
field public static final java.lang.String KEY_MMS_ALIAS_MIN_CHARS_INT = "aliasMinChars";
@@ -37738,6 +37799,7 @@
}
public final class SmsManager {
+ method public java.lang.String createAppSpecificSmsToken(android.app.PendingIntent);
method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
method public void downloadMultimediaMessage(android.content.Context, java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
method public android.os.Bundle getCarrierConfigValues();
@@ -41487,11 +41549,15 @@
public final class ProtoOutputStream {
ctor public ProtoOutputStream();
ctor public ProtoOutputStream(int);
+ ctor public ProtoOutputStream(java.io.OutputStream);
+ ctor public ProtoOutputStream(java.io.FileDescriptor);
method public static int checkFieldId(long, long);
method public static int convertObjectIdToOrdinal(int);
method public void dump(java.lang.String);
+ method public void end(long);
method public void endObject(long);
method public void endRepeatedObject(long);
+ method public void flush();
method public byte[] getBytes();
method public static int getDepthFromToken(long);
method public static int getObjectIdFromToken(long);
@@ -41500,9 +41566,17 @@
method public static int getTagSizeFromToken(long);
method public static long makeFieldId(int, long);
method public static long makeToken(int, boolean, int, int, int);
+ method public long start(long);
method public long startObject(long);
method public long startRepeatedObject(long);
method public static java.lang.String token2String(long);
+ method public void write(long, double);
+ method public void write(long, float);
+ method public void write(long, int);
+ method public void write(long, long);
+ method public void write(long, boolean);
+ method public void write(long, java.lang.String);
+ method public void write(long, byte[]);
method public void writeBool(long, boolean);
method public void writeBytes(long, byte[]);
method public void writeDouble(long, double);
@@ -41512,6 +41586,8 @@
method public void writeFloat(long, float);
method public void writeInt32(long, int);
method public void writeInt64(long, long);
+ method public void writeObject(long, byte[]);
+ method public void writeObjectImpl(int, byte[]);
method public void writePackedBool(long, boolean[]);
method public void writePackedDouble(long, double[]);
method public void writePackedEnum(long, int[]);
@@ -41535,6 +41611,8 @@
method public void writeRepeatedFloat(long, float);
method public void writeRepeatedInt32(long, int);
method public void writeRepeatedInt64(long, long);
+ method public void writeRepeatedObject(long, byte[]);
+ method public void writeRepeatedObjectImpl(int, byte[]);
method public void writeRepeatedSFixed32(long, int);
method public void writeRepeatedSFixed64(long, long);
method public void writeRepeatedSInt32(long, int);
@@ -43719,6 +43797,7 @@
field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
+ field public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 16; // 0x10
field public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192; // 0x2000
field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
@@ -44640,7 +44719,7 @@
field public static final int FLAG_ALT_FOCUSABLE_IM = 131072; // 0x20000
field public static final deprecated int FLAG_BLUR_BEHIND = 4; // 0x4
field public static final int FLAG_DIM_BEHIND = 2; // 0x2
- field public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
+ field public static final deprecated int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
field public static final deprecated int FLAG_DITHER = 4096; // 0x1000
field public static final int FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = -2147483648; // 0x80000000
field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
@@ -62841,13 +62920,13 @@
ctor public Attributes.Name(java.lang.String);
field public static final java.util.jar.Attributes.Name CLASS_PATH;
field public static final java.util.jar.Attributes.Name CONTENT_TYPE;
- field public static final java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
+ field public static final deprecated java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
field public static final java.util.jar.Attributes.Name EXTENSION_LIST;
field public static final java.util.jar.Attributes.Name EXTENSION_NAME;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_TITLE;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_URL;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_URL;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VERSION;
field public static final java.util.jar.Attributes.Name MAIN_CLASS;
field public static final java.util.jar.Attributes.Name MANIFEST_VERSION;
@@ -62914,11 +62993,11 @@
}
public static abstract interface Pack200.Packer {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void pack(java.util.jar.JarFile, java.io.OutputStream) throws java.io.IOException;
method public abstract void pack(java.util.jar.JarInputStream, java.io.OutputStream) throws java.io.IOException;
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
field public static final java.lang.String CLASS_ATTRIBUTE_PFX = "pack.class.attribute.";
field public static final java.lang.String CODE_ATTRIBUTE_PFX = "pack.code.attribute.";
field public static final java.lang.String DEFLATE_HINT = "pack.deflate.hint";
@@ -62941,9 +63020,9 @@
}
public static abstract interface Pack200.Unpacker {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void unpack(java.io.InputStream, java.util.jar.JarOutputStream) throws java.io.IOException;
method public abstract void unpack(java.io.File, java.util.jar.JarOutputStream) throws java.io.IOException;
field public static final java.lang.String DEFLATE_HINT = "unpack.deflate.hint";
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 7967e2a..9fad7bf 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -608,9 +608,10 @@
return;
}
+ char* out = timeBuff[0] == ' ' ? &timeBuff[1] : &timeBuff[0];
int x = xPos;
int y = yPos;
- drawText(timeBuff, font, false, &x, &y);
+ drawText(out, font, false, &x, &y);
}
bool BootAnimation::parseAnimationDesc(Animation& animation)
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 63641a8..3687f10 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -19,6 +19,7 @@
import android.app.ActivityManager;
import android.app.ContentProviderHolder;
import android.app.IActivityManager;
+import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.IContentProvider;
import android.database.Cursor;
@@ -589,8 +590,8 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- Cursor cursor = provider.query(resolveCallingPackage(), mUri, mProjection, mWhere,
- null, mSortOrder, null);
+ Cursor cursor = provider.query(resolveCallingPackage(), mUri, mProjection,
+ ContentResolver.createSqlQueryBundle(mWhere, null, mSortOrder), null);
if (cursor == null) {
System.out.println("No result found.");
return;
diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java
index 0e0ecd0..4be4654 100644
--- a/cmds/media/src/com/android/commands/media/Media.java
+++ b/cmds/media/src/com/android/commands/media/Media.java
@@ -64,13 +64,15 @@
" media dispatch KEY\n" +
" media list-sessions\n" +
" media monitor <tag>\n" +
+ " media volume [options]\n" +
"\n" +
"media dispatch: dispatch a media key to the system.\n" +
" KEY may be: play, pause, play-pause, mute, headsethook,\n" +
" stop, next, previous, rewind, record, fast-forword.\n" +
"media list-sessions: print a list of the current sessions.\n" +
"media monitor: monitor updates to the specified session.\n" +
- " Use the tag from list-sessions.\n"
+ " Use the tag from list-sessions.\n" +
+ "media volume: " + VolumeCtrl.USAGE
);
}
@@ -92,6 +94,8 @@
runListSessions();
} else if (op.equals("monitor")) {
runMonitor();
+ } else if (op.equals("volume")) {
+ runVolume();
} else {
showError("Error: unknown command '" + op + "'");
return;
@@ -322,4 +326,10 @@
System.out.println("***Error listing sessions***");
}
}
+
+ //=================================
+ // "volume" command for stream volume control
+ private void runVolume() throws Exception {
+ VolumeCtrl.run(this);
+ }
}
diff --git a/cmds/media/src/com/android/commands/media/VolumeCtrl.java b/cmds/media/src/com/android/commands/media/VolumeCtrl.java
new file mode 100755
index 0000000..f54ae59
--- /dev/null
+++ b/cmds/media/src/com/android/commands/media/VolumeCtrl.java
@@ -0,0 +1,178 @@
+/*
+**
+** Copyright 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 com.android.commands.media;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.media.IAudioService;
+import android.os.ServiceManager;
+import android.util.AndroidException;
+
+import com.android.internal.os.BaseCommand;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.lang.ArrayIndexOutOfBoundsException;
+
+/**
+ * Command line tool to exercise AudioService.setStreamVolume()
+ * and AudioService.adjustStreamVolume()
+ */
+public class VolumeCtrl {
+
+ private final static String TAG = "VolumeCtrl";
+
+ public final static String USAGE = new String(
+ "the options are as follows: \n" +
+ "\t\t--stream STREAM selects the stream to control, see AudioManager.STREAM_*\n" +
+ "\t\t controls AudioManager.STREAM_MUSIC if no stream is specified\n"+
+ "\t\t--index INDEX sets the volume index value\n" +
+ "\t\t--adj DIRECTION adjusts the volume, use raise|same|lower for the direction\n" +
+ "\t\t--show shows the UI during the volume change \n" +
+ "\texamples:\n" +
+ "\t\tadb shell media volume --show --stream 3 --index 11 \n" +
+ "\t\tadb shell media volume --stream 0 --adj lower \n"
+ );
+
+ private final static int VOLUME_CONTROL_MODE_SET = 0;
+ private final static int VOLUME_CONTROL_MODE_ADJUST = 1;
+
+ private final static String ADJUST_LOWER = "lower";
+ private final static String ADJUST_SAME = "same";
+ private final static String ADJUST_RAISE = "raise";
+
+ public static void run(BaseCommand cmd) throws Exception {
+ //----------------------------------------
+ // Default parameters
+ int stream = AudioManager.STREAM_MUSIC;
+ int volIndex = 5;
+ int mode = VOLUME_CONTROL_MODE_SET;
+ int adjDir = AudioManager.ADJUST_RAISE;
+ boolean showUi = false;
+
+ //----------------------------------------
+ // read options
+ String option;
+ String adjustment = null;
+ while ((option = cmd.nextOption()) != null) {
+ switch (option) {
+ case "--show":
+ showUi = true;
+ break;
+ case "--set":
+ mode = VOLUME_CONTROL_MODE_SET;
+ log(LOG_V, "will set volume");
+ break;
+ case "--adjust":
+ mode = VOLUME_CONTROL_MODE_ADJUST;
+ log(LOG_V, "will adjust volume");
+ break;
+ case "--stream":
+ stream = Integer.decode(cmd.nextArgRequired()).intValue();
+ log(LOG_V, "will control stream=" + stream + " (" + streamName(stream) + ")");
+ break;
+ case "--index":
+ volIndex = Integer.decode(cmd.nextArgRequired()).intValue();
+ mode = VOLUME_CONTROL_MODE_SET;
+ log(LOG_V, "will set volume to index=" + volIndex);
+ break;
+ case "--adj":
+ mode = VOLUME_CONTROL_MODE_ADJUST;
+ adjustment = cmd.nextArgRequired();
+ log(LOG_V, "will adjust volume");
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown argument " + option);
+ }
+ }
+
+ //------------------------------
+ // Read options: validation
+ if (mode == VOLUME_CONTROL_MODE_ADJUST) {
+ if (adjustment == null) {
+ cmd.showError("Error: no valid volume adjustment (null)");
+ return;
+ }
+ switch (adjustment) {
+ case ADJUST_RAISE: adjDir = AudioManager.ADJUST_RAISE; break;
+ case ADJUST_SAME: adjDir = AudioManager.ADJUST_SAME; break;
+ case ADJUST_LOWER: adjDir = AudioManager.ADJUST_LOWER; break;
+ default:
+ cmd.showError("Error: no valid volume adjustment, was " + adjustment
+ + ", expected " + ADJUST_LOWER + "|" + ADJUST_SAME + "|"
+ + ADJUST_RAISE);
+ return;
+ }
+ }
+
+ //----------------------------------------
+ // Test initialization
+ log(LOG_V, "Connecting to AudioService");
+ IAudioService audioService = IAudioService.Stub.asInterface(ServiceManager.checkService(
+ Context.AUDIO_SERVICE));
+ if (audioService == null) {
+ System.err.println(BaseCommand.NO_SYSTEM_ERROR_CODE);
+ throw new AndroidException(
+ "Can't connect to audio service; is the system running?");
+ }
+
+ if (mode == VOLUME_CONTROL_MODE_SET) {
+ if ((volIndex > audioService.getStreamMaxVolume(stream))
+ || (volIndex < audioService.getStreamMinVolume(stream))) {
+ cmd.showError(String.format("Error: invalid volume index %d for stream %d "
+ + "(should be in [%d..%d])", volIndex, stream,
+ audioService.getStreamMinVolume(stream),
+ audioService.getStreamMaxVolume(stream)));
+ return;
+ }
+ }
+
+ //----------------------------------------
+ // Non-interactive test
+ final int flag = showUi? AudioManager.FLAG_SHOW_UI : 0;
+ final String pack = cmd.getClass().getPackage().getName();
+ if (mode == VOLUME_CONTROL_MODE_SET) {
+ audioService.setStreamVolume(stream, volIndex, flag, pack/*callingPackage*/);
+ } else if (mode == VOLUME_CONTROL_MODE_ADJUST) {
+ audioService.adjustStreamVolume(stream, adjDir, flag, pack);
+ }
+ }
+
+ //--------------------------------------------
+ // Utilities
+
+ static final String LOG_V = "[v]";
+ static final String LOG_W = "[w]";
+ static final String LOG_OK = "[ok]";
+
+ static void log(String code, String msg) {
+ System.out.println(code + " " + msg);
+ }
+
+ static String streamName(int stream) {
+ try {
+ return AudioSystem.STREAM_NAMES[stream];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return "invalid stream";
+ }
+ }
+
+}
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 50f46f4..810d2018 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -553,7 +553,7 @@
sessionParams.abiOverride = checkAbiArgument(nextOptionData());
break;
case "--ephemeral":
- sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL;
+ sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
break;
case "--user":
params.userId = UserHandle.parseUserArg(nextOptionData());
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index a41f122..377e29d 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -175,13 +175,20 @@
if (base != NULL) {
if (png) {
- const SkImageInfo info = SkImageInfo::Make(w, h, flinger2skia(f),
- kPremul_SkAlphaType);
- sk_sp<SkData> data(SkImageEncoder::EncodeData(info, base, s*bytesPerPixel(f),
- SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality));
- if (data.get()) {
- write(fd, data->data(), data->size());
- }
+ const SkImageInfo info =
+ SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType);
+ SkPixmap pixmap(info, base, s * bytesPerPixel(f));
+ struct FDWStream final : public SkWStream {
+ size_t fBytesWritten = 0;
+ int fFd;
+ FDWStream(int f) : fFd(f) {}
+ size_t bytesWritten() const override { return fBytesWritten; }
+ bool write(const void* buffer, size_t size) override {
+ fBytesWritten += size;
+ return size == 0 || ::write(fFd, buffer, size) > 0;
+ }
+ } fdStream(fd);
+ (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kPNG, 100);
if (fn != NULL) {
notifyMediaScanner(fn);
}
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk
index d65b0833..af2e25a 100644
--- a/cmds/uiautomator/library/Android.mk
+++ b/cmds/uiautomator/library/Android.mk
@@ -18,7 +18,7 @@
uiautomator.core_src_files := $(call all-java-files-under, core-src) \
$(call all-java-files-under, testrunner-src)
-uiautomator.core_java_libraries := android.test.runner core-junit
+uiautomator.core_java_libraries := android.test.runner junit
uiautomator_internal_api_file := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/uiautomator_api.txt
uiautomator_internal_removed_api_file := \
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index 32b4595..b0ab235 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -20,6 +20,7 @@
import android.app.ContentProviderHolder;
import android.app.IActivityManager;
import android.app.UiAutomation;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
import android.database.Cursor;
@@ -69,10 +70,12 @@
cursor = provider.query(null, Settings.Secure.CONTENT_URI,
new String[] {
Settings.Secure.VALUE
- }, "name=?",
- new String[] {
- Settings.Secure.LONG_PRESS_TIMEOUT
- }, null, null);
+ },
+ ContentResolver.createSqlQueryBundle(
+ "name=?",
+ new String[] { Settings.Secure.LONG_PRESS_TIMEOUT },
+ null),
+ null);
if (cursor.moveToFirst()) {
longPressTimeout = cursor.getInt(0);
}
diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java
index d9b03fa..c9da152 100644
--- a/core/java/android/accessibilityservice/GestureDescription.java
+++ b/core/java/android/accessibilityservice/GestureDescription.java
@@ -23,10 +23,6 @@
import android.graphics.RectF;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
-import android.view.MotionEvent.PointerProperties;
import java.util.ArrayList;
import java.util.List;
@@ -128,9 +124,14 @@
for (int i = 0; i < mStrokes.size(); i++) {
StrokeDescription strokeDescription = mStrokes.get(i);
if (strokeDescription.hasPointForTime(time)) {
- touchPoints[numPointsFound].mPathIndex = i;
- touchPoints[numPointsFound].mIsStartOfPath = (time == strokeDescription.mStartTime);
- touchPoints[numPointsFound].mIsEndOfPath = (time == strokeDescription.mEndTime);
+ touchPoints[numPointsFound].mStrokeId = strokeDescription.getId();
+ touchPoints[numPointsFound].mContinuedStrokeId =
+ strokeDescription.getContinuedStrokeId();
+ touchPoints[numPointsFound].mIsStartOfPath =
+ (strokeDescription.getContinuedStrokeId() < 0)
+ && (time == strokeDescription.mStartTime);
+ touchPoints[numPointsFound].mIsEndOfPath = !strokeDescription.isContinued()
+ && (time == strokeDescription.mEndTime);
strokeDescription.getPosForTime(time, mTempPos);
touchPoints[numPointsFound].mX = Math.round(mTempPos[0]);
touchPoints[numPointsFound].mY = Math.round(mTempPos[1]);
@@ -196,6 +197,10 @@
* Immutable description of stroke that can be part of a gesture.
*/
public static class StrokeDescription {
+ public static final int INVALID_STROKE_ID = -1;
+
+ static int sIdCounter;
+
Path mPath;
long mStartTime;
long mEndTime;
@@ -203,6 +208,9 @@
private PathMeasure mPathMeasure;
// The tap location is only set for zero-length paths
float[] mTapLocation;
+ int mId;
+ boolean mContinued;
+ int mContinuedStrokeId;
/**
* @param path The path to follow. Must have exactly one contour. The bounds of the path
@@ -216,6 +224,32 @@
public StrokeDescription(@NonNull Path path,
@IntRange(from = 0) long startTime,
@IntRange(from = 0) long duration) {
+ this(path, startTime, duration, INVALID_STROKE_ID, false);
+ }
+
+ /**
+ * @param path The path to follow. Must have exactly one contour. The bounds of the path
+ * must not be negative. The path must not be empty. If the path has zero length
+ * (for example, a single {@code moveTo()}), the stroke is a touch that doesn't move.
+ * @param startTime The time, in milliseconds, from the time the gesture starts to the
+ * time the stroke should start. Must not be negative.
+ * @param duration The duration, in milliseconds, the stroke takes to traverse the path.
+ * Must be positive.
+ * @param continuedStrokeId The ID of the stroke that this stroke continues, or
+ * {@link #INVALID_STROKE_ID} if it continues no stroke. The stroke it
+ * continues must have its isContinued flag set to {@code true} and must be in the
+ * gesture dispatched immediately before the one containing this stroke.
+ * @param isContinued {@code true} if this stroke will be continued by one in the
+ * next gesture {@code false} otherwise. Continued strokes keep their pointers down when
+ * the gesture completes.
+ */
+ public StrokeDescription(@NonNull Path path,
+ @IntRange(from = 0) long startTime,
+ @IntRange(from = 0) long duration,
+ @IntRange(from = 0) int continuedStrokeId,
+ boolean isContinued) {
+ mContinued = isContinued;
+ mContinuedStrokeId = continuedStrokeId;
if (duration <= 0) {
throw new IllegalArgumentException("Duration must be positive");
}
@@ -252,6 +286,7 @@
mStartTime = startTime;
mEndTime = startTime + duration;
mTimeToLengthConversion = getLength() / duration;
+ mId = sIdCounter++;
}
/**
@@ -281,6 +316,34 @@
return mEndTime - mStartTime;
}
+ /**
+ * Get the stroke's ID. The ID is used when a stroke is to be continued by another
+ * stroke in a future gesture.
+ *
+ * @return the ID of this stroke
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Check if this stroke is marked to continue in the next gesture.
+ *
+ * @return {@code true} if the stroke is to be continued.
+ */
+ public boolean isContinued() {
+ return mContinued;
+ }
+
+ /**
+ * Get the ID of the stroke that this one will continue.
+ *
+ * @return The ID of the stroke that this stroke continues, or 0 if no such stroke exists.
+ */
+ public int getContinuedStrokeId() {
+ return mContinuedStrokeId;
+ }
+
float getLength() {
return mPathMeasure.getLength();
}
@@ -314,11 +377,12 @@
private static final int FLAG_IS_START_OF_PATH = 0x01;
private static final int FLAG_IS_END_OF_PATH = 0x02;
- int mPathIndex;
- boolean mIsStartOfPath;
- boolean mIsEndOfPath;
- float mX;
- float mY;
+ public int mStrokeId;
+ public int mContinuedStrokeId;
+ public boolean mIsStartOfPath;
+ public boolean mIsEndOfPath;
+ public float mX;
+ public float mY;
public TouchPoint() {
}
@@ -328,7 +392,8 @@
}
public TouchPoint(Parcel parcel) {
- mPathIndex = parcel.readInt();
+ mStrokeId = parcel.readInt();
+ mContinuedStrokeId = parcel.readInt();
int startEnd = parcel.readInt();
mIsStartOfPath = (startEnd & FLAG_IS_START_OF_PATH) != 0;
mIsEndOfPath = (startEnd & FLAG_IS_END_OF_PATH) != 0;
@@ -336,8 +401,9 @@
mY = parcel.readFloat();
}
- void copyFrom(TouchPoint other) {
- mPathIndex = other.mPathIndex;
+ public void copyFrom(TouchPoint other) {
+ mStrokeId = other.mStrokeId;
+ mContinuedStrokeId = other.mContinuedStrokeId;
mIsStartOfPath = other.mIsStartOfPath;
mIsEndOfPath = other.mIsEndOfPath;
mX = other.mX;
@@ -351,7 +417,8 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mPathIndex);
+ dest.writeInt(mStrokeId);
+ dest.writeInt(mContinuedStrokeId);
int startEnd = mIsStartOfPath ? FLAG_IS_START_OF_PATH : 0;
startEnd |= mIsEndOfPath ? FLAG_IS_END_OF_PATH : 0;
dest.writeInt(startEnd);
@@ -426,30 +493,15 @@
}
/**
- * Class to convert a GestureDescription to a series of MotionEvents.
+ * Class to convert a GestureDescription to a series of GestureSteps.
*
* @hide
*/
public static class MotionEventGenerator {
- /**
- * Constants used to initialize all MotionEvents
- */
- private static final int EVENT_META_STATE = 0;
- private static final int EVENT_BUTTON_STATE = 0;
- private static final int EVENT_DEVICE_ID = 0;
- private static final int EVENT_EDGE_FLAGS = 0;
- private static final int EVENT_SOURCE = InputDevice.SOURCE_TOUCHSCREEN;
- private static final int EVENT_FLAGS = 0;
- private static final float EVENT_X_PRECISION = 1;
- private static final float EVENT_Y_PRECISION = 1;
-
/* Lazily-created scratch memory for processing touches */
private static TouchPoint[] sCurrentTouchPoints;
- private static TouchPoint[] sLastTouchPoints;
- private static PointerCoords[] sPointerCoords;
- private static PointerProperties[] sPointerProps;
- static List<GestureStep> getGestureStepsFromGestureDescription(
+ public static List<GestureStep> getGestureStepsFromGestureDescription(
GestureDescription description, int sampleTimeMs) {
final List<GestureStep> gestureSteps = new ArrayList<>();
@@ -474,31 +526,6 @@
return gestureSteps;
}
- public static List<MotionEvent> getMotionEventsFromGestureSteps(List<GestureStep> steps) {
- final List<MotionEvent> motionEvents = new ArrayList<>();
-
- // Number of points in last touch event
- int lastTouchPointSize = 0;
- TouchPoint[] lastTouchPoints;
-
- for (int i = 0; i < steps.size(); i++) {
- GestureStep step = steps.get(i);
- int currentTouchPointSize = step.numTouchPoints;
- lastTouchPoints = getLastTouchPoints(
- Math.max(lastTouchPointSize, currentTouchPointSize));
-
- appendMoveEventIfNeeded(motionEvents, lastTouchPoints, lastTouchPointSize,
- step.touchPoints, currentTouchPointSize, step.timeSinceGestureStart);
- lastTouchPointSize = appendUpEvents(motionEvents, lastTouchPoints,
- lastTouchPointSize, step.touchPoints, currentTouchPointSize,
- step.timeSinceGestureStart);
- lastTouchPointSize = appendDownEvents(motionEvents, lastTouchPoints,
- lastTouchPointSize, step.touchPoints, currentTouchPointSize,
- step.timeSinceGestureStart);
- }
- return motionEvents;
- }
-
private static TouchPoint[] getCurrentTouchPoints(int requiredCapacity) {
if ((sCurrentTouchPoints == null) || (sCurrentTouchPoints.length < requiredCapacity)) {
sCurrentTouchPoints = new TouchPoint[requiredCapacity];
@@ -508,133 +535,5 @@
}
return sCurrentTouchPoints;
}
-
- private static TouchPoint[] getLastTouchPoints(int requiredCapacity) {
- if ((sLastTouchPoints == null) || (sLastTouchPoints.length < requiredCapacity)) {
- sLastTouchPoints = new TouchPoint[requiredCapacity];
- for (int i = 0; i < requiredCapacity; i++) {
- sLastTouchPoints[i] = new TouchPoint();
- }
- }
- return sLastTouchPoints;
- }
-
- private static PointerCoords[] getPointerCoords(int requiredCapacity) {
- if ((sPointerCoords == null) || (sPointerCoords.length < requiredCapacity)) {
- sPointerCoords = new PointerCoords[requiredCapacity];
- for (int i = 0; i < requiredCapacity; i++) {
- sPointerCoords[i] = new PointerCoords();
- }
- }
- return sPointerCoords;
- }
-
- private static PointerProperties[] getPointerProps(int requiredCapacity) {
- if ((sPointerProps == null) || (sPointerProps.length < requiredCapacity)) {
- sPointerProps = new PointerProperties[requiredCapacity];
- for (int i = 0; i < requiredCapacity; i++) {
- sPointerProps[i] = new PointerProperties();
- }
- }
- return sPointerProps;
- }
-
- private static void appendMoveEventIfNeeded(List<MotionEvent> motionEvents,
- TouchPoint[] lastTouchPoints, int lastTouchPointsSize,
- TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
- /* Look for pointers that have moved */
- boolean moveFound = false;
- for (int i = 0; i < currentTouchPointsSize; i++) {
- int lastPointsIndex = findPointByPathIndex(lastTouchPoints, lastTouchPointsSize,
- currentTouchPoints[i].mPathIndex);
- if (lastPointsIndex >= 0) {
- moveFound |= (lastTouchPoints[lastPointsIndex].mX != currentTouchPoints[i].mX)
- || (lastTouchPoints[lastPointsIndex].mY != currentTouchPoints[i].mY);
- lastTouchPoints[lastPointsIndex].copyFrom(currentTouchPoints[i]);
- }
- }
-
- if (moveFound) {
- long downTime = motionEvents.get(motionEvents.size() - 1).getDownTime();
- motionEvents.add(obtainMotionEvent(downTime, currentTime, MotionEvent.ACTION_MOVE,
- lastTouchPoints, lastTouchPointsSize));
- }
- }
-
- private static int appendUpEvents(List<MotionEvent> motionEvents,
- TouchPoint[] lastTouchPoints, int lastTouchPointsSize,
- TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
- /* Look for a pointer at the end of its path */
- for (int i = 0; i < currentTouchPointsSize; i++) {
- if (currentTouchPoints[i].mIsEndOfPath) {
- int indexOfUpEvent = findPointByPathIndex(lastTouchPoints, lastTouchPointsSize,
- currentTouchPoints[i].mPathIndex);
- if (indexOfUpEvent < 0) {
- continue; // Should not happen
- }
- long downTime = motionEvents.get(motionEvents.size() - 1).getDownTime();
- int action = (lastTouchPointsSize == 1) ? MotionEvent.ACTION_UP
- : MotionEvent.ACTION_POINTER_UP;
- action |= indexOfUpEvent << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- motionEvents.add(obtainMotionEvent(downTime, currentTime, action,
- lastTouchPoints, lastTouchPointsSize));
- /* Remove this point from lastTouchPoints */
- for (int j = indexOfUpEvent; j < lastTouchPointsSize - 1; j++) {
- lastTouchPoints[j].copyFrom(lastTouchPoints[j+1]);
- }
- lastTouchPointsSize--;
- }
- }
- return lastTouchPointsSize;
- }
-
- private static int appendDownEvents(List<MotionEvent> motionEvents,
- TouchPoint[] lastTouchPoints, int lastTouchPointsSize,
- TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
- /* Look for a pointer that is just starting */
- for (int i = 0; i < currentTouchPointsSize; i++) {
- if (currentTouchPoints[i].mIsStartOfPath) {
- /* Add the point to last coords and use the new array to generate the event */
- lastTouchPoints[lastTouchPointsSize++].copyFrom(currentTouchPoints[i]);
- int action = (lastTouchPointsSize == 1) ? MotionEvent.ACTION_DOWN
- : MotionEvent.ACTION_POINTER_DOWN;
- long downTime = (action == MotionEvent.ACTION_DOWN) ? currentTime :
- motionEvents.get(motionEvents.size() - 1).getDownTime();
- action |= i << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- motionEvents.add(obtainMotionEvent(downTime, currentTime, action,
- lastTouchPoints, lastTouchPointsSize));
- }
- }
- return lastTouchPointsSize;
- }
-
- private static MotionEvent obtainMotionEvent(long downTime, long eventTime, int action,
- TouchPoint[] touchPoints, int touchPointsSize) {
- PointerCoords[] pointerCoords = getPointerCoords(touchPointsSize);
- PointerProperties[] pointerProperties = getPointerProps(touchPointsSize);
- for (int i = 0; i < touchPointsSize; i++) {
- pointerProperties[i].id = touchPoints[i].mPathIndex;
- pointerProperties[i].toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
- pointerCoords[i].clear();
- pointerCoords[i].pressure = 1.0f;
- pointerCoords[i].size = 1.0f;
- pointerCoords[i].x = touchPoints[i].mX;
- pointerCoords[i].y = touchPoints[i].mY;
- }
- return MotionEvent.obtain(downTime, eventTime, action, touchPointsSize,
- pointerProperties, pointerCoords, EVENT_META_STATE, EVENT_BUTTON_STATE,
- EVENT_X_PRECISION, EVENT_Y_PRECISION, EVENT_DEVICE_ID, EVENT_EDGE_FLAGS,
- EVENT_SOURCE, EVENT_FLAGS);
- }
-
- private static int findPointByPathIndex(TouchPoint[] touchPoints, int touchPointsSize,
- int pathIndex) {
- for (int i = 0; i < touchPointsSize; i++) {
- if (touchPoints[i].mPathIndex == pathIndex) {
- return i;
- }
- }
- return -1;
- }
}
}
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 0c21c4f..4707bed 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -38,8 +38,8 @@
*
* {@sample development/samples/ApiDemos/res/anim/object_animator.xml ObjectAnimatorResources}
*
- * <p>When using resource files, it is possible to use {@link PropertyValuesHolder} and
- * {@link Keyframe} to create more complex animations. Using PropertyValuesHolders
+ * <p>Starting from API 23, it is possible to use {@link PropertyValuesHolder} and
+ * {@link Keyframe} in resource files to create more complex animations. Using PropertyValuesHolders
* allows animators to animate several properties in parallel, as shown in this sample:</p>
*
* {@sample development/samples/ApiDemos/res/anim/object_animator_pvh.xml
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index ed7e89d..f0fc8af 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -49,8 +49,8 @@
*
* {@sample development/samples/ApiDemos/res/anim/animator.xml ValueAnimatorResources}
*
- * <p>It is also possible to use a combination of {@link PropertyValuesHolder} and
- * {@link Keyframe} resource tags to create a multi-step animation.
+ * <p>Starting from API 23, it is also possible to use a combination of {@link PropertyValuesHolder}
+ * and {@link Keyframe} resource tags to create a multi-step animation.
* Note that you can specify explicit fractional values (from 0 to 1) for
* each keyframe to determine when, in the overall duration, the animation should arrive at that
* value. Alternatively, you can leave the fractions off and the keyframes will be equally
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 90fff8d..6dd488f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2030,6 +2030,28 @@
}
/**
+ * Requests to the system that the activity can be automatically put into picture-in-picture
+ * mode when the user leaves the activity causing it normally to be hidden. This is a *not*
+ * a guarantee that the activity will actually be put in picture-in-picture mode, and depends
+ * on a number of factors, including whether there is already something in picture-in-picture.
+ *
+ * If {@param enterPictureInPictureOnMoveToBg} is true, then you may also call
+ * {@link #setPictureInPictureAspectRatio(float)} to specify the aspect ratio to automatically
+ * enter picture-in-picture with.
+ *
+ * @param enterPictureInPictureOnMoveToBg whether or not this activity can automatically enter
+ * picture-in-picture
+ */
+ public void enterPictureInPictureModeOnMoveToBackground(
+ boolean enterPictureInPictureOnMoveToBg) {
+ try {
+ ActivityManagerNative.getDefault().enterPictureInPictureModeOnMoveToBackground(mToken,
+ enterPictureInPictureOnMoveToBg);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Called by the system when the device configuration changes while your
* activity is running. Note that this will <em>only</em> be called if
* you have selected configurations you would like to handle with the
@@ -3044,8 +3066,11 @@
* @hide
*/
@Override
- public void onWindowDismissed(boolean finishTask) {
+ public void onWindowDismissed(boolean finishTask, boolean suppressWindowTransition) {
finish(finishTask ? FINISH_TASK_WITH_ACTIVITY : DONT_FINISH_TASK_WITH_ACTIVITY);
+ if (suppressWindowTransition) {
+ overridePendingTransition(0, 0);
+ }
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 65f74d1..312d3a5 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -561,8 +561,11 @@
/** ID of stack that always on top (always visible) when it exist. */
public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;
+ /** Recents activity stack ID. */
+ public static final int RECENTS_STACK_ID = PINNED_STACK_ID + 1;
+
/** Last static stack stack ID. */
- public static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
+ public static final int LAST_STATIC_STACK_ID = RECENTS_STACK_ID;
/** Start of ID range used by stacks that are created dynamically. */
public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1;
@@ -735,6 +738,13 @@
}
/**
+ * Returns true if the input {@param stackId} is HOME_STACK_ID or RECENTS_STACK_ID
+ */
+ public static boolean isHomeOrRecentsStack(int stackId) {
+ return stackId == HOME_STACK_ID || stackId == RECENTS_STACK_ID;
+ }
+
+ /**
* Returns true if activities contained in this stack can request visible behind by
* calling {@link Activity#requestVisibleBehind}.
*/
@@ -760,7 +770,8 @@
/** Returns true if the input stack and its content can affect the device orientation. */
public static boolean canSpecifyOrientation(int stackId) {
- return stackId == HOME_STACK_ID || stackId == FULLSCREEN_WORKSPACE_STACK_ID;
+ return stackId == HOME_STACK_ID || stackId == RECENTS_STACK_ID
+ || stackId == FULLSCREEN_WORKSPACE_STACK_ID;
}
}
@@ -1509,7 +1520,7 @@
* Ignores all tasks that are on the home stack.
* @hide
*/
- public static final int RECENT_IGNORE_HOME_STACK_TASKS = 0x0008;
+ public static final int RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS = 0x0008;
/**
* Ignores the top task in the docked stack.
@@ -2052,15 +2063,6 @@
}
}
- /** @hide */
- public boolean isInHomeStack(int taskId) {
- try {
- return getService().isInHomeStack(taskId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
/**
* Flag for {@link #moveTaskToFront(int, int)}: also move the "home"
* activity along with the task, so it is positioned immediately behind
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 6cfa362..9f1a539 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -378,6 +378,11 @@
exceptionMessage = sanitizeString(exceptionMessage);
}
+ /** {@hide} */
+ public void appendStackTrace(String tr) {
+ stackTrace = sanitizeString(stackTrace + tr);
+ }
+
/**
* Ensure that the string is of reasonable size, truncating from the middle if needed.
*/
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index abb098f..105d2ca 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -16,6 +16,8 @@
package android.app;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -349,9 +351,7 @@
public BackStackRecord(FragmentManagerImpl manager) {
mManager = manager;
- int targetSdkVersion = manager.mHost.getContext().getApplicationInfo().targetSdkVersion;
- // TODO: make the check N_MR1 or O
- mAllowOptimization = targetSdkVersion > Build.VERSION_CODES.N;
+ mAllowOptimization = getTargetSdk() > Build.VERSION_CODES.N_MR1;
}
public int getId() {
@@ -367,14 +367,14 @@
}
public CharSequence getBreadCrumbTitle() {
- if (mBreadCrumbTitleRes != 0) {
+ if (mBreadCrumbTitleRes != 0 && mManager.mHost != null) {
return mManager.mHost.getContext().getText(mBreadCrumbTitleRes);
}
return mBreadCrumbTitleText;
}
public CharSequence getBreadCrumbShortTitle() {
- if (mBreadCrumbShortTitleRes != 0) {
+ if (mBreadCrumbShortTitleRes != 0 && mManager.mHost != null) {
return mManager.mHost.getContext().getText(mBreadCrumbShortTitleRes);
}
return mBreadCrumbShortTitleText;
@@ -404,14 +404,10 @@
}
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
- if (mManager.mHost.getContext() != null) {
- final int targetSdkVersion =
- mManager.mHost.getContext().getApplicationInfo().targetSdkVersion;
+ if (getTargetSdk() > Build.VERSION_CODES.N_MR1) {
final Class fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
- // TODO: make the check N_MR1 or O
- if (targetSdkVersion > Build.VERSION_CODES.N && (fragmentClass.isAnonymousClass()
- || !Modifier.isPublic(modifiers)
+ if ((fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
|| (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers)))) {
throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
+ " must be a public static class to be properly recreated from"
@@ -917,4 +913,22 @@
public boolean isEmpty() {
return mOps.isEmpty();
}
+
+ /**
+ * @return the target SDK of the FragmentManager's application info. If the
+ * FragmentManager has been torn down, then 0 is returned.
+ */
+ private int getTargetSdk() {
+ FragmentHostCallback host = mManager.mHost;
+ if (host != null) {
+ Context context = host.getContext();
+ if (context != null) {
+ ApplicationInfo info = context.getApplicationInfo();
+ if (info != null) {
+ return info.targetSdkVersion;
+ }
+ }
+ }
+ return 0;
+ }
}
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 6e2c464..9c17780 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -200,6 +200,7 @@
@Nullable Message cancelCallback) {
this(context);
mCancelable = cancelable;
+ updateWindowForCancelable();
mCancelMessage = cancelCallback;
}
@@ -207,6 +208,7 @@
@Nullable OnCancelListener cancelListener) {
this(context);
mCancelable = cancelable;
+ updateWindowForCancelable();
setOnCancelListener(cancelListener);
}
@@ -742,7 +744,7 @@
/** @hide */
@Override
- public void onWindowDismissed(boolean finishTask) {
+ public void onWindowDismissed(boolean finishTask, boolean suppressWindowTransition) {
dismiss();
}
@@ -1187,6 +1189,7 @@
*/
public void setCancelable(boolean flag) {
mCancelable = flag;
+ updateWindowForCancelable();
}
/**
@@ -1200,6 +1203,7 @@
public void setCanceledOnTouchOutside(boolean cancel) {
if (cancel && !mCancelable) {
mCancelable = true;
+ updateWindowForCancelable();
}
mWindow.setCloseOnTouchOutside(cancel);
@@ -1351,4 +1355,8 @@
}
}
}
+
+ private void updateWindowForCancelable() {
+ mWindow.setCloseOnSwipeEnabled(mCancelable);
+ }
}
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 21e3aee..2672798 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -124,13 +124,16 @@
}
public void resetViews() {
+ ViewGroup decorView = getDecor();
+ if (decorView != null) {
+ TransitionManager.endTransitions(decorView);
+ }
if (mTransitioningViews != null) {
showViews(mTransitioningViews, true);
setTransitioningViewsVisiblity(View.VISIBLE, true);
}
showViews(mSharedElements, true);
mIsHidden = true;
- ViewGroup decorView = getDecor();
if (!mIsReturning && decorView != null) {
decorView.suppressLayout(false);
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 1a36d1a..62b3977 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -370,7 +370,6 @@
// Start of L transactions
String getTagForIntentSender(in IIntentSender sender, in String prefix);
boolean startUserInBackground(int userid);
- boolean isInHomeStack(int taskId);
void startLockTaskModeById(int taskId);
void startLockTaskModeByToken(in IBinder token);
void stopLockTaskMode();
@@ -469,6 +468,10 @@
boolean isInPictureInPictureMode(in IBinder token);
void killPackageDependents(in String packageName, int userId);
void enterPictureInPictureMode(in IBinder token);
+ void enterPictureInPictureModeWithAspectRatio(in IBinder token, float aspectRatio);
+ void enterPictureInPictureModeOnMoveToBackground(in IBinder token,
+ boolean enterPictureInPictureOnMoveToBg);
+ void setPictureInPictureAspectRatio(in IBinder token, float aspectRatio);
void activityRelaunched(in IBinder token);
IBinder getUriPermissionOwnerForActivity(in IBinder activityToken);
/**
@@ -569,8 +572,6 @@
boolean updateDisplayOverrideConfiguration(in Configuration values, int displayId);
void unregisterTaskStackListener(ITaskStackListener listener);
void moveStackToDisplay(int stackId, int displayId);
- void enterPictureInPictureModeWithAspectRatio(in IBinder token, float aspectRatio);
- void setPictureInPictureAspectRatio(in IBinder token, float aspectRatio);
boolean requestAutoFillData(in IResultReceiver receiver, in Bundle receiverExtras,
in IBinder activityToken);
void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback);
@@ -579,4 +580,4 @@
// side. If so, make sure they are using the correct transaction ids.
// If a transaction which will also be used on the native side is being inserted, add it
// alongside with other transactions of this kind at the top of this file.
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/MediaRouteActionProvider.java b/core/java/android/app/MediaRouteActionProvider.java
index dffa969..85ca012 100644
--- a/core/java/android/app/MediaRouteActionProvider.java
+++ b/core/java/android/app/MediaRouteActionProvider.java
@@ -119,7 +119,6 @@
}
mButton = new MediaRouteButton(mContext);
- mButton.setCheatSheetEnabled(true);
mButton.setRouteTypes(mRouteTypes);
mButton.setExtendedSettingsClickListener(mExtendedSettingsListener);
mButton.setLayoutParams(new ViewGroup.LayoutParams(
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index 70a5e15..09e95df 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -24,18 +24,13 @@
import android.content.ContextWrapper;
import android.content.res.TypedArray;
import android.graphics.Canvas;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteGroup;
import android.media.MediaRouter.RouteInfo;
-import android.text.TextUtils;
import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.HapticFeedbackConstants;
import android.view.SoundEffectConstants;
import android.view.View;
-import android.widget.Toast;
public class MediaRouteButton extends View {
private final MediaRouter mRouter;
@@ -47,7 +42,6 @@
private Drawable mRemoteIndicator;
private boolean mRemoteActive;
- private boolean mCheatSheetEnabled;
private boolean mIsConnecting;
private int mMinWidth;
@@ -98,7 +92,6 @@
a.recycle();
setClickable(true);
- setLongClickable(true);
setRouteTypes(routeTypes);
}
@@ -178,12 +171,10 @@
throw new IllegalStateException("The MediaRouteButton's Context is not an Activity.");
}
- /**
- * Sets whether to enable showing a toast with the content descriptor of the
- * button when the button is long pressed.
- */
- void setCheatSheetEnabled(boolean enable) {
- mCheatSheetEnabled = enable;
+ @Override
+ public void setContentDescription(CharSequence contentDescription) {
+ super.setContentDescription(contentDescription);
+ setTooltip(contentDescription);
}
@Override
@@ -197,47 +188,6 @@
}
@Override
- public boolean performLongClick() {
- if (super.performLongClick()) {
- return true;
- }
-
- if (!mCheatSheetEnabled) {
- return false;
- }
-
- final CharSequence contentDesc = getContentDescription();
- if (TextUtils.isEmpty(contentDesc)) {
- // Don't show the cheat sheet if we have no description
- return false;
- }
-
- final int[] screenPos = new int[2];
- final Rect displayFrame = new Rect();
- getLocationOnScreen(screenPos);
- getWindowVisibleDisplayFrame(displayFrame);
-
- final Context context = getContext();
- final int width = getWidth();
- final int height = getHeight();
- final int midy = screenPos[1] + height / 2;
- final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
-
- Toast cheatSheet = Toast.makeText(context, contentDesc, Toast.LENGTH_SHORT);
- if (midy < displayFrame.height()) {
- // Show along the top; follow action buttons
- cheatSheet.setGravity(Gravity.TOP | Gravity.END,
- screenWidth - screenPos[0] - width / 2, height);
- } else {
- // Show along the bottom center
- cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
- }
- cheatSheet.show();
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- return true;
- }
-
- @Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 1fd082f4..c1e2072 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -37,6 +37,7 @@
import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.media.AudioManager;
+import android.media.PlayerBase;
import android.media.session.MediaSession;
import android.net.Uri;
import android.os.BadParcelableException;
@@ -2821,6 +2822,7 @@
*/
@Deprecated
public Builder setSound(Uri sound, int streamType) {
+ PlayerBase.deprecateStreamTypeForPlayback(streamType, "Notification", "setSound()");
mN.sound = sound;
mN.audioStreamType = streamType;
return this;
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index c1180e2..c5a8288 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -26,6 +26,8 @@
import android.util.Log;
import com.google.android.collect.Maps;
+
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.XmlUtils;
import dalvik.system.BlockGuard;
@@ -72,6 +74,14 @@
private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
+ /** Current memory state (always increasing) */
+ @GuardedBy("this")
+ private long mCurrentMemoryStateGeneration;
+
+ /** Latest memory state that was committed to disk */
+ @GuardedBy("mWritingToDiskLock")
+ private long mDiskStateGeneration;
+
SharedPreferencesImpl(File file, int mode) {
mFile = file;
mBackupFile = makeBackupFile(file);
@@ -289,7 +299,7 @@
// Return value from EditorImpl#commitToMemory()
private static class MemoryCommitResult {
- public boolean changesMade; // any keys different?
+ public long memoryStateGeneration;
public List<String> keysModified; // may be null
public Set<OnSharedPreferenceChangeListener> listeners; // may be null
public Map<?, ?> mapToWriteToDisk;
@@ -412,9 +422,11 @@
}
synchronized (this) {
+ boolean changesMade = false;
+
if (mClear) {
if (!mMap.isEmpty()) {
- mcr.changesMade = true;
+ changesMade = true;
mMap.clear();
}
mClear = false;
@@ -441,13 +453,19 @@
mMap.put(k, v);
}
- mcr.changesMade = true;
+ changesMade = true;
if (hasListeners) {
mcr.keysModified.add(k);
}
}
mModified.clear();
+
+ if (changesMade) {
+ mCurrentMemoryStateGeneration++;
+ }
+
+ mcr.memoryStateGeneration = mCurrentMemoryStateGeneration;
}
}
return mcr;
@@ -509,10 +527,12 @@
*/
private void enqueueDiskWrite(final MemoryCommitResult mcr,
final Runnable postWriteRunnable) {
+ final boolean isFromSyncCommit = (postWriteRunnable == null);
+
final Runnable writeToDiskRunnable = new Runnable() {
public void run() {
synchronized (mWritingToDiskLock) {
- writeToFile(mcr);
+ writeToFile(mcr, isFromSyncCommit);
}
synchronized (SharedPreferencesImpl.this) {
mDiskWritesInFlight--;
@@ -523,8 +543,6 @@
}
};
- final boolean isFromSyncCommit = (postWriteRunnable == null);
-
// Typical #commit() path with fewer allocations, doing a write on
// the current thread.
if (isFromSyncCommit) {
@@ -538,6 +556,10 @@
}
}
+ if (DEBUG) {
+ Log.d(TAG, "added " + mcr.memoryStateGeneration + " -> " + mFile.getName());
+ }
+
QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
}
@@ -565,17 +587,34 @@
}
// Note: must hold mWritingToDiskLock
- private void writeToFile(MemoryCommitResult mcr) {
+ private void writeToFile(MemoryCommitResult mcr, boolean isFromSyncCommit) {
// Rename the current file so it may be used as a backup during the next read
if (mFile.exists()) {
- if (!mcr.changesMade) {
- // If the file already exists, but no changes were
- // made to the underlying map, it's wasteful to
- // re-write the file. Return as if we wrote it
- // out.
+ boolean needsWrite = false;
+
+ if (isFromSyncCommit) {
+ // Only need to write if the disk state is older than this commit
+ if (mDiskStateGeneration < mcr.memoryStateGeneration) {
+ needsWrite = true;
+ }
+ } else {
+ synchronized (this) {
+ // No need to persist intermediate states. Just wait for the latest state to be
+ // persisted.
+ if (mCurrentMemoryStateGeneration == mcr.memoryStateGeneration) {
+ needsWrite = true;
+ }
+ }
+ }
+
+ if (!needsWrite) {
+ if (DEBUG) {
+ Log.d(TAG, "skipped " + mcr.memoryStateGeneration + " -> " + mFile.getName());
+ }
mcr.setDiskWriteResult(true);
return;
}
+
if (!mBackupFile.exists()) {
if (!mFile.renameTo(mBackupFile)) {
Log.e(TAG, "Couldn't rename file " + mFile
@@ -599,6 +638,11 @@
}
XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
FileUtils.sync(str);
+
+ if (DEBUG) {
+ Log.d(TAG, "wrote " + mcr.memoryStateGeneration + " -> " + mFile.getName());
+ }
+
str.close();
ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
try {
@@ -612,7 +656,11 @@
}
// Writing was successful, delete the backup file if there is one.
mBackupFile.delete();
+
+ mDiskStateGeneration = mcr.memoryStateGeneration;
+
mcr.setDiskWriteResult(true);
+
return;
} catch (XmlPullParserException e) {
Log.w(TAG, "writeToFile: Got exception:", e);
diff --git a/core/java/android/app/admin/ConnectEvent.java b/core/java/android/app/admin/ConnectEvent.java
index c1646bb..5111443 100644
--- a/core/java/android/app/admin/ConnectEvent.java
+++ b/core/java/android/app/admin/ConnectEvent.java
@@ -21,7 +21,6 @@
/**
* A class that represents a connect library call event.
- * @hide
*/
public final class ConnectEvent extends NetworkEvent implements Parcelable {
@@ -31,6 +30,7 @@
/** The destination port number. */
private final int port;
+ /** @hide */
public ConnectEvent(String ipAddress, int port, String packageName, long timestamp) {
super(packageName, timestamp);
this.ipAddress = ipAddress;
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index b1eca5c..aae80ed 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -702,8 +702,6 @@
* @param batchToken The token representing the current batch of network logs.
* @param networkLogsCount The total count of events in the current batch of network logs.
* @see DevicePolicyManager#retrieveNetworkLogs(ComponentName)
- *
- * @hide
*/
public void onNetworkLogsAvailable(Context context, Intent intent, long batchToken,
int networkLogsCount) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 39c8b79..39f415e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -151,6 +151,7 @@
* <li>{@link #EXTRA_PROVISIONING_LOGO_URI}, optional</li>
* <li>{@link #EXTRA_PROVISIONING_MAIN_COLOR}, optional</li>
* <li>{@link #EXTRA_PROVISIONING_SKIP_USER_CONSENT}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION}, optional</li>
* </ul>
*
* <p>When managed provisioning has completed, broadcasts are sent to the application specified
@@ -513,6 +514,20 @@
= "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
/**
+ * Boolean extra to indicate that the migrated account should be kept. This is used in
+ * conjunction with {@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE}. If it's set to {@code true},
+ * the account will not be removed from the primary user after it is migrated to the newly
+ * created user or profile.
+ *
+ * <p> Defaults to {@code false}
+ *
+ * <p> Use with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
+ * {@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE}
+ */
+ public static final String EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION
+ = "android.app.extra.PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION";
+
+ /**
* A String extra that, holds the email address of the account which a managed profile is
* created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}.
@@ -1095,6 +1110,172 @@
public @interface UserProvisioningState {}
/**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE}, {@link #ACTION_PROVISION_MANAGED_USER} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when provisioning is allowed.
+ *
+ * @hide
+ */
+ public static final int CODE_OK = 0;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the device already has a device
+ * owner.
+ *
+ * @hide
+ */
+ public static final int CODE_HAS_DEVICE_OWNER = 1;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the user has a profile owner and for
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE} when the profile owner is already set.
+ *
+ * @hide
+ */
+ public static final int CODE_USER_HAS_PROFILE_OWNER = 2;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the user isn't running.
+ *
+ * @hide
+ */
+ public static final int CODE_USER_NOT_RUNNING = 3;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} if the device has already been setup and
+ * for {@link #ACTION_PROVISION_MANAGED_USER} if the user has already been setup.
+ *
+ * @hide
+ */
+ public static final int CODE_USER_SETUP_COMPLETED = 4;
+
+ /**
+ * Code used to indicate that the device also has a user other than the system user.
+ *
+ * @hide
+ */
+ public static final int CODE_NONSYSTEM_USER_EXISTS = 5;
+
+ /**
+ * Code used to indicate that device has an account that prevents provisioning.
+ *
+ * @hide
+ */
+ public static final int CODE_ACCOUNTS_NOT_EMPTY = 6;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} if the user is not a system user.
+ *
+ * @hide
+ */
+ public static final int CODE_NOT_SYSTEM_USER = 7;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} and {@link #ACTION_PROVISION_MANAGED_USER}
+ * when the device is a watch and is already paired.
+ *
+ * @hide
+ */
+ public static final int CODE_HAS_PAIRED = 8;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} and
+ * {@link #ACTION_PROVISION_MANAGED_USER} on devices which do not support managed users.
+ *
+ * @see {@link PackageManager#FEATURE_MANAGED_USERS}
+ * @hide
+ */
+ public static final int CODE_MANAGED_USERS_NOT_SUPPORTED = 9;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_USER} if the user is a system user.
+ *
+ * @hide
+ */
+ public static final int CODE_SYSTEM_USER = 10;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when the user cannot have more
+ * managed profiles.
+ *
+ * @hide
+ */
+ public static final int CODE_CANNOT_ADD_MANAGED_PROFILE = 11;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_USER} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} on devices not running with split system
+ * user.
+ *
+ * @hide
+ */
+ public static final int CODE_NOT_SYSTEM_USER_SPLIT = 12;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE}, {@link #ACTION_PROVISION_MANAGED_USER} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} on devices which do no support device
+ * admins.
+ *
+ * @hide
+ */
+ public static final int CODE_DEVICE_ADMIN_NOT_SUPPORTED = 13;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when the device has a device owner
+ * and the user is a system user on a split system user device.
+ *
+ * @hide
+ */
+ public static final int CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER = 14;
+
+ /**
+ * Result codes for {@link checkProvisioningPreCondition} indicating all the provisioning pre
+ * conditions.
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({CODE_OK, CODE_HAS_DEVICE_OWNER, CODE_USER_HAS_PROFILE_OWNER, CODE_USER_NOT_RUNNING,
+ CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER, CODE_HAS_PAIRED,
+ CODE_MANAGED_USERS_NOT_SUPPORTED, CODE_SYSTEM_USER, CODE_CANNOT_ADD_MANAGED_PROFILE,
+ CODE_NOT_SYSTEM_USER_SPLIT, CODE_DEVICE_ADMIN_NOT_SUPPORTED,
+ CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER})
+ public @interface ProvisioningPreCondition {}
+
+ /**
* Return true if the given administrator component is currently active (enabled) in the system.
*
* @param admin The administrator component to check for.
@@ -5964,6 +6145,24 @@
}
/**
+ * Checks if provisioning a managed profile or device is possible and returns one of the
+ * {@link ProvisioningPreCondition}.
+ *
+ * @param action One of {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE},
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_USER}
+ * @hide
+ */
+ public @ProvisioningPreCondition int checkProvisioningPreCondition(String action) {
+ try {
+ return mService.checkProvisioningPreCondition(action);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Return if this user is a managed profile of another user. An admin can become the profile
* owner of a managed profile with {@link #ACTION_PROVISION_MANAGED_PROFILE} and of a managed
* user with {@link #createAndManageUser}
@@ -6727,8 +6926,6 @@
* @param enabled whether network logging should be enabled or not.
* @throws {@link SecurityException} if {@code admin} is not a device owner.
* @see #retrieveNetworkLogs
- *
- * @hide
*/
public void setNetworkLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
throwIfParentInstance("setNetworkLoggingEnabled");
@@ -6742,13 +6939,13 @@
/**
* Return whether network logging is enabled by a device owner.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Can only
+ * be {@code null} if the caller has MANAGE_USERS permission.
* @return {@code true} if network logging is enabled by device owner, {@code false} otherwise.
- * @throws {@link SecurityException} if {@code admin} is not a device owner.
- *
- * @hide
+ * @throws {@link SecurityException} if {@code admin} is not a device owner and caller has
+ * no MANAGE_USERS permission
*/
- public boolean isNetworkLoggingEnabled(@NonNull ComponentName admin) {
+ public boolean isNetworkLoggingEnabled(@Nullable ComponentName admin) {
throwIfParentInstance("isNetworkLoggingEnabled");
try {
return mService.isNetworkLoggingEnabled(admin);
@@ -6778,8 +6975,6 @@
* logging is disabled.
* @throws {@link SecurityException} if {@code admin} is not a device owner.
* @see DeviceAdminReceiver#onNetworkLogsAvailable
- *
- * @hide
*/
public @Nullable List<NetworkEvent> retrieveNetworkLogs(@NonNull ComponentName admin,
long batchToken) {
diff --git a/core/java/android/app/admin/DnsEvent.java b/core/java/android/app/admin/DnsEvent.java
index 63ea8db..a3a3f58 100644
--- a/core/java/android/app/admin/DnsEvent.java
+++ b/core/java/android/app/admin/DnsEvent.java
@@ -21,7 +21,6 @@
/**
* A class that represents a DNS lookup event.
- * @hide
*/
public final class DnsEvent extends NetworkEvent implements Parcelable {
@@ -37,6 +36,7 @@
*/
private final int ipAddressesCount;
+ /** @hide */
public DnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount,
String packageName, long timestamp) {
super(packageName, timestamp);
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index f303bbc..3e22825 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -270,6 +270,7 @@
String permission, int grantState);
int getPermissionGrantState(in ComponentName admin, String packageName, String permission);
boolean isProvisioningAllowed(String action);
+ int checkProvisioningPreCondition(String action);
void setKeepUninstalledPackages(in ComponentName admin,in List<String> packageList);
List<String> getKeepUninstalledPackages(in ComponentName admin);
boolean isManagedProfile(in ComponentName admin);
diff --git a/core/java/android/app/admin/NetworkEvent.java b/core/java/android/app/admin/NetworkEvent.java
index 1dbff20..2646c3f 100644
--- a/core/java/android/app/admin/NetworkEvent.java
+++ b/core/java/android/app/admin/NetworkEvent.java
@@ -16,17 +16,19 @@
package android.app.admin;
+import android.content.pm.PackageManager;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.ParcelFormatException;
/**
* An abstract class that represents a network event.
- * @hide
*/
public abstract class NetworkEvent implements Parcelable {
+ /** @hide */
static final int PARCEL_TOKEN_DNS_EVENT = 1;
+ /** @hide */
static final int PARCEL_TOKEN_CONNECT_EVENT = 2;
/** The package name of the UID that performed the query. */
@@ -35,21 +37,29 @@
/** The timestamp of the event being reported in milliseconds. */
long timestamp;
- protected NetworkEvent() {
+ /** @hide */
+ NetworkEvent() {
//empty constructor
}
- protected NetworkEvent(String packageName, long timestamp) {
+ /** @hide */
+ NetworkEvent(String packageName, long timestamp) {
this.packageName = packageName;
this.timestamp = timestamp;
}
- /** Returns the package name of the UID that performed the query. */
+ /**
+ * Returns the package name of the UID that performed the query, as returned by
+ * {@link PackageManager#getNameForUid}.
+ */
public String getPackageName() {
return packageName;
}
- /** Returns the timestamp of the event being reported in milliseconds. */
+ /**
+ * Returns the timestamp of the event being reported in milliseconds, the difference between
+ * the time the event was reported and midnight, January 1, 1970 UTC.
+ */
public long getTimestamp() {
return timestamp;
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index f369409..cda98e5 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -97,6 +97,7 @@
* developer guide.</p>
*/
public abstract class ContentProvider implements ComponentCallbacks2 {
+
private static final String TAG = "ContentProvider";
/*
@@ -118,7 +119,7 @@
private boolean mNoPerms;
private boolean mSingleUser;
- private final ThreadLocal<String> mCallingPackage = new ThreadLocal<String>();
+ private final ThreadLocal<String> mCallingPackage = new ThreadLocal<>();
private Transport mTransport = new Transport();
@@ -205,9 +206,8 @@
}
@Override
- public Cursor query(String callingPkg, Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder,
- ICancellationSignal cancellationSignal) {
+ public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection,
+ @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
@@ -225,9 +225,9 @@
// However, the caller may be expecting to access them my index. Hence,
// we have to execute the query as if allowed to get a cursor with the
// columns. We then use the column names to return an empty cursor.
- Cursor cursor = ContentProvider.this.query(uri, projection, selection,
- selectionArgs, sortOrder, CancellationSignal.fromTransport(
- cancellationSignal));
+ Cursor cursor = ContentProvider.this.query(
+ uri, projection, queryArgs,
+ CancellationSignal.fromTransport(cancellationSignal));
if (cursor == null) {
return null;
}
@@ -238,7 +238,7 @@
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.query(
- uri, projection, selection, selectionArgs, sortOrder,
+ uri, projection, queryArgs,
CancellationSignal.fromTransport(cancellationSignal));
} finally {
setCallingPackage(original);
@@ -893,6 +893,7 @@
* (Content providers do not usually care about things like screen
* orientation, but may want to know about locale changes.)
*/
+ @Override
public void onConfigurationChanged(Configuration newConfig) {
}
@@ -904,9 +905,11 @@
* <p>The default content provider implementation does nothing.
* Subclasses may override this method to take appropriate action.
*/
+ @Override
public void onLowMemory() {
}
+ @Override
public void onTrimMemory(int level) {
}
@@ -1039,6 +1042,45 @@
}
/**
+ * Implement this to handle query requests where the arguments are packed into a {@link Bundle}.
+ * Arguments may include traditional SQL style query arguments. When present these
+ * should be handled according to the contract established in
+ * {@link #query(Uri, String[], String, String[], String, CancellationSignal).
+ *
+ * <p>Traditional SQL arguments can be found in the bundle using the following keys:
+ * <li>{@link ContentResolver#QUERY_ARG_SELECTION}
+ * <li>{@link ContentResolver#QUERY_ARG_SELECTION_ARGS}
+ * <li>{@link ContentResolver#QUERY_ARG_SORT_ORDER}
+ *
+ * @see #query(Uri, String[], String, String[], String, CancellationSignal) for
+ * implementation details.
+ *
+ * @param uri The URI to query. This will be the full URI sent by the client.
+ * TODO: Me wonders about this use case, and how we adapt it.
+ * If the client is requesting a specific record, the URI will end
+ * in a record number that the implementation should parse and add
+ * to a WHERE or HAVING clause, specifying that _id value.
+ * @param projection The list of columns to put into the cursor.
+ * If {@code null} provide a default set of columns.
+ * @param queryArgs A Bundle containing all additional information necessary for the query.
+ * Values in the Bundle may include SQL style arguments.
+ * @param cancellationSignal A signal to cancel the operation in progress,
+ * or {@code null}.
+ * @return a Cursor or {@code null}.
+ */
+ public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+ @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) {
+ queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY;
+ return query(
+ uri,
+ projection,
+ queryArgs.getString(ContentResolver.QUERY_ARG_SELECTION),
+ queryArgs.getStringArray(ContentResolver.QUERY_ARG_SELECTION_ARGS),
+ queryArgs.getString(ContentResolver.QUERY_ARG_SORT_ORDER),
+ cancellationSignal);
+ }
+
+ /**
* Implement this to handle requests for the MIME type of the data at the
* given URI. The returned MIME type should start with
* <code>vnd.android.cursor.item</code> for a single record,
@@ -1412,7 +1454,7 @@
* no file associated with the given URI or the mode is invalid.
* @throws SecurityException Throws SecurityException if the caller does
* not have permission to access the file.
- *
+ *
* @see #openFile(Uri, String)
* @see #openFileHelper(Uri, String)
* @see #getType(android.net.Uri)
@@ -1851,7 +1893,7 @@
/**
* Implement this to shut down the ContentProvider instance. You can then
* invoke this method in unit tests.
- *
+ *
* <p>
* Android normally handles ContentProvider startup and shutdown
* automatically. You do not need to start up or shut down a
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index fd6cddb..732666f 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -128,11 +128,20 @@
}
/** See {@link ContentProvider#query ContentProvider.query} */
- public @Nullable Cursor query(@NonNull Uri url, @Nullable String[] projection,
+ public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
@Nullable String selection, @Nullable String[] selectionArgs,
@Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal)
throws RemoteException {
- Preconditions.checkNotNull(url, "url");
+ Bundle queryArgs =
+ ContentResolver.createSqlQueryBundle(selection, selectionArgs, sortOrder);
+ return query(uri, projection, queryArgs, cancellationSignal);
+ }
+
+ /** See {@link ContentProvider#query ContentProvider.query} */
+ public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+ Bundle queryArgs, @Nullable CancellationSignal cancellationSignal)
+ throws RemoteException {
+ Preconditions.checkNotNull(uri, "url");
beforeRemote();
try {
@@ -142,8 +151,8 @@
remoteCancellationSignal = mContentProvider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- final Cursor cursor = mContentProvider.query(mPackageName, url, projection, selection,
- selectionArgs, sortOrder, remoteCancellationSignal);
+ final Cursor cursor = mContentProvider.query(
+ mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
if (cursor == null) {
return null;
}
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index eadc013..d428a3a 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -16,6 +16,7 @@
package android.content;
+import android.annotation.Nullable;
import android.content.res.AssetFileDescriptor;
import android.database.BulkCursorDescriptor;
import android.database.BulkCursorToCursorAdaptor;
@@ -92,25 +93,13 @@
}
}
- // String selection, String[] selectionArgs...
- String selection = data.readString();
- num = data.readInt();
- String[] selectionArgs = null;
- if (num > 0) {
- selectionArgs = new String[num];
- for (int i = 0; i < num; i++) {
- selectionArgs[i] = data.readString();
- }
- }
-
- String sortOrder = data.readString();
+ Bundle queryArgs = data.readBundle();
IContentObserver observer = IContentObserver.Stub.asInterface(
data.readStrongBinder());
ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
- Cursor cursor = query(callingPkg, url, projection, selection, selectionArgs,
- sortOrder, cancellationSignal);
+ Cursor cursor = query(callingPkg, url, projection, queryArgs, cancellationSignal);
if (cursor != null) {
CursorToBulkCursorAdaptor adaptor = null;
@@ -185,7 +174,7 @@
String callingPkg = data.readString();
final int numOperations = data.readInt();
final ArrayList<ContentProviderOperation> operations =
- new ArrayList<ContentProviderOperation>(numOperations);
+ new ArrayList<>(numOperations);
for (int i = 0; i < numOperations; i++) {
operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
}
@@ -378,6 +367,7 @@
return super.onTransact(code, data, reply, flags);
}
+ @Override
public IBinder asBinder()
{
return this;
@@ -392,14 +382,16 @@
mRemote = remote;
}
+ @Override
public IBinder asBinder()
{
return mRemote;
}
- public Cursor query(String callingPkg, Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal)
- throws RemoteException {
+ @Override
+ public Cursor query(String callingPkg, Uri url, @Nullable String[] projection,
+ @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
+ throws RemoteException {
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -416,19 +408,10 @@
for (int i = 0; i < length; i++) {
data.writeString(projection[i]);
}
- data.writeString(selection);
- if (selectionArgs != null) {
- length = selectionArgs.length;
- } else {
- length = 0;
- }
- data.writeInt(length);
- for (int i = 0; i < length; i++) {
- data.writeString(selectionArgs[i]);
- }
- data.writeString(sortOrder);
+ data.writeBundle(queryArgs);
data.writeStrongBinder(adaptor.getObserver().asBinder());
- data.writeStrongBinder(cancellationSignal != null ? cancellationSignal.asBinder() : null);
+ data.writeStrongBinder(
+ cancellationSignal != null ? cancellationSignal.asBinder() : null);
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
@@ -455,6 +438,7 @@
}
}
+ @Override
public String getType(Uri url) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -475,6 +459,7 @@
}
}
+ @Override
public Uri insert(String callingPkg, Uri url, ContentValues values) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -497,6 +482,7 @@
}
}
+ @Override
public int bulkInsert(String callingPkg, Uri url, ContentValues[] values) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -518,7 +504,8 @@
}
}
- public ContentProviderResult[] applyBatch(String callingPkg,
+ @Override
+ public ContentProviderResult[] applyBatch(String callingPkg,
ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
Parcel data = Parcel.obtain();
@@ -542,6 +529,7 @@
}
}
+ @Override
public int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
throws RemoteException {
Parcel data = Parcel.obtain();
@@ -565,6 +553,7 @@
}
}
+ @Override
public int update(String callingPkg, Uri url, ContentValues values, String selection,
String[] selectionArgs) throws RemoteException {
Parcel data = Parcel.obtain();
@@ -644,6 +633,7 @@
}
}
+ @Override
public Bundle call(String callingPkg, String method, String request, Bundle args)
throws RemoteException {
Parcel data = Parcel.obtain();
@@ -667,6 +657,7 @@
}
}
+ @Override
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -715,6 +706,7 @@
}
}
+ @Override
public ICancellationSignal createCancellationSignal() throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -734,6 +726,7 @@
}
}
+ @Override
public Uri canonicalize(String callingPkg, Uri url) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -755,6 +748,7 @@
}
}
+ @Override
public Uri uncanonicalize(String callingPkg, Uri url) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -775,6 +769,7 @@
}
}
+ @Override
public boolean refresh(String callingPkg, Uri url, Bundle args, ICancellationSignal signal)
throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 54dcd0a..0fe5ce9 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -203,6 +203,26 @@
public static final String EXTRA_REFRESH_SUPPORTED = "android.content.extra.REFRESH_SUPPORTED";
/**
+ * Key for an SQL style selection string that may be present in the query Bundle argument
+ * passed to {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}
+ * when called by a legacy client.
+ */
+ public static final String QUERY_ARG_SELECTION = "android:query-selection";
+
+ /**
+ * Key for sql selection string arguments list.
+ * @see #QUERY_ARG_SELECTION
+ */
+ public static final String QUERY_ARG_SELECTION_ARGS = "android:query-selection-args";
+
+ /**
+ * Key for an SQL style sort string that may be present in the query Bundle argument
+ * passed to {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}
+ * when called by a legacy client.
+ */
+ public static final String QUERY_ARG_SORT_ORDER = "android:query-sort-order";
+
+ /**
* This is the Android platform's base MIME type for a content: URI
* containing a Cursor of a single item. Applications should use this
* as the base type along with their own sub-type of their content: URIs
@@ -517,10 +537,37 @@
* @return A Cursor object, which is positioned before the first entry, or null
* @see Cursor
*/
- public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
+ public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder,
@Nullable CancellationSignal cancellationSignal) {
+ Bundle queryArgs = createSqlQueryBundle(selection, selectionArgs, sortOrder);
+ return query(uri, projection, queryArgs, cancellationSignal);
+ }
+
+ /**
+ * Query the given URI, returning a {@link Cursor} over the result set
+ * with support for cancellation.
+ *
+ * <p>For best performance, the caller should follow these guidelines:
+ *
+ * <li>Provide an explicit projection, to prevent reading data from storage
+ * that aren't going to be used.
+ *
+ * @param uri The URI, using the content:// scheme, for the content to
+ * retrieve.
+ * @param projection A list of which columns to return. Passing null will
+ * return all columns, which is inefficient.
+ * @param queryArgs A Bundle containing any arguments to the query.
+ * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
+ * If the operation is canceled, then {@link OperationCanceledException} will be thrown
+ * when the query is executed.
+ * @return A Cursor object, which is positioned before the first entry, or null
+ * @see Cursor
+ */
+ public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
+ @Nullable String[] projection, @Nullable Bundle queryArgs,
+ @Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(uri, "uri");
IContentProvider unstableProvider = acquireUnstableProvider(uri);
if (unstableProvider == null) {
@@ -539,7 +586,7 @@
}
try {
qCursor = unstableProvider.query(mPackageName, uri, projection,
- selection, selectionArgs, sortOrder, remoteCancellationSignal);
+ queryArgs, remoteCancellationSignal);
} catch (DeadObjectException e) {
// The remote process has died... but we only hold an unstable
// reference though, so we might recover!!! Let's try!!!!
@@ -549,8 +596,8 @@
if (stableProvider == null) {
return null;
}
- qCursor = stableProvider.query(mPackageName, uri, projection,
- selection, selectionArgs, sortOrder, remoteCancellationSignal);
+ qCursor = stableProvider.query(
+ mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
}
if (qCursor == null) {
return null;
@@ -559,7 +606,7 @@
// Force query execution. Might fail and throw a runtime exception here.
qCursor.getCount();
long durationMillis = SystemClock.uptimeMillis() - startTime;
- maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
+ maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs);
// Wrap the cursor object into CursorWrapperInner object.
final IContentProvider provider = (stableProvider != null) ? stableProvider
@@ -2541,6 +2588,7 @@
}
try {
ISyncStatusObserver.Stub observer = new ISyncStatusObserver.Stub() {
+ @Override
public void onStatusChanged(int which) throws RemoteException {
callback.onStatusChanged(which);
}
@@ -2602,9 +2650,8 @@
return (int) (100 * durationMillis / SLOW_THRESHOLD_MILLIS) + 1;
}
- private void maybeLogQueryToEventLog(long durationMillis,
- Uri uri, String[] projection,
- String selection, String sortOrder) {
+ private void maybeLogQueryToEventLog(
+ long durationMillis, Uri uri, String[] projection, @Nullable Bundle queryArgs) {
if (!ENABLE_CONTENT_SAMPLE) return;
int samplePercent = samplePercentForDuration(durationMillis);
if (samplePercent < 100) {
@@ -2615,6 +2662,9 @@
}
}
+ // Ensure a non-null bundle.
+ queryArgs = (queryArgs != null) ? queryArgs : Bundle.EMPTY;
+
StringBuilder projectionBuffer = new StringBuilder(100);
if (projection != null) {
for (int i = 0; i < projection.length; ++i) {
@@ -2636,8 +2686,8 @@
EventLogTags.CONTENT_QUERY_SAMPLE,
uri.toString(),
projectionBuffer.toString(),
- selection != null ? selection : "",
- sortOrder != null ? sortOrder : "",
+ queryArgs.getString(QUERY_ARG_SELECTION, ""),
+ queryArgs.getString(QUERY_ARG_SORT_ORDER, ""),
durationMillis,
blockingPackage != null ? blockingPackage : "",
samplePercent);
@@ -2751,4 +2801,29 @@
public Drawable getTypeDrawable(String mimeType) {
return MimeIconUtils.loadMimeIcon(mContext, mimeType);
}
+
+ /**
+ * @hide
+ */
+ public static @Nullable Bundle createSqlQueryBundle(
+ @Nullable String selection,
+ @Nullable String[] selectionArgs,
+ @Nullable String sortOrder) {
+
+ if (selection == null && selectionArgs == null && sortOrder == null) {
+ return null;
+ }
+
+ Bundle queryArgs = new Bundle();
+ if (selection != null) {
+ queryArgs.putString(QUERY_ARG_SELECTION, selection);
+ }
+ if (selectionArgs != null) {
+ queryArgs.putStringArray(QUERY_ARG_SELECTION_ARGS, selectionArgs);
+ }
+ if (sortOrder != null) {
+ queryArgs.putString(QUERY_ARG_SORT_ORDER, sortOrder);
+ }
+ return queryArgs;
+ }
}
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index ee8a22f..66087fb 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -35,9 +35,9 @@
* @hide
*/
public interface IContentProvider extends IInterface {
- public Cursor query(String callingPkg, Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal)
- throws RemoteException;
+ public Cursor query(String callingPkg, Uri url, @Nullable String[] projection,
+ @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
+ throws RemoteException;
public String getType(Uri url) throws RemoteException;
public Uri insert(String callingPkg, Uri url, ContentValues initialValues)
throws RemoteException;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a5d7999..cda8176 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3483,6 +3483,21 @@
public static final String CATEGORY_OPENABLE = "android.intent.category.OPENABLE";
/**
+ * Used to indicate that an intent filter can accept files which are not necessarily
+ * openable by {@link ContentResolver#openFileDescriptor(Uri, String)}, but
+ * at least streamable via
+ * {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)}
+ * using one of the stream types exposed via
+ * {@link ContentResolver#getStreamTypes(Uri, String)}.
+ *
+ * @see #ACTION_SEND
+ * @see #ACTION_SEND_MULTIPLE
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_TYPED_OPENABLE =
+ "android.intent.category.TYPED_OPENABLE";
+
+ /**
* To be used as code under test for framework instrumentation tests.
*/
public static final String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST =
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index e2ebd46..5d90acc 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -182,12 +182,30 @@
*/
public static final int RESIZE_MODE_RESIZEABLE_AND_PIPABLE = 3;
/**
- * Activity is does not support resizing, but we are forcing it to be resizeable. Only affects
+ * Activity does not support resizing, but we are forcing it to be resizeable. Only affects
* certain pre-N apps where we force them to be resizeable.
* @hide
*/
public static final int RESIZE_MODE_FORCE_RESIZEABLE = 4;
/**
+ * Activity does not support resizing, but we are forcing it to be resizeable as long
+ * as the size remains landscape.
+ * @hide
+ */
+ public static final int RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY = 5;
+ /**
+ * Activity does not support resizing, but we are forcing it to be resizeable as long
+ * as the size remains portrait.
+ * @hide
+ */
+ public static final int RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY = 6;
+ /**
+ * Activity does not support resizing, but we are forcing it to be resizeable as long
+ * as the bounds remain in the same orientation as they are.
+ * @hide
+ */
+ public static final int RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION = 7;
+ /**
* Value indicating if the resizing mode the activity supports.
* See {@link android.R.attr#resizeableActivity}.
* @hide
@@ -859,26 +877,51 @@
* @hide
*/
boolean isFixedOrientation() {
- return screenOrientation == SCREEN_ORIENTATION_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_PORTRAIT
- || screenOrientation == SCREEN_ORIENTATION_SENSOR_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT
- || screenOrientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT
- || screenOrientation == SCREEN_ORIENTATION_USER_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_USER_PORTRAIT
+ return isFixedOrientationLandscape() || isFixedOrientationPortrait()
|| screenOrientation == SCREEN_ORIENTATION_LOCKED;
}
+ /**
+ * Returns true if the activity's orientation is fixed to landscape.
+ * @hide
+ */
+ boolean isFixedOrientationLandscape() {
+ return screenOrientation == SCREEN_ORIENTATION_LANDSCAPE
+ || screenOrientation == SCREEN_ORIENTATION_SENSOR_LANDSCAPE
+ || screenOrientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE
+ || screenOrientation == SCREEN_ORIENTATION_USER_LANDSCAPE;
+ }
+
+ /**
+ * Returns true if the activity's orientation is fixed to portrait.
+ * @hide
+ */
+ boolean isFixedOrientationPortrait() {
+ return screenOrientation == SCREEN_ORIENTATION_PORTRAIT
+ || screenOrientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT
+ || screenOrientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT
+ || screenOrientation == SCREEN_ORIENTATION_USER_PORTRAIT;
+ }
+
/** @hide */
public static boolean isResizeableMode(int mode) {
return mode == RESIZE_MODE_RESIZEABLE
|| mode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE
|| mode == RESIZE_MODE_FORCE_RESIZEABLE
+ || mode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
+ || mode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
+ || mode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION
|| mode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
}
/** @hide */
+ public static boolean isPreserveOrientationMode(int mode) {
+ return mode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
+ || mode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
+ || mode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+ }
+
+ /** @hide */
public static String resizeModeToString(int mode) {
switch (mode) {
case RESIZE_MODE_UNRESIZEABLE:
@@ -891,6 +934,12 @@
return "RESIZE_MODE_RESIZEABLE_AND_PIPABLE";
case RESIZE_MODE_FORCE_RESIZEABLE:
return "RESIZE_MODE_FORCE_RESIZEABLE";
+ case RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY:
+ return "RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY";
+ case RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY:
+ return "RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY";
+ case RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION:
+ return "RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION";
default:
return "unknown=" + mode;
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index ed8143e..646bd3c 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1067,6 +1067,16 @@
}
/** {@hide} */
+ @SystemApi
+ public void setInstallAsInstantApp(boolean isInstantApp) {
+ if (isInstantApp) {
+ installFlags |= PackageManager.INSTALL_EPHEMERAL;
+ } else {
+ installFlags &= ~PackageManager.INSTALL_EPHEMERAL;
+ }
+ }
+
+ /** {@hide} */
public void dump(IndentingPrintWriter pw) {
pw.printPair("mode", mode);
pw.printHexPair("installFlags", installFlags);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3f052d38..ecdd02a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -436,9 +436,10 @@
/**
* Allows querying of packages installed for any user, not just the specific one. This flag
- * is only meant for use by apps that have INTERACT_ACROSS_USERS_FULL permission.
+ * is only meant for use by apps that have INTERACT_ACROSS_USERS permission.
* @hide
*/
+ @SystemApi
public static final int MATCH_ANY_USER = 0x00400000;
/**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index f363bd8..9b2dd68 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -17,6 +17,7 @@
package android.content.pm;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;
@@ -39,6 +40,9 @@
import android.os.PatternMatcher;
import android.os.Trace;
import android.os.UserHandle;
+import android.system.ErrnoException;
+import android.system.OsConstants;
+import android.system.StructStat;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -54,6 +58,8 @@
import android.view.Gravity;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@@ -82,6 +88,9 @@
import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
@@ -259,6 +268,7 @@
private String[] mSeparateProcesses;
private boolean mOnlyCoreApps;
private DisplayMetrics mMetrics;
+ private File mCacheDir;
private static final int SDK_VERSION = Build.VERSION.SDK_INT;
private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
@@ -453,6 +463,13 @@
mMetrics = metrics;
}
+ /**
+ * Sets the cache directory for this package parser.
+ */
+ public void setCacheDir(File cacheDir) {
+ mCacheDir = cacheDir;
+ }
+
public static final boolean isApkFile(File file) {
return isApkPath(file.getName());
}
@@ -806,13 +823,154 @@
* Note that this <em>does not</em> perform signature verification; that
* must be done separately in {@link #collectCertificates(Package, int)}.
*
+ * If {@code useCaches} is true, the package parser might return a cached
+ * result from a previous parse of the same {@code packageFile} with the same
+ * {@code flags}. Note that this method does not check whether {@code packageFile}
+ * has changed since the last parse, it's up to callers to do so.
+ *
* @see #parsePackageLite(File, int)
*/
- public Package parsePackage(File packageFile, int flags) throws PackageParserException {
+ public Package parsePackage(File packageFile, int flags, boolean useCaches)
+ throws PackageParserException {
+ Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
+ if (parsed != null) {
+ return parsed;
+ }
+
if (packageFile.isDirectory()) {
- return parseClusterPackage(packageFile, flags);
+ parsed = parseClusterPackage(packageFile, flags);
} else {
- return parseMonolithicPackage(packageFile, flags);
+ parsed = parseMonolithicPackage(packageFile, flags);
+ }
+
+ cacheResult(packageFile, flags, parsed);
+
+ return parsed;
+ }
+
+ /**
+ * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
+ */
+ public Package parsePackage(File packageFile, int flags) throws PackageParserException {
+ return parsePackage(packageFile, flags, false /* useCaches */);
+ }
+
+ /**
+ * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
+ */
+ private String getCacheKey(File packageFile, int flags) {
+ StringBuilder sb = new StringBuilder(packageFile.getName());
+ sb.append('-');
+ sb.append(flags);
+
+ return sb.toString();
+ }
+
+ @VisibleForTesting
+ protected Package fromCacheEntry(byte[] bytes) throws IOException {
+ return null;
+ }
+
+ @VisibleForTesting
+ protected byte[] toCacheEntry(Package pkg) throws IOException {
+ return null;
+ }
+
+ /**
+ * Given a {@code packageFile} and a {@code cacheFile} returns whether the
+ * cache file is up to date based on the mod-time of both files.
+ */
+ private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
+ try {
+ // NOTE: We don't use the File.lastModified API because it has the very
+ // non-ideal failure mode of returning 0 with no excepions thrown.
+ // The nio2 Files API is a little better but is considerably more expensive.
+ final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
+ final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
+ return pkg.st_mtime < cache.st_mtime;
+ } catch (ErrnoException ee) {
+ // The most common reason why stat fails is that a given cache file doesn't
+ // exist. We ignore that here. It's easy to reason that it's safe to say the
+ // cache isn't up to date if we see any sort of exception here.
+ //
+ // (1) Exception while stating the package file : This should never happen,
+ // and if it does, we do a full package parse (which is likely to throw the
+ // same exception).
+ // (2) Exception while stating the cache file : If the file doesn't exist, the
+ // cache is obviously out of date. If the file *does* exist, we can't read it.
+ // We will attempt to delete and recreate it after parsing the package.
+ if (ee.errno != OsConstants.ENOENT) {
+ Slog.w("Error while stating package cache : ", ee);
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
+ * or {@code null} if no cached result exists.
+ */
+ private Package getCachedResult(File packageFile, int flags) {
+ if (mCacheDir == null) {
+ return null;
+ }
+
+ final String cacheKey = getCacheKey(packageFile, flags);
+ final File cacheFile = new File(mCacheDir, cacheKey);
+
+ // If the cache is not up to date, return null.
+ if (!isCacheUpToDate(packageFile, cacheFile)) {
+ return null;
+ }
+
+ try {
+ final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
+ return fromCacheEntry(bytes);
+ } catch (IOException ioe) {
+ Slog.w(TAG, "Error reading package cache: ", ioe);
+
+ // If something went wrong while reading the cache entry, delete the cache file
+ // so that we regenerate it the next time.
+ cacheFile.delete();
+ return null;
+ }
+ }
+
+ /**
+ * Caches the parse result for {@code packageFile} with flags {@code flags}.
+ */
+ private void cacheResult(File packageFile, int flags, Package parsed) {
+ if (mCacheDir == null) {
+ return;
+ }
+
+ final String cacheKey = getCacheKey(packageFile, flags);
+ final File cacheFile = new File(mCacheDir, cacheKey);
+
+ if (cacheFile.exists()) {
+ if (!cacheFile.delete()) {
+ Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
+ }
+ }
+
+ final byte[] cacheEntry;
+ try {
+ cacheEntry = toCacheEntry(parsed);
+ } catch (IOException ioe) {
+ Slog.e(TAG, "Unable to serialize parsed package for: " + packageFile);
+ return;
+ }
+
+ if (cacheEntry == null) {
+ return;
+ }
+
+ try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
+ fos.write(cacheEntry);
+ } catch (IOException ioe) {
+ Slog.w(TAG, "Error writing cache entry.", ioe);
+ cacheFile.delete();
}
}
@@ -3741,8 +3899,15 @@
// resize preference isn't set and target sdk version doesn't support resizing apps by
// default. For the app to be resizeable if it isn't fixed orientation or immersive.
- aInfo.resizeMode = (aInfo.isFixedOrientation() || (aInfo.flags & FLAG_IMMERSIVE) != 0)
- ? RESIZE_MODE_UNRESIZEABLE : RESIZE_MODE_FORCE_RESIZEABLE;
+ if (aInfo.isFixedOrientationPortrait()) {
+ aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+ } else if (aInfo.isFixedOrientationLandscape()) {
+ aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
+ } else if (aInfo.isFixedOrientation()) {
+ aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+ } else {
+ aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
+ }
}
private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index a854b89..56f914e 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -314,9 +314,11 @@
*
* @hide
*/
- public void enforceMandatoryFields() {
+ public void enforceMandatoryFields(boolean forPinned) {
Preconditions.checkStringNotEmpty(mId, "Shortcut ID must be provided");
- Preconditions.checkNotNull(mActivity, "Activity must be provided");
+ if (!forPinned) {
+ Preconditions.checkNotNull(mActivity, "Activity must be provided");
+ }
if (mTitle == null && mTitleResId == 0) {
throw new IllegalArgumentException("Short label must be provided");
}
@@ -1055,6 +1057,11 @@
* Launcher apps should show the launcher icon for the returned activity alongside
* this shortcut.
*
+ * <p>When a shortcut is dynamic or manifest
+ * (i.e. either {@link #isDynamic()} or {@link #isDeclaredInManifest()} returns {@code TRUE}),
+ * then it should always have a non-null target activity.
+ * Otherwise it will return null.
+ *
* @see Builder#setActivity
*/
@Nullable
@@ -1361,7 +1368,7 @@
}
/**
- * @return true if pinned but neither static nor dynamic.
+ * Return {@code TRUE} if a shortcut is pinned but neither manifest nor dynamic.
* @hide
*/
public boolean isFloating() {
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index b0d0d79..db24ffe 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -815,9 +815,9 @@
/*package*/ static final int STYLE_DENSITY = 5;
@FastNative
- /*package*/ native static final boolean applyStyle(long theme,
+ /*package*/ native static final void applyStyle(long theme,
int defStyleAttr, int defStyleRes, long xmlParser,
- int[] inAttrs, int[] outValues, int[] outIndices);
+ int[] inAttrs, int length, long outValuesAddress, long outIndicesAddress);
@FastNative
/*package*/ native static final boolean resolveAttrs(long theme,
int defStyleAttr, int defStyleRes, int[] inValues,
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index c46fe29..eb010e4 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -1126,7 +1126,7 @@
final XmlBlock.Parser parser = (XmlBlock.Parser) set;
AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
parser != null ? parser.mParseState : 0,
- attrs, array.mData, array.mIndices);
+ attrs, attrs.length, array.mDataAddress, array.mIndicesAddress);
array.mTheme = wrapper;
array.mXml = parser;
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 1e44a5c..ca95ce1 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -30,6 +30,8 @@
import com.android.internal.util.XmlUtils;
+import dalvik.system.VMRuntime;
+
import java.util.Arrays;
/**
@@ -44,28 +46,17 @@
public class TypedArray {
static TypedArray obtain(Resources res, int len) {
- final TypedArray attrs = res.mTypedArrayPool.acquire();
- if (attrs != null) {
- attrs.mLength = len;
- attrs.mRecycled = false;
-
- // Reset the assets, which may have changed due to configuration changes
- // or further resource loading.
- attrs.mAssets = res.getAssets();
-
- final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
- if (attrs.mData.length >= fullLen) {
- return attrs;
- }
-
- attrs.mData = new int[fullLen];
- attrs.mIndices = new int[1 + len];
- return attrs;
+ TypedArray attrs = res.mTypedArrayPool.acquire();
+ if (attrs == null) {
+ attrs = new TypedArray(res);
}
- return new TypedArray(res,
- new int[len*AssetManager.STYLE_NUM_ENTRIES],
- new int[1+len], len);
+ attrs.mRecycled = false;
+ // Reset the assets, which may have changed due to configuration changes
+ // or further resource loading.
+ attrs.mAssets = res.getAssets();
+ attrs.resize(len);
+ return attrs;
}
private final Resources mResources;
@@ -77,10 +68,25 @@
/*package*/ XmlBlock.Parser mXml;
/*package*/ Resources.Theme mTheme;
/*package*/ int[] mData;
+ /*package*/ long mDataAddress;
/*package*/ int[] mIndices;
+ /*package*/ long mIndicesAddress;
/*package*/ int mLength;
/*package*/ TypedValue mValue = new TypedValue();
+ private void resize(int len) {
+ mLength = len;
+ final int dataLen = len * AssetManager.STYLE_NUM_ENTRIES;
+ final int indicesLen = len + 1;
+ final VMRuntime runtime = VMRuntime.getRuntime();
+ if (mData == null || mData.length < dataLen) {
+ mData = (int[]) runtime.newNonMovableArray(int.class, dataLen);
+ mDataAddress = runtime.addressOf(mData);
+ mIndices = (int[]) runtime.newNonMovableArray(int.class, indicesLen);
+ mIndicesAddress = runtime.addressOf(mIndices);
+ }
+ }
+
/**
* Returns the number of values in this array.
*
@@ -1217,13 +1223,11 @@
return mAssets.getPooledStringForCookie(cookie, data[index+AssetManager.STYLE_DATA]);
}
- /*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) {
+ /** @hide */
+ protected TypedArray(Resources resources) {
mResources = resources;
mMetrics = mResources.getDisplayMetrics();
mAssets = mResources.getAssets();
- mData = data;
- mIndices = indices;
- mLength = len;
}
@Override
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 3e79118..1a05904 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -348,9 +348,7 @@
Size[] sizes = streamConfigurations.getOutputSizes(surfaceType);
if (sizes == null) {
- // WAR: Override default format to IMPLEMENTATION_DEFINED for b/9487482
- if ((surfaceType >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
- surfaceType <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
+ if (surfaceType == ImageFormat.PRIVATE) {
// YUV_420_888 is always present in LEGACY for all
// IMPLEMENTATION_DEFINED output sizes, and is publicly visible in the
@@ -649,7 +647,16 @@
*/
public static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException {
checkNotNull(surface);
- return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface));
+ int surfaceType = nativeDetectSurfaceType(surface);
+
+ // TODO: remove this override since the default format should be
+ // ImageFormat.PRIVATE. b/9487482
+ if ((surfaceType >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
+ surfaceType <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
+ surfaceType = ImageFormat.PRIVATE;
+ }
+
+ return LegacyExceptionUtils.throwOnError(surfaceType);
}
/**
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index dfa19b0..dbe1394 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -408,12 +408,6 @@
// See if consumer is flexible.
boolean isFlexible = SurfaceUtils.isFlexibleConsumer(surface);
- // Override RGB formats to IMPLEMENTATION_DEFINED, b/9487482
- if ((surfaceFormat >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
- surfaceFormat <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
- surfaceFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- }
-
StreamConfiguration[] configs =
surfaceDataspace != HAL_DATASPACE_DEPTH ? mConfigurations : mDepthConfigurations;
for (StreamConfiguration config : configs) {
diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
index 4b958df..e1e1c4f 100644
--- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java
+++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
@@ -118,15 +118,7 @@
* @param surface The high speed output surface to be checked.
*/
private static void checkHighSpeedSurfaceFormat(Surface surface) {
- // TODO: remove this override since the default format should be
- // ImageFormat.PRIVATE. b/9487482
- final int HAL_FORMAT_RGB_START = 1; // HAL_PIXEL_FORMAT_RGBA_8888 from graphics.h
- final int HAL_FORMAT_RGB_END = 5; // HAL_PIXEL_FORMAT_BGRA_8888 from graphics.h
int surfaceFormat = SurfaceUtils.getSurfaceFormat(surface);
- if (surfaceFormat >= HAL_FORMAT_RGB_START &&
- surfaceFormat <= HAL_FORMAT_RGB_END) {
- surfaceFormat = ImageFormat.PRIVATE;
- }
if (surfaceFormat != ImageFormat.PRIVATE) {
throw new IllegalArgumentException("Surface format(" + surfaceFormat + ") is not"
diff --git a/core/java/android/net/EventLogTags.logtags b/core/java/android/net/EventLogTags.logtags
new file mode 100644
index 0000000..d5ed014
--- /dev/null
+++ b/core/java/android/net/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.net
+
+50080 ntp_success (server|3),(rtt|2),(offset|2)
+50081 ntp_failure (server|3),(msg|3)
diff --git a/core/java/android/net/INetworkRecommendationProvider.aidl b/core/java/android/net/INetworkRecommendationProvider.aidl
new file mode 100644
index 0000000..5e455d3
--- /dev/null
+++ b/core/java/android/net/INetworkRecommendationProvider.aidl
@@ -0,0 +1,41 @@
+/**
+ * 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.net;
+
+import android.net.RecommendationRequest;
+import android.os.IRemoteCallback;
+
+/**
+ * The service responsible for answering network recommendation requests.
+ * @hide
+ */
+oneway interface INetworkRecommendationProvider {
+
+ /**
+ * Request a recommendation for the best network to connect to
+ * taking into account the inputs from the {@link RecommendationRequest}.
+ *
+ * @param request a {@link RecommendationRequest} instance containing the details of the request
+ * @param callback a {@link IRemoteCallback} instance to invoke when the recommendation
+ * is available
+ * @param sequence an internal number used for tracking the request
+ * @hide
+ */
+ void requestRecommendation(in RecommendationRequest request,
+ in IRemoteCallback callback,
+ int sequence);
+}
\ No newline at end of file
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index 43869264..24f4504 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -17,6 +17,8 @@
package android.net;
import android.net.INetworkScoreCache;
+import android.net.RecommendationRequest;
+import android.net.RecommendationResult;
import android.net.ScoredNetwork;
/**
@@ -54,14 +56,35 @@
void disableScoring();
/**
- * Register a network subsystem for scoring.
+ * Register a cache to receive scoring updates.
+ *
+ * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
+ * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
+ * @param filterType the {@link CacheUpdateFilter} to apply
+ * @throws SecurityException if the caller is not the system
+ * @throws IllegalArgumentException if a score cache is already registed for this type
+ * @hide
+ */
+ void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache, int filterType);
+
+ /**
+ * Unregister a cache to receive scoring updates.
*
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller is not the system.
- * @throws IllegalArgumentException if a score cache is already registed for this type.
* @hide
*/
- void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache);
+ void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache);
+
+ /**
+ * Request a recommendation for the best network to connect to
+ * taking into account the inputs from the {@link RecommendationRequest}.
+ *
+ * @param request a {@link RecommendationRequest} instance containing the details of the request
+ * @return a {@link RecommendationResult} containing the recommended network to connect to
+ * @throws SecurityException if the caller is not the system
+ */
+ RecommendationResult requestRecommendation(in RecommendationRequest request);
}
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
new file mode 100644
index 0000000..cd2ede8
--- /dev/null
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -0,0 +1,114 @@
+package android.net;
+
+import android.annotation.SystemApi;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IRemoteCallback;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * The base class for implementing a network recommendation provider.
+ * @hide
+ */
+@SystemApi
+public abstract class NetworkRecommendationProvider {
+ private static final String TAG = "NetworkRecProvider";
+ /** The key into the callback Bundle where the RecommendationResult will be found. */
+ public static final String EXTRA_RECOMMENDATION_RESULT =
+ "android.net.extra.RECOMMENDATION_RESULT";
+ /** The key into the callback Bundle where the sequence will be found. */
+ public static final String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
+ private static final String EXTRA_RECOMMENDATION_REQUEST =
+ "android.net.extra.RECOMMENDATION_REQUEST";
+ private final IBinder mService;
+
+ /**
+ * Constructs a new instance.
+ * @param handler indicates which thread to use when handling requests. Cannot be {@code null}.
+ */
+ public NetworkRecommendationProvider(Handler handler) {
+ if (handler == null) {
+ throw new IllegalArgumentException("The provided handler cannot be null.");
+ }
+ mService = new ServiceWrapper(new ServiceHandler(handler.getLooper()));
+ }
+
+ /**
+ * Invoked when a recommendation has been requested.
+ *
+ * @param request a {@link RecommendationRequest} instance containing additional
+ * request details
+ * @return a {@link RecommendationResult} instance containing the recommended
+ * network to connect to
+ */
+ public abstract RecommendationResult onRequestRecommendation(RecommendationRequest request);
+
+
+ /**
+ * Services that can handle {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS} should
+ * return this Binder from their <code>onBind()</code> method.
+ */
+ public final IBinder getBinder() {
+ return mService;
+ }
+
+ private final class ServiceHandler extends Handler {
+ static final int MSG_GET_RECOMMENDATION = 1;
+
+ ServiceHandler(Looper looper) {
+ super(looper, null /*callback*/, true /*async*/);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ final int what = msg.what;
+ switch (what) {
+ case MSG_GET_RECOMMENDATION:
+ final IRemoteCallback callback = (IRemoteCallback) msg.obj;
+ final int seq = msg.arg1;
+ final RecommendationRequest request =
+ msg.getData().getParcelable(EXTRA_RECOMMENDATION_REQUEST);
+ final RecommendationResult result = onRequestRecommendation(request);
+ final Bundle data = new Bundle();
+ data.putInt(EXTRA_SEQUENCE, seq);
+ data.putParcelable(EXTRA_RECOMMENDATION_RESULT, result);
+ try {
+ callback.sendResult(data);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Callback failed for seq: " + seq, e);
+ }
+
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown message: " + what);
+ }
+ }
+ }
+
+ /**
+ * A wrapper around INetworkRecommendationProvider that sends calls to the internal Handler.
+ */
+ private static final class ServiceWrapper extends INetworkRecommendationProvider.Stub {
+ private final Handler mHandler;
+
+ ServiceWrapper(Handler handler) {
+ mHandler = handler;
+ }
+
+ @Override
+ public void requestRecommendation(RecommendationRequest request, IRemoteCallback callback,
+ int sequence) throws RemoteException {
+ final Message msg = mHandler.obtainMessage(
+ ServiceHandler.MSG_GET_RECOMMENDATION, sequence, 0 /*arg2*/, callback);
+ final Bundle data = new Bundle();
+ data.putParcelable(EXTRA_RECOMMENDATION_REQUEST, request);
+ msg.setData(data);
+ msg.sendToTarget();
+ }
+ }
+}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index a0f74ec..865b8dd 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -17,6 +17,7 @@
package android.net;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -28,6 +29,9 @@
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.UserHandle;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Class that manages communication between network subsystems and a network scorer.
*
@@ -117,12 +121,43 @@
public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
/**
+ * Service action: Used to discover and bind to a network recommendation provider.
+ * Implementations should return {@link NetworkRecommendationProvider#getBinder()} from
+ * their <code>onBind()</code> method.
+ */
+ @SdkConstant(SdkConstantType.SERVICE_ACTION)
+ public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
+
+ /**
* Extra used with {@link #ACTION_SCORER_CHANGED} to specify the newly selected scorer's package
* name. Will be null if scoring was disabled. Can be obtained with
* {@link android.content.Intent#getStringExtra(String)}.
*/
public static final String EXTRA_NEW_SCORER = "newScorer";
+ /** @hide */
+ @IntDef({CACHE_FILTER_NONE, CACHE_FILTER_CURRENT_NETWORK, CACHE_FILTER_SCAN_RESULTS})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CacheUpdateFilter {}
+
+ /**
+ * Do not filter updates sent to the cache.
+ * @hide
+ */
+ public static final int CACHE_FILTER_NONE = 0;
+
+ /**
+ * Only send cache updates when the network matches the connected network.
+ * @hide
+ */
+ public static final int CACHE_FILTER_CURRENT_NETWORK = 1;
+
+ /**
+ * Only send cache updates when the network is part of the current scan result set.
+ * @hide
+ */
+ public static final int CACHE_FILTER_SCAN_RESULTS = 2;
+
private final Context mContext;
private final INetworkScoreService mService;
@@ -260,11 +295,65 @@
* @throws SecurityException if the caller does not hold the
* {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
+ * @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE.
* @hide
*/
+ @Deprecated // migrate to registerNetworkScoreCache(int, INetworkScoreCache, int)
public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+ registerNetworkScoreCache(networkType, scoreCache, CACHE_FILTER_NONE);
+ }
+
+ /**
+ * Register a network score cache.
+ *
+ * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
+ * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
+ * @param filterType the {@link CacheUpdateFilter} to apply
+ * @throws SecurityException if the caller does not hold the
+ * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * @throws IllegalArgumentException if a score cache is already registered for this type.
+ * @hide
+ */
+ public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache,
+ @CacheUpdateFilter int filterType) {
try {
- mService.registerNetworkScoreCache(networkType, scoreCache);
+ mService.registerNetworkScoreCache(networkType, scoreCache, filterType);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unregister a network score cache.
+ *
+ * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
+ * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
+ * @throws SecurityException if the caller does not hold the
+ * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * @throws IllegalArgumentException if a score cache is already registered for this type.
+ * @hide
+ */
+ public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+ try {
+ mService.unregisterNetworkScoreCache(networkType, scoreCache);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Request a recommendation for which network to connect to.
+ *
+ * @param request a {@link RecommendationRequest} instance containing additional
+ * request details
+ * @return a {@link RecommendationResult} instance containing the recommended network
+ * to connect to
+ * @throws SecurityException
+ */
+ public RecommendationResult requestRecommendation(RecommendationRequest request)
+ throws SecurityException {
+ try {
+ return mService.requestRecommendation(request);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/net/RecommendationRequest.aidl b/core/java/android/net/RecommendationRequest.aidl
new file mode 100644
index 0000000..76497b8
--- /dev/null
+++ b/core/java/android/net/RecommendationRequest.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.net;
+
+parcelable RecommendationRequest;
diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java
new file mode 100644
index 0000000..05ca1aa
--- /dev/null
+++ b/core/java/android/net/RecommendationRequest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.net;
+
+
+import android.annotation.SystemApi;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A request for a network recommendation.
+ *
+ * @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}.
+ * @hide
+ */
+@SystemApi
+public final class RecommendationRequest implements Parcelable {
+ private final ScanResult[] mScanResults;
+ private final WifiConfiguration mCurrentSelectedConfig;
+ private final NetworkCapabilities mRequiredCapabilities;
+
+ /**
+ * Builder class for constructing {@link RecommendationRequest} instances.
+ * @hide
+ */
+ public static final class Builder {
+ private ScanResult[] mScanResults;
+ private WifiConfiguration mCurrentConfig;
+ private NetworkCapabilities mNetworkCapabilities;
+
+ public Builder setScanResults(ScanResult[] scanResults) {
+ mScanResults = scanResults;
+ return this;
+ }
+
+ public Builder setCurrentRecommendedWifiConfig(WifiConfiguration config) {
+ this.mCurrentConfig = config;
+ return this;
+ }
+
+ public Builder setNetworkCapabilities(NetworkCapabilities capabilities) {
+ mNetworkCapabilities = capabilities;
+ return this;
+ }
+
+ public RecommendationRequest build() {
+ return new RecommendationRequest(mScanResults, mCurrentConfig, mNetworkCapabilities);
+ }
+ }
+
+ /**
+ * @return the array of {@link ScanResult}s the recommendation must be constrained to i.e. if a
+ * non-null wifi config recommendation is returned then it must be able to connect to
+ * one of the networks in the results list.
+ *
+ * If the array is {@code null} or empty then there is no constraint.
+ */
+ public ScanResult[] getScanResults() {
+ return mScanResults;
+ }
+
+ /**
+ * @return The best recommendation at the time this {@code RecommendationRequest} instance
+ * was created. This may be null which indicates that no recommendation is available.
+ */
+ public WifiConfiguration getCurrentSelectedConfig() {
+ return mCurrentSelectedConfig;
+ }
+
+ /**
+ *
+ * @return The set of {@link NetworkCapabilities} the recommendation must be constrained to.
+ * This may be {@code null} which indicates that there are no constraints on the
+ * capabilities of the recommended network.
+ */
+ public NetworkCapabilities getRequiredCapabilities() {
+ return mRequiredCapabilities;
+ }
+
+ @VisibleForTesting
+ RecommendationRequest(ScanResult[] scanResults,
+ WifiConfiguration currentSelectedConfig,
+ NetworkCapabilities requiredCapabilities) {
+ mScanResults = scanResults;
+ mCurrentSelectedConfig = currentSelectedConfig;
+ mRequiredCapabilities = requiredCapabilities;
+ }
+
+ protected RecommendationRequest(Parcel in) {
+ mScanResults = (ScanResult[]) in.readParcelableArray(ScanResult.class.getClassLoader());
+ mCurrentSelectedConfig = in.readParcelable(WifiConfiguration.class.getClassLoader());
+ mRequiredCapabilities = in.readParcelable(NetworkCapabilities.class.getClassLoader());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelableArray(mScanResults, flags);
+ dest.writeParcelable(mCurrentSelectedConfig, flags);
+ dest.writeParcelable(mRequiredCapabilities, flags);
+ }
+
+ public static final Creator<RecommendationRequest> CREATOR =
+ new Creator<RecommendationRequest>() {
+ @Override
+ public RecommendationRequest createFromParcel(Parcel in) {
+ return new RecommendationRequest(in);
+ }
+
+ @Override
+ public RecommendationRequest[] newArray(int size) {
+ return new RecommendationRequest[size];
+ }
+ };
+}
diff --git a/core/java/android/net/RecommendationResult.aidl b/core/java/android/net/RecommendationResult.aidl
new file mode 100644
index 0000000..f36995b
--- /dev/null
+++ b/core/java/android/net/RecommendationResult.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.net;
+
+parcelable RecommendationResult;
diff --git a/core/java/android/net/RecommendationResult.java b/core/java/android/net/RecommendationResult.java
new file mode 100644
index 0000000..a330d84
--- /dev/null
+++ b/core/java/android/net/RecommendationResult.java
@@ -0,0 +1,75 @@
+/*
+ * 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.net;
+
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.net.wifi.WifiConfiguration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * The result of a network recommendation.
+ *
+ * @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}.
+ * @hide
+ */
+@SystemApi
+public final class RecommendationResult implements Parcelable {
+ private final WifiConfiguration mWifiConfiguration;
+
+ public RecommendationResult(@Nullable WifiConfiguration wifiConfiguration) {
+ mWifiConfiguration = wifiConfiguration;
+ }
+
+ private RecommendationResult(Parcel in) {
+ mWifiConfiguration = in.readParcelable(WifiConfiguration.class.getClassLoader());
+ }
+
+ /**
+ * @return The recommended {@link WifiConfiguration} to connect to. A {@code null} value
+ * indicates that no WiFi connection should be attempted at this time.
+ */
+ public WifiConfiguration getWifiConfiguration() {
+ return mWifiConfiguration;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(mWifiConfiguration, flags);
+ }
+
+ public static final Creator<RecommendationResult> CREATOR =
+ new Creator<RecommendationResult>() {
+ @Override
+ public RecommendationResult createFromParcel(Parcel in) {
+ return new RecommendationResult(in);
+ }
+
+ @Override
+ public RecommendationResult[] newArray(int size) {
+ return new RecommendationResult[size];
+ }
+ };
+}
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 8582150..0f3f957 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.SystemApi;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,6 +30,20 @@
*/
@SystemApi
public class ScoredNetwork implements Parcelable {
+ /**
+ * Extra used with {@link #attributes} to specify whether the
+ * network is believed to have a captive portal.
+ * <p>
+ * This data may be used, for example, to display a visual indicator
+ * in a network selection list.
+ * <p>
+ * Note that the this extra conveys the possible presence of a
+ * captive portal, not its state or the user's ability to open
+ * the portal.
+ * <p>
+ * If no value is associated with this key then it's unknown.
+ */
+ public static final String EXTRA_HAS_CAPTIVE_PORTAL = "android.net.extra.HAS_CAPTIVE_PORTAL";
/** A {@link NetworkKey} uniquely identifying this network. */
public final NetworkKey networkKey;
@@ -53,6 +68,14 @@
public final boolean meteredHint;
/**
+ * An additional collection of optional attributes set by
+ * the Network Recommendation Provider.
+ *
+ * @see #EXTRA_HAS_CAPTIVE_PORTAL
+ */
+ public final Bundle attributes;
+
+ /**
* Construct a new {@link ScoredNetwork}.
*
* @param networkKey the {@link NetworkKey} uniquely identifying this network.
@@ -81,9 +104,29 @@
* metered.
*/
public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve, boolean meteredHint) {
+ this(networkKey, rssiCurve, false /* meteredHint */, null /* attributes */);
+ }
+
+ /**
+ * Construct a new {@link ScoredNetwork}.
+ *
+ * @param networkKey the {@link NetworkKey} uniquely identifying this network
+ * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
+ * RSSI. This field is optional, and may be skipped to represent a network which the scorer
+ * has opted not to score at this time. Passing a null value here is strongly preferred to
+ * not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
+ * indicates to the system not to request scores for this network in the future, although
+ * the scorer may choose to issue an out-of-band update at any time.
+ * @param meteredHint a boolean value indicating whether or not the network is believed to be
+ * metered
+ * @param attributes optional provider specific attributes
+ */
+ public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve, boolean meteredHint,
+ Bundle attributes) {
this.networkKey = networkKey;
this.rssiCurve = rssiCurve;
this.meteredHint = meteredHint;
+ this.attributes = attributes;
}
private ScoredNetwork(Parcel in) {
@@ -94,6 +137,7 @@
rssiCurve = null;
}
meteredHint = in.readByte() != 0;
+ attributes = in.readBundle();
}
@Override
@@ -111,6 +155,8 @@
out.writeByte((byte) 0);
}
out.writeByte((byte) (meteredHint ? 1 : 0));
+ out.writeBundle(attributes);
+
}
@Override
@@ -121,19 +167,24 @@
ScoredNetwork that = (ScoredNetwork) o;
return Objects.equals(networkKey, that.networkKey)
- && Objects.equals(rssiCurve, that.rssiCurve)
- && Objects.equals(meteredHint, that.meteredHint);
+ && Objects.equals(rssiCurve, that.rssiCurve)
+ && Objects.equals(meteredHint, that.meteredHint)
+ && Objects.equals(attributes, that.attributes);
}
@Override
public int hashCode() {
- return Objects.hash(networkKey, rssiCurve, meteredHint);
+ return Objects.hash(networkKey, rssiCurve, meteredHint, attributes);
}
@Override
public String toString() {
- return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve
- + ",meteredHint=" + meteredHint + "]";
+ return "ScoredNetwork{" +
+ "networkKey=" + networkKey +
+ ", rssiCurve=" + rssiCurve +
+ ", meteredHint=" + meteredHint +
+ ", attributes=" + attributes +
+ '}';
}
public static final Parcelable.Creator<ScoredNetwork> CREATOR =
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index cf9243f..cea56b5 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -36,8 +36,7 @@
* }
* </pre>
*/
-public class SntpClient
-{
+public class SntpClient {
private static final String TAG = "SntpClient";
private static final boolean DBG = true;
@@ -88,6 +87,7 @@
try {
address = InetAddress.getByName(host);
} catch (Exception e) {
+ EventLogTags.writeNtpFailure(host, e.toString());
if (DBG) Log.d(TAG, "request time failed: " + e);
return false;
}
@@ -142,6 +142,7 @@
// = (transit + skew - transit + skew)/2
// = (2 * skew)/2 = skew
long clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2;
+ EventLogTags.writeNtpSuccess(address.toString(), roundTripTime, clockOffset);
if (DBG) {
Log.d(TAG, "round trip: " + roundTripTime + "ms, " +
"clock offset: " + clockOffset + "ms");
@@ -153,6 +154,7 @@
mNtpTimeReference = responseTicks;
mRoundTripTime = roundTripTime;
} catch (Exception e) {
+ EventLogTags.writeNtpFailure(address.toString(), e.toString());
if (DBG) Log.d(TAG, "request time failed: " + e);
return false;
} finally {
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index 3b3fa69..0667495 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -42,6 +42,15 @@
public static final int NETWORK_DISCONNECTED = 7;
/** {@hide} */
+ public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8;
+ /** {@hide} */
+ public static final int NETWORK_REVALIDATION_SUCCESS = 9;
+ /** {@hide} */
+ public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10;
+ /** {@hide} */
+ public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11;
+
+ /** {@hide} */
@IntDef(value = {
NETWORK_CONNECTED,
NETWORK_VALIDATED,
@@ -50,6 +59,10 @@
NETWORK_LINGER,
NETWORK_UNLINGER,
NETWORK_DISCONNECTED,
+ NETWORK_FIRST_VALIDATION_SUCCESS,
+ NETWORK_REVALIDATION_SUCCESS,
+ NETWORK_FIRST_VALIDATION_PORTAL_FOUND,
+ NETWORK_REVALIDATION_PORTAL_FOUND,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventType {}
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 1a31b56..a724ec1 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -44,10 +44,8 @@
public static final int DNS_FAILURE = 0;
public static final int DNS_SUCCESS = 1;
- /** {@hide} */
- @IntDef(value = {PROBE_DNS, PROBE_HTTP, PROBE_HTTPS, PROBE_PAC})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ProbeType {}
+ private static final int FIRST_VALIDATION = 1 << 8;
+ private static final int REVALIDATION = 2 << 8;
/** {@hide} */
@IntDef(value = {DNS_FAILURE, DNS_SUCCESS})
@@ -56,12 +54,17 @@
public final int netId;
public final long durationMs;
- public final @ProbeType int probeType;
+ // probeType byte format (MSB to LSB):
+ // byte 0: unused
+ // byte 1: unused
+ // byte 2: 0 = UNKNOWN, 1 = FIRST_VALIDATION, 2 = REVALIDATION
+ // byte 3: PROBE_* constant
+ public final int probeType;
public final @ReturnCode int returnCode;
/** {@hide} */
public ValidationProbeEvent(
- int netId, long durationMs, @ProbeType int probeType, @ReturnCode int returnCode) {
+ int netId, long durationMs, int probeType, @ReturnCode int returnCode) {
this.netId = netId;
this.durationMs = durationMs;
this.probeType = probeType;
@@ -100,8 +103,18 @@
};
/** @hide */
+ public static int makeProbeType(int probeType, boolean firstValidation) {
+ return (probeType & 0xff) | (firstValidation ? FIRST_VALIDATION : REVALIDATION);
+ }
+
+ /** @hide */
public static String getProbeName(int probeType) {
- return Decoder.constants.get(probeType, "PROBE_???");
+ return Decoder.constants.get(probeType & 0xff, "PROBE_???");
+ }
+
+ /** @hide */
+ public static String getValidationStage(int probeType) {
+ return Decoder.constants.get(probeType & 0xff00, "UNKNOWN");
}
public static void logEvent(int netId, long durationMs, int probeType, int returnCode) {
@@ -109,12 +122,13 @@
@Override
public String toString() {
- return String.format("ValidationProbeEvent(%d, %s:%d, %dms)",
- netId, getProbeName(probeType), returnCode, durationMs);
+ return String.format("ValidationProbeEvent(%d, %s:%d %s, %dms)", netId,
+ getProbeName(probeType), returnCode, getValidationStage(probeType), durationMs);
}
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
- new Class[]{ValidationProbeEvent.class}, new String[]{"PROBE_"});
+ new Class[]{ValidationProbeEvent.class},
+ new String[]{"PROBE_", "FIRST_", "REVALIDATION"});
}
}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 9dafe29..d443b66 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -87,4 +87,6 @@
in String[] disallowedPackages);
boolean isUserUnlockingOrUnlocked(int userId);
int getManagedProfileBadge(int userId);
+ boolean isUserUnlocked(int userId);
+ boolean isUserRunning(int userId);
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 85f999b..e15f086a 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1297,6 +1297,29 @@
}
/**
+ * Flatten a {@code List} containing arbitrary {@code Parcelable} objects into this parcel
+ * at the current position. They can later be retrieved using
+ * {@link #readParcelableList(List, ClassLoader)} if required.
+ *
+ * @see #readParcelableList(List, ClassLoader)
+ * @hide
+ */
+ public final <T extends Parcelable> void writeParcelableList(List<T> val, int flags) {
+ if (val == null) {
+ writeInt(-1);
+ return;
+ }
+
+ int N = val.size();
+ int i=0;
+ writeInt(N);
+ while (i < N) {
+ writeParcelable(val.get(i), flags);
+ i++;
+ }
+ }
+
+ /**
* Flatten a heterogeneous array containing a particular object type into
* the parcel, at
* the current dataPosition() and growing dataCapacity() if needed. The
@@ -2244,9 +2267,6 @@
* Read into the given List items IBinder objects that were written with
* {@link #writeBinderList} at the current dataPosition().
*
- * @return A newly created ArrayList containing strings with the same data
- * as those that were previously written.
- *
* @see #writeBinderList
*/
public final void readBinderList(List<IBinder> list) {
@@ -2265,6 +2285,34 @@
}
/**
+ * Read the list of {@code Parcelable} objects at the current data position into the
+ * given {@code list}. The contents of the {@code list} are replaced. If the serialized
+ * list was {@code null}, {@code list} is cleared.
+ *
+ * @see #writeParcelableList(List, int)
+ * @hide
+ */
+ public final <T extends Parcelable> void readParcelableList(List<T> list, ClassLoader cl) {
+ final int N = readInt();
+ if (N == -1) {
+ list.clear();
+ return;
+ }
+
+ final int M = list.size();
+ int i = 0;
+ for (; i < M && i < N; i++) {
+ list.set(i, (T) readParcelable(cl));
+ }
+ for (; i<N; i++) {
+ list.add((T) readParcelable(cl));
+ }
+ for (; i<M; i++) {
+ list.remove(N);
+ }
+ }
+
+ /**
* Read and return a new array containing a particular object type from
* the parcel at the current dataPosition(). Returns null if the
* previously written array was null. The array <em>must</em> have
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index f2519be..fd0970e 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1474,9 +1474,6 @@
if (violations == null) {
violations = new ArrayList<ViolationInfo>(1);
gatheredViolations.set(violations);
- } else if (violations.size() >= 5) {
- // Too many. In a loop or something? Don't gather them all.
- return;
}
for (ViolationInfo previous : violations) {
if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
@@ -1990,18 +1987,14 @@
if (violations == null) {
p.writeInt(0);
} else {
- p.writeInt(violations.size());
- for (int i = 0; i < violations.size(); ++i) {
- int start = p.dataPosition();
- violations.get(i).writeToParcel(p, 0 /* unused flags? */);
- int size = p.dataPosition()-start;
- if (size > 10*1024) {
- Slog.d(TAG, "Wrote violation #" + i + " of " + violations.size() + ": "
- + (p.dataPosition()-start) + " bytes");
- }
+ // To avoid taking up too much transaction space, only include
+ // details for the first 3 violations. Deep inside, CrashInfo
+ // will truncate each stack trace to ~20kB.
+ final int size = Math.min(violations.size(), 3);
+ p.writeInt(size);
+ for (int i = 0; i < size; i++) {
+ violations.get(i).writeToParcel(p, 0);
}
- if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
- violations.clear(); // somewhat redundant, as we're about to null the threadlocal
}
gatheredViolations.set(null);
}
@@ -2015,40 +2008,19 @@
/* package */ static void readAndHandleBinderCallViolations(Parcel p) {
// Our own stack trace to append
StringWriter sw = new StringWriter();
+ sw.append("# via Binder call with stack:\n");
PrintWriter pw = new FastPrintWriter(sw, false, 256);
new LogStackTrace().printStackTrace(pw);
pw.flush();
String ourStack = sw.toString();
- int policyMask = getThreadPolicyMask();
- boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
+ final int policyMask = getThreadPolicyMask();
+ final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
- int numViolations = p.readInt();
- for (int i = 0; i < numViolations; ++i) {
- if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i);
- ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
- if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 30000) {
- String front = info.crashInfo.stackTrace.substring(0, 256);
- // 30000 characters is way too large for this to be any sane kind of
- // strict mode collection of stacks. We've had a problem where we leave
- // strict mode violations associated with the thread, and it keeps tacking
- // more and more stacks on to the violations. Looks like we're in this casse,
- // so we'll report it and bail on all of the current strict mode violations
- // we currently are maintaining for this thread.
- // First, drain the remaining violations from the parcel.
- i++; // Skip the current entry.
- for (; i < numViolations; i++) {
- info = new ViolationInfo(p, !currentlyGathering);
- }
- // Next clear out all gathered violations.
- clearGatheredViolations();
- // Now report the problem.
- Slog.wtfStack(TAG, "Stack is too large: numViolations=" + numViolations
- + " policy=#" + Integer.toHexString(policyMask)
- + " front=" + front);
- return;
- }
- info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack;
+ final int size = p.readInt();
+ for (int i = 0; i < size; i++) {
+ final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
+ info.crashInfo.appendStackTrace(ourStack);
BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
if (policy instanceof AndroidBlockGuardPolicy) {
((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
@@ -2391,7 +2363,7 @@
* @hide
*/
public static class ViolationInfo implements Parcelable {
- public String message;
+ public final String message;
/**
* Stack and other stuff info.
@@ -2450,6 +2422,7 @@
* Create an uninitialized instance of ViolationInfo
*/
public ViolationInfo() {
+ message = null;
crashInfo = null;
policy = 0;
}
@@ -2496,7 +2469,9 @@
@Override
public int hashCode() {
int result = 17;
- result = 37 * result + crashInfo.stackTrace.hashCode();
+ if (crashInfo != null) {
+ result = 37 * result + crashInfo.stackTrace.hashCode();
+ }
if (numAnimationsRunning != 0) {
result *= 37;
}
@@ -2526,7 +2501,11 @@
*/
public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
message = in.readString();
- crashInfo = new ApplicationErrorReport.CrashInfo(in);
+ if (in.readInt() != 0) {
+ crashInfo = new ApplicationErrorReport.CrashInfo(in);
+ } else {
+ crashInfo = null;
+ }
int rawPolicy = in.readInt();
if (unsetGatheringBit) {
policy = rawPolicy & ~PENALTY_GATHER;
@@ -2548,7 +2527,12 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(message);
- crashInfo.writeToParcel(dest, flags);
+ if (crashInfo != null) {
+ dest.writeInt(1);
+ crashInfo.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
int start = dest.dataPosition();
dest.writeInt(policy);
dest.writeInt(durationMillis);
@@ -2576,7 +2560,9 @@
* Dump a ViolationInfo instance to a Printer.
*/
public void dump(Printer pw, String prefix) {
- crashInfo.dump(pw, prefix);
+ if (crashInfo != null) {
+ crashInfo.dump(pw, prefix);
+ }
pw.println(prefix + "policy: " + policy);
if (durationMillis != -1) {
pw.println(prefix + "durationMillis: " + durationMillis);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a79b0c4..0d3b328 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -187,6 +187,8 @@
* Specifies if a user is disallowed from configuring bluetooth.
* This does <em>not</em> restrict the user from turning bluetooth on or off.
* The default value is <code>false</code>.
+ * <p>This restriction doesn't prevent the user from using bluetooth. For disallowing usage of
+ * bluetooth completely on the device, use {@link #DISALLOW_BLUETOOTH}.
* <p>This restriction has no effect in a managed profile.
*
* <p>Key for user restrictions.
@@ -198,6 +200,20 @@
public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
/**
+ * Specifies if bluetooth is disallowed on the device.
+ *
+ * <p> This restriction can only be set by the device owner and the profile owner on the
+ * primary user and it applies globally - i.e. it disables bluetooth on the entire device.
+ * <p>The default value is <code>false</code>.
+ * <p>Key for user restrictions.
+ * <p>Type: Boolean
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_BLUETOOTH = "no_bluetooth";
+
+ /**
* Specifies if a user is disallowed from transferring files over
* USB. This can only be set by device owners and profile owners on the primary user.
* The default value is <code>false</code>.
@@ -996,10 +1012,9 @@
}
/** {@hide} */
- public boolean isUserRunning(int userId) {
- // TODO Switch to using UMS internal isUserRunning
+ public boolean isUserRunning(@UserIdInt int userId) {
try {
- return ActivityManager.getService().isUserRunning(userId, 0);
+ return mService.isUserRunning(userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -1096,8 +1111,7 @@
/** {@hide} */
public boolean isUserUnlocked(@UserIdInt int userId) {
try {
- return ActivityManager.getService().isUserRunning(userId,
- ActivityManager.FLAG_AND_UNLOCKED);
+ return mService.isUserUnlocked(userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 4bdb92b..1447e7d 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -142,6 +142,12 @@
public abstract boolean isUserUnlockingOrUnlocked(int userId);
/**
+ * Return whether the given user is running in an
+ * {@code UserState.STATE_RUNNING_UNLOCKED} state.
+ */
+ public abstract boolean isUserUnlocked(int userId);
+
+ /**
* Return whether the given user is running
*/
public abstract boolean isUserRunning(int userId);
diff --git a/core/java/android/provider/SearchIndexablesContract.java b/core/java/android/provider/SearchIndexablesContract.java
index 93ac7f6..ff8b9dd 100644
--- a/core/java/android/provider/SearchIndexablesContract.java
+++ b/core/java/android/provider/SearchIndexablesContract.java
@@ -108,6 +108,8 @@
RawData.COLUMN_INTENT_TARGET_CLASS, // 11
RawData.COLUMN_KEY, // 12
RawData.COLUMN_USER_ID, // 13
+ RawData.PAYLOAD_TYPE, // 14
+ RawData.PAYLOAD // 15
};
/**
@@ -127,6 +129,14 @@
public static final int COLUMN_INDEX_RAW_INTENT_TARGET_CLASS = 11;
public static final int COLUMN_INDEX_RAW_KEY = 12;
public static final int COLUMN_INDEX_RAW_USER_ID = 13;
+ /**
+ * @hide
+ */
+ public static final int COLUMN_INDEX_RAW_PAYLOAD_TYPE = 14;
+ /**
+ * @hide
+ */
+ public static final int COLUMN_INDEX_RAW_PAYLOAD = 15;
/**
* Indexable raw data columns.
@@ -213,6 +223,18 @@
* UserId associated with the raw data.
*/
public static final String COLUMN_USER_ID = "user_id";
+
+ /**
+ * Identifier for the Payload object type.
+ * @hide
+ */
+ public static final String PAYLOAD_TYPE = "payload_type";
+
+ /**
+ * Generic payload for improving Search result expressiveness.
+ * @hide
+ */
+ public static final String PAYLOAD = "payload";
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0946906..37222ad 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -44,6 +44,7 @@
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
+import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.IBinder;
@@ -52,7 +53,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.os.Build.VERSION_CODES;
import android.speech.tts.TextToSpeech;
import android.text.TextUtils;
import android.util.AndroidException;
@@ -1321,6 +1321,20 @@
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_WEBVIEW_SETTINGS = "android.settings.WEBVIEW_SETTINGS";
+ /**
+ * Activity Action: Show enterprise privacy section.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS
+ = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
+
// End of Intent actions for Settings
/**
@@ -1566,12 +1580,13 @@
private final Uri mUri;
- private static final String[] SELECT_VALUE =
- new String[] { Settings.NameValueTable.VALUE };
+ private static final String[] SELECT_VALUE_PROJECTION = new String[] {
+ Settings.NameValueTable.VALUE
+ };
private static final String NAME_EQ_PLACEHOLDER = "name=?";
// Must synchronize on 'this' to access mValues and mValuesVersion.
- private final HashMap<String, String> mValues = new HashMap<String, String>();
+ private final HashMap<String, String> mValues = new HashMap<>();
// Initially null; set lazily and held forever. Synchronized on 'this'.
private IContentProvider mContentProvider = null;
@@ -1724,8 +1739,9 @@
Cursor c = null;
try {
- c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE, NAME_EQ_PLACEHOLDER,
- new String[]{name}, null, null);
+ Bundle queryArgs = ContentResolver.createSqlQueryBundle(
+ NAME_EQ_PLACEHOLDER, new String[]{name}, null);
+ c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, null);
if (c == null) {
Log.w(TAG, "Can't get key " + name + " from " + mUri);
return null;
@@ -1793,7 +1809,7 @@
private static final HashSet<String> MOVED_TO_SECURE;
static {
- MOVED_TO_SECURE = new HashSet<String>(30);
+ MOVED_TO_SECURE = new HashSet<>(30);
MOVED_TO_SECURE.add(Secure.ANDROID_ID);
MOVED_TO_SECURE.add(Secure.HTTP_PROXY);
MOVED_TO_SECURE.add(Secure.LOCATION_PROVIDERS_ALLOWED);
@@ -1830,8 +1846,8 @@
private static final HashSet<String> MOVED_TO_GLOBAL;
private static final HashSet<String> MOVED_TO_SECURE_THEN_GLOBAL;
static {
- MOVED_TO_GLOBAL = new HashSet<String>();
- MOVED_TO_SECURE_THEN_GLOBAL = new HashSet<String>();
+ MOVED_TO_GLOBAL = new HashSet<>();
+ MOVED_TO_SECURE_THEN_GLOBAL = new HashSet<>();
// these were originally in system but migrated to secure in the past,
// so are duplicated in the Secure.* namespace
@@ -4149,12 +4165,12 @@
private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
private static final HashSet<String> MOVED_TO_GLOBAL;
static {
- MOVED_TO_LOCK_SETTINGS = new HashSet<String>(3);
+ MOVED_TO_LOCK_SETTINGS = new HashSet<>(3);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_ENABLED);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_VISIBLE);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
- MOVED_TO_GLOBAL = new HashSet<String>();
+ MOVED_TO_GLOBAL = new HashSet<>();
MOVED_TO_GLOBAL.add(Settings.Global.ADB_ENABLED);
MOVED_TO_GLOBAL.add(Settings.Global.ASSISTED_GPS_ENABLED);
MOVED_TO_GLOBAL.add(Settings.Global.BLUETOOTH_ON);
@@ -5189,6 +5205,7 @@
* @hide
* @deprecated
*/
+ @Deprecated
public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE =
"accessibility_display_magnification_auto_update";
@@ -6443,7 +6460,7 @@
* @hide
*/
public static final String DOWNLOADS_BACKUP_ENABLED = "downloads_backup_enabled";
-
+
/**
* Whether Downloads folder backup should only occur if the device is using a metered
* network.
@@ -7741,6 +7758,26 @@
public static final String WIFI_SCAN_ALWAYS_AVAILABLE =
"wifi_scan_always_enabled";
+ /**
+ * Value to specify if Wi-Fi Wakeup feature is enabled.
+ *
+ * Type: int (0 for false, 1 for true)
+ * @hide
+ */
+ @SystemApi
+ public static final String WIFI_WAKEUP_ENABLED = "wifi_wakeup_enabled";
+
+ /**
+ * Value to specify if network recommendations from
+ * {@link com.android.server.NetworkScoreService} are enabled.
+ *
+ * Type: int (0 for false, 1 for true)
+ * @hide
+ */
+ @SystemApi
+ public static final String NETWORK_RECOMMENDATIONS_ENABLED =
+ "network_recommendations_enabled";
+
/**
* Settings to allow BLE scans to be enabled even when Bluetooth is turned off for
* connectivity.
@@ -9105,7 +9142,7 @@
// Certain settings have been moved from global to the per-user secure namespace
private static final HashSet<String> MOVED_TO_SECURE;
static {
- MOVED_TO_SECURE = new HashSet<String>(1);
+ MOVED_TO_SECURE = new HashSet<>(1);
MOVED_TO_SECURE.add(Settings.Global.INSTALL_NON_MARKET_APPS);
}
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 4b272e9..7af93c2 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -15,8 +15,7 @@
*/
package android.service.notification;
-import android.annotation.SystemApi;
-import android.net.Uri;
+import android.app.NotificationChannel;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,33 +26,39 @@
public final class Adjustment implements Parcelable {
private final String mPackage;
private final String mKey;
- private final int mImportance;
private final CharSequence mExplanation;
- private final Uri mReference;
private final Bundle mSignals;
private final int mUser;
/**
+ * Data type: {@code String}. See {@link NotificationChannel#getId()}.
+ */
+ public static final String KEY_CHANNEL_ID = "key_channel_id";
+ /**
+ * Data type: ArrayList of {@code String}, where each is a representation of a
+ * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}.
+ * See {@link android.app.Notification.Builder#addPerson(String)}.
+ */
+ public static final String KEY_PEOPLE = "key_people";
+ /**
+ * Parcelable {@code ArrayList} of {@link SnoozeCriterion}.
+ */
+ public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
+
+ /**
* Create a notification adjustment.
*
* @param pkg The package of the notification.
* @param key The notification key.
- * @param importance The recommended importance of the notification.
- * @param signals A bundle of signals that should inform notification grouping and ordering.
+ * @param signals A bundle of signals that should inform notification display, ordering, and
+ * interruptiveness.
* @param explanation A human-readable justification for the adjustment.
- * @param reference A reference to an external object that augments the
- * explanation, such as a
- * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI},
- * or null.
*/
- public Adjustment(String pkg, String key, int importance, Bundle signals,
- CharSequence explanation, Uri reference, int user) {
+ public Adjustment(String pkg, String key, Bundle signals, CharSequence explanation, int user) {
mPackage = pkg;
mKey = key;
- mImportance = importance;
mSignals = signals;
mExplanation = explanation;
- mReference = reference;
mUser = user;
}
@@ -68,13 +73,11 @@
} else {
mKey = null;
}
- mImportance = in.readInt();
if (in.readInt() == 1) {
mExplanation = in.readCharSequence();
} else {
mExplanation = null;
}
- mReference = in.readParcelable(Uri.class.getClassLoader());
mSignals = in.readBundle();
mUser = in.readInt();
}
@@ -99,18 +102,10 @@
return mKey;
}
- public int getImportance() {
- return mImportance;
- }
-
public CharSequence getExplanation() {
return mExplanation;
}
- public Uri getReference() {
- return mReference;
- }
-
public Bundle getSignals() {
return mSignals;
}
@@ -138,14 +133,12 @@
} else {
dest.writeInt(0);
}
- dest.writeInt(mImportance);
if (mExplanation != null) {
dest.writeInt(1);
dest.writeCharSequence(mExplanation);
} else {
dest.writeInt(0);
}
- dest.writeParcelable(mReference, flags);
dest.writeBundle(mSignals);
dest.writeInt(mUser);
}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 37674a6..1bc605f 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -16,11 +16,11 @@
package android.service.notification;
+import android.app.NotificationChannel;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.annotation.SdkConstant;
import android.app.INotificationManager;
@@ -49,8 +49,7 @@
import android.widget.RemoteViews;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.SomeArgs;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -1112,7 +1111,10 @@
}
}
- private void applyUpdateLocked(NotificationRankingUpdate update) {
+ /**
+ * @hide
+ */
+ public final void applyUpdateLocked(NotificationRankingUpdate update) {
mRankingMap = new RankingMap(update);
}
@@ -1148,6 +1150,12 @@
private CharSequence mImportanceExplanation;
// System specified group key.
private String mOverrideGroupKey;
+ // Notification assistant channel override.
+ private NotificationChannel mOverrideChannel;
+ // Notification assistant people override.
+ private ArrayList<String> mOverridePeople;
+ // Notification assistant snooze criteria.
+ private ArrayList<SnoozeCriterion> mSnoozeCriteria;
public Ranking() {}
@@ -1217,7 +1225,7 @@
}
/**
- * If the importance has been overriden by user preference, then this will be non-null,
+ * If the importance has been overridden by user preference, then this will be non-null,
* and should be displayed to the user.
*
* @return the explanation for the importance, or null if it is the natural importance
@@ -1227,16 +1235,44 @@
}
/**
- * If the system has overriden the group key, then this will be non-null, and this
+ * If the system has overridden the group key, then this will be non-null, and this
* key should be used to bundle notifications.
*/
public String getOverrideGroupKey() {
return mOverrideGroupKey;
}
+ /**
+ * If the {@link NotificationAssistantService} has overridden the channel this notification
+ * was posted to, then this will not match the channel provided by the posting application
+ * and this should be used to determine the interruptiveness of the notification instead.
+ */
+ public NotificationChannel getChannel() {
+ return mOverrideChannel;
+ }
+
+ /**
+ * If the {@link NotificationAssistantService} has added people to this notification, then
+ * this will be non-null.
+ */
+ public List<String> getAdditionalPeople() {
+ return mOverridePeople;
+ }
+
+ /**
+ * Returns snooze criteria provided by the {@link NotificationAssistantService}. If your
+ * user interface displays options for snoozing notifications these criteria should be
+ * displayed as well.
+ */
+ public List<SnoozeCriterion> getSnoozeCriteria() {
+ return mSnoozeCriteria;
+ }
+
private void populate(String key, int rank, boolean matchesInterruptionFilter,
int visibilityOverride, int suppressedVisualEffects, int importance,
- CharSequence explanation, String overrideGroupKey) {
+ CharSequence explanation, String overrideGroupKey,
+ NotificationChannel overrideChannel, ArrayList<String> overridePeople,
+ ArrayList<SnoozeCriterion> snoozeCriteria) {
mKey = key;
mRank = rank;
mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW;
@@ -1246,6 +1282,9 @@
mImportance = importance;
mImportanceExplanation = explanation;
mOverrideGroupKey = overrideGroupKey;
+ mOverrideChannel = overrideChannel;
+ mOverridePeople = overridePeople;
+ mSnoozeCriteria = snoozeCriteria;
}
/**
@@ -1289,6 +1328,9 @@
private ArrayMap<String, Integer> mImportance;
private ArrayMap<String, String> mImportanceExplanation;
private ArrayMap<String, String> mOverrideGroupKeys;
+ private ArrayMap<String, NotificationChannel> mOverrideChannels;
+ private ArrayMap<String, ArrayList<String>> mOverridePeople;
+ private ArrayMap<String, ArrayList<SnoozeCriterion>> mSnoozeCriteria;
private RankingMap(NotificationRankingUpdate rankingUpdate) {
mRankingUpdate = rankingUpdate;
@@ -1315,7 +1357,8 @@
int rank = getRank(key);
outRanking.populate(key, rank, !isIntercepted(key),
getVisibilityOverride(key), getSuppressedVisualEffects(key),
- getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key));
+ getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key),
+ getOverrideChannel(key), getOverridePeople(key), getSnoozeCriteria(key));
return rank >= 0;
}
@@ -1395,6 +1438,33 @@
return mOverrideGroupKeys.get(key);
}
+ private NotificationChannel getOverrideChannel(String key) {
+ synchronized (this) {
+ if (mOverrideChannels == null) {
+ buildOverrideChannelsLocked();
+ }
+ }
+ return mOverrideChannels.get(key);
+ }
+
+ private ArrayList<String> getOverridePeople(String key) {
+ synchronized (this) {
+ if (mOverridePeople == null) {
+ buildOverridePeopleLocked();
+ }
+ }
+ return mOverridePeople.get(key);
+ }
+
+ private ArrayList<SnoozeCriterion> getSnoozeCriteria(String key) {
+ synchronized (this) {
+ if (mSnoozeCriteria == null) {
+ buildSnoozeCriteriaLocked();
+ }
+ }
+ return mSnoozeCriteria.get(key);
+ }
+
// Locked by 'this'
private void buildRanksLocked() {
String[] orderedKeys = mRankingUpdate.getOrderedKeys();
@@ -1458,6 +1528,33 @@
}
}
+ // Locked by 'this'
+ private void buildOverrideChannelsLocked() {
+ Bundle overrideChannels = mRankingUpdate.getOverrideChannels();
+ mOverrideChannels = new ArrayMap<>(overrideChannels.size());
+ for (String key : overrideChannels.keySet()) {
+ mOverrideChannels.put(key, overrideChannels.getParcelable(key));
+ }
+ }
+
+ // Locked by 'this'
+ private void buildOverridePeopleLocked() {
+ Bundle overridePeople = mRankingUpdate.getOverridePeople();
+ mOverridePeople = new ArrayMap<>(overridePeople.size());
+ for (String key : overridePeople.keySet()) {
+ mOverridePeople.put(key, overridePeople.getStringArrayList(key));
+ }
+ }
+
+ // Locked by 'this'
+ private void buildSnoozeCriteriaLocked() {
+ Bundle snoozeCriteria = mRankingUpdate.getSnoozeCriteria();
+ mSnoozeCriteria = new ArrayMap<>(snoozeCriteria.size());
+ for (String key : snoozeCriteria.keySet()) {
+ mSnoozeCriteria.put(key, snoozeCriteria.getParcelableArrayList(key));
+ }
+ }
+
// ----------- Parcelable
@Override
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index 788b5c0..a2cdeff 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -31,10 +31,14 @@
private final int[] mImportance;
private final Bundle mImportanceExplanation;
private final Bundle mOverrideGroupKeys;
+ private final Bundle mOverrideChannels;
+ private final Bundle mOverridePeople;
+ private final Bundle mSnoozeCriteria;
public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
Bundle visibilityOverrides, Bundle suppressedVisualEffects,
- int[] importance, Bundle explanation, Bundle overrideGroupKeys) {
+ int[] importance, Bundle explanation, Bundle overrideGroupKeys,
+ Bundle overrideChannels, Bundle overridePeople, Bundle snoozeCriteria) {
mKeys = keys;
mInterceptedKeys = interceptedKeys;
mVisibilityOverrides = visibilityOverrides;
@@ -42,6 +46,9 @@
mImportance = importance;
mImportanceExplanation = explanation;
mOverrideGroupKeys = overrideGroupKeys;
+ mOverrideChannels = overrideChannels;
+ mOverridePeople = overridePeople;
+ mSnoozeCriteria = snoozeCriteria;
}
public NotificationRankingUpdate(Parcel in) {
@@ -53,6 +60,9 @@
in.readIntArray(mImportance);
mImportanceExplanation = in.readBundle();
mOverrideGroupKeys = in.readBundle();
+ mOverrideChannels = in.readBundle();
+ mOverridePeople = in.readBundle();
+ mSnoozeCriteria = in.readBundle();
}
@Override
@@ -69,6 +79,9 @@
out.writeIntArray(mImportance);
out.writeBundle(mImportanceExplanation);
out.writeBundle(mOverrideGroupKeys);
+ out.writeBundle(mOverrideChannels);
+ out.writeBundle(mOverridePeople);
+ out.writeBundle(mSnoozeCriteria);
}
public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -109,4 +122,16 @@
public Bundle getOverrideGroupKeys() {
return mOverrideGroupKeys;
}
+
+ public Bundle getOverrideChannels() {
+ return mOverrideChannels;
+ }
+
+ public Bundle getOverridePeople() {
+ return mOverridePeople;
+ }
+
+ public Bundle getSnoozeCriteria() {
+ return mSnoozeCriteria;
+ }
}
diff --git a/core/java/android/service/notification/SnoozeCriterion.aidl b/core/java/android/service/notification/SnoozeCriterion.aidl
new file mode 100644
index 0000000..9b666d8
--- /dev/null
+++ b/core/java/android/service/notification/SnoozeCriterion.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.service.notification;
+
+parcelable SnoozeCriterion;
\ No newline at end of file
diff --git a/core/java/android/service/notification/SnoozeCriterion.java b/core/java/android/service/notification/SnoozeCriterion.java
new file mode 100644
index 0000000..f37f1ae
--- /dev/null
+++ b/core/java/android/service/notification/SnoozeCriterion.java
@@ -0,0 +1,139 @@
+/*
+ * 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.service.notification;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents an option to be shown to users for snoozing a notification until a given context
+ * instead of for a fixed amount of time.
+ */
+public final class SnoozeCriterion implements Parcelable {
+ private final String mId;
+ private final CharSequence mExplanation;
+ private final CharSequence mConfirmation;
+
+ public SnoozeCriterion(String id, CharSequence explanation, CharSequence confirmation) {
+ mId = id;
+ mExplanation = explanation;
+ mConfirmation = confirmation;
+ }
+
+ protected SnoozeCriterion(Parcel in) {
+ if (in.readByte() != 0) {
+ mId = in.readString();
+ } else {
+ mId = null;
+ }
+ if (in.readByte() != 0) {
+ mExplanation = in.readCharSequence();
+ } else {
+ mExplanation = null;
+ }
+ if (in.readByte() != 0) {
+ mConfirmation = in.readCharSequence();
+ } else {
+ mConfirmation = null;
+ }
+ }
+
+ /**
+ * Returns the id of this criterion.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * Returns the user visible explanation of how long a notification will be snoozed if
+ * this criterion is chosen.
+ */
+ public CharSequence getExplanation() {
+ return mExplanation;
+ }
+
+ /**
+ * Returns the user visible confirmation message shown when this criterion is chosen.
+ */
+ public CharSequence getConfirmation() {
+ return mConfirmation;
+ }
+
+ public static final Creator<SnoozeCriterion> CREATOR = new Creator<SnoozeCriterion>() {
+ @Override
+ public SnoozeCriterion createFromParcel(Parcel in) {
+ return new SnoozeCriterion(in);
+ }
+
+ @Override
+ public SnoozeCriterion[] newArray(int size) {
+ return new SnoozeCriterion[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mId != null) {
+ dest.writeByte((byte) 1);
+ dest.writeString(mId);
+ } else {
+ dest.writeByte((byte) 0);
+ }
+ if (mExplanation != null) {
+ dest.writeByte((byte) 1);
+ dest.writeCharSequence(mExplanation);
+ } else {
+ dest.writeByte((byte) 0);
+ }
+ if (mConfirmation != null) {
+ dest.writeByte((byte) 1);
+ dest.writeCharSequence(mConfirmation);
+ } else {
+ dest.writeByte((byte) 0);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ SnoozeCriterion that = (SnoozeCriterion) o;
+
+ if (mId != null ? !mId.equals(that.mId) : that.mId != null) return false;
+ if (mExplanation != null ? !mExplanation.equals(that.mExplanation)
+ : that.mExplanation != null) {
+ return false;
+ }
+ return mConfirmation != null ? mConfirmation.equals(that.mConfirmation)
+ : that.mConfirmation == null;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mId != null ? mId.hashCode() : 0;
+ result = 31 * result + (mExplanation != null ? mExplanation.hashCode() : 0);
+ result = 31 * result + (mConfirmation != null ? mConfirmation.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index ccaf204..749cf08 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -19,7 +19,6 @@
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
-import android.os.Process;
import libcore.io.IoUtils;
import dalvik.system.CloseGuard;
@@ -37,13 +36,13 @@
* each other.
* <p>
* The data structure is designed to have one owner process that can
- * read/write. There may be multiple client processes that can only read or
- * read/write depending how the data structure was configured when
- * instantiated. The owner process is the process that created the array.
- * The shared memory is pinned (not reclaimed by the system) until the
- * owning process dies or the data structure is closed. This class
- * is <strong>not</strong> thread safe. You should not interact with
- * an instance of this class once it is closed.
+ * read/write. There may be multiple client processes that can only read.
+ * The owner process is the process that created the array. The shared
+ * memory is pinned (not reclaimed by the system) until the owning process
+ * dies or the data structure is closed. This class is <strong>not</strong>
+ * thread safe. You should not interact with an instance of this class
+ * once it is closed. If you pass back to the owner process an instance
+ * it will be read only even in the owning process.
* </p>
*
* @hide
@@ -55,8 +54,7 @@
private final CloseGuard mCloseGuard = CloseGuard.get();
- private final int mOwnerPid;
- private final boolean mClientWritable;
+ private final boolean mIsOwner;
private final long mMemoryAddr;
private int mFd;
@@ -65,35 +63,27 @@
*
* @param size The size of the array in terms of integer slots. Cannot be
* more than {@link #getMaxSize()}.
- * @param clientWritable Whether other processes can write to the array.
* @throws IOException If an error occurs while accessing the shared memory.
*/
- public MemoryIntArray(int size, boolean clientWritable) throws IOException {
+ public MemoryIntArray(int size) throws IOException {
if (size > MAX_SIZE) {
throw new IllegalArgumentException("Max size is " + MAX_SIZE);
}
- mOwnerPid = Process.myPid();
- mClientWritable = clientWritable;
+ mIsOwner = true;
final String name = UUID.randomUUID().toString();
mFd = nativeCreate(name, size);
- mMemoryAddr = nativeOpen(mFd, true, clientWritable);
+ mMemoryAddr = nativeOpen(mFd, mIsOwner);
mCloseGuard.open("close");
}
private MemoryIntArray(Parcel parcel) throws IOException {
- mOwnerPid = parcel.readInt();
- mClientWritable = (parcel.readInt() == 1);
+ mIsOwner = false;
ParcelFileDescriptor pfd = parcel.readParcelable(null);
if (pfd == null) {
throw new IOException("No backing file descriptor");
}
mFd = pfd.detachFd();
- final long memoryAddress = parcel.readLong();
- if (isOwner()) {
- mMemoryAddr = memoryAddress;
- } else {
- mMemoryAddr = nativeOpen(mFd, false, mClientWritable);
- }
+ mMemoryAddr = nativeOpen(mFd, mIsOwner);
mCloseGuard.open("close");
}
@@ -102,7 +92,7 @@
*/
public boolean isWritable() {
enforceNotClosed();
- return isOwner() || mClientWritable;
+ return mIsOwner;
}
/**
@@ -115,7 +105,7 @@
public int get(int index) throws IOException {
enforceNotClosed();
enforceValidIndex(index);
- return nativeGet(mFd, mMemoryAddr, index, isOwner());
+ return nativeGet(mFd, mMemoryAddr, index);
}
/**
@@ -131,7 +121,7 @@
enforceNotClosed();
enforceWritable();
enforceValidIndex(index);
- nativeSet(mFd, mMemoryAddr, index, value, isOwner());
+ nativeSet(mFd, mMemoryAddr, index, value);
}
/**
@@ -152,7 +142,7 @@
@Override
public void close() throws IOException {
if (!isClosed()) {
- nativeClose(mFd, mMemoryAddr, isOwner());
+ nativeClose(mFd, mMemoryAddr, mIsOwner);
mFd = -1;
mCloseGuard.close();
}
@@ -184,11 +174,8 @@
public void writeToParcel(Parcel parcel, int flags) {
ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd);
try {
- parcel.writeInt(mOwnerPid);
- parcel.writeInt(mClientWritable ? 1 : 0);
// Don't let writing to a parcel to close our fd - plz
parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- parcel.writeLong(mMemoryAddr);
} finally {
pfd.detachFd();
}
@@ -214,10 +201,6 @@
return mFd;
}
- private boolean isOwner() {
- return mOwnerPid == Process.myPid();
- }
-
private void enforceNotClosed() {
if (isClosed()) {
throw new IllegalStateException("cannot interact with a closed instance");
@@ -239,10 +222,10 @@
}
private native int nativeCreate(String name, int size);
- private native long nativeOpen(int fd, boolean owner, boolean writable);
+ private native long nativeOpen(int fd, boolean owner);
private native void nativeClose(int fd, long memoryAddr, boolean owner);
- private native int nativeGet(int fd, long memoryAddr, int index, boolean owner);
- private native void nativeSet(int fd, long memoryAddr, int index, int value, boolean owner);
+ private native int nativeGet(int fd, long memoryAddr, int index);
+ private native void nativeSet(int fd, long memoryAddr, int index, int value);
private native int nativeSize(int fd);
/**
@@ -259,8 +242,7 @@
try {
return new MemoryIntArray(parcel);
} catch (IOException ioe) {
- Log.e(TAG, "Error unparceling MemoryIntArray");
- return null;
+ throw new IllegalArgumentException("Error unparceling MemoryIntArray");
}
}
diff --git a/core/java/android/util/jar/StrictJarFile.java b/core/java/android/util/jar/StrictJarFile.java
index d9556aa..bc4a19d 100644
--- a/core/java/android/util/jar/StrictJarFile.java
+++ b/core/java/android/util/jar/StrictJarFile.java
@@ -134,6 +134,7 @@
} catch (IOException | SecurityException e) {
nativeClose(this.nativeHandle);
IoUtils.closeQuietly(fd);
+ closed = true;
throw e;
}
diff --git a/core/java/android/util/jar/StrictJarVerifier.java b/core/java/android/util/jar/StrictJarVerifier.java
index cb71ecc..debc170 100644
--- a/core/java/android/util/jar/StrictJarVerifier.java
+++ b/core/java/android/util/jar/StrictJarVerifier.java
@@ -17,7 +17,7 @@
package android.util.jar;
-import java.io.ByteArrayInputStream;
+import android.util.apk.ApkSignatureSchemeV2Verifier;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
@@ -33,13 +33,9 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
-import android.util.ArraySet;
-import android.util.apk.ApkSignatureSchemeV2Verifier;
-import libcore.io.Base64;
import sun.security.jca.Providers;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
@@ -139,7 +135,7 @@
*/
void verify() {
byte[] d = digest.digest();
- if (!MessageDigest.isEqual(d, Base64.decode(hash))) {
+ if (!verifyMessageDigest(d, hash)) {
throw invalidDigest(JarFile.MANIFEST_NAME, name, name);
}
verifiedEntries.put(name, certChains);
@@ -490,12 +486,22 @@
md.update(data, start, end - start);
}
byte[] b = md.digest();
- byte[] hashBytes = hash.getBytes(StandardCharsets.ISO_8859_1);
- return MessageDigest.isEqual(b, Base64.decode(hashBytes));
+ byte[] encodedHashBytes = hash.getBytes(StandardCharsets.ISO_8859_1);
+ return verifyMessageDigest(b, encodedHashBytes);
}
return ignorable;
}
+ private static boolean verifyMessageDigest(byte[] expected, byte[] encodedActual) {
+ byte[] actual;
+ try {
+ actual = java.util.Base64.getDecoder().decode(encodedActual);
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ return MessageDigest.isEqual(expected, actual);
+ }
+
/**
* Returns all of the {@link java.security.cert.Certificate} chains that
* were used to verify the signature on the JAR entry called
diff --git a/core/java/android/util/proto/ProtoOutputStream.java b/core/java/android/util/proto/ProtoOutputStream.java
index 8f99399..81251fc 100644
--- a/core/java/android/util/proto/ProtoOutputStream.java
+++ b/core/java/android/util/proto/ProtoOutputStream.java
@@ -19,6 +19,10 @@
import android.annotation.TestApi;
import android.util.Log;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
@@ -179,6 +183,11 @@
private EncodedBuffer mBuffer;
/**
+ * Our stream. If there is one.
+ */
+ private OutputStream mStream;
+
+ /**
* Current nesting depth of startObject calls.
*/
private int mDepth;
@@ -226,6 +235,690 @@
mBuffer = new EncodedBuffer(chunkSize);
}
+ /**
+ * Construct a ProtoOutputStream that sits on top of an OutputStream.
+ * @more
+ * The {@link #flush() flush()} method must be called when done writing
+ * to flush any remanining data, althought data *may* be written at intermediate
+ * points within the writing as well.
+ */
+ public ProtoOutputStream(OutputStream stream) {
+ this();
+ mStream = stream;
+ }
+
+ /**
+ * Construct a ProtoOutputStream that sits on top of a FileDescriptor.
+ * @more
+ * The {@link #flush() flush()} method must be called when done writing
+ * to flush any remanining data, althought data *may* be written at intermediate
+ * points within the writing as well.
+ */
+ public ProtoOutputStream(FileDescriptor fd) {
+ this(new FileOutputStream(fd));
+ }
+
+ /**
+ * Write a value for the given fieldId.
+ *
+ * Will automatically convert for the following field types, and
+ * throw an exception for others: double, float, int32, int64, uint32, uint64,
+ * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, double val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // double
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeDoubleImpl(id, (double)val);
+ break;
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedDoubleImpl(id, (double)val);
+ break;
+ // float
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFloatImpl(id, (float)val);
+ break;
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFloatImpl(id, (float)val);
+ break;
+ // int32
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt32Impl(id, (int)val);
+ break;
+ // int64
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt64Impl(id, (long)val);
+ break;
+ // uint32
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt32Impl(id, (int)val);
+ break;
+ // uint64
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt64Impl(id, (long)val);
+ break;
+ // sint32
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt32Impl(id, (int)val);
+ break;
+ // sint64
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt64Impl(id, (long)val);
+ break;
+ // fixed32
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed32Impl(id, (int)val);
+ break;
+ // fixed64
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed64Impl(id, (long)val);
+ break;
+ // sfixed32
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed32Impl(id, (int)val);
+ break;
+ // sfixed64
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed64Impl(id, (long)val);
+ break;
+ // bool
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBoolImpl(id, val != 0);
+ break;
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBoolImpl(id, val != 0);
+ break;
+ // enum
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeEnumImpl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedEnumImpl(id, (int)val);
+ break;
+ // string, bytes, object not allowed here.
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, double) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a value for the given fieldId.
+ *
+ * Will automatically convert for the following field types, and
+ * throw an exception for others: double, float, int32, int64, uint32, uint64,
+ * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, float val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // double
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeDoubleImpl(id, (double)val);
+ break;
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedDoubleImpl(id, (double)val);
+ break;
+ // float
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFloatImpl(id, (float)val);
+ break;
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFloatImpl(id, (float)val);
+ break;
+ // int32
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt32Impl(id, (int)val);
+ break;
+ // int64
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt64Impl(id, (long)val);
+ break;
+ // uint32
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt32Impl(id, (int)val);
+ break;
+ // uint64
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt64Impl(id, (long)val);
+ break;
+ // sint32
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt32Impl(id, (int)val);
+ break;
+ // sint64
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt64Impl(id, (long)val);
+ break;
+ // fixed32
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed32Impl(id, (int)val);
+ break;
+ // fixed64
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed64Impl(id, (long)val);
+ break;
+ // sfixed32
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed32Impl(id, (int)val);
+ break;
+ // sfixed64
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed64Impl(id, (long)val);
+ break;
+ // bool
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBoolImpl(id, val != 0);
+ break;
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBoolImpl(id, val != 0);
+ break;
+ // enum
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeEnumImpl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedEnumImpl(id, (int)val);
+ break;
+ // string, bytes, object not allowed here.
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, float) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a value for the given fieldId.
+ *
+ * Will automatically convert for the following field types, and
+ * throw an exception for others: double, float, int32, int64, uint32, uint64,
+ * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, int val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // double
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeDoubleImpl(id, (double)val);
+ break;
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedDoubleImpl(id, (double)val);
+ break;
+ // float
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFloatImpl(id, (float)val);
+ break;
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFloatImpl(id, (float)val);
+ break;
+ // int32
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt32Impl(id, (int)val);
+ break;
+ // int64
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt64Impl(id, (long)val);
+ break;
+ // uint32
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt32Impl(id, (int)val);
+ break;
+ // uint64
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt64Impl(id, (long)val);
+ break;
+ // sint32
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt32Impl(id, (int)val);
+ break;
+ // sint64
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt64Impl(id, (long)val);
+ break;
+ // fixed32
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed32Impl(id, (int)val);
+ break;
+ // fixed64
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed64Impl(id, (long)val);
+ break;
+ // sfixed32
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed32Impl(id, (int)val);
+ break;
+ // sfixed64
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed64Impl(id, (long)val);
+ break;
+ // bool
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBoolImpl(id, val != 0);
+ break;
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBoolImpl(id, val != 0);
+ break;
+ // enum
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeEnumImpl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedEnumImpl(id, (int)val);
+ break;
+ // string, bytes, object not allowed here.
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, int) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a value for the given fieldId.
+ *
+ * Will automatically convert for the following field types, and
+ * throw an exception for others: double, float, int32, int64, uint32, uint64,
+ * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, long val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // double
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeDoubleImpl(id, (double)val);
+ break;
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedDoubleImpl(id, (double)val);
+ break;
+ // float
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFloatImpl(id, (float)val);
+ break;
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFloatImpl(id, (float)val);
+ break;
+ // int32
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt32Impl(id, (int)val);
+ break;
+ // int64
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt64Impl(id, (long)val);
+ break;
+ // uint32
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt32Impl(id, (int)val);
+ break;
+ // uint64
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt64Impl(id, (long)val);
+ break;
+ // sint32
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt32Impl(id, (int)val);
+ break;
+ // sint64
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt64Impl(id, (long)val);
+ break;
+ // fixed32
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed32Impl(id, (int)val);
+ break;
+ // fixed64
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed64Impl(id, (long)val);
+ break;
+ // sfixed32
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed32Impl(id, (int)val);
+ break;
+ // sfixed64
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed64Impl(id, (long)val);
+ break;
+ // bool
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBoolImpl(id, val != 0);
+ break;
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBoolImpl(id, val != 0);
+ break;
+ // enum
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeEnumImpl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedEnumImpl(id, (int)val);
+ break;
+ // string, bytes, object not allowed here.
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, long) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a boolean value for the given fieldId.
+ *
+ * If the field is not a bool field, an exception will be thrown.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, boolean val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // bool
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBoolImpl(id, val);
+ break;
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBoolImpl(id, val);
+ break;
+ // nothing else allowed
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, boolean) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a string value for the given fieldId.
+ *
+ * If the field is not a string field, an exception will be thrown.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, String val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // string
+ case (int)((FIELD_TYPE_STRING | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeStringImpl(id, val);
+ break;
+ case (int)((FIELD_TYPE_STRING | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_STRING | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedStringImpl(id, val);
+ break;
+ // nothing else allowed
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, String) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a byte[] value for the given fieldId.
+ *
+ * If the field is not a bytes or object field, an exception will be thrown.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, byte[] val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // bytes
+ case (int)((FIELD_TYPE_BYTES | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBytesImpl(id, val);
+ break;
+ case (int)((FIELD_TYPE_BYTES | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BYTES | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBytesImpl(id, val);
+ break;
+ // Object
+ case (int)((FIELD_TYPE_OBJECT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeObjectImpl(id, val);
+ break;
+ case (int)((FIELD_TYPE_OBJECT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_OBJECT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedObjectImpl(id, val);
+ break;
+ // nothing else allowed
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, byte[]) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Start a sub object.
+ */
+ public long start(long fieldId) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ if ((fieldId & FIELD_TYPE_MASK) == FIELD_TYPE_OBJECT) {
+ final long count = fieldId & FIELD_COUNT_MASK;
+ if (count == FIELD_COUNT_SINGLE) {
+ return startObjectImpl(id, false);
+ } else if (count == FIELD_COUNT_REPEATED || count == FIELD_COUNT_PACKED) {
+ return startObjectImpl(id, true);
+ }
+ }
+ throw new IllegalArgumentException("Attempt to call start(long) with "
+ + getFieldIdString(fieldId));
+ }
+
+ /**
+ * End the object started by start() that returned token.
+ */
+ public void end(long token) {
+ endObjectImpl(token, getRepeatedFromToken(token));
+ }
+
//
// proto3 type: double
// java type: double
@@ -240,6 +933,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_DOUBLE);
+ writeDoubleImpl(id, val);
+ }
+
+ private void writeDoubleImpl(int id, double val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(Double.doubleToLongBits(val));
@@ -253,6 +950,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_DOUBLE);
+ writeRepeatedDoubleImpl(id, val);
+ }
+
+ private void writeRepeatedDoubleImpl(int id, double val) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(Double.doubleToLongBits(val));
}
@@ -287,6 +988,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FLOAT);
+ writeFloatImpl(id, val);
+ }
+
+ private void writeFloatImpl(int id, float val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(Float.floatToIntBits(val));
@@ -300,6 +1005,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FLOAT);
+ writeRepeatedFloatImpl(id, val);
+ }
+
+ private void writeRepeatedFloatImpl(int id, float val) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(Float.floatToIntBits(val));
}
@@ -357,6 +1066,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_INT32);
+ writeInt32Impl(id, val);
+ }
+
+ private void writeInt32Impl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
writeUnsignedVarintFromSignedInt(val);
@@ -374,6 +1087,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_INT32);
+ writeRepeatedInt32Impl(id, val);
+ }
+
+ private void writeRepeatedInt32Impl(int id, int val) {
writeTag(id, WIRE_TYPE_VARINT);
writeUnsignedVarintFromSignedInt(val);
}
@@ -418,6 +1135,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_INT64);
+ writeInt64Impl(id, val);
+ }
+
+ private void writeInt64Impl(int id, long val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint64(val);
@@ -431,6 +1152,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_INT64);
+ writeRepeatedInt64Impl(id, val);
+ }
+
+ private void writeRepeatedInt64Impl(int id, long val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint64(val);
}
@@ -470,6 +1195,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_UINT32);
+ writeUInt32Impl(id, val);
+ }
+
+ private void writeUInt32Impl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint32(val);
@@ -483,6 +1212,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_UINT32);
+ writeRepeatedUInt32Impl(id, val);
+ }
+
+ private void writeRepeatedUInt32Impl(int id, int val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint32(val);
}
@@ -522,6 +1255,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_UINT64);
+ writeUInt64Impl(id, val);
+ }
+
+ private void writeUInt64Impl(int id, long val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint64(val);
@@ -535,6 +1272,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_UINT64);
+ writeRepeatedUInt64Impl(id, val);
+ }
+
+ private void writeRepeatedUInt64Impl(int id, long val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint64(val);
}
@@ -574,6 +1315,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SINT32);
+ writeSInt32Impl(id, val);
+ }
+
+ private void writeSInt32Impl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawZigZag32(val);
@@ -587,6 +1332,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SINT32);
+ writeRepeatedSInt32Impl(id, val);
+ }
+
+ private void writeRepeatedSInt32Impl(int id, int val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawZigZag32(val);
}
@@ -626,6 +1375,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SINT64);
+ writeSInt64Impl(id, val);
+ }
+
+ private void writeSInt64Impl(int id, long val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawZigZag64(val);
@@ -639,6 +1392,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SINT64);
+ writeRepeatedSInt64Impl(id, val);
+ }
+
+ private void writeRepeatedSInt64Impl(int id, long val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawZigZag64(val);
}
@@ -677,6 +1434,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FIXED32);
+ writeFixed32Impl(id, val);
+ }
+
+ private void writeFixed32Impl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(val);
@@ -690,6 +1451,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FIXED32);
+ writeRepeatedFixed32Impl(id, val);
+ }
+
+ private void writeRepeatedFixed32Impl(int id, int val) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(val);
}
@@ -724,6 +1489,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FIXED64);
+ writeFixed64Impl(id, val);
+ }
+
+ private void writeFixed64Impl(int id, long val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(val);
@@ -737,6 +1506,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FIXED64);
+ writeRepeatedFixed64(id, val);
+ }
+
+ private void writeRepeatedFixed64Impl(int id, long val) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(val);
}
@@ -770,6 +1543,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SFIXED32);
+ writeSFixed32Impl(id, val);
+ }
+
+ private void writeSFixed32Impl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(val);
@@ -783,6 +1560,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SFIXED32);
+ writeRepeatedSFixed32Impl(id, val);
+ }
+
+ private void writeRepeatedSFixed32Impl(int id, int val) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(val);
}
@@ -817,6 +1598,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SFIXED64);
+ writeSFixed64Impl(id, val);
+ }
+
+ private void writeSFixed64Impl(int id, long val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(val);
@@ -830,6 +1615,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SFIXED64);
+ writeRepeatedSFixed64(id, val);
+ }
+
+ private void writeRepeatedSFixed64Impl(int id, long val) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(val);
}
@@ -864,6 +1653,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_BOOL);
+ writeBoolImpl(id, val);
+ }
+
+ private void writeBoolImpl(int id, boolean val) {
if (val) {
writeTag(id, WIRE_TYPE_VARINT);
// 0 and 1 are the same as their varint counterparts
@@ -878,6 +1671,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BOOL);
+ writeRepeatedBool(id, val);
+ }
+
+ private void writeRepeatedBoolImpl(int id, boolean val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawByte((byte)(val ? 1 : 0));
}
@@ -916,6 +1713,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_STRING);
+ writeStringImpl(id, val);
+ }
+
+ private void writeStringImpl(int id, String val) {
if (val != null && val.length() > 0) {
writeUtf8String(id, val);
}
@@ -928,6 +1729,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_STRING);
+ writeRepeatedStringImpl(id, val);
+ }
+
+ private void writeRepeatedStringImpl(int id, String val) {
if (val == null || val.length() == 0) {
writeKnownLengthHeader(id, 0);
} else {
@@ -963,6 +1768,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_BYTES);
+ writeBytesImpl(id, val);
+ }
+
+ private void writeBytesImpl(int id, byte[] val) {
if (val != null && val.length > 0) {
writeKnownLengthHeader(id, val.length);
mBuffer.writeRawBuffer(val);
@@ -976,6 +1785,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BYTES);
+ writeRepeatedBytesImpl(id, val);
+ }
+
+ private void writeRepeatedBytesImpl(int id, byte[] val) {
writeKnownLengthHeader(id, val == null ? 0 : val.length);
mBuffer.writeRawBuffer(val);
}
@@ -995,6 +1808,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_ENUM);
+ writeEnumImpl(id, val);
+ }
+
+ private void writeEnumImpl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
writeUnsignedVarintFromSignedInt(val);
@@ -1008,6 +1825,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_ENUM);
+ writeRepeatedEnumImpl(id, val);
+ }
+
+ private void writeRepeatedEnumImpl(int id, int val) {
writeTag(id, WIRE_TYPE_VARINT);
writeUnsignedVarintFromSignedInt(val);
}
@@ -1239,6 +2060,38 @@
}
}
+ /**
+ * Write an object that has already been flattend.
+ */
+ public void writeObject(long fieldId, byte[] value) {
+ assertNotCompacted();
+ final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_OBJECT);
+
+ writeObjectImpl(id, value);
+ }
+
+ public void writeObjectImpl(int id, byte[] value) {
+ if (value != null && value.length != 0) {
+ writeKnownLengthHeader(id, value.length);
+ mBuffer.writeRawBuffer(value);
+ }
+ }
+
+ /**
+ * Write an object that has already been flattend.
+ */
+ public void writeRepeatedObject(long fieldId, byte[] value) {
+ assertNotCompacted();
+ final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_OBJECT);
+
+ writeRepeatedObjectImpl(id, value);
+ }
+
+ public void writeRepeatedObjectImpl(int id, byte[] value) {
+ writeKnownLengthHeader(id, value == null ? 0 : value.length);
+ mBuffer.writeRawBuffer(value);
+ }
+
//
// Tags
//
@@ -1358,6 +2211,25 @@
}
}
+ /**
+ * Get a debug string for a fieldId.
+ */
+ private String getFieldIdString(long fieldId) {
+ final long fieldCount = fieldId & FIELD_COUNT_MASK;
+ String countString = getFieldCountString(fieldCount);
+ if (countString == null) {
+ countString = "fieldCount=" + fieldCount;
+ }
+
+ final long fieldType = fieldId & FIELD_TYPE_MASK;
+ String typeString = getFieldTypeString(fieldType);
+ if (typeString == null) {
+ typeString = "fieldType=" + fieldType;
+ }
+
+ return fieldCount + " " + typeString + " tag=" + ((int)fieldId)
+ + " fieldId=0x" + Long.toHexString(fieldId);
+ }
/**
* Return how many bytes an encoded field tag will require.
@@ -1580,6 +2452,37 @@
}
/**
+ * Write remaining data to the output stream. If there is no output stream,
+ * this function does nothing. Any currently open objects (i.e. ones that
+ * have not had endObject called for them will not be written). Whether this
+ * writes objects that are closed if there are remaining open objects is
+ * undefined (current implementation does not write it, future ones will).
+ * For now, can either call getBytes() or flush(), but not both.
+ */
+ public void flush() {
+ if (mStream == null) {
+ return;
+ }
+ if (mDepth != 0) {
+ // TODO: The compacting code isn't ready yet to compact unless we're done.
+ // TODO: Fix that.
+ return;
+ }
+ if (mCompacted) {
+ // If we're compacted, we already wrote it finished.
+ return;
+ }
+ compactIfNecessary();
+ final byte[] data = mBuffer.getBytes(mBuffer.getReadableSize());
+ try {
+ mStream.write(data);
+ mStream.flush();
+ } catch (IOException ex) {
+ throw new RuntimeException("Error flushing proto to stream", ex);
+ }
+ }
+
+ /**
* Read a raw tag from the buffer.
*/
private int readRawTag() {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f9a03c0..316b123 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2912,6 +2912,30 @@
public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
/**
+ * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
+ * trigger undefined behavior on older platforms with apps compiled against a new SDK.
+ */
+ private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
+
+ /**
+ * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
+ * trigger undefined behavior on older platforms with apps compiled against a new SDK.
+ */
+ private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
+
+ /**
+ * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
+ * that is compatible with light navigation bar backgrounds.
+ *
+ * <p>For this to take effect, the window must request
+ * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
+ * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
+ * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
+ * FLAG_TRANSLUCENT_NAVIGATION}.
+ */
+ public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
+
+ /**
* @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
*/
@Deprecated
@@ -3104,7 +3128,7 @@
*
* Makes status bar transparent (but not the navigation bar).
*/
- public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
+ public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
/**
* @hide
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 2c13831..7c1bcee 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -301,6 +301,7 @@
private boolean mDestroyed;
private boolean mOverlayWithDecorCaptionEnabled = false;
+ private boolean mCloseOnSwipeEnabled = false;
// The current window attributes.
private final WindowManager.LayoutParams mWindowAttributes =
@@ -579,8 +580,10 @@
* Called when a window is dismissed. This informs the callback that the
* window is gone, and it should finish itself.
* @param finishTask True if the task should also be finished.
+ * @param suppressWindowTransition True if the resulting exit and enter window transition
+ * animations should be suppressed.
*/
- void onWindowDismissed(boolean finishTask);
+ void onWindowDismissed(boolean finishTask, boolean suppressWindowTransition);
}
/** @hide */
@@ -869,9 +872,10 @@
}
/** @hide */
- public final void dispatchOnWindowDismissed(boolean finishTask) {
+ public final void dispatchOnWindowDismissed(
+ boolean finishTask, boolean suppressWindowTransition) {
if (mOnWindowDismissedCallback != null) {
- mOnWindowDismissedCallback.onWindowDismissed(finishTask);
+ mOnWindowDismissedCallback.onWindowDismissed(finishTask, suppressWindowTransition);
}
}
@@ -2209,4 +2213,21 @@
* @hide
*/
public abstract void reportActivityRelaunched();
+
+ /**
+ * Called to set flag to check if the close on swipe is enabled. This will only function if
+ * FEATURE_SWIPE_TO_DISMISS has been set.
+ * @hide
+ */
+ public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
+ mCloseOnSwipeEnabled = closeOnSwipeEnabled;
+ }
+
+ /**
+ * @return {@code true} if the close on swipe is enabled.
+ * @hide
+ */
+ public boolean isCloseOnSwipeEnabled() {
+ return mCloseOnSwipeEnabled;
+ }
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index b8408dd..aa7631d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -922,8 +922,11 @@
* unlock credential) than the user will still need to confirm it before
* seeing this window, unless {@link #FLAG_SHOW_WHEN_LOCKED} has
* also been set.
- * @see KeyguardManager#dismissKeyguard
+ * @deprecated Use {@link #FLAG_SHOW_WHEN_LOCKED} or {@link KeyguardManager#dismissKeyguard}
+ * instead. The Keyguard should never be dismissed automatically repeatedly as it also
+ * guards against unintentional touches.
*/
+ @Deprecated
public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
/** Window flag: when set the window will accept for touch events
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 2f55fc9..caa09cc 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -482,16 +482,6 @@
*/
public void switchInputMethod(boolean forwardDirection);
- /**
- * Returns the visibility of the current input method window (false if there is none).
- */
- public boolean isInputMethodWindowVisible();
-
- /**
- * Hides the current input method, if visible.
- */
- public void hideCurrentInputMethod();
-
public void shutdown(boolean confirm);
public void reboot(boolean confirm);
public void rebootSafeMode(boolean confirm);
@@ -523,6 +513,11 @@
void notifyShowingDreamChanged();
/**
+ * @return The currently active input method window.
+ */
+ WindowState getInputMethodWindowLw();
+
+ /**
* Notifies window manager that {@link #isKeyguardTrustedLw} has changed.
*/
void notifyKeyguardTrustedChanged();
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index c206974..e0d589a 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -53,6 +53,10 @@
return sPackage.packageName;
}
+ public static boolean isMultiprocessEnabled() {
+ return sMultiprocessEnabled && sPackage != null;
+ }
+
public static void setMultiprocessEnabled(boolean enabled) {
sMultiprocessEnabled = enabled;
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index a8d3984..043eb34 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -142,6 +142,12 @@
/** @hide */
@Override
+ protected boolean supportsAutoSizeText() {
+ return false;
+ }
+
+ /** @hide */
+ @Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfoInternal(info);
if (isEnabled()) {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index fc1520b..5fa1d2b 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1835,7 +1835,8 @@
// can expect the OnAttachStateChangeListener to have been called prior
// to executing this method, so we can rely on that instead.
final Transition exitTransition = mExitTransition;
- if (mIsAnchorRootAttached && exitTransition != null && decorView.isLaidOut()) {
+ if (exitTransition != null && decorView.isLaidOut()
+ && (mIsAnchorRootAttached || mAnchorRoot == null)) {
// The decor view is non-interactive and non-IME-focusable during exit transitions.
final LayoutParams p = (LayoutParams) decorView.getLayoutParams();
p.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -1843,18 +1844,13 @@
p.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
mWindowManager.updateViewLayout(decorView, p);
+ final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
+ final Rect epicenter = getTransitionEpicenter();
+
// Once we start dismissing the decor view, all state (including
// the anchor root) needs to be moved to the decor view since we
// may open another popup while it's busy exiting.
- final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
- final Rect epicenter = getTransitionEpicenter();
- exitTransition.setEpicenterCallback(new EpicenterCallback() {
- @Override
- public Rect onGetEpicenter(Transition transition) {
- return epicenter;
- }
- });
- decorView.startExitTransition(exitTransition, anchorRoot,
+ decorView.startExitTransition(exitTransition, anchorRoot, epicenter,
new TransitionListenerAdapter() {
@Override
public void onTransitionEnd(Transition transition) {
@@ -2349,8 +2345,9 @@
* its {@code onTransitionEnd} method called even if the transition
* never starts; however, it may be called with a {@code null} argument.
*/
- public void startExitTransition(Transition transition, final View anchorRoot,
- final TransitionListener listener) {
+ public void startExitTransition(@NonNull Transition transition,
+ @Nullable final View anchorRoot, @Nullable final Rect epicenter,
+ @NonNull final TransitionListener listener) {
if (transition == null) {
return;
}
@@ -2358,24 +2355,35 @@
// The anchor view's window may go away while we're executing our
// transition, in which case we need to end the transition
// immediately and execute the listener to remove the popup.
- anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+ if (anchorRoot != null) {
+ anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+ }
// The exit listener MUST be called for cleanup, even if the
// transition never starts or ends. Stash it for later.
mPendingExitListener = new TransitionListenerAdapter() {
@Override
- public void onTransitionEnd(Transition transition) {
- anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
- listener.onTransitionEnd(transition);
+ public void onTransitionEnd(Transition t) {
+ if (anchorRoot != null) {
+ anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+ }
+
+ listener.onTransitionEnd(t);
// The listener was called. Our job here is done.
mPendingExitListener = null;
- transition.removeListener(this);
+ t.removeListener(this);
}
};
final Transition exitTransition = transition.clone();
exitTransition.addListener(mPendingExitListener);
+ exitTransition.setEpicenterCallback(new EpicenterCallback() {
+ @Override
+ public Rect onGetEpicenter(Transition transition) {
+ return epicenter;
+ }
+ });
final int count = getChildCount();
for (int i = 0; i < count; i++) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b85175d..44655f1 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1534,7 +1534,7 @@
}
// Setup auto-size.
- if (mEditor == null) {
+ if (supportsAutoSizeText()) {
switch (mAutoSizeType) {
case AUTO_SIZE_TYPE_NONE:
// Nothing to do.
@@ -9261,8 +9261,8 @@
}
/**
- * @return true if this TextView is specialized for showing and interacting with the extracted
- * text in a full-screen input method.
+ * @return {@code true} if this TextView is specialized for showing and interacting with the
+ * extracted text in a full-screen input method.
* @hide
*/
public boolean isInExtractedMode() {
@@ -9270,6 +9270,14 @@
}
/**
+ * @return {@code true} if this TextView supports autosizing text to fit within its container.
+ * @hide
+ */
+ protected boolean supportsAutoSizeText() {
+ return true;
+ }
+
+ /**
* This is a temporary method. Future versions may support multi-locale text.
* Caveat: This method may not return the latest spell checker locale, but this should be
* acceptable and it's more important to make this method asynchronous.
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
deleted file mode 100644
index 419c3d8..0000000
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2008 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.android.internal.os;
-
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import com.android.internal.util.Preconditions;
-
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * Represents a connection to {@code installd}. Allows multiple connect and
- * disconnect cycles.
- *
- * @hide for internal use only
- */
-public class InstallerConnection {
- private static final String TAG = "InstallerConnection";
- private static final boolean LOCAL_DEBUG = false;
-
- private InputStream mIn;
- private OutputStream mOut;
- private LocalSocket mSocket;
-
- private volatile Object mWarnIfHeld;
-
- private final byte buf[] = new byte[1024];
-
- public InstallerConnection() {
- }
-
- /**
- * Yell loudly if someone tries making future calls while holding a lock on
- * the given object.
- */
- public void setWarnIfHeld(Object warnIfHeld) {
- Preconditions.checkState(mWarnIfHeld == null);
- mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
- }
-
- public synchronized String transact(String cmd) {
- if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
- Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
- + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
- }
-
- if (!connect()) {
- Slog.e(TAG, "connection failed");
- return "-1";
- }
-
- if (!writeCommand(cmd)) {
- /*
- * If installd died and restarted in the background (unlikely but
- * possible) we'll fail on the next write (this one). Try to
- * reconnect and write the command one more time before giving up.
- */
- Slog.e(TAG, "write command failed? reconnect!");
- if (!connect() || !writeCommand(cmd)) {
- return "-1";
- }
- }
- if (LOCAL_DEBUG) {
- Slog.i(TAG, "send: '" + cmd + "'");
- }
-
- final int replyLength = readReply();
- if (replyLength > 0) {
- String s = new String(buf, 0, replyLength);
- if (LOCAL_DEBUG) {
- Slog.i(TAG, "recv: '" + s + "'");
- }
- return s;
- } else {
- if (LOCAL_DEBUG) {
- Slog.i(TAG, "fail");
- }
- return "-1";
- }
- }
-
- public String[] execute(String cmd, Object... args) throws InstallerException {
- final StringBuilder builder = new StringBuilder(cmd);
- for (Object arg : args) {
- String escaped;
- if (arg == null) {
- escaped = "";
- } else {
- escaped = String.valueOf(arg);
- }
- if (escaped.indexOf('\0') != -1 || escaped.indexOf(' ') != -1 || "!".equals(escaped)) {
- throw new InstallerException(
- "Invalid argument while executing " + cmd + " " + Arrays.toString(args));
- }
- if (TextUtils.isEmpty(escaped)) {
- escaped = "!";
- }
- builder.append(' ').append(escaped);
- }
- final String[] resRaw = transact(builder.toString()).split(" ");
- int res = -1;
- try {
- res = Integer.parseInt(resRaw[0]);
- } catch (ArrayIndexOutOfBoundsException | NumberFormatException ignored) {
- }
- if (res != 0) {
- throw new InstallerException(
- "Failed to execute " + cmd + " " + Arrays.toString(args) + ": " + res);
- }
- return resRaw;
- }
-
- public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
- int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)
- throws InstallerException {
- dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded, null /*outputPath*/, dexFlags,
- compilerFilter, volumeUuid, sharedLibraries);
- }
-
- public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
- int dexoptNeeded, String outputPath, int dexFlags, String compilerFilter,
- String volumeUuid, String sharedLibraries) throws InstallerException {
- execute("dexopt",
- apkPath,
- uid,
- pkgName,
- instructionSet,
- dexoptNeeded,
- outputPath,
- dexFlags,
- compilerFilter,
- volumeUuid,
- sharedLibraries);
- }
-
- private boolean safeParseBooleanResult(String[] res) throws InstallerException {
- if ((res == null) || (res.length != 2)) {
- throw new InstallerException("Invalid size result: " + Arrays.toString(res));
- }
-
- // Just as a sanity check. Anything != "true" will be interpreted as false by parseBoolean.
- if (!res[1].equals("true") && !res[1].equals("false")) {
- throw new InstallerException("Invalid boolean result: " + Arrays.toString(res));
- }
-
- return Boolean.parseBoolean(res[1]);
- }
-
- public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
- final String[] res = execute("merge_profiles", uid, pkgName);
-
- return safeParseBooleanResult(res);
- }
-
- public boolean dumpProfiles(String gid, String packageName, String codePaths)
- throws InstallerException {
- final String[] res = execute("dump_profiles", gid, packageName, codePaths);
-
- return safeParseBooleanResult(res);
- }
-
- private boolean connect() {
- if (mSocket != null) {
- return true;
- }
- Slog.i(TAG, "connecting...");
- try {
- mSocket = new LocalSocket();
-
- LocalSocketAddress address = new LocalSocketAddress("installd",
- LocalSocketAddress.Namespace.RESERVED);
-
- mSocket.connect(address);
-
- mIn = mSocket.getInputStream();
- mOut = mSocket.getOutputStream();
- } catch (IOException ex) {
- disconnect();
- return false;
- }
- return true;
- }
-
- public void disconnect() {
- Slog.i(TAG, "disconnecting...");
- IoUtils.closeQuietly(mSocket);
- IoUtils.closeQuietly(mIn);
- IoUtils.closeQuietly(mOut);
-
- mSocket = null;
- mIn = null;
- mOut = null;
- }
-
-
- private boolean readFully(byte[] buffer, int len) {
- try {
- Streams.readFully(mIn, buffer, 0, len);
- } catch (IOException ioe) {
- Slog.e(TAG, "read exception");
- disconnect();
- return false;
- }
-
- if (LOCAL_DEBUG) {
- Slog.i(TAG, "read " + len + " bytes");
- }
-
- return true;
- }
-
- private int readReply() {
- if (!readFully(buf, 2)) {
- return -1;
- }
-
- final int len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8);
- if ((len < 1) || (len > buf.length)) {
- Slog.e(TAG, "invalid reply length (" + len + ")");
- disconnect();
- return -1;
- }
-
- if (!readFully(buf, len)) {
- return -1;
- }
-
- return len;
- }
-
- private boolean writeCommand(String cmdString) {
- final byte[] cmd = cmdString.getBytes();
- final int len = cmd.length;
- if ((len < 1) || (len > buf.length)) {
- return false;
- }
-
- buf[0] = (byte) (len & 0xff);
- buf[1] = (byte) ((len >> 8) & 0xff);
- try {
- mOut.write(buf, 0, 2);
- mOut.write(cmd, 0, len);
- } catch (IOException ex) {
- Slog.e(TAG, "write error");
- disconnect();
- return false;
- }
- return true;
- }
-
- public void waitForConnection() {
- for (;;) {
- try {
- execute("ping");
- return;
- } catch (InstallerException ignored) {
- }
- Slog.w(TAG, "installd not ready");
- SystemClock.sleep(1000);
- }
- }
-
- public static class InstallerException extends Exception {
- public InstallerException(String detailMessage) {
- super(detailMessage);
- }
- }
-}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index cdd267e..c88e9da 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -26,11 +26,16 @@
import android.icu.util.ULocale;
import android.net.LocalServerSocket;
import android.opengl.EGL14;
+import android.os.IInstalld;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.ZygoteProcess;
+import android.os.storage.StorageManager;
import android.security.keystore.AndroidKeyStoreProvider;
import android.system.ErrnoException;
import android.system.Os;
@@ -43,7 +48,6 @@
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.os.InstallerConnection.InstallerException;
import dalvik.system.DexFile;
import dalvik.system.PathClassLoader;
@@ -494,54 +498,55 @@
*/
private static void performSystemServerDexOpt(String classPath) {
final String[] classPathElements = classPath.split(":");
- final InstallerConnection installer = new InstallerConnection();
- installer.waitForConnection();
+ final IInstalld installd = IInstalld.Stub
+ .asInterface(ServiceManager.getService("installd"));
final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
- try {
- String sharedLibraries = "";
- for (String classPathElement : classPathElements) {
- // System server is fully AOTed and never profiled
- // for profile guided compilation.
- // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
+ String sharedLibraries = "";
+ for (String classPathElement : classPathElements) {
+ // System server is fully AOTed and never profiled
+ // for profile guided compilation.
+ // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
- int dexoptNeeded;
- try {
- dexoptNeeded = DexFile.getDexOptNeeded(
- classPathElement, instructionSet, "speed",
- false /* newProfile */);
- } catch (FileNotFoundException ignored) {
- // Do not add to the classpath.
- Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
- continue;
- } catch (IOException e) {
- // Not fully clear what to do here as we don't know the cause of the
- // IO exception. Add to the classpath to be conservative, but don't
- // attempt to compile it.
- Log.w(TAG, "Error checking classpath element for system server: "
- + classPathElement, e);
- dexoptNeeded = DexFile.NO_DEXOPT_NEEDED;
- }
-
- if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- try {
- installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
- dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/,
- sharedLibraries);
- } catch (InstallerException e) {
- // Ignore (but log), we need this on the classpath for fallback mode.
- Log.w(TAG, "Failed compiling classpath element for system server: "
- + classPathElement, e);
- }
- }
-
- if (!sharedLibraries.isEmpty()) {
- sharedLibraries += ":";
- }
- sharedLibraries += classPathElement;
+ int dexoptNeeded;
+ try {
+ dexoptNeeded = DexFile.getDexOptNeeded(
+ classPathElement, instructionSet, "speed",
+ false /* newProfile */);
+ } catch (FileNotFoundException ignored) {
+ // Do not add to the classpath.
+ Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
+ continue;
+ } catch (IOException e) {
+ // Not fully clear what to do here as we don't know the cause of the
+ // IO exception. Add to the classpath to be conservative, but don't
+ // attempt to compile it.
+ Log.w(TAG, "Error checking classpath element for system server: "
+ + classPathElement, e);
+ dexoptNeeded = DexFile.NO_DEXOPT_NEEDED;
}
- } finally {
- installer.disconnect();
+
+ if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
+ final String packageName = "*";
+ final String outputPath = null;
+ final int dexFlags = 0;
+ final String compilerFilter = "speed";
+ final String uuid = StorageManager.UUID_PRIVATE_INTERNAL;
+ try {
+ installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName,
+ instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter,
+ uuid, sharedLibraries);
+ } catch (RemoteException | ServiceSpecificException e) {
+ // Ignore (but log), we need this on the classpath for fallback mode.
+ Log.w(TAG, "Failed compiling classpath element for system server: "
+ + classPathElement, e);
+ }
+ }
+
+ if (!sharedLibraries.isEmpty()) {
+ sharedLibraries += ":";
+ }
+ sharedLibraries += classPathElement;
}
}
@@ -572,7 +577,7 @@
String args[] = {
"--setuid=1000",
"--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
+ "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 2a004cfb..ec068a3 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2502,6 +2502,7 @@
// System.out.println("Features: 0x" + Integer.toHexString(features));
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
layoutResource = R.layout.screen_swipe_dismiss;
+ setCloseOnSwipeEnabled(true);
} else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
@@ -2573,7 +2574,7 @@
}
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
- registerSwipeCallbacks();
+ registerSwipeCallbacks(contentParent);
}
// Remaining setup -- of background and title -- that only applies
@@ -2987,25 +2988,26 @@
return (mRightIconView = (ImageView)findViewById(R.id.right_icon));
}
- private void registerSwipeCallbacks() {
- SwipeDismissLayout swipeDismiss =
- (SwipeDismissLayout) findViewById(R.id.content);
+ private void registerSwipeCallbacks(ViewGroup contentParent) {
+ if (!(contentParent instanceof SwipeDismissLayout)) {
+ Log.w(TAG, "contentParent is not a SwipeDismissLayout: " + contentParent);
+ return;
+ }
+ SwipeDismissLayout swipeDismiss = (SwipeDismissLayout) contentParent;
swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
@Override
public void onDismissed(SwipeDismissLayout layout) {
- dispatchOnWindowDismissed(false /*finishTask*/);
+ dispatchOnWindowDismissed(false /*finishTask*/, true /*suppressWindowTransition*/);
}
});
swipeDismiss.setOnSwipeProgressChangedListener(
new SwipeDismissLayout.OnSwipeProgressChangedListener() {
- private static final float ALPHA_DECREASE = 0.5f;
- private boolean mIsTranslucent = false;
@Override
public void onSwipeProgressChanged(
- SwipeDismissLayout layout, float progress, float translate) {
+ SwipeDismissLayout layout, float alpha, float translate) {
WindowManager.LayoutParams newParams = getAttributes();
newParams.x = (int) translate;
- newParams.alpha = 1 - (progress * ALPHA_DECREASE);
+ newParams.alpha = alpha;
setAttributes(newParams);
int flags = 0;
@@ -3028,6 +3030,16 @@
});
}
+ /** @hide */
+ @Override
+ public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
+ if (hasFeature(Window.FEATURE_SWIPE_TO_DISMISS) // swipe-to-dismiss feature is requested
+ && mContentParent instanceof SwipeDismissLayout) { // check casting mContentParent
+ ((SwipeDismissLayout) mContentParent).setDismissable(closeOnSwipeEnabled);
+ }
+ super.setCloseOnSwipeEnabled(closeOnSwipeEnabled);
+ }
+
/**
* Helper method for calling the {@link Callback#onPanelClosed(int, Menu)}
* callback. This method will grab whatever extra state is needed for the
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 0bf170e..af4f777 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -20,28 +20,22 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
import android.widget.ActionMenuView;
import android.widget.ForwardingListener;
import android.widget.TextView;
-import android.widget.Toast;
/**
* @hide
*/
public class ActionMenuItemView extends TextView
- implements MenuView.ItemView, View.OnClickListener, View.OnLongClickListener,
- ActionMenuView.ActionMenuChildView {
+ implements MenuView.ItemView, View.OnClickListener, ActionMenuView.ActionMenuChildView {
private static final String TAG = "ActionMenuItemView";
private MenuItemImpl mItemData;
@@ -59,9 +53,6 @@
private static final int MAX_ICON_SIZE = 32; // dp
private int mMaxIconSize;
- private Toast mTooltip;
- private Runnable mShowTooltipRunnable = () -> showTooltip(Toast.LENGTH_LONG);
-
public ActionMenuItemView(Context context) {
this(context, null);
}
@@ -88,7 +79,6 @@
mMaxIconSize = (int) (MAX_ICON_SIZE * density + 0.5f);
setOnClickListener(this);
- setOnLongClickListener(this);
mSavedPaddingLeft = -1;
setSaveEnabled(false);
@@ -193,6 +183,9 @@
(mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat));
setText(visible ? mTitle : null);
+
+ // Show the tooltip for items that do not already show text.
+ setTooltip(visible ? null : mTitle);
}
public void setIcon(Drawable icon) {
@@ -249,7 +242,6 @@
@Override
public boolean dispatchHoverEvent(MotionEvent event) {
- updateTooltip(event);
// Don't allow children to hover; we want this to be treated as a single component.
return onHoverEvent(event);
}
@@ -267,68 +259,6 @@
}
@Override
- public boolean onLongClick(View v) {
- return showTooltip(Toast.LENGTH_SHORT);
- }
-
- private boolean showTooltip(@Toast.Duration int duration) {
- if (hasText()) {
- // Don't show the cheat sheet for items that already show text.
- return false;
- }
-
- final int[] screenPos = new int[2];
- final Rect displayFrame = new Rect();
- getLocationOnScreen(screenPos);
- getWindowVisibleDisplayFrame(displayFrame);
-
- final Context context = getContext();
- final int width = getWidth();
- final int height = getHeight();
- final int midy = screenPos[1] + height / 2;
- int referenceX = screenPos[0] + width / 2;
- if (getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
- final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
- referenceX = screenWidth - referenceX; // mirror
- }
- hideTooltip ();
- mTooltip = Toast.makeText(context, mItemData.getTitle(), duration);
- if (midy < displayFrame.height()) {
- // Show along the top; follow action buttons
- mTooltip.setGravity(Gravity.TOP | Gravity.END, referenceX,
- screenPos[1] + height - displayFrame.top);
- } else {
- // Show along the bottom center
- mTooltip.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
- }
- mTooltip.show();
- return true;
- }
-
- private void hideTooltip() {
- if (mTooltip != null) {
- mTooltip.cancel();
- mTooltip = null;
- }
- getHandler().removeCallbacks(mShowTooltipRunnable);
- }
-
- private void updateTooltip(MotionEvent event) {
- AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
- if (manager.isEnabled() && manager.isTouchExplorationEnabled()) {
- return;
- }
-
- final int action = event.getAction();
- if (action == MotionEvent.ACTION_HOVER_MOVE) {
- hideTooltip();
- getHandler().postDelayed(mShowTooltipRunnable, ViewConfiguration.getLongPressTimeout());
- } else if (action == MotionEvent.ACTION_HOVER_EXIT) {
- hideTooltip();
- }
- }
-
- @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final boolean textVisible = hasText();
if (textVisible && mSavedPaddingLeft >= 0) {
diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java
index c458ab1..b419113 100644
--- a/core/java/com/android/internal/widget/DecorCaptionView.java
+++ b/core/java/com/android/internal/widget/DecorCaptionView.java
@@ -408,7 +408,8 @@
if (mClickTarget == mMaximize) {
maximizeWindow();
} else if (mClickTarget == mClose) {
- mOwner.dispatchOnWindowDismissed(true /*finishTask*/);
+ mOwner.dispatchOnWindowDismissed(
+ true /*finishTask*/, false /*suppressWindowTransition*/);
}
return true;
}
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index 358be60..a5d2bf3 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -71,10 +71,14 @@
.setTextDirection(getTextDirectionHeuristic())
.setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier())
.setIncludePad(getIncludeFontPadding())
- .setEllipsize(shouldEllipsize ? effectiveEllipsize : null)
- .setEllipsizedWidth(ellipsisWidth)
.setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
- .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL)
+ .setMaxLines(getMaxLines() >= 0 ? getMaxLines() : Integer.MAX_VALUE);
+ if (shouldEllipsize) {
+ builder.setEllipsize(effectiveEllipsize)
+ .setEllipsizedWidth(ellipsisWidth);
+ }
+
// we set the endmargin on the requested number of lines.
int endMargin = getContext().getResources().getDimensionPixelSize(
R.dimen.notification_content_picture_margin);
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index d2a43b7..cb123a1 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -126,7 +126,8 @@
// Pretend we need the image padding for all views, we don't know which
// one will end up needing to do this (might end up not using all the space,
// but calculating this exactly would be more expensive).
- ((ImageFloatingTextView) child).setNumIndentLines(mIndentLines);
+ ((ImageFloatingTextView) child).setNumIndentLines(
+ mIndentLines == 2 ? 3 : mIndentLines);
}
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
@@ -147,6 +148,9 @@
// Now that we know which views to take, fix up the indents and see what width we get.
int measuredWidth = mPaddingLeft + mPaddingRight;
int imageLines = mIndentLines;
+ // Need to redo the height because it may change due to changing indents.
+ totalHeight = mPaddingTop + mPaddingBottom;
+ first = true;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
@@ -173,6 +177,9 @@
measuredWidth = Math.max(measuredWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin
+ mPaddingLeft + mPaddingRight);
+ totalHeight = Math.max(totalHeight, totalHeight + child.getMeasuredHeight() +
+ lp.topMargin + lp.bottomMargin + (first ? 0 : mSpacing));
+ first = false;
}
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index ffd9b24..4466575 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -40,7 +40,6 @@
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
-import android.widget.Toast;
/**
* This widget implements the dynamic action bar tab behavior that can change
@@ -360,7 +359,7 @@
tabView.getTab().select();
}
- private class TabView extends LinearLayout implements OnLongClickListener {
+ private class TabView extends LinearLayout {
private ActionBar.Tab mTab;
private TextView mTextView;
private ImageView mIconView;
@@ -472,35 +471,10 @@
if (mIconView != null) {
mIconView.setContentDescription(tab.getContentDescription());
}
-
- if (!hasText && !TextUtils.isEmpty(tab.getContentDescription())) {
- setOnLongClickListener(this);
- } else {
- setOnLongClickListener(null);
- setLongClickable(false);
- }
+ setTooltip(hasText? null : tab.getContentDescription());
}
}
- public boolean onLongClick(View v) {
- final int[] screenPos = new int[2];
- getLocationOnScreen(screenPos);
-
- final Context context = getContext();
- final int width = getWidth();
- final int height = getHeight();
- final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
-
- Toast cheatSheet = Toast.makeText(context, mTab.getContentDescription(),
- Toast.LENGTH_SHORT);
- // Show under the tab
- cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
- (screenPos[0] + width / 2) - screenWidth / 2, height);
-
- cheatSheet.show();
- return true;
- }
-
public ActionBar.Tab getTab() {
return mTab;
}
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index d88f479..83b49eb 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -16,6 +16,10 @@
package com.android.internal.widget;
+import android.animation.Animator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -30,6 +34,7 @@
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
/**
@@ -49,12 +54,12 @@
/**
* Called when the layout has been swiped and the position of the window should change.
*
- * @param progress A number in [0, 1] representing how far to the
- * right the window has been swiped
+ * @param alpha A number in [0, 1] representing what the alpha transparency of the window
+ * should be.
* @param translate A number in [0, w], where w is the width of the
* layout. This is equivalent to progress * layout.getWidth().
*/
- void onSwipeProgressChanged(SwipeDismissLayout layout, float progress, float translate);
+ void onSwipeProgressChanged(SwipeDismissLayout layout, float alpha, float translate);
void onSwipeCancelled(SwipeDismissLayout layout);
}
@@ -72,6 +77,9 @@
private boolean mDiscardIntercept;
private VelocityTracker mVelocityTracker;
private float mTranslationX;
+ private boolean mBlockGesture = false;
+
+ private final DismissAnimator mDismissAnimator = new DismissAnimator();
private OnDismissedListener mDismissedListener;
private OnSwipeProgressChangedListener mProgressListener;
@@ -110,6 +118,8 @@
private float mLastX;
+ private boolean mDismissable = true;
+
public SwipeDismissLayout(Context context) {
super(context);
init(context);
@@ -166,6 +176,14 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ checkGesture((ev));
+ if (mBlockGesture) {
+ return true;
+ }
+ if (!mDismissable) {
+ return super.onInterceptTouchEvent(ev);
+ }
+
// offset because the view is translated during swipe
ev.offsetLocation(mTranslationX, 0);
@@ -225,7 +243,11 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (mVelocityTracker == null) {
+ checkGesture((ev));
+ if (mBlockGesture) {
+ return true;
+ }
+ if (mVelocityTracker == null || !mDismissable) {
return super.onTouchEvent(ev);
}
// offset because the view is translated during swipe
@@ -234,9 +256,9 @@
case MotionEvent.ACTION_UP:
updateDismiss(ev);
if (mDismissed) {
- dismiss();
+ mDismissAnimator.animateDismissal(ev.getRawX() - mDownX);
} else if (mSwiping) {
- cancel();
+ mDismissAnimator.animateRecovery(ev.getRawX() - mDownX);
}
resetMembers();
break;
@@ -264,7 +286,8 @@
private void setProgress(float deltaX) {
mTranslationX = deltaX;
if (mProgressListener != null && deltaX >= 0) {
- mProgressListener.onSwipeProgressChanged(this, deltaX / getWidth(), deltaX);
+ mProgressListener.onSwipeProgressChanged(
+ this, progressToAlpha(deltaX / getWidth()), deltaX);
}
}
@@ -363,4 +386,100 @@
return checkV && v.canScrollHorizontally((int) -dx);
}
+
+ public void setDismissable(boolean dismissable) {
+ if (!dismissable && mDismissable) {
+ cancel();
+ resetMembers();
+ }
+
+ mDismissable = dismissable;
+ }
+
+ private void checkGesture(MotionEvent ev) {
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mBlockGesture = mDismissAnimator.isAnimating();
+ }
+ }
+
+ private float progressToAlpha(float progress) {
+ return 1 - progress * progress * progress;
+ }
+
+ private class DismissAnimator implements AnimatorUpdateListener, Animator.AnimatorListener {
+ private final TimeInterpolator DISMISS_INTERPOLATOR = new DecelerateInterpolator(1.5f);
+ private final long DISMISS_DURATION = 250;
+
+ private final ValueAnimator mDismissAnimator = new ValueAnimator();
+ private boolean mWasCanceled = false;
+ private boolean mDismissOnComplete = false;
+
+ /* package */ DismissAnimator() {
+ mDismissAnimator.addUpdateListener(this);
+ mDismissAnimator.addListener(this);
+ }
+
+ /* package */ void animateDismissal(float currentTranslation) {
+ animate(
+ currentTranslation / getWidth(),
+ 1,
+ DISMISS_DURATION,
+ DISMISS_INTERPOLATOR,
+ true /* dismiss */);
+ }
+
+ /* package */ void animateRecovery(float currentTranslation) {
+ animate(
+ currentTranslation / getWidth(),
+ 0,
+ DISMISS_DURATION,
+ DISMISS_INTERPOLATOR,
+ false /* don't dismiss */);
+ }
+
+ /* package */ boolean isAnimating() {
+ return mDismissAnimator.isStarted();
+ }
+
+ private void animate(float from, float to, long duration, TimeInterpolator interpolator,
+ boolean dismissOnComplete) {
+ mDismissAnimator.cancel();
+ mDismissOnComplete = dismissOnComplete;
+ mDismissAnimator.setFloatValues(from, to);
+ mDismissAnimator.setDuration(duration);
+ mDismissAnimator.setInterpolator(interpolator);
+ mDismissAnimator.start();
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float value = (Float) animation.getAnimatedValue();
+ setProgress(value * getWidth());
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mWasCanceled = false;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mWasCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mWasCanceled) {
+ if (mDismissOnComplete) {
+ dismiss();
+ } else {
+ cancel();
+ }
+ }
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+ }
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 77934fe..e447dd2 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -249,6 +249,7 @@
libGLESv1_CM \
libGLESv2 \
libvulkan \
+ libziparchive \
libETC1 \
libhardware \
libhardware_legacy \
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index d9aa8f1..178e073 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -668,42 +668,34 @@
static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
jint format, jint quality,
jobject jstream, jbyteArray jstorage) {
-
- LocalScopedBitmap bitmap(bitmapHandle);
- SkImageEncoder::Type fm;
-
+ SkEncodedImageFormat fm;
switch (format) {
case kJPEG_JavaEncodeFormat:
- fm = SkImageEncoder::kJPEG_Type;
+ fm = SkEncodedImageFormat::kJPEG;
break;
case kPNG_JavaEncodeFormat:
- fm = SkImageEncoder::kPNG_Type;
+ fm = SkEncodedImageFormat::kPNG;
break;
case kWEBP_JavaEncodeFormat:
- fm = SkImageEncoder::kWEBP_Type;
+ fm = SkEncodedImageFormat::kWEBP;
break;
default:
return JNI_FALSE;
}
+ LocalScopedBitmap bitmap(bitmapHandle);
if (!bitmap.valid()) {
return JNI_FALSE;
}
- bool success = false;
-
std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
if (!strm.get()) {
return JNI_FALSE;
}
- std::unique_ptr<SkImageEncoder> encoder(SkImageEncoder::Create(fm));
- if (encoder.get()) {
- SkBitmap skbitmap;
- bitmap->getSkBitmap(&skbitmap);
- success = encoder->encodeStream(strm.get(), skbitmap, quality);
- }
- return success ? JNI_TRUE : JNI_FALSE;
+ SkBitmap skbitmap;
+ bitmap->getSkBitmap(&skbitmap);
+ return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
}
static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 2923f94..e86acc4 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -48,31 +48,31 @@
using namespace android;
-jstring encodedFormatToString(JNIEnv* env, SkEncodedFormat format) {
+jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format) {
const char* mimeType;
switch (format) {
- case SkEncodedFormat::kBMP_SkEncodedFormat:
+ case SkEncodedImageFormat::kBMP:
mimeType = "image/bmp";
break;
- case SkEncodedFormat::kGIF_SkEncodedFormat:
+ case SkEncodedImageFormat::kGIF:
mimeType = "image/gif";
break;
- case SkEncodedFormat::kICO_SkEncodedFormat:
+ case SkEncodedImageFormat::kICO:
mimeType = "image/x-ico";
break;
- case SkEncodedFormat::kJPEG_SkEncodedFormat:
+ case SkEncodedImageFormat::kJPEG:
mimeType = "image/jpeg";
break;
- case SkEncodedFormat::kPNG_SkEncodedFormat:
+ case SkEncodedImageFormat::kPNG:
mimeType = "image/png";
break;
- case SkEncodedFormat::kWEBP_SkEncodedFormat:
+ case SkEncodedImageFormat::kWEBP:
mimeType = "image/webp";
break;
- case SkEncodedFormat::kWBMP_SkEncodedFormat:
+ case SkEncodedImageFormat::kWBMP:
mimeType = "image/vnd.wap.wbmp";
break;
- case SkEncodedFormat::kDNG_SkEncodedFormat:
+ case SkEncodedImageFormat::kDNG:
mimeType = "image/x-adobe-dng";
break;
default:
@@ -309,7 +309,8 @@
// Set the options and return if the client only wants the size.
if (options != NULL) {
- jstring mimeType = encodedFormatToString(env, codec->getEncodedFormat());
+ jstring mimeType = encodedFormatToString(
+ env, (SkEncodedImageFormat)codec->getEncodedFormat());
if (env->ExceptionCheck()) {
return nullObjectReturn("OOM in encodedFormatToString()");
}
diff --git a/core/jni/android/graphics/BitmapFactory.h b/core/jni/android/graphics/BitmapFactory.h
index 07825df..76db41d 100644
--- a/core/jni/android/graphics/BitmapFactory.h
+++ b/core/jni/android/graphics/BitmapFactory.h
@@ -2,7 +2,7 @@
#define _ANDROID_GRAPHICS_BITMAP_FACTORY_H_
#include "GraphicsJNI.h"
-#include "SkEncodedFormat.h"
+#include "SkEncodedImageFormat.h"
extern jclass gOptions_class;
extern jfieldID gOptions_justBoundsFieldID;
@@ -20,7 +20,7 @@
extern jfieldID gOptions_mCancelID;
extern jfieldID gOptions_bitmapFieldID;
-jstring encodedFormatToString(JNIEnv* env, SkEncodedFormat format);
+jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format);
jobject decodeBitmap(JNIEnv* env, void* data, size_t size);
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 3b2d5d2..3247851 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -187,7 +187,7 @@
env->SetIntField(options, gOptions_widthFieldID, bitmap.width());
env->SetIntField(options, gOptions_heightFieldID, bitmap.height());
env->SetObjectField(options, gOptions_mimeFieldID,
- encodedFormatToString(env, brd->getEncodedFormat()));
+ encodedFormatToString(env, (SkEncodedImageFormat)brd->getEncodedFormat()));
if (env->ExceptionCheck()) {
return nullObjectReturn("OOM in encodedFormatToString()");
}
diff --git a/core/jni/android/graphics/Movie_FactoryDefault.cpp b/core/jni/android/graphics/Movie_FactoryDefault.cpp
index 175e0a6..610f08f 100644
--- a/core/jni/android/graphics/Movie_FactoryDefault.cpp
+++ b/core/jni/android/graphics/Movie_FactoryDefault.cpp
@@ -7,6 +7,7 @@
#include "Movie.h"
#include "SkStream.h"
+#include "SkTRegistry.h"
typedef SkTRegistry<Movie*(*)(SkStreamRewindable*)> MovieReg;
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 04a7543..a31bd80 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -183,26 +183,46 @@
return result ? JNI_TRUE : JNI_FALSE;
}
+// SkRegion::Op and SkClipOp are numerically identical, so we can freely cast
+// from one to the other (though SkClipOp is destined to become a strict subset)
+static_assert(SkRegion::kDifference_Op == static_cast<SkRegion::Op>(kDifference_SkClipOp), "");
+static_assert(SkRegion::kIntersect_Op == static_cast<SkRegion::Op>(kIntersect_SkClipOp), "");
+static_assert(SkRegion::kUnion_Op == static_cast<SkRegion::Op>(kUnion_SkClipOp), "");
+static_assert(SkRegion::kXOR_Op == static_cast<SkRegion::Op>(kXOR_SkClipOp), "");
+static_assert(SkRegion::kReverseDifference_Op == static_cast<SkRegion::Op>(kReverseDifference_SkClipOp), "");
+static_assert(SkRegion::kReplace_Op == static_cast<SkRegion::Op>(kReplace_SkClipOp), "");
+
+static SkClipOp opHandleToClipOp(jint opHandle) {
+ // The opHandle is defined in Canvas.java to be Region::Op
+ SkRegion::Op rgnOp = static_cast<SkRegion::Op>(opHandle);
+
+ // In the future, when we no longer support the wide range of ops (e.g. Union, Xor)
+ // this function can perform a range check and throw an unsupported-exception.
+ // e.g. if (rgnOp != kIntersect && rgnOp != kDifference) throw...
+
+ // Skia now takes a different type, SkClipOp, as the parameter to clipping calls
+ // This type is binary compatible with SkRegion::Op, so a static_cast<> is safe.
+ return static_cast<SkClipOp>(rgnOp);
+}
+
static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
jfloat r, jfloat b, jint opHandle) {
- SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
- bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
+ bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b,
+ opHandleToClipOp(opHandle));
return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
}
static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
jint opHandle) {
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
- bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op);
+ bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, opHandleToClipOp(opHandle));
return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
}
static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
jint opHandle) {
SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
- SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
- bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
+ bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, opHandleToClipOp(opHandle));
return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
}
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index f4135c2..64c9fe8 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -600,6 +600,9 @@
static void
android_glColorPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -618,17 +621,29 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data ) */
static void
android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -644,20 +659,34 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data ) */
static void
android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -674,9 +703,14 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) */
@@ -781,6 +815,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -885,6 +925,12 @@
jint _remaining;
GLvoid *indices = (GLvoid *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (GLvoid *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -1026,6 +1072,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1144,6 +1196,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1278,6 +1336,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1424,6 +1488,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1542,6 +1612,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1676,6 +1752,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1825,6 +1907,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1947,11 +2035,20 @@
static void
android_glLoadMatrixf__Ljava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *m = (GLfloat *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfloat *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1960,9 +2057,14 @@
glLoadMatrixf(
(GLfloat *)m
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLoadMatrixx ( const GLfixed *m ) */
@@ -2011,11 +2113,20 @@
static void
android_glLoadMatrixx__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2024,9 +2135,14 @@
glLoadMatrixx(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLogicOp ( GLenum opcode ) */
@@ -2134,6 +2250,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2279,6 +2401,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2383,11 +2511,20 @@
static void
android_glMultMatrixf__Ljava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *m = (GLfloat *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfloat *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2396,9 +2533,14 @@
glMultMatrixf(
(GLfloat *)m
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultMatrixx ( const GLfixed *m ) */
@@ -2447,11 +2589,20 @@
static void
android_glMultMatrixx__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2460,9 +2611,14 @@
glMultMatrixx(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultiTexCoord4f ( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q ) */
@@ -2517,6 +2673,9 @@
static void
android_glNormalPointerBounds__IILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2534,6 +2693,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */
@@ -2630,11 +2792,20 @@
static void
android_glReadPixels__IIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *pixels = (GLvoid *) 0;
+ if (!pixels_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pixels == null";
+ goto exit;
+ }
pixels = (GLvoid *)getPointer(_env, pixels_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pixels == NULL) {
char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -2649,8 +2820,13 @@
(GLenum)type,
(GLvoid *)pixels
);
+
+exit:
if (_array) {
- releasePointer(_env, _array, pixels, JNI_TRUE);
+ releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2776,6 +2952,9 @@
static void
android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2794,6 +2973,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexEnvf ( GLenum target, GLenum pname, GLfloat param ) */
@@ -2880,6 +3062,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3001,6 +3189,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3042,6 +3236,9 @@
static void
android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3068,6 +3265,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterf ( GLenum target, GLenum pname, GLfloat param ) */
@@ -3096,6 +3296,9 @@
static void
android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3122,6 +3325,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTranslatef ( GLfloat x, GLfloat y, GLfloat z ) */
@@ -3150,6 +3356,9 @@
static void
android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3168,6 +3377,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height ) */
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 4dc4233..533bda4 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -540,6 +540,12 @@
jint _exponentRemaining;
GLint *exponent = (GLint *) 0;
+ if (!mantissa_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "mantissa == null";
+ goto exit;
+ }
mantissa = (GLfixed *)getPointer(_env, mantissa_buf, (jarray*)&_mantissaArray, &_mantissaRemaining, &_mantissaBufferOffset);
if (_mantissaRemaining < 16) {
_exception = 1;
@@ -547,6 +553,12 @@
_exceptionMessage = "remaining() < 16 < needed";
goto exit;
}
+ if (!exponent_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "exponent == null";
+ goto exit;
+ }
exponent = (GLint *)getPointer(_env, exponent_buf, (jarray*)&_exponentArray, &_exponentRemaining, &_exponentBufferOffset);
if (_exponentRemaining < 16) {
_exception = 1;
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 2625e03..923f7a8 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -505,6 +505,12 @@
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < size) {
_exception = 1;
@@ -587,6 +593,12 @@
jint _remaining;
GLfloat *equation = (GLfloat *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfloat *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (equation == NULL) {
char * _equationBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -596,6 +608,8 @@
(GLenum)plane,
(GLfloat *)equation
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)equation, JNI_ABORT);
}
@@ -659,6 +673,12 @@
jint _remaining;
GLfixed *equation = (GLfixed *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfixed *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (equation == NULL) {
char * _equationBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -668,6 +688,8 @@
(GLenum)plane,
(GLfixed *)equation
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)equation, JNI_ABORT);
}
@@ -761,6 +783,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -865,6 +893,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -967,6 +1001,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -1054,6 +1094,12 @@
jint _remaining;
GLfloat *eqn = (GLfloat *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfloat *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -1140,6 +1186,12 @@
jint _remaining;
GLfixed *eqn = (GLfixed *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfixed *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -1212,11 +1264,20 @@
static void
android_glGetFixedv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1226,8 +1287,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1333,6 +1399,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1471,6 +1543,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1607,6 +1685,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1741,6 +1825,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1863,6 +1953,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1973,6 +2069,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2083,6 +2185,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2182,6 +2290,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2270,6 +2384,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2358,6 +2478,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2499,6 +2625,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2595,6 +2727,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2624,6 +2762,9 @@
static void
android_glPointSizePointerOESBounds__IILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2641,6 +2782,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
@@ -2739,6 +2883,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2838,6 +2988,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2937,6 +3093,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3025,6 +3187,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index fb85cb0..f7498d5 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -572,6 +572,12 @@
jint _remaining;
GLshort *coords = (GLshort *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLshort *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -656,6 +662,12 @@
jint _remaining;
GLint *coords = (GLint *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLint *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -740,6 +752,12 @@
jint _remaining;
GLfixed *coords = (GLfixed *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLfixed *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -837,6 +855,12 @@
jint _remaining;
GLfloat *coords = (GLfloat *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLfloat *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -865,11 +889,20 @@
static void
android_glEGLImageTargetTexture2DOES__ILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jobject image_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLeglImageOES image = (GLeglImageOES) 0;
+ if (!image_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "image == null";
+ goto exit;
+ }
image = (GLeglImageOES)getPointer(_env, image_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (image == NULL) {
char * _imageBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -879,8 +912,13 @@
(GLenum)target,
(GLeglImageOES)image
);
+
+exit:
if (_array) {
- releasePointer(_env, _array, image, JNI_TRUE);
+ releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -888,11 +926,20 @@
static void
android_glEGLImageTargetRenderbufferStorageOES__ILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jobject image_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLeglImageOES image = (GLeglImageOES) 0;
+ if (!image_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "image == null";
+ goto exit;
+ }
image = (GLeglImageOES)getPointer(_env, image_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (image == NULL) {
char * _imageBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -902,8 +949,13 @@
(GLenum)target,
(GLeglImageOES)image
);
+
+exit:
if (_array) {
- releasePointer(_env, _array, image, JNI_TRUE);
+ releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -985,11 +1037,20 @@
static void
android_glClipPlanexOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *equation = (GLfixed *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfixed *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (equation == NULL) {
char * _equationBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -999,9 +1060,14 @@
(GLenum)plane,
(GLfixed *)equation
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)equation, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glColor4xOES ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha ) */
@@ -1083,11 +1149,20 @@
static void
android_glFogxvOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1097,9 +1172,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glFrustumxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ) */
@@ -1177,6 +1257,12 @@
jint _remaining;
GLfixed *eqn = (GLfixed *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfixed *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -1249,11 +1335,20 @@
static void
android_glGetFixedvOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1263,8 +1358,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1316,11 +1416,20 @@
static void
android_glGetLightxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1331,8 +1440,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1384,11 +1498,20 @@
static void
android_glGetMaterialxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1399,8 +1522,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1452,11 +1580,20 @@
static void
android_glGetTexEnvxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1467,8 +1604,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1520,11 +1662,20 @@
static void
android_glGetTexParameterxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1535,8 +1686,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1597,11 +1753,20 @@
static void
android_glLightModelxvOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1611,9 +1776,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLightxOES ( GLenum light, GLenum pname, GLfixed param ) */
@@ -1675,11 +1845,20 @@
static void
android_glLightxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1690,9 +1869,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLineWidthxOES ( GLfixed width ) */
@@ -1750,11 +1934,20 @@
static void
android_glLoadMatrixxOES__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1763,9 +1956,14 @@
glLoadMatrixxOES(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMaterialxOES ( GLenum face, GLenum pname, GLfixed param ) */
@@ -1827,11 +2025,20 @@
static void
android_glMaterialxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1842,9 +2049,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultMatrixxOES ( const GLfixed *m ) */
@@ -1893,11 +2105,20 @@
static void
android_glMultMatrixxOES__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1906,9 +2127,14 @@
glMultMatrixxOES(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultiTexCoord4xOES ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q ) */
@@ -2006,11 +2232,20 @@
static void
android_glPointParameterxvOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2020,9 +2255,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glPointSizexOES ( GLfixed size ) */
@@ -2136,11 +2376,20 @@
static void
android_glTexEnvxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2151,9 +2400,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterxOES ( GLenum target, GLenum pname, GLfixed param ) */
@@ -2215,11 +2469,20 @@
static void
android_glTexParameterxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2230,9 +2493,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTranslatexOES ( GLfixed x, GLfixed y, GLfixed z ) */
@@ -2328,6 +2596,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -2414,6 +2688,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -2513,6 +2793,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2621,6 +2907,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -2707,6 +2999,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -2831,6 +3129,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2887,6 +3191,9 @@
static void
android_glMatrixIndexPointerOESBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2905,12 +3212,18 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glWeightPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) */
static void
android_glWeightPointerOESBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2929,6 +3242,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glDepthRangefOES ( GLclampf zNear, GLclampf zFar ) */
@@ -3016,11 +3332,20 @@
static void
android_glClipPlanefOES__ILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *equation = (GLfloat *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfloat *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (equation == NULL) {
char * _equationBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3030,9 +3355,14 @@
(GLenum)plane,
(GLfloat *)equation
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)equation, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn ) */
@@ -3096,6 +3426,12 @@
jint _remaining;
GLfloat *eqn = (GLfloat *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfloat *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -3189,11 +3525,20 @@
static void
android_glTexGenfvOES__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3204,9 +3549,14 @@
(GLenum)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexGeniOES ( GLenum coord, GLenum pname, GLint param ) */
@@ -3268,11 +3618,20 @@
static void
android_glTexGenivOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3283,9 +3642,14 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexGenxOES ( GLenum coord, GLenum pname, GLfixed param ) */
@@ -3347,11 +3711,20 @@
static void
android_glTexGenxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3362,9 +3735,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params ) */
@@ -3415,11 +3793,20 @@
static void
android_glGetTexGenfvOES__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3430,8 +3817,13 @@
(GLenum)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3483,11 +3875,20 @@
static void
android_glGetTexGenivOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3498,8 +3899,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3551,11 +3957,20 @@
static void
android_glGetTexGenxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3566,8 +3981,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index b5c0b64..791233b 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -640,6 +640,12 @@
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < size) {
_exception = 1;
@@ -742,11 +748,20 @@
static void
android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -762,20 +777,34 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data ) */
static void
android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -792,9 +821,14 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) */
@@ -919,6 +953,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1005,6 +1045,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1100,6 +1146,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1195,6 +1247,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1317,6 +1375,12 @@
jint _remaining;
GLvoid *indices = (GLvoid *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (GLvoid *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -1471,6 +1535,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1566,6 +1636,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1652,6 +1728,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1738,6 +1820,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -2514,6 +2602,12 @@
goto exit;
}
}
+ if (!shaders_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "shaders == null";
+ goto exit;
+ }
shaders = (GLuint *)getPointer(_env, shaders_buf, (jarray*)&_shadersArray, &_shadersRemaining, &_shadersBufferOffset);
if (_shadersRemaining < maxcount) {
_exception = 1;
@@ -2659,6 +2753,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2758,11 +2858,20 @@
static void
android_glGetFramebufferAttachmentParameteriv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2774,8 +2883,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2856,6 +2970,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2963,6 +3083,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3051,6 +3177,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3194,6 +3326,12 @@
jint _precisionRemaining;
GLint *precision = (GLint *) 0;
+ if (!range_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "range == null";
+ goto exit;
+ }
range = (GLint *)getPointer(_env, range_buf, (jarray*)&_rangeArray, &_rangeRemaining, &_rangeBufferOffset);
if (_rangeRemaining < 1) {
_exception = 1;
@@ -3201,6 +3339,12 @@
_exceptionMessage = "remaining() < 1 < needed";
goto exit;
}
+ if (!precision_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "precision == null";
+ goto exit;
+ }
precision = (GLint *)getPointer(_env, precision_buf, (jarray*)&_precisionArray, &_precisionRemaining, &_precisionBufferOffset);
if (_precisionRemaining < 1) {
_exception = 1;
@@ -3409,6 +3553,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3497,6 +3647,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3585,6 +3741,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3673,6 +3835,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3806,6 +3974,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3916,6 +4090,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -4082,11 +4262,20 @@
static void
android_glReadPixels__IIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *pixels = (GLvoid *) 0;
+ if (!pixels_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pixels == null";
+ goto exit;
+ }
pixels = (GLvoid *)getPointer(_env, pixels_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pixels == NULL) {
char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -4101,8 +4290,13 @@
(GLenum)type,
(GLvoid *)pixels
);
+
+exit:
if (_array) {
- releasePointer(_env, _array, pixels, JNI_TRUE);
+ releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4179,6 +4373,12 @@
_env->GetIntArrayElements(shaders_ref, (jboolean *)0);
shaders = shaders_base + offset;
+ if (!binary_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binary == null";
+ goto exit;
+ }
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_array, &_binaryRemaining, &_bufferOffset);
if (_binaryRemaining < length) {
_exception = 1;
@@ -4227,7 +4427,19 @@
jint _binaryRemaining;
GLvoid *binary = (GLvoid *) 0;
+ if (!shaders_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "shaders == null";
+ goto exit;
+ }
shaders = (GLuint *)getPointer(_env, shaders_buf, (jarray*)&_shadersArray, &_shadersRemaining, &_shadersBufferOffset);
+ if (!binary_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binary == null";
+ goto exit;
+ }
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_binaryArray, &_binaryRemaining, &_binaryBufferOffset);
if (_binaryRemaining < length) {
_exception = 1;
@@ -4349,6 +4561,9 @@
static void
android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -4375,6 +4590,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterf ( GLenum target, GLenum pname, GLfloat param ) */
@@ -4450,6 +4668,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -4549,6 +4773,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -4579,6 +4809,9 @@
static void
android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -4605,6 +4838,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniform1f ( GLint location, GLfloat x ) */
@@ -4679,6 +4915,12 @@
jint _remaining;
GLfloat *v = (GLfloat *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLfloat *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -4777,6 +5019,12 @@
jint _remaining;
GLint *v = (GLint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -4876,6 +5124,12 @@
jint _remaining;
GLfloat *v = (GLfloat *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLfloat *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*2) {
_exception = 1;
@@ -4975,6 +5229,12 @@
jint _remaining;
GLint *v = (GLint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*2) {
_exception = 1;
@@ -5075,6 +5335,12 @@
jint _remaining;
GLfloat *v = (GLfloat *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLfloat *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*3) {
_exception = 1;
@@ -5175,6 +5441,12 @@
jint _remaining;
GLint *v = (GLint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*3) {
_exception = 1;
@@ -5276,6 +5548,12 @@
jint _remaining;
GLfloat *v = (GLfloat *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLfloat *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*4) {
_exception = 1;
@@ -5377,6 +5655,12 @@
jint _remaining;
GLint *v = (GLint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*4) {
_exception = 1;
@@ -5466,6 +5750,12 @@
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*4) {
_exception = 1;
@@ -5556,6 +5846,12 @@
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*9) {
_exception = 1;
@@ -5646,6 +5942,12 @@
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*16) {
_exception = 1;
@@ -5762,6 +6064,12 @@
jint _remaining;
GLfloat *values = (GLfloat *) 0;
+ if (!values_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "values == null";
+ goto exit;
+ }
values = (GLfloat *)getPointer(_env, values_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -5859,6 +6167,12 @@
jint _remaining;
GLfloat *values = (GLfloat *) 0;
+ if (!values_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "values == null";
+ goto exit;
+ }
values = (GLfloat *)getPointer(_env, values_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 2) {
_exception = 1;
@@ -5957,6 +6271,12 @@
jint _remaining;
GLfloat *values = (GLfloat *) 0;
+ if (!values_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "values == null";
+ goto exit;
+ }
values = (GLfloat *)getPointer(_env, values_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 3) {
_exception = 1;
@@ -6056,6 +6376,12 @@
jint _remaining;
GLfloat *values = (GLfloat *) 0;
+ if (!values_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "values == null";
+ goto exit;
+ }
values = (GLfloat *)getPointer(_env, values_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -6099,6 +6425,9 @@
static void
android_glVertexAttribPointerBounds__IIIZILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint indx, jint size, jint type, jboolean normalized, jint stride, jobject ptr_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -6119,6 +6448,9 @@
(GLvoid *)ptr,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height ) */
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 59b8911..736fd99 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -455,11 +455,20 @@
static void
android_glDrawRangeElements__IIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint mode, jint start, jint end, jint count, jint type, jobject indices_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *indices = (GLvoid *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (GLvoid *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (indices == NULL) {
char * _indicesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -473,9 +482,14 @@
(GLenum)type,
(GLvoid *)indices
);
+
+exit:
if (_array) {
releasePointer(_env, _array, indices, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glDrawRangeElements ( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLsizei offset ) */
@@ -496,6 +510,9 @@
static void
android_glTexImage3D__IIIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint depth, jint border, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -523,6 +540,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexImage3D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLsizei offset ) */
@@ -547,11 +567,20 @@
static void
android_glTexSubImage3D__IIIIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint zoffset, jint width, jint height, jint depth, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *pixels = (GLvoid *) 0;
+ if (!pixels_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pixels == null";
+ goto exit;
+ }
pixels = (GLvoid *)getPointer(_env, pixels_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pixels == NULL) {
char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -570,9 +599,14 @@
(GLenum)type,
(GLvoid *)pixels
);
+
+exit:
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexSubImage3D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei offset ) */
@@ -615,11 +649,20 @@
static void
android_glCompressedTexImage3D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint depth, jint border, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -636,9 +679,14 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexImage3D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, GLsizei offset ) */
@@ -662,11 +710,20 @@
static void
android_glCompressedTexSubImage3D__IIIIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint zoffset, jint width, jint height, jint depth, jint format, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -685,9 +742,14 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexSubImage3D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, GLsizei offset ) */
@@ -756,11 +818,20 @@
static void
android_glGenQueries__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject ids_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (ids == NULL) {
char * _idsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -770,8 +841,13 @@
(GLsizei)n,
(GLuint *)ids
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)ids, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)ids, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -822,11 +898,20 @@
static void
android_glDeleteQueries__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject ids_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (ids == NULL) {
char * _idsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -836,9 +921,14 @@
(GLsizei)n,
(GLuint *)ids
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)ids, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* GLboolean glIsQuery ( GLuint id ) */
@@ -919,11 +1009,20 @@
static void
android_glGetQueryiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -934,8 +1033,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -987,11 +1091,20 @@
static void
android_glGetQueryObjectuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint id, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1002,8 +1115,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1076,11 +1194,20 @@
static void
android_glDrawBuffers__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject bufs_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLenum *bufs = (GLenum *) 0;
+ if (!bufs_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "bufs == null";
+ goto exit;
+ }
bufs = (GLenum *)getPointer(_env, bufs_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (bufs == NULL) {
char * _bufsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1090,9 +1217,14 @@
(GLsizei)n,
(GLenum *)bufs
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)bufs, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix2x3fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1144,11 +1276,20 @@
static void
android_glUniformMatrix2x3fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1160,9 +1301,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix3x2fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1214,11 +1360,20 @@
static void
android_glUniformMatrix3x2fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1230,9 +1385,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix2x4fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1284,11 +1444,20 @@
static void
android_glUniformMatrix2x4fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1300,9 +1469,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix4x2fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1354,11 +1528,20 @@
static void
android_glUniformMatrix4x2fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1370,9 +1553,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix3x4fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1424,11 +1612,20 @@
static void
android_glUniformMatrix3x4fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1440,9 +1637,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix4x3fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1494,11 +1696,20 @@
static void
android_glUniformMatrix4x3fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1510,9 +1721,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glBlitFramebuffer ( GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter ) */
@@ -1639,11 +1855,20 @@
static void
android_glDeleteVertexArrays__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject arrays_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *arrays = (GLuint *) 0;
+ if (!arrays_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "arrays == null";
+ goto exit;
+ }
arrays = (GLuint *)getPointer(_env, arrays_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (arrays == NULL) {
char * _arraysBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1653,9 +1878,14 @@
(GLsizei)n,
(GLuint *)arrays
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)arrays, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGenVertexArrays ( GLsizei n, GLuint *arrays ) */
@@ -1705,11 +1935,20 @@
static void
android_glGenVertexArrays__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject arrays_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *arrays = (GLuint *) 0;
+ if (!arrays_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "arrays == null";
+ goto exit;
+ }
arrays = (GLuint *)getPointer(_env, arrays_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (arrays == NULL) {
char * _arraysBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1719,8 +1958,13 @@
(GLsizei)n,
(GLuint *)arrays
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)arrays, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)arrays, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1783,11 +2027,20 @@
static void
android_glGetIntegeri_v__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint index, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *data = (GLint *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLint *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1798,8 +2051,13 @@
(GLuint)index,
(GLint *)data
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)data, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)data, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2240,6 +2498,9 @@
static void
android_glVertexAttribIPointerBounds__IIIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint index, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2259,6 +2520,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glVertexAttribIPointer ( GLuint index, GLint size, GLenum type, GLsizei stride, GLsizei offset ) */
@@ -2322,11 +2586,20 @@
static void
android_glGetVertexAttribIiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint index, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2337,8 +2610,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2390,11 +2668,20 @@
static void
android_glGetVertexAttribIuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint index, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2405,8 +2692,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2483,11 +2775,20 @@
static void
android_glVertexAttribI4iv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint index, jobject v_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *v = (GLint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (v == NULL) {
char * _vBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2497,9 +2798,14 @@
(GLuint)index,
(GLint *)v
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)v, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glVertexAttribI4uiv ( GLuint index, const GLuint *v ) */
@@ -2549,11 +2855,20 @@
static void
android_glVertexAttribI4uiv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint index, jobject v_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *v = (GLuint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLuint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (v == NULL) {
char * _vBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2563,9 +2878,14 @@
(GLuint)index,
(GLuint *)v
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)v, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetUniformuiv ( GLuint program, GLint location, GLuint *params ) */
@@ -2616,11 +2936,20 @@
static void
android_glGetUniformuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2631,8 +2960,13 @@
(GLint)location,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2764,11 +3098,20 @@
static void
android_glUniform1uiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2779,9 +3122,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniform2uiv ( GLint location, GLsizei count, const GLuint *value ) */
@@ -2832,11 +3180,20 @@
static void
android_glUniform2uiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2847,9 +3204,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniform3uiv ( GLint location, GLsizei count, const GLuint *value ) */
@@ -2900,11 +3262,20 @@
static void
android_glUniform3uiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2915,9 +3286,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniform4uiv ( GLint location, GLsizei count, const GLuint *value ) */
@@ -2968,11 +3344,20 @@
static void
android_glUniform4uiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2983,9 +3368,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glClearBufferiv ( GLenum buffer, GLint drawbuffer, const GLint *value ) */
@@ -3036,11 +3426,20 @@
static void
android_glClearBufferiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint buffer, jint drawbuffer, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *value = (GLint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3051,9 +3450,14 @@
(GLint)drawbuffer,
(GLint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glClearBufferuiv ( GLenum buffer, GLint drawbuffer, const GLuint *value ) */
@@ -3104,11 +3508,20 @@
static void
android_glClearBufferuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint buffer, jint drawbuffer, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3119,9 +3532,14 @@
(GLint)drawbuffer,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glClearBufferfv ( GLenum buffer, GLint drawbuffer, const GLfloat *value ) */
@@ -3172,11 +3590,20 @@
static void
android_glClearBufferfv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint buffer, jint drawbuffer, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3187,9 +3614,14 @@
(GLint)drawbuffer,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glClearBufferfi ( GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil ) */
@@ -3453,6 +3885,9 @@
static void
android_glGetActiveUniformsiv__IILjava_nio_IntBuffer_2ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint uniformCount, jobject uniformIndices_buf, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _uniformIndicesArray = (jintArray) 0;
jint _uniformIndicesBufferOffset = (jint) 0;
jintArray _paramsArray = (jintArray) 0;
@@ -3462,7 +3897,19 @@
jint _paramsRemaining;
GLint *params = (GLint *) 0;
+ if (!uniformIndices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "uniformIndices == null";
+ goto exit;
+ }
uniformIndices = (GLuint *)getPointer(_env, uniformIndices_buf, (jarray*)&_uniformIndicesArray, &_uniformIndicesRemaining, &_uniformIndicesBufferOffset);
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_paramsArray, &_paramsRemaining, &_paramsBufferOffset);
if (uniformIndices == NULL) {
char * _uniformIndicesBase = (char *)_env->GetIntArrayElements(_uniformIndicesArray, (jboolean *) 0);
@@ -3479,12 +3926,17 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_paramsArray) {
- _env->ReleaseIntArrayElements(_paramsArray, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_paramsArray, (jint*)params, _exception ? JNI_ABORT : 0);
}
if (_uniformIndicesArray) {
_env->ReleaseIntArrayElements(_uniformIndicesArray, (jint*)uniformIndices, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* GLuint glGetUniformBlockIndex ( GLuint program, const GLchar *uniformBlockName ) */
@@ -3570,11 +4022,20 @@
static void
android_glGetActiveUniformBlockiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint uniformBlockIndex, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3586,8 +4047,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3877,11 +4343,20 @@
static void
android_glGetInteger64v__ILjava_nio_LongBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jlongArray _array = (jlongArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint64 *params = (GLint64 *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint64 *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetLongArrayElements(_array, (jboolean *) 0);
@@ -3891,8 +4366,13 @@
(GLenum)pname,
(GLint64 *)params
);
+
+exit:
if (_array) {
- _env->ReleaseLongArrayElements(_array, (jlong*)params, 0);
+ _env->ReleaseLongArrayElements(_array, (jlong*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3966,6 +4446,9 @@
static void
android_glGetSynciv__JIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jlong sync, jint pname, jint bufSize, jobject length_buf, jobject values_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _lengthArray = (jintArray) 0;
jint _lengthBufferOffset = (jint) 0;
jintArray _valuesArray = (jintArray) 0;
@@ -3978,6 +4461,12 @@
if (length_buf) {
length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
}
+ if (!values_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "values == null";
+ goto exit;
+ }
values = (GLint *)getPointer(_env, values_buf, (jarray*)&_valuesArray, &_valuesRemaining, &_valuesBufferOffset);
if (length_buf && length == NULL) {
char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
@@ -3994,11 +4483,16 @@
(GLsizei *)length,
(GLint *)values
);
+
+exit:
if (_valuesArray) {
- _env->ReleaseIntArrayElements(_valuesArray, (jint*)values, 0);
+ _env->ReleaseIntArrayElements(_valuesArray, (jint*)values, _exception ? JNI_ABORT : 0);
}
if (_lengthArray) {
- _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, 0);
+ _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4050,11 +4544,20 @@
static void
android_glGetInteger64i_v__IILjava_nio_LongBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint index, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jlongArray _array = (jlongArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint64 *data = (GLint64 *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLint64 *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetLongArrayElements(_array, (jboolean *) 0);
@@ -4065,8 +4568,13 @@
(GLuint)index,
(GLint64 *)data
);
+
+exit:
if (_array) {
- _env->ReleaseLongArrayElements(_array, (jlong*)data, 0);
+ _env->ReleaseLongArrayElements(_array, (jlong*)data, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4118,11 +4626,20 @@
static void
android_glGetBufferParameteri64v__IILjava_nio_LongBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jlongArray _array = (jlongArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint64 *params = (GLint64 *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint64 *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetLongArrayElements(_array, (jboolean *) 0);
@@ -4133,8 +4650,13 @@
(GLenum)pname,
(GLint64 *)params
);
+
+exit:
if (_array) {
- _env->ReleaseLongArrayElements(_array, (jlong*)params, 0);
+ _env->ReleaseLongArrayElements(_array, (jlong*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4185,11 +4707,20 @@
static void
android_glGenSamplers__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint count, jobject samplers_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *samplers = (GLuint *) 0;
+ if (!samplers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "samplers == null";
+ goto exit;
+ }
samplers = (GLuint *)getPointer(_env, samplers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (samplers == NULL) {
char * _samplersBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4199,8 +4730,13 @@
(GLsizei)count,
(GLuint *)samplers
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)samplers, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)samplers, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4251,11 +4787,20 @@
static void
android_glDeleteSamplers__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint count, jobject samplers_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *samplers = (GLuint *) 0;
+ if (!samplers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "samplers == null";
+ goto exit;
+ }
samplers = (GLuint *)getPointer(_env, samplers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (samplers == NULL) {
char * _samplersBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4265,9 +4810,14 @@
(GLsizei)count,
(GLuint *)samplers
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)samplers, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* GLboolean glIsSampler ( GLuint sampler ) */
@@ -4350,11 +4900,20 @@
static void
android_glSamplerParameteriv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *param = (GLint *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLint *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4365,9 +4924,14 @@
(GLenum)pname,
(GLint *)param
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glSamplerParameterf ( GLuint sampler, GLenum pname, GLfloat param ) */
@@ -4429,11 +4993,20 @@
static void
android_glSamplerParameterfv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *param = (GLfloat *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLfloat *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -4444,9 +5017,14 @@
(GLenum)pname,
(GLfloat *)param
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetSamplerParameteriv ( GLuint sampler, GLenum pname, GLint *params ) */
@@ -4497,11 +5075,20 @@
static void
android_glGetSamplerParameteriv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4512,8 +5099,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4565,11 +5157,20 @@
static void
android_glGetSamplerParameterfv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -4580,8 +5181,13 @@
(GLenum)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4652,11 +5258,20 @@
static void
android_glDeleteTransformFeedbacks__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject ids_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (ids == NULL) {
char * _idsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4666,9 +5281,14 @@
(GLsizei)n,
(GLuint *)ids
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)ids, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGenTransformFeedbacks ( GLsizei n, GLuint *ids ) */
@@ -4718,11 +5338,20 @@
static void
android_glGenTransformFeedbacks__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject ids_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (ids == NULL) {
char * _idsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4732,8 +5361,13 @@
(GLsizei)n,
(GLuint *)ids
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)ids, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)ids, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4810,6 +5444,12 @@
_env->GetIntArrayElements(binaryFormat_ref, (jboolean *)0);
binaryFormat = binaryFormat_base + binaryFormatOffset;
+ if (!binary_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binary == null";
+ goto exit;
+ }
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_array, &_binaryRemaining, &_bufferOffset);
if (binary == NULL) {
char * _binaryBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -4844,6 +5484,9 @@
static void
android_glGetProgramBinary__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint program, jint bufSize, jobject length_buf, jobject binaryFormat_buf, jobject binary_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _lengthArray = (jintArray) 0;
jint _lengthBufferOffset = (jint) 0;
jintArray _binaryFormatArray = (jintArray) 0;
@@ -4860,7 +5503,19 @@
if (length_buf) {
length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
}
+ if (!binaryFormat_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binaryFormat == null";
+ goto exit;
+ }
binaryFormat = (GLenum *)getPointer(_env, binaryFormat_buf, (jarray*)&_binaryFormatArray, &_binaryFormatRemaining, &_binaryFormatBufferOffset);
+ if (!binary_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binary == null";
+ goto exit;
+ }
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_binaryArray, &_binaryRemaining, &_binaryBufferOffset);
if (length_buf && length == NULL) {
char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
@@ -4881,14 +5536,19 @@
(GLenum *)binaryFormat,
(GLvoid *)binary
);
+
+exit:
if (_binaryArray) {
- releasePointer(_env, _binaryArray, binary, JNI_TRUE);
+ releasePointer(_env, _binaryArray, binary, _exception ? JNI_FALSE : JNI_TRUE);
}
if (_binaryFormatArray) {
- _env->ReleaseIntArrayElements(_binaryFormatArray, (jint*)binaryFormat, 0);
+ _env->ReleaseIntArrayElements(_binaryFormatArray, (jint*)binaryFormat, _exception ? JNI_ABORT : 0);
}
if (_lengthArray) {
- _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, 0);
+ _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4896,11 +5556,20 @@
static void
android_glProgramBinary__IILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint program, jint binaryFormat, jobject binary_buf, jint length) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *binary = (GLvoid *) 0;
+ if (!binary_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binary == null";
+ goto exit;
+ }
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (binary == NULL) {
char * _binaryBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -4912,9 +5581,14 @@
(GLvoid *)binary,
(GLsizei)length
);
+
+exit:
if (_array) {
releasePointer(_env, _array, binary, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramParameteri ( GLuint program, GLenum pname, GLint value ) */
@@ -4976,11 +5650,20 @@
static void
android_glInvalidateFramebuffer__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint numAttachments, jobject attachments_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLenum *attachments = (GLenum *) 0;
+ if (!attachments_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "attachments == null";
+ goto exit;
+ }
attachments = (GLenum *)getPointer(_env, attachments_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (attachments == NULL) {
char * _attachmentsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4991,9 +5674,14 @@
(GLsizei)numAttachments,
(GLenum *)attachments
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)attachments, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glInvalidateSubFramebuffer ( GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height ) */
@@ -5048,11 +5736,20 @@
static void
android_glInvalidateSubFramebuffer__IILjava_nio_IntBuffer_2IIII
(JNIEnv *_env, jobject _this, jint target, jint numAttachments, jobject attachments_buf, jint x, jint y, jint width, jint height) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLenum *attachments = (GLenum *) 0;
+ if (!attachments_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "attachments == null";
+ goto exit;
+ }
attachments = (GLenum *)getPointer(_env, attachments_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (attachments == NULL) {
char * _attachmentsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -5067,9 +5764,14 @@
(GLsizei)width,
(GLsizei)height
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)attachments, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexStorage2D ( GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height ) */
@@ -5149,11 +5851,20 @@
static void
android_glGetInternalformativ__IIIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint internalformat, jint pname, jint bufSize, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -5166,8 +5877,13 @@
(GLsizei)bufSize,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/jni/android_opengl_GLES31.cpp b/core/jni/android_opengl_GLES31.cpp
index 156e7bd..0e596dc 100644
--- a/core/jni/android_opengl_GLES31.cpp
+++ b/core/jni/android_opengl_GLES31.cpp
@@ -547,11 +547,20 @@
static void
android_glGetFramebufferParameteriv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -562,8 +571,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -616,11 +630,20 @@
static void
android_glGetProgramInterfaceiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint programInterface, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -632,8 +655,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -777,6 +805,9 @@
static void
android_glGetProgramResourceiv__IIIILjava_nio_IntBuffer_2ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint programInterface, jint index, jint propCount, jobject props_buf, jint bufSize, jobject length_buf, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _propsArray = (jintArray) 0;
jint _propsBufferOffset = (jint) 0;
jintArray _lengthArray = (jintArray) 0;
@@ -790,10 +821,22 @@
jint _paramsRemaining;
GLint *params = (GLint *) 0;
+ if (!props_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "props == null";
+ goto exit;
+ }
props = (GLenum *)getPointer(_env, props_buf, (jarray*)&_propsArray, &_propsRemaining, &_propsBufferOffset);
if (length_buf) {
length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
}
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_paramsArray, &_paramsRemaining, &_paramsBufferOffset);
if (props == NULL) {
char * _propsBase = (char *)_env->GetIntArrayElements(_propsArray, (jboolean *) 0);
@@ -817,15 +860,20 @@
(GLsizei *)length,
(GLint *)params
);
+
+exit:
if (_paramsArray) {
- _env->ReleaseIntArrayElements(_paramsArray, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_paramsArray, (jint*)params, _exception ? JNI_ABORT : 0);
}
if (_lengthArray) {
- _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, 0);
+ _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, _exception ? JNI_ABORT : 0);
}
if (_propsArray) {
_env->ReleaseIntArrayElements(_propsArray, (jint*)props, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* GLint glGetProgramResourceLocation ( GLuint program, GLenum programInterface, const GLchar *name ) */
@@ -1008,11 +1056,20 @@
static void
android_glDeleteProgramPipelines__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject pipelines_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *pipelines = (GLuint *) 0;
+ if (!pipelines_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pipelines == null";
+ goto exit;
+ }
pipelines = (GLuint *)getPointer(_env, pipelines_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pipelines == NULL) {
char * _pipelinesBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1022,9 +1079,14 @@
(GLsizei)n,
(GLuint *)pipelines
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)pipelines, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGenProgramPipelines ( GLsizei n, GLuint *pipelines ) */
@@ -1074,11 +1136,20 @@
static void
android_glGenProgramPipelines__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject pipelines_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *pipelines = (GLuint *) 0;
+ if (!pipelines_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pipelines == null";
+ goto exit;
+ }
pipelines = (GLuint *)getPointer(_env, pipelines_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pipelines == NULL) {
char * _pipelinesBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1088,8 +1159,13 @@
(GLsizei)n,
(GLuint *)pipelines
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)pipelines, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)pipelines, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1152,11 +1228,20 @@
static void
android_glGetProgramPipelineiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pipeline, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1167,8 +1252,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1371,11 +1461,20 @@
static void
android_glProgramUniform1iv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *value = (GLint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1387,9 +1486,14 @@
(GLsizei)count,
(GLint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform2iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
@@ -1441,11 +1545,20 @@
static void
android_glProgramUniform2iv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *value = (GLint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1457,9 +1570,14 @@
(GLsizei)count,
(GLint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform3iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
@@ -1511,11 +1629,20 @@
static void
android_glProgramUniform3iv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *value = (GLint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1527,9 +1654,14 @@
(GLsizei)count,
(GLint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform4iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
@@ -1581,11 +1713,20 @@
static void
android_glProgramUniform4iv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *value = (GLint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1597,9 +1738,14 @@
(GLsizei)count,
(GLint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform1uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
@@ -1651,11 +1797,20 @@
static void
android_glProgramUniform1uiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1667,9 +1822,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform2uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
@@ -1721,11 +1881,20 @@
static void
android_glProgramUniform2uiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1737,9 +1906,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform3uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
@@ -1791,11 +1965,20 @@
static void
android_glProgramUniform3uiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1807,9 +1990,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform4uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
@@ -1861,11 +2049,20 @@
static void
android_glProgramUniform4uiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1877,9 +2074,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform1fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
@@ -1931,11 +2133,20 @@
static void
android_glProgramUniform1fv__IIILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1947,9 +2158,14 @@
(GLsizei)count,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform2fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
@@ -2001,11 +2217,20 @@
static void
android_glProgramUniform2fv__IIILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2017,9 +2242,14 @@
(GLsizei)count,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform3fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
@@ -2071,11 +2301,20 @@
static void
android_glProgramUniform3fv__IIILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2087,9 +2326,14 @@
(GLsizei)count,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform4fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
@@ -2141,11 +2385,20 @@
static void
android_glProgramUniform4fv__IIILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2157,9 +2410,14 @@
(GLsizei)count,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2212,11 +2470,20 @@
static void
android_glProgramUniformMatrix2fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2229,9 +2496,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2284,11 +2556,20 @@
static void
android_glProgramUniformMatrix3fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2301,9 +2582,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2356,11 +2642,20 @@
static void
android_glProgramUniformMatrix4fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2373,9 +2668,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix2x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2428,11 +2728,20 @@
static void
android_glProgramUniformMatrix2x3fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2445,9 +2754,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix3x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2500,11 +2814,20 @@
static void
android_glProgramUniformMatrix3x2fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2517,9 +2840,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix2x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2572,11 +2900,20 @@
static void
android_glProgramUniformMatrix2x4fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2589,9 +2926,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix4x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2644,11 +2986,20 @@
static void
android_glProgramUniformMatrix4x2fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2661,9 +3012,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix3x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2716,11 +3072,20 @@
static void
android_glProgramUniformMatrix3x4fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2733,9 +3098,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix4x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2788,11 +3158,20 @@
static void
android_glProgramUniformMatrix4x3fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2805,9 +3184,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glValidateProgramPipeline ( GLuint pipeline ) */
@@ -2901,11 +3285,20 @@
static void
android_glGetBooleani_v__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint index, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLboolean *data = (GLboolean *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLboolean *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2916,8 +3309,13 @@
(GLuint)index,
(GLboolean *)data
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)data, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)data, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3001,11 +3399,20 @@
static void
android_glGetMultisamplefv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jint index, jobject val_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *val = (GLfloat *) 0;
+ if (!val_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "val == null";
+ goto exit;
+ }
val = (GLfloat *)getPointer(_env, val_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (val == NULL) {
char * _valBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3016,8 +3423,13 @@
(GLuint)index,
(GLfloat *)val
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)val, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)val, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3080,11 +3492,20 @@
static void
android_glGetTexLevelParameteriv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3096,8 +3517,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3150,11 +3576,20 @@
static void
android_glGetTexLevelParameterfv__IIILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3166,8 +3601,13 @@
(GLenum)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/jni/android_opengl_GLES31Ext.cpp b/core/jni/android_opengl_GLES31Ext.cpp
index 5be7be0..9f2b0c5 100644
--- a/core/jni/android_opengl_GLES31Ext.cpp
+++ b/core/jni/android_opengl_GLES31Ext.cpp
@@ -499,11 +499,20 @@
static void
android_glDebugMessageControlKHR__IIIILjava_nio_IntBuffer_2Z
(JNIEnv *_env, jobject _this, jint source, jint type, jint severity, jint count, jobject ids_buf, jboolean enabled) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (ids == NULL) {
char * _idsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -517,9 +526,14 @@
(GLuint *)ids,
(GLboolean)enabled
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)ids, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glDebugMessageInsertKHR ( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf ) */
@@ -915,11 +929,20 @@
static void
android_glTexParameterIivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -930,9 +953,14 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterIuivEXT ( GLenum target, GLenum pname, const GLuint *params ) */
@@ -983,11 +1011,20 @@
static void
android_glTexParameterIuivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -998,9 +1035,14 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetTexParameterIivEXT ( GLenum target, GLenum pname, GLint *params ) */
@@ -1051,11 +1093,20 @@
static void
android_glGetTexParameterIivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1066,8 +1117,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1119,11 +1175,20 @@
static void
android_glGetTexParameterIuivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1134,8 +1199,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1187,11 +1257,20 @@
static void
android_glSamplerParameterIivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *param = (GLint *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLint *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1202,9 +1281,14 @@
(GLenum)pname,
(GLint *)param
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glSamplerParameterIuivEXT ( GLuint sampler, GLenum pname, const GLuint *param ) */
@@ -1255,11 +1339,20 @@
static void
android_glSamplerParameterIuivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *param = (GLuint *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLuint *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1270,9 +1363,14 @@
(GLenum)pname,
(GLuint *)param
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetSamplerParameterIivEXT ( GLuint sampler, GLenum pname, GLint *params ) */
@@ -1323,11 +1421,20 @@
static void
android_glGetSamplerParameterIivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1338,8 +1445,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1391,11 +1503,20 @@
static void
android_glGetSamplerParameterIuivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1406,8 +1527,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/jni/android_opengl_GLES32.cpp b/core/jni/android_opengl_GLES32.cpp
index f9a1a8e..aa917a0 100644
--- a/core/jni/android_opengl_GLES32.cpp
+++ b/core/jni/android_opengl_GLES32.cpp
@@ -535,6 +535,12 @@
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -852,6 +858,12 @@
jint _remaining;
void *indices = (void *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (void *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count-basevertex) {
_exception = 1;
@@ -892,6 +904,12 @@
jint _remaining;
void *indices = (void *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (void *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count-basevertex) {
_exception = 1;
@@ -1022,6 +1040,12 @@
jint _remaining;
void *data = (void *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (void *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < bufSize) {
_exception = 1;
@@ -1116,6 +1140,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < bufSize) {
_exception = 1;
@@ -1206,6 +1236,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < bufSize) {
_exception = 1;
@@ -1296,6 +1332,12 @@
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < bufSize) {
_exception = 1;
@@ -1390,11 +1432,20 @@
static void
android_glTexParameterIiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1405,9 +1456,14 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterIuiv ( GLenum target, GLenum pname, const GLuint *params ) */
@@ -1458,11 +1514,20 @@
static void
android_glTexParameterIuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1473,9 +1538,14 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetTexParameterIiv ( GLenum target, GLenum pname, GLint *params ) */
@@ -1526,11 +1596,20 @@
static void
android_glGetTexParameterIiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1541,8 +1620,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1594,11 +1678,20 @@
static void
android_glGetTexParameterIuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1609,8 +1702,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1662,11 +1760,20 @@
static void
android_glSamplerParameterIiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *param = (GLint *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLint *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1677,9 +1784,14 @@
(GLenum)pname,
(GLint *)param
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glSamplerParameterIuiv ( GLuint sampler, GLenum pname, const GLuint *param ) */
@@ -1730,11 +1842,20 @@
static void
android_glSamplerParameterIuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *param = (GLuint *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLuint *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1745,9 +1866,14 @@
(GLenum)pname,
(GLuint *)param
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetSamplerParameterIiv ( GLuint sampler, GLenum pname, GLint *params ) */
@@ -1798,11 +1924,20 @@
static void
android_glGetSamplerParameterIiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1813,8 +1948,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1866,11 +2006,20 @@
static void
android_glGetSamplerParameterIuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1881,8 +2030,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 10090a1..740b24d 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -25,6 +25,8 @@
#include <JNIHelp.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/base/1.0/IBase.h>
+#include <android/hidl/base/1.0/IHwBase.h>
#include <android_runtime/AndroidRuntime.h>
#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
@@ -240,10 +242,17 @@
sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
+ sp<hidl::base::V1_0::IBase> base = hidl::base::V1_0::IHwBase::asInterface(binder);
+ if (base.get() == nullptr) {
+ LOG(ERROR) << "IBinder object cannot be casted to the base interface.";
+ signalExceptionForError(env, UNKNOWN_ERROR);
+ return;
+ }
+
bool ok = hardware::defaultServiceManager()->add(
interfaceChain,
serviceName,
- binder);
+ base);
env->ReleaseStringUTFChars(serviceNameObj, serviceName);
serviceName = NULL;
@@ -289,8 +298,10 @@
hardware::defaultServiceManager()->get(
ifaceName,
serviceName,
- [&service](sp<hardware::IBinder> out) {
- service = out;
+ [&service](sp<hidl::base::V1_0::IBase> out) {
+ service = hardware::toBinder<
+ hidl::base::V1_0::IBase, hidl::base::V1_0::IHwBase
+ >(out);
});
env->ReleaseStringUTFChars(ifaceNameObj, ifaceName);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index d70fbb9..d382f24 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1179,67 +1179,17 @@
return result ? JNI_TRUE : JNI_FALSE;
}
-static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
- jlong themeToken,
- jint defStyleAttr,
- jint defStyleRes,
- jlong xmlParserToken,
- jintArray attrs,
- jintArray outValues,
- jintArray outIndices)
-{
- if (themeToken == 0) {
- jniThrowNullPointerException(env, "theme token");
- return JNI_FALSE;
- }
- if (attrs == NULL) {
- jniThrowNullPointerException(env, "attrs");
- return JNI_FALSE;
- }
- if (outValues == NULL) {
- jniThrowNullPointerException(env, "out values");
- return JNI_FALSE;
- }
-
- const jsize NI = env->GetArrayLength(attrs);
- const jsize NV = env->GetArrayLength(outValues);
- if (NV < (NI*STYLE_NUM_ENTRIES)) {
- jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
- return JNI_FALSE;
- }
-
- jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
- if (src == NULL) {
- return JNI_FALSE;
- }
-
- jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
- if (baseDest == NULL) {
- env->ReleasePrimitiveArrayCritical(attrs, src, 0);
- return JNI_FALSE;
- }
-
- jint* indices = NULL;
- if (outIndices != NULL) {
- if (env->GetArrayLength(outIndices) > NI) {
- indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
- }
- }
-
+static void android_content_AssetManager_applyStyle(JNIEnv* env, jobject, jlong themeToken,
+ jint defStyleAttr, jint defStyleRes, jlong xmlParserToken, jintArray attrsObj, jint length,
+ jlong outValuesAddress, jlong outIndicesAddress) {
+ jint* attrs = env->GetIntArrayElements(attrsObj, 0);
ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
- bool result = ApplyStyle(theme, xmlParser,
- defStyleAttr, defStyleRes,
- (uint32_t*) src, NI,
- (uint32_t*) baseDest,
- (uint32_t*) indices);
-
- if (indices != NULL) {
- env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
- }
- env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
- env->ReleasePrimitiveArrayCritical(attrs, src, 0);
- return result ? JNI_TRUE : JNI_FALSE;
+ uint32_t* outValues = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outValuesAddress));
+ uint32_t* outIndices = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outIndicesAddress));
+ ApplyStyle(theme, xmlParser, defStyleAttr, defStyleRes,
+ reinterpret_cast<const uint32_t*>(attrs), length, outValues, outIndices);
+ env->ReleaseIntArrayElements(attrsObj, attrs, JNI_ABORT);
}
static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
@@ -1795,7 +1745,7 @@
{ "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
(void*) android_content_AssetManager_dumpTheme },
// @FastNative
- { "applyStyle","(JIIJ[I[I[I)Z",
+ { "applyStyle","(JIIJ[IIJJ)V",
(void*) android_content_AssetManager_applyStyle },
// @FastNative
{ "resolveAttrs","(JII[I[I[I[I)Z",
diff --git a/core/jni/android_util_MemoryIntArray.cpp b/core/jni/android_util_MemoryIntArray.cpp
index 9513c8b..2dfbe3e 100644
--- a/core/jni/android_util_MemoryIntArray.cpp
+++ b/core/jni/android_util_MemoryIntArray.cpp
@@ -54,7 +54,7 @@
}
static jlong android_util_MemoryIntArray_open(JNIEnv* env, jobject clazz, jint fd,
- jboolean owner, jboolean writable)
+ jboolean owner)
{
if (fd < 0) {
jniThrowException(env, "java/io/IOException", "bad file descriptor");
@@ -72,19 +72,35 @@
return -1;
}
- int protMode = (owner || writable) ? (PROT_READ | PROT_WRITE) : PROT_READ;
+ // IMPORTANT: Ashmem allows the caller to change its size until
+ // it is memory mapped for the first time which lazily creates
+ // the underlying VFS file. So the size we get above may not
+ // reflect the size of the underlying shared memory region. Therefore,
+ // we first memory map to set the size in stone an verify if
+ // the underlying ashmem region has the same size as the one we
+ // memory mapped. This is critical as we use the underlying
+ // ashmem size for boundary checks and memory unmapping.
+ int protMode = owner ? (PROT_READ | PROT_WRITE) : PROT_READ;
void* ashmemAddr = mmap(NULL, ashmemSize, protMode, MAP_SHARED, fd, 0);
if (ashmemAddr == MAP_FAILED) {
jniThrowException(env, "java/io/IOException", "cannot mmap ashmem");
return -1;
}
+ // Check if the mapped size is the same as the ashmem region.
+ int mmapedSize = ashmem_get_size_region(fd);
+ if (mmapedSize != ashmemSize) {
+ munmap(reinterpret_cast<void *>(ashmemAddr), ashmemSize);
+ jniThrowException(env, "java/io/IOException", "bad file descriptor");
+ return -1;
+ }
+
if (owner) {
int size = ashmemSize / sizeof(std::atomic_int);
new (ashmemAddr) std::atomic_int[size];
}
- if (owner && !writable) {
+ if (owner) {
int setProtResult = ashmem_set_prot_region(fd, PROT_READ);
if (setProtResult < 0) {
jniThrowException(env, "java/io/IOException", "cannot set ashmem prot mode");
@@ -131,7 +147,7 @@
}
static jint android_util_MemoryIntArray_get(JNIEnv* env, jobject clazz,
- jint fd, jlong address, jint index, jboolean owner)
+ jint fd, jlong address, jint index)
{
if (fd < 0) {
jniThrowException(env, "java/io/IOException", "bad file descriptor");
@@ -153,7 +169,7 @@
}
static void android_util_MemoryIntArray_set(JNIEnv* env, jobject clazz,
- jint fd, jlong address, jint index, jint newValue, jboolean owner)
+ jint fd, jlong address, jint index, jint newValue)
{
if (fd < 0) {
jniThrowException(env, "java/io/IOException", "bad file descriptor");
@@ -195,10 +211,10 @@
static const JNINativeMethod methods[] = {
{"nativeCreate", "(Ljava/lang/String;I)I", (void*)android_util_MemoryIntArray_create},
- {"nativeOpen", "(IZZ)J", (void*)android_util_MemoryIntArray_open},
+ {"nativeOpen", "(IZ)J", (void*)android_util_MemoryIntArray_open},
{"nativeClose", "(IJZ)V", (void*)android_util_MemoryIntArray_close},
- {"nativeGet", "(IJIZ)I", (void*)android_util_MemoryIntArray_get},
- {"nativeSet", "(IJIIZ)V", (void*) android_util_MemoryIntArray_set},
+ {"nativeGet", "(IJI)I", (void*)android_util_MemoryIntArray_get},
+ {"nativeSet", "(IJII)V", (void*) android_util_MemoryIntArray_set},
{"nativeSize", "(I)I", (void*) android_util_MemoryIntArray_size},
};
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index 4b105ca..53c9ff0 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -196,7 +196,8 @@
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
nativeCanvas->setBitmap(bitmap);
- nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom);
+ nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom,
+ kIntersect_SkClipOp);
if (dirtyRect) {
INVOKEV(dirtyRect, gRectClassInfo.set,
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index b6c81cf8..63997e5 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -339,7 +339,7 @@
if (dirtyRectPtr) {
nativeCanvas->clipRect(dirtyRect.left, dirtyRect.top,
- dirtyRect.right, dirtyRect.bottom);
+ dirtyRect.right, dirtyRect.bottom, kIntersect_SkClipOp);
}
if (dirtyRectObj) {
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 268aec5..351dce9 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -166,7 +166,8 @@
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
nativeCanvas->setBitmap(bitmap);
- nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom);
+ nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom,
+ kIntersect_SkClipOp);
if (dirtyRect) {
INVOKEV(dirtyRect, gRectClassInfo.set,
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index ad7d744..bf0e9ed 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -420,6 +420,9 @@
static void
android_glColorPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -438,17 +441,29 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data ) */
static void
android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -464,20 +479,34 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data ) */
static void
android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -494,9 +523,14 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) */
@@ -601,6 +635,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -705,6 +745,12 @@
jint _remaining;
GLvoid *indices = (GLvoid *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (GLvoid *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -860,6 +906,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1006,6 +1058,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1154,6 +1212,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1580,6 +1644,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2038,6 +2108,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2166,6 +2242,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2322,6 +2404,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2505,6 +2593,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2644,11 +2738,20 @@
static void
android_glLoadMatrixf__Ljava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *m = (GLfloat *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfloat *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2657,9 +2760,14 @@
glLoadMatrixf(
(GLfloat *)m
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLoadMatrixx ( const GLfixed *m ) */
@@ -2708,11 +2816,20 @@
static void
android_glLoadMatrixx__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2721,9 +2838,14 @@
glLoadMatrixx(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLogicOp ( GLenum opcode ) */
@@ -2836,6 +2958,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2991,6 +3119,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3100,11 +3234,20 @@
static void
android_glMultMatrixf__Ljava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *m = (GLfloat *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfloat *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3113,9 +3256,14 @@
glMultMatrixf(
(GLfloat *)m
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultMatrixx ( const GLfixed *m ) */
@@ -3164,11 +3312,20 @@
static void
android_glMultMatrixx__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3177,9 +3334,14 @@
glMultMatrixx(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultiTexCoord4f ( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q ) */
@@ -3234,6 +3396,9 @@
static void
android_glNormalPointerBounds__IILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3251,6 +3416,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */
@@ -3347,11 +3515,20 @@
static void
android_glReadPixels__IIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *pixels = (GLvoid *) 0;
+ if (!pixels_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pixels == null";
+ goto exit;
+ }
pixels = (GLvoid *)getPointer(_env, pixels_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pixels == NULL) {
char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -3366,8 +3543,13 @@
(GLenum)type,
(GLvoid *)pixels
);
+
+exit:
if (_array) {
- releasePointer(_env, _array, pixels, JNI_TRUE);
+ releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3493,6 +3675,9 @@
static void
android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3511,6 +3696,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexEnvf ( GLenum target, GLenum pname, GLfloat param ) */
@@ -3608,6 +3796,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3751,6 +3945,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3803,6 +4003,9 @@
static void
android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3829,6 +4032,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterf ( GLenum target, GLenum pname, GLfloat param ) */
@@ -3857,6 +4063,9 @@
static void
android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3883,6 +4092,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTranslatef ( GLfloat x, GLfloat y, GLfloat z ) */
@@ -3911,6 +4123,9 @@
static void
android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3929,6 +4144,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height ) */
@@ -4041,6 +4259,12 @@
jint _exponentRemaining;
GLint *exponent = (GLint *) 0;
+ if (!mantissa_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "mantissa == null";
+ goto exit;
+ }
mantissa = (GLfixed *)getPointer(_env, mantissa_buf, (jarray*)&_mantissaArray, &_mantissaRemaining, &_mantissaBufferOffset);
if (_mantissaRemaining < 16) {
_exception = 1;
@@ -4048,6 +4272,12 @@
_exceptionMessage = "remaining() < 16 < needed";
goto exit;
}
+ if (!exponent_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "exponent == null";
+ goto exit;
+ }
exponent = (GLint *)getPointer(_env, exponent_buf, (jarray*)&_exponentArray, &_exponentRemaining, &_exponentBufferOffset);
if (_exponentRemaining < 16) {
_exception = 1;
@@ -4144,6 +4374,12 @@
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < size) {
_exception = 1;
@@ -4232,6 +4468,12 @@
jint _remaining;
GLfloat *equation = (GLfloat *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfloat *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -4318,6 +4560,12 @@
jint _remaining;
GLfixed *equation = (GLfixed *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfixed *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -4428,6 +4676,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -4532,6 +4786,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -4604,11 +4864,20 @@
static void
android_glGetBooleanv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLboolean *params = (GLboolean *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLboolean *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4618,8 +4887,13 @@
(GLenum)pname,
(GLboolean *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4686,11 +4960,20 @@
static void
android_glGetClipPlanef__ILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *eqn = (GLfloat *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfloat *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (eqn == NULL) {
char * _eqnBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -4700,8 +4983,13 @@
(GLenum)pname,
(GLfloat *)eqn
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)eqn, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)eqn, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4752,11 +5040,20 @@
static void
android_glGetClipPlanex__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *eqn = (GLfixed *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfixed *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (eqn == NULL) {
char * _eqnBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4766,8 +5063,13 @@
(GLenum)pname,
(GLfixed *)eqn
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)eqn, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)eqn, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4818,11 +5120,20 @@
static void
android_glGetFixedv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4832,8 +5143,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4884,11 +5200,20 @@
static void
android_glGetFloatv__ILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -4898,8 +5223,13 @@
(GLenum)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -5007,6 +5337,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5179,6 +5515,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5337,6 +5679,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5481,6 +5829,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5619,6 +5973,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5751,6 +6111,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5861,6 +6227,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -5949,6 +6321,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6037,6 +6415,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6178,6 +6562,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6274,6 +6664,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6303,6 +6699,9 @@
static void
android_glPointSizePointerOESBounds__IILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -6320,6 +6719,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
@@ -6429,6 +6831,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -6539,6 +6947,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6638,6 +7052,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6726,6 +7146,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6846,6 +7272,12 @@
jint _remaining;
GLfloat *coords = (GLfloat *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLfloat *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -6943,6 +7375,12 @@
jint _remaining;
GLint *coords = (GLint *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLint *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -7040,6 +7478,12 @@
jint _remaining;
GLshort *coords = (GLshort *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLshort *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -7137,6 +7581,12 @@
jint _remaining;
GLfixed *coords = (GLfixed *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLfixed *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -7172,6 +7622,9 @@
static void
android_glMatrixIndexPointerOESBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -7190,6 +7643,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMatrixIndexPointerOES ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
@@ -7208,6 +7664,9 @@
static void
android_glWeightPointerOESBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -7226,6 +7685,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glWeightPointerOES ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
@@ -7403,6 +7865,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -7499,6 +7967,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -7644,6 +8118,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -7740,6 +8220,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -7824,11 +8310,20 @@
"glGetFramebufferAttachmentParameterivOES");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -7840,8 +8335,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -7903,11 +8403,20 @@
"glGetRenderbufferParameterivOES");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -7918,8 +8427,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -7981,11 +8495,20 @@
"glGetTexGenfv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -7996,8 +8519,13 @@
(GLint)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -8059,11 +8587,20 @@
"glGetTexGeniv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -8074,8 +8611,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -8137,11 +8679,20 @@
"glGetTexGenxv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -8152,8 +8703,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -8280,11 +8836,20 @@
"glTexGenfv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -8295,8 +8860,13 @@
(GLint)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -8374,11 +8944,20 @@
"glTexGeniv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -8389,8 +8968,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -8468,11 +9052,20 @@
"glTexGenxv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -8483,8 +9076,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 62ff85d..40fd881 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2715,6 +2715,8 @@
This is a normal permission: an app requesting it will always be granted the
permission, without the user needing to approve or see it. -->
<permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
+ android:label="@string/permlab_requestIgnoreBatteryOptimizations"
+ android:description="@string/permdesc_requestIgnoreBatteryOptimizations"
android:protectionLevel="normal" />
<!-- @SystemApi Allows an application to collect battery statistics -->
diff --git a/core/res/res/anim/slide_in_enter_micro.xml b/core/res/res/anim/slide_in_enter_micro.xml
index 6e7df4f..c70874c 100644
--- a/core/res/res/anim/slide_in_enter_micro.xml
+++ b/core/res/res/anim/slide_in_enter_micro.xml
@@ -19,7 +19,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:zAdjustment="top">
- <translate android:fromXDelta="5%p" android:toXDelta="0"
+ <translate android:fromYDelta="5%p" android:toYDelta="0"
android:duration="417"
android:interpolator="@android:interpolator/launch_task_micro_ydelta" />
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
diff --git a/core/res/res/anim/slide_out_micro.xml b/core/res/res/anim/slide_out_micro.xml
index cccf697..01df0da 100644
--- a/core/res/res/anim/slide_out_micro.xml
+++ b/core/res/res/anim/slide_out_micro.xml
@@ -20,7 +20,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:zAdjustment="normal">
- <translate android:fromXDelta="0" android:toXDelta="5%p"
+ <translate android:fromYDelta="0" android:toYDelta="5%p"
android:duration="250"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
diff --git a/core/res/res/layout/date_picker_material.xml b/core/res/res/layout/date_picker_material.xml
index 763f2a4..dd8a45d2 100644
--- a/core/res/res/layout/date_picker_material.xml
+++ b/core/res/res/layout/date_picker_material.xml
@@ -25,10 +25,16 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
- <include
- layout="@layout/date_picker_view_animator_material"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
+ <ScrollView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:fadeScrollbars="false"
+ android:scrollIndicators="top|bottom">
+ <include
+ layout="@layout/date_picker_view_animator_material"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+ </ScrollView>
</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index a24bce1..f9ae7cf 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Laat die program toe om die kitsboodskapdiens te gebruik om oproepe sonder jou ingryping te maak."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lees foonstatus en identiteit"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Laat die program toe om toegang tot die foonfunksies van die toestel te verkry. Hierdie toestemming laat die program toe om te bepaal wat die foonnommer en toestel-IDs is, of die oproep aan die gang is, en die afgeleë nommer wat deur \'n oproep verbind word."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lees foonnommer"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Gee die program toegang tot die toestel se foonnommer."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"verhoed dat tablet slaap"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"keer TV om te sluimer"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"verhoed foon om te slaap"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Laat \'n program toe om installasiesessies te lees. Dit laat dit toe om besonderhede van aktiewe pakketinstallasies te sien."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"versoek installeerpakkette"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Laat \'n program toe om te versoek dat pakkette geïnstalleer word."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Klop twee keer vir zoembeheer"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Kon nie legstuk byvoeg nie."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Gaan"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Kies jaar"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> uitgevee"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Raak en hou Terug om hierdie skerm te ontspeld."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Program is vasgespeld: Dit mag nie op hierdie toestel ontspeld word nie."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skerm vasgespeld"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Stel nou terug"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Het <xliff:g id="LABEL">%1$s</xliff:g> gedeaktiveer"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferensie-oproep"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Nutswenk-opspringer"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Nutswenk"</string>
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 6bab82c..e24ffce 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"መተግበሪያው ያለእርስዎ ጣልቃ ገብነት ጥሪዎችን ለማድረግ የአይኤምኤስ አገልግሎቱን እንዲጠቀም ያስችለዋል።"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"የስልክ ሁኔታና ማንነት አንብብ"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"መተግበሪያው የመሳሪያውን የስልክ ባህሪያት ላይ እንዲደርስ ይፈቅድለታል። ይህ ፈቃድ መተግበሪያው የስልክ ቁጥሩን እና የመሳሪያውን መታወቂያዎች፣ ጥሪ የነቃ እንደሆነ፣ እና በጥሪ የተገናኘውን የሩቅ ቁጥር እንዲወስን ይፈቅድለታል።"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ስልክ ቁጥር አንብብ"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"መተግበሪያው የመሣሪያውን ስልክ ቁጥር እንዲደርስበት ይፈቅድለታል።"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ጡባዊ ከማንቀላፋት ተከላከል"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ቴሌቪዥን እንዳይተኛ አግድ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ስልክ ከማንቀላፋት ተከላከል"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"መተግበሪያው የመጫን ክፍለ ጊዜዎችን እንዲያነብ ይፈቅድለታል። ይህም ስለ ገቢር የጥቅል ጭነቶች ዝርዝር መረጃን እንዲያይ ይፈቅድለታል።"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"የጭነት ጥቅሎችን መጠየቅ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"መተግበሪያ የጥቅሎች መጫንን እንዲጠይቅ ይፈቅዳል።"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ለአጉላ መቆጣጠሪያ ሁለት ጊዜ ነካ አድርግ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ምግብር ማከል አልተቻለም።"</string>
<string name="ime_action_go" msgid="8320845651737369027">"ሂድ"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"ዓመት ይምረጡ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ተሰርዟል"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2ኛ ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3ኛ ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ይህን ማያ ገጽ ለመንቀል ተመለስን ይንኩትና ያዙት።"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"መተግበሪያ ተሰክቷል፦ በዚህ መሣሪያ ላይ ማላቀቅ አይፈቀድም።"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ማያ ገጽ ተሰክቷል"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"አሁን ዳግም አስጀምር"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ተሰናክሏል"</string>
<string name="conference_call" msgid="3751093130790472426">"የስብሰባ ጥሪ"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"የመሣሪያ ጥቆማ ብቅ-ባይ"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"የመሣሪያ ጥቆማ"</string>
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 7c9baeb..bd0a658 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -389,6 +389,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"للسماح للتطبيق باستخدام خدمة الرسائل الفورية لإجراء المكالمات دون تدخل منك."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"قراءة حالة الهاتف والهوية"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"للسماح للتطبيق بالدخول إلى ميزات الهاتف في الجهاز. ويتيح هذا الإذن للتطبيق تحديد رقم الهاتف ومعرّفات الجهاز، وما إذا كانت هناك مكالمة نشطة والرقم البعيد الذي تم الاتصال به في المكالمة."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"قراءة رقم الهاتف"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"للسماح للتطبيق بالوصول إلى رقم الهاتف على الجهاز."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"منع الجهاز اللوحي من الدخول في وضع السكون"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"منع التلفزيون من الدخول في وضع السكون"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"منع الهاتف من الدخول في وضع السكون"</string>
@@ -783,7 +785,7 @@
<string name="js_dialog_before_unload_title" msgid="2619376555525116593">"تأكيد الانتقال"</string>
<string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"مغادرة هذه الصفحة"</string>
<string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"البقاء في هذه الصفحة"</string>
- <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nهل تريد بالتأكيد الانتقال بعيدًا عن هذه الصفحة؟"</string>
+ <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nهل تريد فعلًا الانتقال بعيدًا عن هذه الصفحة؟"</string>
<string name="save_password_label" msgid="6860261758665825069">"تأكيد"</string>
<string name="double_tap_toast" msgid="4595046515400268881">"نصيحة: اضغط مرتين للتكبير والتصغير."</string>
<string name="autofill_this_form" msgid="4616758841157816676">"ملء تلقائي"</string>
@@ -1310,6 +1312,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"للسماح لأحد التطبيقات بقراءة جلسات التثبيت. ويسمح لك هذا بالاطلاع على تفاصيل بشأن عمليات تثبيت الحزم النشطة."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"طلب حزم التثبيت"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"للسماح لتطبيق ما بطلب تثبيت الحزم."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"اضغط مرتين للتحكم في التكبير/التصغير"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"تعذرت إضافة أداة."</string>
<string name="ime_action_go" msgid="8320845651737369027">"تنفيذ"</string>
@@ -1668,10 +1674,8 @@
<string name="select_year" msgid="7952052866994196170">"تحديد العام"</string>
<string name="deleted_key" msgid="7659477886625566590">"تم حذف <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> المخصص للعمل"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"العمل الثاني <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"العمل الثالث <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"لإزالة تثبيت هذه الشاشة، يمكنك لمس زر الرجوع مع الاستمرار."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"التطبيق مقيد: ولا يسمح بإلغاء التقييد على هذا الجهاز."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"تم تثبيت الشاشة"</string>
@@ -1827,5 +1831,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"إعادة التعيين الآن"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"تم تعطيل <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"مكالمة جماعية"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"نافذة منبثقة لتلميح"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"تلميح"</string>
</resources>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 11133d1..6322bfa 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Tətbiqə müdaxilə olmadan zəng etmək üçün IMS xidmətindən istifadə etməyə imkan verir."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefon statusunu və identifikasiyanı oxuyur"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Tətbiqə cihazın telefon funksiyalarına giriş icazəsi verir. Belə icazəli tətbiq bu telefonun nömrəsini və cihaz İD\'ni, zəngin aktiv olub-olmadığını və zəng edilən nömrəni müəyyən edə bilər."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"telefon nömrəsini oxuyun"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Tətbiqə cihazın telefon nömrəsinə daxil olmağa icazə verir."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"planşetin yuxu rejiminin qarşısını almaq"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV-ni yuxu rejiminə keçməyə qoyma"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"telefonun yuxu rejiminə keçməsini əngəllə"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Tətbiqə quraşdırma sessiyalarını oxumağa yardım edir. Bu da aktiv paket quraşdırmaları haqqında məlumatları görməyə imkan verir."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"paketləri quraşdırma sorğusu"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Tətbiqə paketləri quraşdırma sorğusu göndərməyə icazə verir."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Zoom kontrolu üçün iki dəfə toxunun"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget əlavə edilə bilmədi."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Get"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"İl seçin"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> silindi"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-ci İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-cü İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Sancağı götürmək üçün Geri düyməsinə toxunun və saxlayın."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Tətbiq sancılıb: Açmağa bu cihazda icazə verilmir."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"İndi sıfırlayın"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> deaktiv edildi"</string>
<string name="conference_call" msgid="3751093130790472426">"Konfrans Zəngi"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Tooltip Popap"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tooltip"</string>
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index d2799c4..b44b180 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Dozvoljava aplikaciji da koristi uslugu razmene trenutnih poruka da bi upućivala pozive bez vaše intervencije."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čitanje statusa i identiteta telefona"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Dozvoljava aplikaciji da pristupa funkcijama telefona na uređaju. Ova dozvola omogućava aplikaciji da utvrdi broj telefona i ID-ove uređaja, zatim da li je poziv aktivan, kao i broj daljinskog uređaja sa kojim je uspostavljen poziv."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"čitanje broja telefona"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Dozvoljava aplikaciji da pristupa broju telefona na uređaju."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"sprečavanje prelaska tableta u stanje spavanja"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"sprečavanje TV-a da pređe u stanje spavanja"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"sprečavanje prelaska telefona u stanje spavanja"</string>
@@ -1235,6 +1237,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Dozvoljava aplikaciji da čita sesije instaliranja. To joj dozvoljava da vidi detalje o aktivnim instalacijama paketa."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"zahtevanje paketa za instaliranje"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Omogućava da aplikacija zahteva instalaciju paketa."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Dodirnite dvaput za kontrolu zumiranja"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nije moguće dodati vidžet."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Idi"</string>
@@ -1587,10 +1593,8 @@
<string name="select_year" msgid="7952052866994196170">"Izaberite godinu"</string>
<string name="deleted_key" msgid="7659477886625566590">"Izbrisali ste <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> na poslu"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. poslovni imejl <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Da biste otkačili ovaj ekran, dodirnite i zadržite Nazad."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je zakačena: otkačinjanje nije dozvoljeno na ovom uređaju."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran je zakačen"</string>
@@ -1719,5 +1723,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Resetuj"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Vidžet <xliff:g id="LABEL">%1$s</xliff:g> je onemogućen"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferencijski poziv"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Iskačuće objašnjenje"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Objašnjenje"</string>
</resources>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index a7be24e..b035e9c 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Дазваляе праграмам выкарыстоўваць службу IMS, каб рабіць выклікі без вашага ўмяшання."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"чытанне статусу тэлефона і ідэнтыфікацыя"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Дазваляе прыкладанням атрымлiваць доступ да функцый тэлефона на прыладзе. Дзякуючы гэтаму дазволу прыкладанне можа вызначаць iдэнтыфiкатары нумару тэлефона i прылады, незалежна ад таго, цi актыўны выклiк, i аддалены нумар, на якi робiцца выклiк."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"чытаць нумар тэлефона"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Праграма зможа атрымліваць доступ да тэлефоннага нумара прылады."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"прадухіліць планшэт ад пераходу ў рэжым сну"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"прадухіленне пераходу тэлевізара ў рэжым сну"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"забараняць тэлефону пераходзіць ў рэжым сну"</string>
@@ -1260,6 +1262,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Дазваляе праграме счытваць сеансы ўсталёўкі. Гэта дазваляе ёй праглядаць інфармацыю аб актыўных усталёўках пакета."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"запытваць усталёўку пакетаў"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Дазваляе праграме запытваць усталёўку пакетаў."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Націсніце двойчы, каб кіраваць маштабаваннем"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Немагчыма дадаць віджэт."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Пачаць"</string>
@@ -1614,10 +1620,8 @@
<string name="select_year" msgid="7952052866994196170">"Выберыце год"</string>
<string name="deleted_key" msgid="7659477886625566590">"Выдалена: <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (праца)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Другая праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Трэцяя праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Каб адмацаваць гэты экран, дакраніцеся і ўтрымлівайце кнопку \"Назад\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Праграма замацавана: адмацаванне на гэтай прыладзе не дапускаецца."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран замацаваны"</string>
@@ -1755,5 +1759,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Выканаць скід"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Адключаны <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Канферэнц-выклік"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Усплывальная падказка"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Падказка"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 1900b074..4caa906 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Разрешава на приложението да използва услугата за незабавни съобщения за извършване на обаждания без намеса от ваша страна."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"четене на състоянието и идентификационните данни на телефона"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Разрешава на приложението достъп до телефонните функции на устройството. Това разрешение позволява на приложението да определя телефонния номер и идентификационния номер на устройството, дали се води разговор и отдалечения номер, до който е установена връзка с обаждането."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"четене на телефонния номер"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Разрешава на приложението да осъществява достъп до телефонния номер на устройството."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"предотвратяване на спящия режим на таблета"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"предотвратяване на преминаването на телевизора в спящ режим"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"предотвратява спящ режим на телефона"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Разрешава на приложението да чете сесии за инсталиране. Това му позволява да вижда подробности за активните инсталирания на пакети."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"заявка на пакети за инсталиране"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Разрешава на приложението да заявява инсталиране на пакети."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Докоснете двукратно за управление на промяната на мащаба"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Приспособлението не можа да бъде добавено."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Старт"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Избиране на година"</string>
<string name="deleted_key" msgid="7659477886625566590">"Изтрихте <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> за работа"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Втори служебен профил (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Трети служебен профил (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"За да освободите този екран, докоснете и задръжте бутона за връщане назад."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Приложението е фиксирано. Освобождаването му не е разрешено на това устройство."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екранът е фиксиран"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Нулиране сега"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g>: Деактивирано"</string>
<string name="conference_call" msgid="3751093130790472426">"Конферентно обаждане"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Изскачащ прозорец с подсказка"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Подсказка"</string>
</resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index bdbea68..0c73ecd 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"আপনার হস্তক্ষেপ ছাড়াই কল করতে অ্যাপ্লিকেশানটিকে IMS পরিষেবা ব্যবহারের অনুমতি দিন৷"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ফোনের স্থিতি এবং পরিচয় পড়ুন"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"অ্যাপ্লিকেশানটিকে ডিভাইসের ফোন বৈশিষ্ট্যগুলিকে অ্যাক্সেস করার অনুমতি দেয়৷ এই অনুমতিটি অ্যাপ্লিকেশানটিকে একটি কল সক্রিয় থাকা অবস্থায় এবং দূরবর্তী নম্বর একটি কল দ্বারা সংযুক্ত থাকাকালীনও ফোন নম্বর এবং ডিভাইসের IDগুলি নির্ধারণ করার অনুমতি দেয়৷"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"অ্যাপটিকে ফোন নম্বর পড়ার অনুমতি দিন"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"অ্যাপটিকে এই ডিভাইসের ফোন নম্বর অ্যাক্সেস করার মঞ্জুরি দেয়"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ঘুমানো থেকে ট্যাবলেটকে প্রতিরোধ করে"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"টিভিকে নিদ্রায় যাওয়া থেকে প্রতিরোধ করে"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ঘুমানো থেকে ফোনটিকে প্রতিরোধ করে"</string>
@@ -605,7 +607,7 @@
<string name="phoneTypeRadio" msgid="4093738079908667513">"রেডিও"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"টেলেক্স"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
- <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"কার্যক্ষেত্রের মোবাইল"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"অফিসের মোবাইল"</string>
<string name="phoneTypeWorkPager" msgid="649938731231157056">"কার্যক্ষেত্রের পেজার"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"সহায়ক"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"মিডিয়ার ভলিউম"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"বিজ্ঞপ্তির ভলিউম"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ডিফল্ট রিংটোন"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ডিফল্ট (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"কোনো কিছুই নয়"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"রিংটোনগুলি"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"অ্যালার্মের শব্দ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"বিজ্ঞপ্তির শব্দ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"অজানা"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">ওয়াই-ফাই নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
<item quantity="other">ওয়াই-ফাই নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"কোনো অ্যাপ্লিকেশানকে সেশনগুলি পড়ার অনুমতি দেয়। এটি সক্রিয় প্যাকেজ ইনস্টলেশনের বিশদ বিবরণ দেখতে দেয়।"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"প্যাকেজগুলি ইনস্টল করার অনুরোধ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"একটি অ্যাপ্লিকেশানকে প্যাকেজগুলির ইনস্টল করার অনুরোধ জানাতে অনুমতি দেয়৷"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"জুম নিয়ন্ত্রণের জন্য দুবার আলতো চাপুন"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"উইজেট যোগ করা যায়নি৷"</string>
<string name="ime_action_go" msgid="8320845651737369027">"যান"</string>
@@ -1240,7 +1242,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"ওয়ালপেপার"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"ওয়ালপেপার পরিবর্তন করুন"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"বিজ্ঞপ্তির শ্রোতা"</string>
- <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR শ্রোতা"</string>
+ <string name="vr_listener_binding_label" msgid="4316591939343607306">"(ভিআর)VR শ্রোতা"</string>
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"শর্ত প্রদানকারী"</string>
<string name="notification_ranker_binding_label" msgid="774540592299064747">"বিজ্ঞপ্তি র্যাঙ্কার পরিষেবা"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN সক্রিয়"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"বছর নির্বাচন করুন"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> মুছে ফেলা হয়েছে"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"কর্মক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"দ্বিতীয় কার্যক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"তৃতীয় কার্যক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"এই স্ক্রীনটিকে আনপিন করতে, \'ফিরুন\' স্পর্শ করুন এবং ধরে রাখুন৷"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"অ্যাপ্লিকেশান পিন করা আছে: এই ডিভাইস এটিকে পিনমুক্ত করা মঞ্জুরিপ্রাপ্ত নয়৷"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"স্ক্রীন পিন করা হয়েছে"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"এখনই পুনরায় সেট করুন"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"অক্ষম করা <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"কনফারেন্স কল"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"সরঞ্জামটিপ"</string>
</resources>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index f62dac7..f831874 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Omogućava aplikaciji da koristi IMS uslugu za pozivanje bez vaše intervencije."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čitanje statusa i identiteta telefona"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Omogućava aplikaciji pristup telefonskim funkcijama uređaja. Ova dozvola omogućava aplikaciji određivanje telefonskog i identifikacionog broja uređaja, bez obzira da li je poziv aktivan i da li je uspostavljena veza sa pozivanim brojem."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"čitanje telefonskog broja"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Dopušta aplikaciji pristup telefonskom broju telefona."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"sprečavanje tableta da uđe u režim mirovanja"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"spriječi ulazak TV-a u režim mirovanja"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"sprečavanje telefona da uđe u režim mirovanja"</string>
@@ -646,17 +648,17 @@
<string name="relationTypeAssistant" msgid="6274334825195379076">"Pomoćnik"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"Brat"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"Dijete"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Domaći partner"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Nevjenčani partner"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"Otac"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"Prijatelj"</string>
- <string name="relationTypeManager" msgid="6365677861610137895">"Menadžer"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"Šef"</string>
<string name="relationTypeMother" msgid="4578571352962758304">"Majka"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Roditelj"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Partner"</string>
<string name="relationTypeReferredBy" msgid="101573059844135524">"Uputio(la)"</string>
- <string name="relationTypeRelative" msgid="1799819930085610271">"Rođak"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"Rođak/ica"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Sestra"</string>
- <string name="relationTypeSpouse" msgid="394136939428698117">"Bračni partner"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"Suprug/a"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"Prilagođeno"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Kuća"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Posao"</string>
@@ -1237,6 +1239,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Dozvoljava aplikaciji da čita sesije instalacija. Ovim se aplikaciji omogućava da vidi detalje o aktivnim instalacijama paketa."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"zahtijevanje paketa za instaliranje"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Omogućava aplikaciji da zahtijeva instalaciju paket ā."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Dodirnite dvaput za kontrolu uvećanja"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Dodavanje vidžeta nije uspjelo."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Počni"</string>
@@ -1589,10 +1595,8 @@
<string name="select_year" msgid="7952052866994196170">"Odaberite godinu"</string>
<string name="deleted_key" msgid="7659477886625566590">"Broj <xliff:g id="KEY">%1$s</xliff:g> je izbrisan"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Da biste otkačili ovaj ekran, dodirnite i držite dugme Nazad."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je prikačena. Na ovom uređaju nije dozvoljeno otkačivanje."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran je zakačen"</string>
@@ -1721,5 +1725,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Vrati sada na početne postavke"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Onemogućen <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferencijski poziv"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Iskočni prozor sa savjetom u vezi alata"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Savjet za alat"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index f335d44..30d1706 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permet que l\'aplicació utilitzi el servei IMS per fer trucades sense la teva intervenció."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"veure l\'estat i la identitat del telèfon"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permet que l\'aplicació accedeixi a les funcions de telèfon del dispositiu. Aquest permís permet que l\'aplicació determini el número de telèfon i els identificadors del dispositiu, si hi ha una trucada activa i el número remot connectat amb una trucada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"llegeix el número de telèfon"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permet que l\'aplicació accedeixi al número de telèfon del dispositiu."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evita que la tauleta entri en mode de repòs"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"impedir que el televisor entri en mode de repòs"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir que el telèfon entri en mode de repòs"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permet que una aplicació llegeixi les sessions d\'instal·lació i això permet veure detalls sobre les instal·lacions de paquet actives."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"sol·licitar la instal·lació de paquets"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permet que una aplicació sol·liciti la instal·lació de paquets."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Piqueu dos cops per controlar el zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"No s\'ha pogut afegir el widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Vés"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Selecciona un any"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> suprimit"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2n <xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3r <xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Toca i mantén premuda l\'opció Enrere per deixar de fixar aquesta pantalla."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"S\'ha fixat l\'aplicació. En aquest dispositiu no es permet anul·lar-ne la fixació."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fixada"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Restableix ara"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> s\'ha desactivat"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferència"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Descripció emergent"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Descripció emergent"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0bdd212..d4ffbaa 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Umožňuje aplikaci používat službu zasílání rychlých zpráv k uskutečňování hovorů bez vašeho zásahu."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čtení stavu a identity telefonu"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Umožňuje aplikaci získat přístup k telefonním funkcím zařízení. Toto oprávnění umožňuje aplikaci zjistit telefonní číslo telefonu, identifikační čísla zařízení, zda zrovna probíhá hovor, a vzdálené číslo, ke kterému je hovor připojen."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"přístup k telefonnímu číslu"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Umožňuje aplikaci zobrazit telefonní číslo zařízení."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"bránění přechodu tabletu do režimu spánku"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"zabránění přechodu televize do režimu spánku"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"bránění přechodu telefonu do režimu spánku"</string>
@@ -1260,6 +1262,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Povoluje aplikaci číst instalační relace. Díky tomu můžete zobrazit podrobnosti o aktivních instalacích balíčku."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"odesílání žádostí o přístup k instalačním balíčkům"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Umožňuje aplikaci požádat o instalaci balíčků."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Poklepáním můžete ovládat přiblížení"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget nelze přidat."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Přejít"</string>
@@ -1614,10 +1620,8 @@
<string name="select_year" msgid="7952052866994196170">"Vyberte rok"</string>
<string name="deleted_key" msgid="7659477886625566590">"Číslice <xliff:g id="KEY">%1$s</xliff:g> byla smazána"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Pracovní <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Chcete-li tuto obrazovku uvolnit, klepněte na tlačítko Zpět a podržte jej."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikace je připnutá: Odepnutí v tomto zařízení není povoleno."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Obrazovka připnuta"</string>
@@ -1755,5 +1759,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Resetovat"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – zakázáno"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferenční hovor"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Vyskakovací okno s popiskem"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Popisek"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f80f5f0..815c324 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Tillader, at appen kan bruge chat-tjenesten til at foretage opkald, uden du gør noget."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"læse telefonens status og identitet"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Tillader, at appen kan få adgang til telefonfunktionerne på enheden. Med denne tilladelse kan appen fastslå telefonnummeret og enheds-id\'erne, hvorvidt et opkald er aktivt samt det eksterne nummer, der oprettes forbindelse til via et opkald."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"læs telefonnummer"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Tillader, at appen har adgang til enhedens telefonnummer."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"afholde tabletcomputeren fra at gå i dvale"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"forhindre tv i at gå i dvale"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"afholde telefonen fra at gå i dvale"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Medielydstyrke"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Lydstyrke for meddelelser"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Standardringetone"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Standard (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Ringetoner"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Alarmlyde"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Meddelelseslyde"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Ukendt"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Tilgængelige Wi-Fi-netværk</item>
<item quantity="other">Tilgængelige Wi-Fi-netværk</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Tillader, at en applikation læser installationssessioner. Dermed kan applikationen se oplysninger om aktive pakkeinstallationer."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"anmod om installation af pakker"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Tillader, at en app anmoder om installation af pakker."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tryk to gange for zoomkontrol"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget kunne ikke tilføjes."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Gå"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Vælg år"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> er slettet"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> – arbejde"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Hvis du vil frigøre dette skærmbillede, skal du trykke på Tilbage og holde fingeren nede."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Appen er fastgjort: Det er ikke tilladt at frigøre den på denne enhed."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skærmen blev fastgjort"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Nulstil nu"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – deaktiveret"</string>
<string name="conference_call" msgid="3751093130790472426">"Telefonmøde"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Værktøjstip"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 1ceb0cc..c729160 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Ermöglicht der App die Verwendung des IMS-Dienstes zum Tätigen von Anrufen ohne Nutzereingriffe"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"Telefonstatus und Identität abrufen"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ermöglicht der App, auf die Telefonfunktionen des Geräts zuzugreifen. Die Berechtigung erlaubt der App, die Telefonnummer und Geräte-IDs zu erfassen, festzustellen, ob gerade ein Gespräch geführt wird, und die Rufnummer verbundener Anrufer zu lesen."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"Telefonnummer lesen"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Der App den Zugriff auf die Telefonnummer des Geräts erlauben."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Ruhezustand des Tablets deaktivieren"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"Ruhemodus des Fernsehers deaktivieren"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Ruhezustand deaktivieren"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Medienlautstärke"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Benachrichtigungslautstärke"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Standard-Klingelton"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Standard (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Ohne"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Klingeltöne"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Weckertöne"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Benachrichtigungstöne"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Unbekannt"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">WLAN-Netzwerke verfügbar</item>
<item quantity="one">WLAN-Netzwerk verfügbar</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ermöglicht der App, Installationssitzungen zu lesen. Dadurch kann sie Details aktiver Paketinstallationen abrufen."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"Installation von Paketen anfordern"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Ermöglicht der App, die Installation von Paketen anzufordern"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Für Zoomeinstellung zweimal berühren"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget konnte nicht hinzugefügt werden."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Los"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Jahr auswählen"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> gelöscht"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Um die Fixierung dieses Bildschirms aufzuheben, \"Zurück\" berühren und halten."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Die App ist fixiert. Das Aufheben der Fixierung ist auf diesem Gerät nicht zulässig."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Bildschirm fixiert"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Jetzt zurücksetzen"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> deaktiviert"</string>
<string name="conference_call" msgid="3751093130790472426">"Telefonkonferenz"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Kurzinfo"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index b9d9503..4f0d2f1 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Επιτρέπει στην εφαρμογή τη χρήση της υπηρεσίας IMS για την πραγματοποίηση κλήσεων χωρίς τη δική σας παρέμβαση."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"διαβάζει την κατάσταση και ταυτότητα τηλεφώνου"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Επιτρέπει στην εφαρμογή την πρόσβαση στις λειτουργίες τηλεφώνου της συσκευής. Αυτή η άδεια δίνει τη δυνατότητα στην εφαρμογή να καθορίζει τον αριθμό τηλεφώνου και τα αναγνωριστικά συσκευών, εάν μια κλήση είναι ενεργή, καθώς και τον απομακρυσμένο αριθμό που συνδέεται από μια κλήση."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ανάγνωση αριθμού τηλεφώνου"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Επιτρέπει στην εφαρμογή να έχει πρόσβαση στον αριθμό τηλεφώνου της συσκευής."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"αποτρέπει την μετάβαση του tablet σε κατάσταση αδράνειας"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"αποτρέπει την μετάβαση της τηλεόρασης σε κατάσταση αδράνειας"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"αποτρέπει το τηλεφώνο να μεταβεί σε κατάσταση αδράνειας"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Επιτρέπει σε μια εφαρμογή την ανάγνωση των περιόδων σύνδεσης εγκατάστασης. Αυτό της επιτρέπει να βλέπει λεπτομέρειες σχετικά με τις εγκαταστάσεις του ενεργού πακέτου."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ζητά πακέτα εγκατάστασης"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Επιτρέπει σε μια εφαρμογή να ζητά εγκατάσταση πακέτων."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Πατήστε δύο φορές για έλεγχο εστίασης"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Δεν ήταν δυνατή η προσθήκη του γραφικού στοιχείου."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Μετάβαση"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Επιλογή έτους"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> διαγράφηκε"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Εργασία <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> εργασίας 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> εργασίας 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Για να ξεκαρφιτσώσετε αυτήν την οθόνη, αγγίξτε παρατεταμένα \"Επιστροφή\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Η εφαρμογή καρφιτσώθηκε: Το ξεκαρφίτσωμα δεν επιτρέπεται σε αυτήν τη συσκευή."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Η οθόνη καρφιτσώθηκε"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Επαναφορά τώρα"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Απενεργοποιημένο <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Κλήση συνδιάσκεψης"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Αναδυόμενο παράθυρο επεξήγησης εργαλείου"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Επεξήγηση εργαλείου"</string>
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 5bc43e0..a85976d 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Allows the app to use the IMS service to make calls without your intervention."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"read phone status and identity"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"read phone number"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Allows the app to access the phone number of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"prevent TV from sleeping"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"prevent phone from sleeping"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Allows an application to read install sessions. This allows it to see details about active package installations."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"request install packages"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Allows an application to request installation of packages."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Go"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Select year"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"To unpin this screen, touch & hold Back."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is pinned: unpinning isn\'t allowed on this device."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reset now"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Disabled <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conference Call"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Tooltip Pop-up"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tooltip"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 5bc43e0..a85976d 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Allows the app to use the IMS service to make calls without your intervention."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"read phone status and identity"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"read phone number"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Allows the app to access the phone number of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"prevent TV from sleeping"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"prevent phone from sleeping"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Allows an application to read install sessions. This allows it to see details about active package installations."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"request install packages"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Allows an application to request installation of packages."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Go"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Select year"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"To unpin this screen, touch & hold Back."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is pinned: unpinning isn\'t allowed on this device."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reset now"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Disabled <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conference Call"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Tooltip Pop-up"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tooltip"</string>
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 5bc43e0..a85976d 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Allows the app to use the IMS service to make calls without your intervention."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"read phone status and identity"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"read phone number"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Allows the app to access the phone number of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"prevent TV from sleeping"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"prevent phone from sleeping"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Allows an application to read install sessions. This allows it to see details about active package installations."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"request install packages"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Allows an application to request installation of packages."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Go"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Select year"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"To unpin this screen, touch & hold Back."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is pinned: unpinning isn\'t allowed on this device."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reset now"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Disabled <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conference Call"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Tooltip Pop-up"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tooltip"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index cd2c5aa..19d00d0 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que la aplicación utilice el servicio IMS para hacer llamadas sin tu intervención."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"leer la identidad y el estado del dispositivo"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que la aplicación acceda a las funciones de teléfono del dispositivo. La aplicación puede utilizar este permiso para descubrir identificadores de dispositivos y números de teléfono, para saber si una llamada está activa y para conocer el número remoto con el que se ha establecido conexión mediante una llamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"leer el número de teléfono"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que la app acceda al número de teléfono del dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evitar que el tablet entre en estado de inactividad"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"evitar que la TV entre en suspensión"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"evitar que el dispositivo entre en estado de inactividad"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que una aplicación lea sesiones de instalación. Esto le permite ver detalles acerca de instalaciones de paquetes activas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar la instalación de paquetes"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite que una aplicación solicite la instalación de paquetes."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Presiona dos veces para obtener el control del zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"No se pudo agregar el widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Seleccionar año"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> borrado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Para dejar de fijar esta pantalla, mantén presionado Atrás."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"La aplicación está fijada, no se puede anular la fijación en este dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fija"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Restablecer ahora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Se inhabilitó <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferencia"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Ventana emergente de la información sobre la herramienta"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Información sobre la herramienta"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index fe7d1ac..487cf74 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que la aplicación utilice el servicio IMS para realizar llamadas sin tu intervención."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"consultar la identidad y el estado del teléfono"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que la aplicación acceda a las funciones de teléfono del dispositivo. La aplicación puede utilizar este permiso para descubrir identificadores de dispositivos y números de teléfono, para saber si una llamada está activa y para conocer el número remoto con el que se ha establecido conexión mediante una llamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"leer el número de teléfono"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que la aplicación acceda al número de teléfono del dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir que el tablet entre en modo de suspensión"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"evitar que la TV entre en suspensión"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir que el teléfono entre en modo de suspensión"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que una aplicación consulte sesiones de instalación para ver detalles sobre instalaciones de paquetes activos."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar instalación de paquetes"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite a una aplicación solicitar la instalación de paquetes."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Da dos toques para acceder al control de zoom."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"No se ha podido añadir el widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Seleccionar año"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Mantén pulsado el botón Atrás para dejar de fijar esta pantalla."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"La aplicación está fijada: no se puede deshacer la fijación en este dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fijada"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Restablecer ahora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> inhabilitado"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferencia"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Descripción emergente"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Descripción emergente"</string>
</resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 09668cb..7f46309 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Võimaldab rakendusel kasutada IMS-teenust kõnede tegemiseks ilma, et peaksite sekkuma."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lugege telefoni olekut ja identiteeti"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Annab rakendusele juurdepääsu seadme telefonifunktsioonidele. See luba võimaldab rakendusel määrata telefoninumbri ja seadme ID-d ning kontrollida, kas kõne on aktiivne ja kaugnumber on kõne kaudu telefoniga ühendatud."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lugeda telefoninumbrit"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Lubab rakendusel juurde pääseda seadme telefoninumbrile."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"tahvelarvuti uinumise vältimine"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"teleri unerežiimi lülitumise takistamine"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"väldi telefoni uinumist"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Meediumi helitugevus"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Teatise helitugevus"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Vaikehelin"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Vaikimisi (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Puudub"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Helinad"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Äratuse helid"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Märguannete helid"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Teadmata"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">WiFi-võrgud on saadaval</item>
<item quantity="one">WiFi-võrk on saadaval</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Lubab rakendusel lugeda installiseansse. See võimaldab näha aktiivse paketi installimise üksikasju."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"installipakettide taotlemine"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Võimaldab rakendusel pakettide installimist taotleda."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Suumi kasutamiseks koputage kaks korda"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Vidinat ei saanud lisada."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Mine"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Aasta valimine"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> on kustutatud"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Ekraani vabastamiseks puudutage pikalt nuppu Tagasi."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Rakendus on kinnitatud: vabastamine pole selles seadmes lubatud."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekraan on kinnitatud"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Lähtesta kohe"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Keelatud <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Konverentskõne"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tööriistavihje"</string>
</resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 2ea4bed..2490b21 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Zuk ezer egin beharrik gabe deiak egiteko IMS zerbitzua erabiltzea baimentzen die aplikazioei."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefonoaren egoera eta identitatea irakurtzea"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Gailuaren telefono-eginbideak atzitzeko baimena ematen die aplikazioei. Baimen horrek aplikazioari telefono-zenbakia eta gailu IDak zein diren, deirik aktibo dagoen eta deia zer zenbakirekin konektatuta dagoen zehazteko baimena ematen die aplikazioei."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"Irakurri telefono-zenbakia"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Gailuaren telefono-zenbakia atzitzea baimentzen dio aplikazioari."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Eragotzi tableta inaktibo ezartzea"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"Eragotzi telebista inaktibo geratzea"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Eragotzi telefonoa inaktibo ezartzea"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Instalazio-saioak irakurtzea baimentzen die aplikazioei. Horrela, pakete-instalazio aktiboei buruzko xehetasunak ikus ditzakete."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"Eskatu instalazio-paketeak"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Paketeak instalatzeko eskatzea baimentzen die aplikazioei."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Sakatu birritan zooma kontrolatzeko"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Ezin izan da widgeta gehitu."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Joan"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Hautatu urtea"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ezabatu da"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Laneko <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Laneko 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Laneko 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Pantailari aingura kentzeko, eduki sakatuta Atzera botoia."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikazioa ainguratuta dago. Gailu honetan ezin da aingura kendu."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantaila ainguratu da"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Berrezarri"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> desgaituta dago"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferentzia-deia"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Aholkudun leiho gainerakorra"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Aholkua"</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 55e67bc..63c0d2a 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"به برنامه اجازه میدهد از سرویس IMS برای برقراری تماسها بدون دخالت شما استفاده کند."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"خواندن وضعیت تلفن و شناسه"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"به برنامه اجازه میدهد به ویژگیهای تلفن دستگاه شما دسترسی پیدا کند. این مجوز به برنامه اجازه میدهد شماره تلفن و شناسههای دستگاه، فعال بودن یک تماس و شماره راه دوری که با یک تماس متصل شده است را مشخص کند."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"خواندن شماره تلفن"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"به برنامه اجازه میدهد به شماره تلفن دستگاه دسترسی پیدا کند."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ممانعت از به خواب رفتن رایانهٔ لوحی"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"جلوگیری از به حالت خواب رفتن تلویزیون"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ممانعت از به خواب رفتن تلفن"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"میزان صدای رسانه"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"میزان صدای اعلان"</string>
<string name="ringtone_default" msgid="3789758980357696936">"آهنگ زنگ پیشفرض"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"پیشفرض (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"هیچکدام"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"آهنگهای زنگ"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"صداهای زنگ هشدار"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"صداهای اعلان"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"نامشخص"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">شبکه Wi-Fi در دسترس</item>
<item quantity="other">شبکه Wi-Fi در دسترس</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"به برنامه اجازه میدهد جلسات نصب را بخواند. این کار به برنامه اجازه میدهد جزئیات نصبهای بسته فعال را ببیند."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"درخواست نصب بسته"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"به برنامه اجازه میدهد درخواست نصب بستهبندی کند."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"برای کنترل بزرگنمایی، دو بار ضربه بزنید"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"افزودن ابزارک انجام نشد."</string>
<string name="ime_action_go" msgid="8320845651737369027">"برو"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"انتخاب سال"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> حذف شد"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> محل کار"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"کار دوم <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"کار سوم <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"برای برداشتن پین این صفحه، «برگشت» را لمس کنید و نگه دارید."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"برنامه پین شده است: برداشتن پین در این دستگاه مجاز نیست."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"صفحه پین شد"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"بازنشانی در این لحظه"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> غیرفعال شد"</string>
<string name="conference_call" msgid="3751093130790472426">"تماس کنفرانسی"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"نکتهابزار"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 6800fa8..9e9d3d1 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Antaa sovelluksen soittaa puheluita pikaviestipalvelun avulla ilman käyttäjän toimia."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lue puhelimen tila ja identiteetti"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Antaa sovelluksen käyttää laitteen puhelinominaisuuksia. Sovellus voi määrittää puhelinnumeron ja laitteen tunnuksen, puhelun tilan sekä soitetun numeron."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lukea puhelinnumeron"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Anna sovelluksen käyttää laitteen puhelinnumeroa."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"estä tablet-laitetta menemästä virransäästötilaan"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"Estä television siirtyminen virransäästötilaan"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"estä puhelinta menemästä virransäästötilaan"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Sallii sovelluksen lukea asennusistuntoja. Toiminto sallii sovelluksen lukea aktiivisten asennuspakettien tietoja."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"pyytää asennuspaketteja"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Antaa sovelluksen pyytää pakettien asennusta."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Hallitse zoomausta napauttamalla kahdesti"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widgetin lisääminen epäonnistui."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Siirry"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Valitse vuosi"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> poistettiin"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (työ)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Toinen <xliff:g id="LABEL">%1$s</xliff:g>, työ"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Kolmas <xliff:g id="LABEL">%1$s</xliff:g>, työ"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Irrota näyttö koskettamalla Takaisin-painiketta pitkään."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Sovellus on kiinnitetty. Irrottaminen ei ole sallittua tällä laitteella."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Näyttö kiinnitetty"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Palauta nyt"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ei ole käytössä."</string>
<string name="conference_call" msgid="3751093130790472426">"Puhelinneuvottelu"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Työkaluvinkki ponnahdusikkunassa"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Työkaluvinkki"</string>
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 009b9eb..15aaf84 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permet à l\'application d\'utiliser le service IMS pour faire des appels sans votre intervention."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"voir l\'état et l\'identité du téléphone"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permet à l\'application d\'accéder aux fonctionnalités téléphoniques de l\'appareil. Cette autorisation permet à l\'application de déterminer le numéro de téléphone et les identifiants de l\'appareil, si un appel est actif et le numéro distant connecté par un appel."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lire le numéro de téléphone"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permet à l\'application d\'accéder au numéro de téléphone de l\'appareil."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"empêcher la tablette de passer en mode veille"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"empêcher le téléviseur de passer en mode veille"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"empêcher le téléphone de passer en mode veille"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Volume"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume des notifications"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Sonnerie par défaut"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Défaut (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Aucune"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Sonneries"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Sons d\'alarme"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Sons de notification"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Inconnu"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Réseau Wi-Fi à proximité</item>
<item quantity="other">Réseaux Wi-Fi à proximité</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permet à une application d\'accéder aux sessions d\'installation. Cela lui permet de consulter les détails relatifs à l\'installation des paquets actifs."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"demander l\'installation de paquets"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permet à une application de demander l\'installation de paquets."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Appuyer deux fois pour régler le zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Impossible d\'ajouter le widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Aller"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Sélectionnez une année"</string>
<string name="deleted_key" msgid="7659477886625566590">"« <xliff:g id="KEY">%1$s</xliff:g> » a été supprimé"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e <xliff:g id="LABEL">%1$s</xliff:g> professionnel(le)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e <xliff:g id="LABEL">%1$s</xliff:g> professionnel(le)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Pour annuler l\'épinglage de cet écran, maintenez enfoncée la touche Retour."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"L\'application est épinglée : l\'annulation de l\'épinglage n\'est pas autorisée sur cet appareil."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Écran épinglé"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Réinitialiser maintenant"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Désactivé : <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conférence téléphonique"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Infobulle"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 5b21dd4..b8fe1e0 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permet à l\'application d\'utiliser le service IMS pour passer des appels sans votre intervention."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"Voir l\'état et l\'identité du téléphone"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permet à l\'application d\'accéder aux fonctionnalités téléphoniques de l\'appareil. Cette autorisation permet à l\'application de déterminer le numéro de téléphone et les identifiants de l\'appareil, si un appel est actif et le numéro distant connecté par un appel."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lire le numéro de téléphone"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permet à l\'application d\'accéder au numéro de téléphone de l\'appareil."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"empêcher la tablette de passer en mode veille"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"empêcher l\'activation du mode veille sur le téléviseur"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"empêcher le téléphone de passer en mode veille"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Volume"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume des notifications"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Sonnerie par défaut"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Sonnerie par défaut (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Aucune"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Sonneries"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Sons de l\'alarme"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Sons de notification"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Inconnue"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Réseau Wi-Fi disponible</item>
<item quantity="other">Réseaux Wi-Fi disponibles</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permet à une application d\'accéder aux sessions d\'installation. Cela lui permet de consulter les détails relatifs à l\'installation des packages actifs."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"demander l\'installation de packages"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permet à une application de demander l\'installation de packages."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Appuyer deux fois pour régler le zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Impossible d\'ajouter le widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"OK"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Sélectionner une année"</string>
<string name="deleted_key" msgid="7659477886625566590">"\"<xliff:g id="KEY">%1$s</xliff:g>\" supprimé"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e <xliff:g id="LABEL">%1$s</xliff:g> professionnelle"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e <xliff:g id="LABEL">%1$s</xliff:g> professionnelle"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Pour annuler l\'épinglage, appuyez de manière prolongée sur \"Retour\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"L\'application est épinglée. L\'annulation de l\'épinglage n\'est pas autorisée sur cet appareil."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Écran épinglé."</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Réinitialiser maintenant"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Élément \"<xliff:g id="LABEL">%1$s</xliff:g>\" désactivé"</string>
<string name="conference_call" msgid="3751093130790472426">"Conférence téléphonique"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Info-bulle"</string>
</resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 10a7647..b3fbfe8 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que a aplicación use o servizo de IMS para facer chamadas sen a túa intervención."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ler o estado e a identidade do teléfono"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite á aplicación acceder ás funcións de teléfono do dispositivo. Con este permiso a aplicación pode determinar o número de teléfono e os ID do dispositivo, se unha chamada está activa e o número remoto conectado mediante unha chamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ler número de teléfono"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que a aplicación acceda ao número de teléfono do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evitar que a tableta entre en modo de inactividade"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"evitar que a televisión entre en modo de suspensión"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"evitar que o teléfono entre en modo de suspensión"</string>
@@ -551,7 +553,7 @@
<item msgid="7897544654242874543">"Traballo"</item>
<item msgid="1103601433382158155">"Fax do traballo"</item>
<item msgid="1735177144948329370">"Fax particular"</item>
- <item msgid="603878674477207394">"Busca"</item>
+ <item msgid="603878674477207394">"Buscapersoas"</item>
<item msgid="1650824275177931637">"Outros"</item>
<item msgid="9192514806975898961">"Personalizado"</item>
</string-array>
@@ -594,7 +596,7 @@
<string name="phoneTypeWork" msgid="8863939667059911633">"Traballo"</string>
<string name="phoneTypeFaxWork" msgid="3517792160008890912">"Fax do traballo"</string>
<string name="phoneTypeFaxHome" msgid="2067265972322971467">"Fax particular"</string>
- <string name="phoneTypePager" msgid="7582359955394921732">"Busca"</string>
+ <string name="phoneTypePager" msgid="7582359955394921732">"Buscapersoas"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"Outro"</string>
<string name="phoneTypeCallback" msgid="2712175203065678206">"Devolver chamada"</string>
<string name="phoneTypeCar" msgid="8738360689616716982">"Coche"</string>
@@ -606,7 +608,7 @@
<string name="phoneTypeTelex" msgid="3367879952476250512">"Télex"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
<string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Móbil do traballo"</string>
- <string name="phoneTypeWorkPager" msgid="649938731231157056">"Busca do traballo"</string>
+ <string name="phoneTypeWorkPager" msgid="649938731231157056">"Buscapersoas do traballo"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Asistente"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
<string name="eventTypeCustom" msgid="7837586198458073404">"Personalizados"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que unha aplicación consulte as sesións de instalación. Desta forma, pode ver os detalles acerca das instalacións de paquetes activas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar instalación de paquetes"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite a unha aplicación solicitar a instalación dos paquetes."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Toca dúas veces para controlar o zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Non se puido engadir o widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Seleccionar ano"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Para soltar a pantalla, mantén premido Volver."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"A aplicación está fixada: non se permite soltala neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fixada"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Restablecer agora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Desactivouse <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferencia telefónica"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Ventá emerxente do cadro de información"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Cadro de información"</string>
</resources>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 9a7d432..d8578c9 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"તમારા હસ્તક્ષેપ વગર કૉલ્સ કરવા માટે IMS સેવાનો ઉપયોગ કરવાની એપ્લિકેશનને મંજૂરી આપે છે."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ફોન સ્થિતિ અને ઓળખ વાંચો"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"એપ્લિકેશનને ફોન સુવિધાઓને ઍક્સેસ કરવાની મંજૂરી આપે છે. આ પરવાનગી એપ્લિકેશનને ફોન નંબર અને ઉપકરણ ID, કૉલ સક્રિય છે અને કોઈ કૉલ દ્વારા કનેક્ટ થયેલ રિમોટ નંબર નિર્ધારિત કરવાની મંજૂરી આપે છે."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ફોન નંબર વાંચવા"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ઍપ્લિકેશનને ઉપકરણના ફોન નંબરને ઍક્સેસ કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ટેબ્લેટને નિષ્ક્રિય થતું અટકાવો"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ટીવીને નિષ્ક્રિય થતો અટકાવો"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ફોનને નિષ્ક્રિય થતો અટકાવો"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"એપ્લિકેશનને ઇન્સ્ટોલ સત્રોને વાંચવાની મંજૂરી આપે છે. આ તેને સક્રિય પૅકેજ ઇન્સ્ટોલેશન્સ વિશે વિગતો જોવાની મંજૂરી આપે છે."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"પૅકેજેસ ઇન્સ્ટૉલ કરવાની વિનંતી કરો"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"એપ્લિકેશનને પૅકેજેસના ઇન્સ્ટોલેશનની વિનંતી કરવાની મંજૂરી આપો."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ઝૂમ નિયંત્રણ માટે બેવાર ટૅપ કરો"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"વિજેટ ઉમેરી શકાયું નથી."</string>
<string name="ime_action_go" msgid="8320845651737369027">"જાઓ"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"વર્ષ પસંદ કરો"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> કાઢી નાખી"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"કાર્યાલય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2જું કાર્ય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3જું કાર્ય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"આ સ્ક્રીનને અનપિન કરવા માટે, પાછળને ટચ કરીને પકડી રાખો."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ઍપ્લિકેશન પિન કરેલ છે. આ ઉપકરણ પર અનપિન કરવાની મંજૂરી નથી."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"સ્ક્રીન પિન કરી"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"હમણાં ફરીથી સેટ કરો"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> અક્ષમ કર્યું"</string>
<string name="conference_call" msgid="3751093130790472426">"કોન્ફરન્સ કૉલ"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"ટૂલટિપ પોપઅપ"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ટૂલટિપ"</string>
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index c46102b..c2f35f9 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"आपके हस्तक्षेप के बिना कॉल करने के लिए, ऐप को IMS सेवा का उपयोग करने देती है."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"फ़ोन की स्थिति और पहचान पढ़ें"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ऐप्स को डिवाइस की फ़ोन सुविधाओं तक पहुंचने देता है. यह अनुमति ऐप्स को फ़ोन नंबर और डिवाइस आईडी, कॉल सक्रिय है या नहीं, और कॉल द्वारा कनेक्ट किया गया दूरस्थ नंबर निर्धारित करने देती है."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"फ़ोन नंबर पढ़ें"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ऐप्लिकेशन को डिवाइस का फ़ोन नंबर एक्सेस करने देती है."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"टेबलेट को निष्क्रिय होने से रोकें"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"टीवी को निष्क्रिय होने से रोकना"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"फ़ोन को निष्क्रिय होने से रोकें"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"मीडिया वॉल्यूम"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"नोटिफिकेशन वॉल्यूम"</string>
<string name="ringtone_default" msgid="3789758980357696936">"डिफ़ॉल्ट रिंगटोन"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"डिफ़ॉल्ट (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"कोई नहीं"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"रिंगटोन"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"अलार्म ध्वनियां"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"नोटिफ़िकेशन ध्वनि"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"अज्ञात"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">वाई-फ़ाई नेटवर्क उपलब्ध</item>
<item quantity="other">वाई-फ़ाई नेटवर्क उपलब्ध</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ऐप्लिकेशन को इंस्टॉल सत्रों को पढ़ने देती है. इससे उसे सक्रिय पैकेज इंस्टॉलेशन के बारे में विवरण देखने की अनुमति मिल जाती है."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"पैकेज इंस्टॉल करने का अनुरोध करें"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"किसी ऐप्लिकेशन को पैकेज इंस्टॉल करने के अनुरोध की अनुमति देता है."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ज़ूम नियंत्रण के लिए दो बार टैप करें"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"विजेट नहीं जोड़ा जा सका."</string>
<string name="ime_action_go" msgid="8320845651737369027">"जाएं"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"वर्ष चुनें"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> को हटा दिया गया"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्यस्थल का <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"दूसरा कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"तीसरा कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"इस स्क्रीन को अनपिन करने के लिए, वापस जाएं को स्पर्श करके रखें."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ऐप पिन किया गया है: इस डिवाइस पर अनपिन करने की अनुमति नहीं है."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"स्क्रीन पिन की गई"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"अभी रीसेट करें"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"अक्षम <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"कॉन्फ़्रेंस कॉल"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"टूलटिप"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index fa593acd..7106e35 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Omogućuje aplikaciji upotrebu usluge izravnih poruka za uspostavljanje poziva bez vaše intervencije."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čitanje statusa i identiteta telefona"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Aplikaciji omogućuje pristup telefonskim značajkama uređaja. Ta dozvola aplikaciji omogućuje utvrđivanje telefonskog broja i ID-ova uređaja, je li poziv aktivan te udaljeni broj koji je povezan pozivom."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"čitati telefonski broj"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Omogućuje aplikaciji da pristupi telefonskom broju uređaja."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"spriječi mirovanje tabletnog uređaja"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"sprječavanje mirovanja televizora"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"sprečava telefon da prijeđe u stanje mirovanja"</string>
@@ -646,7 +648,7 @@
<string name="relationTypeAssistant" msgid="6274334825195379076">"Pomoćnik"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"Brat"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"Dijete"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Partner u kućan."</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Vanbračni partner"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"Otac"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"Prijatelj"</string>
<string name="relationTypeManager" msgid="6365677861610137895">"Voditelj"</string>
@@ -1235,6 +1237,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Omogućuje aplikaciji čitanje sesija instaliranja. Aplikacija može vidjeti pojedinosti o aktivnim instaliranjima paketa."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"zahtijevati instaliranje paketa"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Aplikaciji omogućuje zahtijevanje instaliranja paketa."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Dvaput dotaknite za upravljanje zumiranjem"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget nije moguće dodati."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Idi"</string>
@@ -1587,10 +1593,8 @@
<string name="select_year" msgid="7952052866994196170">"Odaberite godinu"</string>
<string name="deleted_key" msgid="7659477886625566590">"Izbrisan je broj <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Da biste otkvačili ovaj zaslon, dodirnite i zadržite Natrag."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je prikvačena: otkvačivanje nije dopušteno na tom uređaju."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Zaslon je pričvršćen"</string>
@@ -1719,5 +1723,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Vrati na zadano sada"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – onemogućeno"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferencijski poziv"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Skočni prozor opisa"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Opis"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d21e47e..6acbcb6 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Az alkalmazás az IMS-szolgáltatást használhatja híváskezdeményezéshez az Ön közbeavatkozása nélkül."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefonállapot és azonosító olvasása"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lehetővé teszi az alkalmazás számára, hogy hozzáférjen az eszköz telefonálási funkcióihoz. Az engedéllyel rendelkező alkalmazás meghatározhatja a telefonszámot és eszközazonosítókat, hogy egy hívás aktív-e, valamint híváskor a másik fél telefonszámát."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"telefonszám beolvasása"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Engedélyezi az alkalmazás számára, hogy hozzáférjen az eszköz telefonszámához."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"táblagép alvás üzemmódjának megakadályozása"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"a tévé alvó üzemmódba való lépésének megakadályozása"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"telefon alvó üzemmódjának megakadályozása"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Engedélyezi az alkalmazásnak a telepítési munkamenetek olvasását. Ezáltal részleteket kaphat az egyes csomagok éppen folyamatban lévő telepítéséről."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"telepítőcsomagok kérése"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Lehetővé teszi az alkalmazás számára csomagok telepítésének kérését."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Érintse meg kétszer a nagyítás beállításához"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nem sikerült hozzáadni a modult."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ugrás"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Válassza ki az évet"</string>
<string name="deleted_key" msgid="7659477886625566590">"A(z) <xliff:g id="KEY">%1$s</xliff:g> érték törölve"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"A képernyő rögzítésének feloldásához tartsa lenyomva a Vissza lehetőséget."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Az alkalmazás rögzítve van: a rögzítés feloldása nem engedélyezett ezen az eszközön."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Képernyő rögzítve"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Visszaállítás most"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"A(z) <xliff:g id="LABEL">%1$s</xliff:g> letiltva"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferenciahívás"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Elemleíró előugró ablak"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Elemleírás"</string>
</resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 10072a2..85fb492 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Թույլ է տալիս հավելվածին IMS ծառայության միջոցով կատարել զանգեր՝ առանց ձեր միջամտության:"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"կարդալ հեռախոսի կարգավիճակը և ինքնությունը"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Թույլ է տալիս հավելվածին օգտագործել սարքի հեռախոսային գործիքները: Այս թույլտվությունը հավելվածին հնարավորություն է տալիս որոշել հեռախոսահամարը և սարքի ID-ները, արդյոք զանգը ակտիվ է և միացված զանգի հեռակա հեռախոսահամարը:"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"կարդալ հեռախոսահամարը"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Հավելվածին թույլ է տալիս օգտագործել սարքի հեռախոսահամարը:"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"զերծ պահել պլանշետը քնելուց"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"թույլ չտալ հեռուստացույցին մտնել քնի ռեժիմ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"կանխել հեռախոսի քնի ռեժիմին անցնելը"</string>
@@ -598,7 +600,7 @@
<string name="phoneTypeOther" msgid="1544425847868765990">"Այլ"</string>
<string name="phoneTypeCallback" msgid="2712175203065678206">"Ետզանգ"</string>
<string name="phoneTypeCar" msgid="8738360689616716982">"Մեքենա"</string>
- <string name="phoneTypeCompanyMain" msgid="540434356461478916">"Ընկերության գլխավոր"</string>
+ <string name="phoneTypeCompanyMain" msgid="540434356461478916">"Ընկերության հիմնական"</string>
<string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
<string name="phoneTypeMain" msgid="6766137010628326916">"Հիմնական"</string>
<string name="phoneTypeOtherFax" msgid="8587657145072446565">"Այլ ֆաքս"</string>
@@ -643,14 +645,14 @@
<string name="relationTypeAssistant" msgid="6274334825195379076">"Օգնական"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"Եղբայր"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"Երեխա"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Տեղական գործընկեր"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Կենակից"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"Հայր"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"Ընկեր"</string>
<string name="relationTypeManager" msgid="6365677861610137895">"Կառավարիչ"</string>
<string name="relationTypeMother" msgid="4578571352962758304">"Մայր"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Ծնող"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Գործընկեր"</string>
- <string name="relationTypeReferredBy" msgid="101573059844135524">"Հղված է"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"Հանձնարարված"</string>
<string name="relationTypeRelative" msgid="1799819930085610271">"Բարեկամ"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Քույր"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"Ամուսին"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Մեդիա ձայնի բարձրություն"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Ծանուցումների ձայնի ուժգնությունը"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Կանխադրված զանգերանգ"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Կանխադրված (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Ոչ մեկը"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Զանգերանգներ"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Զարթուցիչի զանգերանգներ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Ծանուցման զանգերանգներ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Անհայտ է"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Հասանելի են Wi-Fi ցանցեր</item>
<item quantity="other">Հասանելի են Wi-Fi ցանցեր</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ծրագրին թույլ է տալիս կարդալ տեղադրման աշխատաշրջանները: Սա թույլ է տալիս տեղեկանալ փաթեթների ակտիվ տեղադրումների մանրամասներին:"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"պահանջել տեղադրման փաթեթներ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Թույլ է տալիս հավելվածին պահանջել փաթեթների տեղադրումը:"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Հպեք երկու անգամ` խոշորացման վերահսկման համար"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Չհաջողվեց վիջեթ ավելացնել:"</string>
<string name="ime_action_go" msgid="8320845651737369027">"Առաջ"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Ընտրեք տարին"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> թիվը ջնջված է"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Աշխատանքային <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Այս էկրանն ապամրացնելու համար հպեք և պահեք Հետ կոճակը:"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Հավելվածն ամրացված է: Ապամրացումն այս սարքում չի թույլատրվում:"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Էկրանն ամրացված է"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Վերակայել հիմա"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Անջատած <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Կոնֆերանս զանգ"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Հուշակ"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 29d820e..343191c 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Memungkinkan aplikasi menggunakan layanan IMS untuk melakukan panggilan tanpa campur tangan Anda."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"baca identitas dan status ponsel"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Memungkinkan aplikasi mengakses fitur telepon perangkat. Izin ini memungkinkan aplikasi menentukan nomor telepon dan ID perangkat, apakah suatu panggilan aktif atau tidak, dan nomor jarak jauh yang tersambung oleh sebuah panggilan."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"baca nomor telepon"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Mengizinkan aplikasi mengakses nomor telepon perangkat ini."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"cegah tablet dari tidur"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"cegah agar TV tidak tidur"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"mencegah ponsel menjadi tidak aktif"</string>
@@ -988,7 +990,7 @@
<string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"Jepret gambar"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Gunakan secara default untuk tindakan ini."</string>
<string name="use_a_different_app" msgid="8134926230585710243">"Gunakan aplikasi yang berbeda"</string>
- <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Menghapus default di Setelan sistem > Apl > Terunduh."</string>
+ <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Menghapus default di Setelan sistem > Apl > Terdownload."</string>
<string name="chooseActivity" msgid="7486876147751803333">"Pilih tindakan"</string>
<string name="chooseUsbActivity" msgid="6894748416073583509">"Pilih apl untuk perangkat USB"</string>
<string name="noApplications" msgid="2991814273936504689">"Tidak ada apl yang dapat melakukan tindakan ini."</string>
@@ -1016,7 +1018,7 @@
<string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> telah diluncurkan aslinya."</string>
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Selalu tampilkan"</string>
- <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Aktifkan kembali dialog ini di Setelan sistem > Apl > Terunduh."</string>
+ <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Aktifkan kembali dialog ini di Setelan sistem > Apl > Terdownload."</string>
<string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak mendukung setelan Ukuran layar saat ini dan dapat menunjukkan perilaku yang tak diharapkan."</string>
<string name="unsupported_display_size_show" msgid="7969129195360353041">"Selalu tampilkan"</string>
<string name="smv_application" msgid="3307209192155442829">"Apl <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) telah melanggar kebijakan StrictMode yang diberlakukannya sendiri."</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Memungkinkan aplikasi membaca sesi pemasangan. Tindakan ini memungkinkannya melihat detail tentang pemasangan paket aktif."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"minta pasang paket"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Mengizinkan aplikasi meminta pemasangan paket."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ketuk dua kali untuk kontrol perbesar/perkecil"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Tidak dapat menambahkan widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Buka"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Pilih tahun"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dihapus"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Kantor <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Upaya ke-2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Upaya ke-3 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Untuk melepas pin layar ini, sentuh & tahan tombol Kembali."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Pin dipasang ke aplikasi. Melepas pin tidak diizinkan di perangkat ini."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Layar disematkan"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Setel ulang sekarang"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> dinonaktifkan"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferensi Telepon"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Munculan Keterangan Alat"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Keterangan alat"</string>
</resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 655c521..a875301 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Leyfir forriti að nota IMS-þjónustu til að hringja án inngrips frá þér."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lesa stöðu símans og auðkenni"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Leyfir forriti að fá aðgang að símaeiginleikum tækisins. Þessi heimild gerir forritinu kleift að komast að símanúmeri og auðkennum tækisins, hvort símtal er í gangi og símanúmeri viðmælanda í símtali."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lesa símanúmer"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Veitir forritinu aðgang að símanúmeri tækisins."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"koma í veg fyrir að spjaldtölvan fari í biðstöðu"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"koma í veg fyrir að sjónvarpið fari í biðstöðu"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"koma í veg fyrir að síminn fari í biðstöðu"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Leyfir forriti að lesa uppsetningarlotur. Þetta gerir því kleift að sjá upplýsingar um virkar pakkauppsetningar."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"fara fram á uppsetningu pakka"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Leyfir forriti að fara fram á uppsetningu pakka."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ýttu tvisvar til að opna aðdráttarstýringar"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Ekki tókst að bæta græju við."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Áfram"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Veldu ár"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eytt"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu (2)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu (3)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Til að taka lásinn af þessari skjámynd skaltu halda inni bakkhnappinum."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Forritið er fest: Ekki er hægt að losa forrit í þessu tæki."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skjár festur"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Endurstilla núna"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Slökkt <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Símafundur"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Ábendingarsprettigluggi"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Ábending"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 446e367..7bae091 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Consente all\'app di utilizzare il servizio IMS per fare chiamate senza il tuo intervento."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lettura stato e identità telefono"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Consente all\'applicazione di accedere alle funzioni telefoniche del dispositivo. Questa autorizzazione consente all\'applicazione di determinare il numero di telefono e gli ID dei dispositivi, se una chiamata è attiva e il numero remoto connesso da una chiamata."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"leggi il numero di telefono"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Consente all\'app di accedere al numero di telefono del dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"disattivazione stand-by del tablet"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"divieto di attivazione della modalità di sospensione della TV"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"disattivazione stand-by del telefono"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Consente a un\'applicazione di leggere le sessioni di installazione. L\'app può conoscere i dettagli sulle installazioni di pacchetti attive."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"richiesta di pacchetti di installazione"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Consente a un\'applicazione di richiedere l\'installazione di pacchetti."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tocca due volte per il comando dello zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Aggiunta del widget non riuscita."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Vai"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Seleziona anno"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminato"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> lavoro"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> di lavoro (2°)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> di lavoro (3°)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Per sbloccare questa schermata tieni premuta l\'opzione Indietro."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"L\'app è bloccata. Su questo dispositivo non è consentito lo sblocco."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Schermata bloccata"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Ripristina ora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Widget <xliff:g id="LABEL">%1$s</xliff:g> disattivato"</string>
<string name="conference_call" msgid="3751093130790472426">"Audioconferenza"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Popup descrizione comando"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Descrizione comando"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 1881ae4..c79f889 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"מאפשר לאפליקציה להשתמש בשירות ה-IMS לביצוע שיחות ללא התערבותך."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"קריאת הסטטוס והזהות של הטלפון"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"מאפשר לאפליקציה לגשת לתכונות הטלפון של המכשיר. אישור זה מתיר לאפליקציה לגלות את מספר הטלפון ואת זיהויי המכשיר, האם שיחה פעילה ואת המספר המרוחק המחובר באמצעות שיחה."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"קריאת מספר טלפון"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"מאפשרת לאפליקציה לגשת למספר הטלפון של המכשיר."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"מנע מהטאבלט לעבור למצב שינה"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"מניעת מעבר למצב שינה בטלוויזיה"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"מניעת מעבר הטלפון למצב שינה"</string>
@@ -599,7 +601,7 @@
<string name="phoneTypeMobile" msgid="6501463557754751037">"נייד"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"עבודה"</string>
<string name="phoneTypeFaxWork" msgid="3517792160008890912">"פקס בעבודה"</string>
- <string name="phoneTypeFaxHome" msgid="2067265972322971467">"מס\' פקס בבית"</string>
+ <string name="phoneTypeFaxHome" msgid="2067265972322971467">"פקס בבית"</string>
<string name="phoneTypePager" msgid="7582359955394921732">"זימונית"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"אחר"</string>
<string name="phoneTypeCallback" msgid="2712175203065678206">"התקשרות חזרה"</string>
@@ -612,7 +614,7 @@
<string name="phoneTypeTelex" msgid="3367879952476250512">"טלקס"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
<string name="phoneTypeWorkMobile" msgid="1311426989184065709">"נייד של העבודה"</string>
- <string name="phoneTypeWorkPager" msgid="649938731231157056">"איתורית של העבודה"</string>
+ <string name="phoneTypeWorkPager" msgid="649938731231157056">"זימונית מהעבודה"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"מסייע"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
<string name="eventTypeCustom" msgid="7837586198458073404">"מותאם אישית"</string>
@@ -1105,16 +1107,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"עוצמת קול של מדיה"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"עוצמת קול של התראות"</string>
<string name="ringtone_default" msgid="3789758980357696936">"רינגטון ברירת מחדל"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ברירת מחדל (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ללא"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"רינגטונים"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"צלילי התראה"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"צלילי הודעה"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"לא ידוע"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="two">יש רשתות Wi-Fi זמינות</item>
<item quantity="many">יש רשתות Wi-Fi זמינות</item>
@@ -1264,6 +1262,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"מאפשר לאפליקציה לקרוא הפעלות התקנה. הרשאה זו מאפשרת לה לראות פרטים על התקנות פעילות של חבילות."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"בקשה להתקנת חבילות"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"מתיר לאפליקציה לבקש התקנה של חבילות."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"הקש פעמיים לבקרת מרחק מתצוגה"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"לא ניתן להוסיף widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"התחל"</string>
@@ -1618,10 +1620,8 @@
<string name="select_year" msgid="7952052866994196170">"בחר שנה"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> נמחק"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"עבודה <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> שני בעבודה"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> שלישי בעבודה"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"כדי לבטל את הצמדת המסך הזה, לחץ לחיצה ממושכת על הלחצן \'הקודם\'."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"האפליקציה מוצמדת: ביטול ההצמדה אסור במכשיר הזה."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"המסך מוצמד"</string>
@@ -1759,6 +1759,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"אפס עכשיו"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> הושבת"</string>
<string name="conference_call" msgid="3751093130790472426">"שיחת ועידה"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"הסבר קצר"</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index fdfb890..f2e927e 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"IMSサービスがユーザー操作なしで電話をかけることをアプリに許可します。"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"端末情報と ID の読み取り"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"端末の電話機能へのアクセスをアプリに許可します。これにより、電話番号、端末ID、通話中かどうか、通話相手の電話番号をアプリから特定できるようになります。"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"電話番号の読み取り"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"端末の電話番号へのアクセスをアプリに許可します。"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"タブレットのスリープを無効化"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"テレビのスリープを無効化"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"端末のスリープを無効にする"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"メディアの音量"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
<string name="ringtone_default" msgid="3789758980357696936">"プリセット着信音"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"デフォルト(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"なし"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"着信音"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"アラーム音"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"通知音"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"不明"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">複数のWi-Fiネットワークが利用できます</item>
<item quantity="one">Wi-Fiネットワークが利用できます</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"インストールセッションの読み取りをアプリに許可します。これにより、アプリはアクティブパッケージのインストールに関する詳細情報を参照できるようになります。"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"インストールパッケージのリクエスト"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"パッケージのインストールをリクエストすることをアプリケーションに許可します。"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ダブルタップでズームします"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ウィジェットを追加できませんでした。"</string>
<string name="ime_action_go" msgid="8320845651737369027">"移動"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"年を選択"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g>を削除しました"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"仕事の<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 番目の仕事用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 番目の仕事用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"この画面の固定を解除するには [戻る] を押し続けます。"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"アプリは固定されています。この端末では固定を解除できません。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"画面を固定しました"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"今すぐリセット"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"停止済みの「<xliff:g id="LABEL">%1$s</xliff:g>」"</string>
<string name="conference_call" msgid="3751093130790472426">"グループ通話"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ツールチップ"</string>
</resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 56f0a62..dfdc182c 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"აპს შეეძლება, გამოიყენოს IMS სერვისი ზარების თქვენი ჩარევის გარეშე განსახორციელებლად."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ტელეფონის სტატუსისა და იდენტობის წაკითხვა"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"აპს შეეძლება ჰქონდეს წვდომა მოწყობილობის სატელეფონო ფუნქციებზე. აპმა მსგავსი უფლებით შეძლებს დაადგინოს ტელეფონის ნომერი, მისი სერიული გამოცემა, აქტიური ზარი, დაკავშირებული ნომერი და მსგავსი."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ტელეფონის ნომრის წაკითხვა"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"აპს მოწყობილობის ტელეფონის ნომერზე წვდომის საშუალებას მისცემს."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"დაიცავით ტაბლეტი დაძინებისგან"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ტელევიზორის დაცვა დაძინებისაგან"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ტელეფონის ძილის რეჟიმში გადასვლის აღკვეთა"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"საშუალებას აძლევს აპლიკაციას წაიკითხოს ინსტალაციის სესიები. ამით მას საშუალება აქვს იხილოს პაკეტის აქტიური ინსტალაციები."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"პაკეტების ინსტალაციის მოთხოვნა"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"აპლიკაციას შეეძლება მოითხოვოს პაკეტების ინსტალაცია."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"მასშტაბის ცვლილებისთვის შეეხეთ ორჯერ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ვერ დაემატა ვიჯეტი."</string>
<string name="ime_action_go" msgid="8320845651737369027">"გადასვლა"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"აირჩიეთ წელი"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> წაიშალა"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"მე-2 სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"მე-3 სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ამ ეკრანის ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ ღილაკს „უკან“."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"აპი მიმაგრებულია: მიმაგრების მოხსნა არ არის ნებადართული ამ მოწყობილობაზე."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ეკრანი დაფიქსირდა"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ახლავე გადაყენება"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"გათიშული <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"საკონფერენციო ზარი"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"მინიშნების კონტექსტური სარკმელი"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"მინიშნება"</string>
</resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 51d1dcc..bd4e171 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Сіздің қатысуыңызсыз қоңыраулар соғу үшін қолданбаға IMS қызметін пайдалануға рұқсат етеді."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"телефон күйін оқу немесе анықтау"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Қолданбаға құрылғыдағы телефон функцияларына кіру мүмкіндігін береді. Бұл рұқсат қолданбаға телефон нөмірі, құрылғы жеке анықтағышы, қоңырау белсенділігі және сол қоңырауға байланысты қашықтағы нөмірді анықтау мүмкіндігін береді."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"телефон нөмірін оқу"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Қолданбаға құрылғының телефон нөмірін алуға рұқсат береді."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"планшетті ұйқыдан бөгеу"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ТД ұйықтауын болдырмау"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"телефонды ұйқыдан бөгеу"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Meдиа дыбысының қаттылығы"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Хабар дыбысының қаттылығы"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Әдепкі рингтон"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Әдепкі (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Ешқандай"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Қоңырау әуендері"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Дабыл сигналдары"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Хабарландыру сигналдары"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Белгісіз"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Wi-Fi желілері қол жетімді</item>
<item quantity="one">Wi-Fi желісі қол жетімді</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Қолданбаға орнату сеанстарын оқуға рұқсат етеді. Бұл оған белсенді бума орнатулары туралы мәліметтерді көруге рұқсат етеді."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"орнату бумаларын сұрау"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Қолданбаның бумаларды орнатуға рұқсат сұрауына мүмкіндік береді."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Масштабтау параметрін басқару үшін екі рет түртіңіз"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Виджетті қосу."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Өту"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Жыл таңдау"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> жойылды"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Жұмыс <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-ші жұмыс профилі (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-ші жұмыс профилі (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Осы экранды босату үшін \"Артқа\" түймесін басып тұрыңыз."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Бағдарлама белгіленді: Бұл құрылғыда белгіні алуға рұқсат берілмейді."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран түйрелді"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Қазір бастапқы күйге қайтару"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> өшірулі"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференциялық қоңырау"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Қалқыма сөзкөмек"</string>
</resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index aa6cb77..49d3a64 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"អនុញ្ញាតឲ្យកម្មវិធីនេះប្រើសេវាកម្ម IMS ដើម្បីធ្វើការហៅដោយគ្មានការអន្តរាគមន៍ពីអ្នក។"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"អានស្ថានភាព និងអត្តសញ្ញាណទូរស័ព្ទ"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ឲ្យកម្មវិធីចូលដំណើរការលក្ខណៈទូរស័ព្ទនៃឧបករណ៍។ សិទ្ធិនេះឲ្យកម្មវិធីកំណត់លេខទូរស័ព្ទ និងលេខសម្គាល់ឧបករណ៍ ថាតើការហៅសកម្ម និងលេខពីចម្ងាយបានភ្ជាប់ដោយការហៅ។"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"អានលេខទូរសព្ទ"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"អនុញ្ញាតឲ្យកម្មវិធីនេះចូលប្រើលេខទូរសព្ទរបស់ឧបករណ៍នេះ។"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ការពារកុំព្យូទ័របន្ទះមិនឲ្យដេក"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"បង្ការទូរទស្សន៍ពីការបិទពន្លឺ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ការពារទូរស័ព្ទមិនឲ្យដេក"</string>
@@ -605,9 +607,9 @@
<string name="phoneTypeRadio" msgid="4093738079908667513">"វិទ្យុ"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"ទូរសារ"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
- <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"ទូរស័ព្ទកន្លែងធ្វើការ"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"ទូរសព្ទកន្លែងធ្វើការ"</string>
<string name="phoneTypeWorkPager" msgid="649938731231157056">"ភេយ័រកន្លែងធ្វើការ"</string>
- <string name="phoneTypeAssistant" msgid="5596772636128562884">"អ្នកជំនួយការ"</string>
+ <string name="phoneTypeAssistant" msgid="5596772636128562884">"ជំនួយការ"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"សារ MMS"</string>
<string name="eventTypeCustom" msgid="7837586198458073404">"តាមតម្រូវការ"</string>
<string name="eventTypeBirthday" msgid="2813379844211390740">"ថ្ងៃខួបកំណើត"</string>
@@ -640,10 +642,10 @@
<string name="orgTypeOther" msgid="3951781131570124082">"ផ្សេងៗ"</string>
<string name="orgTypeCustom" msgid="225523415372088322">"តាមតម្រូវការ"</string>
<string name="relationTypeCustom" msgid="3542403679827297300">"តាមបំណង"</string>
- <string name="relationTypeAssistant" msgid="6274334825195379076">"អ្នកជំនួយការ"</string>
+ <string name="relationTypeAssistant" msgid="6274334825195379076">"ជំនួយការ"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"បងប្អូនប្រុស"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"កូន"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"ដៃគូក្នុងស្រុក"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"ដៃគូរួមរស់ជាមួយគ្នា"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"ឪពុក"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"មិត្តភ័ក្ដិ"</string>
<string name="relationTypeManager" msgid="6365677861610137895">"អ្នកគ្រប់គ្រង"</string>
@@ -1061,16 +1063,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"កម្រិតសំឡេងមេឌៀ"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"កម្រិតសំឡេងការជូនដំណឹង"</string>
<string name="ringtone_default" msgid="3789758980357696936">"សំឡេងរោទ៍លំនាំដើម"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>) លំនាំដើម"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"គ្មាន"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"សំឡេងរោទ៍"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"សំឡេងម៉ោងរោទិ៍"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"សំឡេងជូនដំណឹង"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"មិនស្គាល់"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">មានបណ្តាញ Wi-Fi</item>
<item quantity="one">មានបណ្តាញ Wi-Fi</item>
@@ -1216,6 +1214,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ឲ្យកម្មវិធីអានសម័យដំឡើង។ វាអនុញ្ញាតឲ្យឃើញព័ត៌មានលម្អិតអំពីការដំឡើងកញ្ចប់សកម្ម។"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ស្នើសុំកញ្ចប់ដំឡើង"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"អនុញ្ញាតឲ្យកម្មវិធីស្នើសុំដំឡើងកញ្ចប់ (ឯកសារ/មាតិកា)។"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ប៉ះ ពីរដងដើម្បីពិនិត្យការពង្រីក"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"មិនអាចបន្ថែមធាតុក្រាហ្វិក។"</string>
<string name="ime_action_go" msgid="8320845651737369027">"ទៅ"</string>
@@ -1566,10 +1568,8 @@
<string name="select_year" msgid="7952052866994196170">"ជ្រើសឆ្នាំ"</string>
<string name="deleted_key" msgid="7659477886625566590">"បានលុប <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"កន្លែងធ្វើការ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ដើម្បីផ្តាច់អេក្រង់នេះ សូមប៉ះ និងសង្កត់ប៊ូតុងថយក្រោយឲ្យជាប់។"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"កម្មវិធីនេះត្រូវបានខ្ទាស់។ មិនអនុញ្ញាតឲ្យដោះការខ្ទាស់នៅលើឧបករណ៍នេះទេ។"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"បានភ្ជាប់អេក្រង់"</string>
@@ -1689,6 +1689,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"កំណត់ឡើងវិញឥឡូវនេះ"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ដែលបានបិទដំណើរការ"</string>
<string name="conference_call" msgid="3751093130790472426">"ការហៅជាក្រុម"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ផ្ទាំងលោត"</string>
</resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 30d7e4e0..bfd69d6 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"ನಿಮ್ಮ ಮಧ್ಯಸ್ಥಿಕೆ ಇಲ್ಲದೆಯೇ ಕರೆಗಳನ್ನು ಮಾಡಲು IMS ಸೇವೆಯನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ಫೋನ್ ಸ್ಥಿತಿ ಮತ್ತು ಗುರುತಿಸುವಿಕೆಯನ್ನು ಓದಿ"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ಸಾಧನದ ಫೋನ್ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ಫೋನ್ ಸಂಖ್ಯೆ ಮತ್ತು ಸಾಧನದ ID ಗಳನ್ನು ನಿರ್ಧರಿಸಲು, ಕರೆಯು ಸಕ್ರಿಯವಾಗಿದೆಯೇ ಮತ್ತು ಕರೆಯ ಮೂಲಕ ರಿಮೋಟ್ ಸಂಖ್ಯೆಯು ಸಂಪರ್ಕಗೊಂಡಿವೆಯೇ ಎಂಬುದನ್ನೂ ನಿರ್ಧರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಕಲ್ಪಿಸುತ್ತದೆ."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ಫೋನ್ ಸಂಖ್ಯೆ ಓದಿ"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ಸಾಧನದ ಫೋನ್ ಸಂಖ್ಯೆ ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ಟ್ಯಾಬ್ಲೆಟ್ ನಿದ್ರಾವಸ್ಥೆಯನ್ನು ತಡೆಯಿರಿ"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ಟಿವಿಗೆ ನಿದ್ರಿಸುವುದನ್ನು ತಪ್ಪಿಸಿ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ಫೋನ್ ಆಫ್ ಆಗುವುದರಿಂದ ತಡೆಯಿರಿ"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"ಮೀಡಿಯಾ ವಾಲ್ಯೂಮ್"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"ಅಧಿಸೂಚನೆಯ ವಾಲ್ಯೂಮ್"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ಡಿಫಾಲ್ಟ್ ರಿಂಗ್ಟೋನ್"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ಡಿಫಾಲ್ಟ್ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ಯಾವುದೂ ಇಲ್ಲ"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ರಿಂಗ್ಟೋನ್ಗಳು"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"ಅಲಾರಮ್ ಧ್ವನಿಗಳು"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"ಅಧಿಸೂಚನೆ ಧ್ವನಿಗಳು"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"ಅಪರಿಚಿತ"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿವೆ</item>
<item quantity="other">ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿವೆ</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ಸ್ಥಾಪಿತ ಸೆಷನ್ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ. ಸಕ್ರಿಯ ಪ್ಯಾಕೇಜ್ ಸ್ಥಾಪನೆಗಳ ಕುರಿತು ವಿವರಣೆಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಇದು ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ಸ್ಥಾಪನೆ ಪ್ಯಾಕೇಜ್ಗಳನ್ನು ವಿನಂತಿಸಿ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ಪ್ಯಾಕೇಜ್ಗಳ ಸ್ಥಾಪನೆಯನ್ನು ವಿನಂತಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ಝೂಮ್ ನಿಯಂತ್ರಿಸಲು ಎರಡು ಬಾರಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ವಿಜೆಟ್ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string>
<string name="ime_action_go" msgid="8320845651737369027">"ಹೋಗು"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"ವರ್ಷವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ಅಳಿಸಲಾಗಿದೆ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ಕೆಲಸ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 ನೇ ಕೆಲಸದ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 ನೇ ಕೆಲಸದ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ಈ ಪರದೆಯನ್ನು ಅನ್ಪಿನ್ ಮಾಡಲು, ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಂಂದೆ ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ಅಪ್ಲಿಕೇಶನ್ ಪಿನ್ ಮಾಡಲಾಗಿದೆ: ಈ ಸಾಧನದಲ್ಲಿ ಅನ್ಪಿನ್ ಮಾಡುವುದನ್ನು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ಸ್ಕ್ರೀನ್ ಪಿನ್ ಮಾಡಲಾಗಿದೆ"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ಈಗಲೇ ಮರುಹೊಂದಿಸು"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="conference_call" msgid="3751093130790472426">"ಕಾನ್ಫರೆನ್ಸ್ ಕರೆ"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ಟೂಲ್ಟಿಪ್"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index dbb14890..e81de03 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"앱이 IMS 서비스를 사용하여 자동으로 전화를 걸 수 있도록 허용합니다."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"휴대전화 상태 및 ID 읽기"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"앱이 기기의 휴대전화 기능에 액세스할 수 있도록 허용합니다. 이 권한을 사용하면 앱이 전화번호 및 기기의 ID, 활성 통화인지 여부, 통화가 연결된 원격 번호 등을 확인할 수 있습니다."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"전화번호 읽기"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"앱에서 기기의 전화번호에 액세스할 수 있도록 허용합니다."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"태블릿이 절전 모드로 전환되지 않도록 설정"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV의 절전 모드 전환 방지"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"휴대전화가 절전 모드로 전환되지 않도록 설정"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"미디어 볼륨"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"알림 볼륨"</string>
<string name="ringtone_default" msgid="3789758980357696936">"기본 벨소리"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"기본값(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"없음"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"벨소리"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"알람 소리"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"알림 사운드"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"알 수 없음"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Wi-Fi 네트워크 사용 가능</item>
<item quantity="one">Wi-Fi 네트워크 사용 가능</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"애플리케이션의 설치 세션 읽기를 허용하면, 활성 패키지 설치에 대한 세부 정보를 볼 수 있습니다."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"패키지 설치 요청"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"애플리케이션이 패키지 설치를 요청하도록 허용합니다."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"확대/축소하려면 두 번 탭하세요."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"위젯을 추가할 수 없습니다."</string>
<string name="ime_action_go" msgid="8320845651737369027">"이동"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"연도 선택"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> 삭제됨"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"두 번째 업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"세 번째 업무용<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"이 화면을 고정 해제하려면 \'뒤로\'를 길게 터치합니다."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"앱이 고정되었습니다. 이 기기에서는 고정 해제를 허용하지 않습니다."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"화면 고정됨"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"지금 초기화"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> 사용 중지됨"</string>
<string name="conference_call" msgid="3751093130790472426">"다자간 통화"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"도움말"</string>
</resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 3583189..d4fa9d8 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Колдонмого сизди катыштырбай туруп, IMS кызматынын жардамы менен чалууларды жасоо мүмкүнчүлүгүн берет."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"телефондун абалын жана аныктыгын окуу"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Колдонмого түзмөктүн чалуу мүмкүнчүлүктөрүнө жетки алуу уруксатын берет. Бул уруксат колдонмого, телефондун номурун, түзмөктүн ID-син, чалуунун абалын жана байланышта чыккан номурду аныктоого жол берет."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"телефон номерин окуу"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Колдонмого түзмөктүн телефон номерин окуу мүмкүнчүлүгү берилет."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"планшетти уктатпай сактоо"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"сыналгыны көшүтпөө"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"телефонду уктатпай сактоо"</string>
@@ -641,18 +643,18 @@
<string name="orgTypeCustom" msgid="225523415372088322">"Өзгөчө"</string>
<string name="relationTypeCustom" msgid="3542403679827297300">"Өзгөчө"</string>
<string name="relationTypeAssistant" msgid="6274334825195379076">"Жардамчы"</string>
- <string name="relationTypeBrother" msgid="8757913506784067713">"Ага-ини"</string>
- <string name="relationTypeChild" msgid="1890746277276881626">"Баласы"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Жергиликтүү Өнөктөш"</string>
- <string name="relationTypeFather" msgid="5228034687082050725">"Атасы"</string>
- <string name="relationTypeFriend" msgid="7313106762483391262">"Досу"</string>
- <string name="relationTypeManager" msgid="6365677861610137895">"Менежер"</string>
- <string name="relationTypeMother" msgid="4578571352962758304">"Энеси"</string>
+ <string name="relationTypeBrother" msgid="8757913506784067713">"Ага/Ини"</string>
+ <string name="relationTypeChild" msgid="1890746277276881626">"Бала"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Жарандык нике"</string>
+ <string name="relationTypeFather" msgid="5228034687082050725">"Ата"</string>
+ <string name="relationTypeFriend" msgid="7313106762483391262">"Дос"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"Башчы"</string>
+ <string name="relationTypeMother" msgid="4578571352962758304">"Эне"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Ата/эне"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Өнөк"</string>
- <string name="relationTypeReferredBy" msgid="101573059844135524">"Төмөнкүдөй аталат"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"Сунушталган"</string>
<string name="relationTypeRelative" msgid="1799819930085610271">"Тууган"</string>
- <string name="relationTypeSister" msgid="1735983554479076481">"Эже-сиңди"</string>
+ <string name="relationTypeSister" msgid="1735983554479076481">"Эже/Сиңди"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"Жубай"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"Өзгөчө"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Үй"</string>
@@ -1058,10 +1060,10 @@
<string name="volume_icon_description_incall" msgid="8890073218154543397">"Чалуунун үн деңгээли"</string>
<string name="volume_icon_description_media" msgid="4217311719665194215">"Медиа үнүнүн деңгээли"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Эскертме үнүнүн деңгээли"</string>
- <string name="ringtone_default" msgid="3789758980357696936">"Демейки рингтон"</string>
- <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Демейки рингтон (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+ <string name="ringtone_default" msgid="3789758980357696936">"Демейки шыңгыр"</string>
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Демейки шыңгыр (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Эч бир"</string>
- <string name="ringtone_picker_title" msgid="3515143939175119094">"Ринтондор"</string>
+ <string name="ringtone_picker_title" msgid="3515143939175119094">"Шыңгырлар"</string>
<string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Ойготкучтун добуштары"</string>
<string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Эскертменин добуштары"</string>
<string name="ringtone_unknown" msgid="3914515995813061520">"Белгисиз"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Колдонмого орнотуу сеанстарын окуу мүмкүнчүлүгүн берет. Ушуну менен, ал жигердүү топтом орнотууларынын чоо-жайын көрө алат."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"орнотуу топтомдорун суроо"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Колдонмо топтомдорду орнотууга уруксат сурай алат."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Масштабдын параметрлерин өзгөртүү үчүн бул жерди эки жолу басыңыз."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Виджетти кошуу мүмкүн болбоду."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Өтүү"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Жылды тандаңыз"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> өчүрүлдү"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Бул экранды бошотуу үчүн \"Артка\" баскычын басып, кармап туруңуз."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Колдонмо кадалган: Бул түзмөктө бошотууга уруксат жок."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран кадалды"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Баштапкы абалга келтирүү"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> өчүрүлдү"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференц чалуу"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Калкып чыгуучу кеңеш"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Калкып чыгуучу кеңеш"</string>
</resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index baf6d51..7e0f79c 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"ອະນຸຍາດໃຫ້ແອັບໃຊ້ການບໍລິການ IMS ເພື່ອໂທໂດຍບໍ່ມີການຊ່ວຍເຫຼືອຂອງທ່ານ."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ອ່ານສະຖານະ ແລະຂໍ້ມູນລະບຸໂຕຕົນຂອງໂທລະສັບ"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ອະນຸຍາດໃຫ້ແອັບຯ ເຂົ້າເຖິງຄວາມສາມາດການໂທລະສັບຂອງອຸປະກອນ. ການກຳນົດສິດນີ້ເຮັດໃຫ້ແອັບຯສາມາດກວດສອບເບີໂທລະສັບ ແລະ ID ຂອງອຸປະກອນ, ບໍ່ວ່າການໂທຈະຍັງດຳເນີນຢູ່ ແລະເບີປາຍທາງເຊື່ອມຕໍ່ຢູ່ຫຼືບໍ່ກໍຕາມ."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"read phone number"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Allows the app to access the phone number of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ຂັດຂວາງບໍ່ໃຫ້ປິດໜ້າຈໍແທັບເລັດ"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ປ້ອງກັນບໍ່ໃຫ້ໂທລະພາບຫຼັບພັກ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ຂັດຂວາງບໍ່ໃຫ້ໂທລະສັບປິດໜ້າຈໍ"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"ລະດັບສຽງຂອງສື່"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"ລະດັບສຽງການແຈ້ງເຕືອນ"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ຣິງໂທນເລີ່ມຕົ້ນ"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Default (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ບໍ່ມີ"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ຣິງໂທນ"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Alarm sounds"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Notification sounds"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"ບໍ່ຮູ້ຈັກ"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">ເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
<item quantity="one">ເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນອ່ານເຊດຊັນການຕິດຕັ້ງໄດ້. ນີ້ຈະອະນຸຍາດໃຫ້ມັນເບິ່ງເຫັນລາຍລະອຽດກ່ຽວກັບການຕິດຕັ້ງແພັກເກດທີ່ເຮັດວຽກຢູ່ໄດ້."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ຂໍຕິດຕັ້ງແພັກເກດ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນຂອງການຕິດຕັ້ງແພັກເກດ."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ແຕະສອງເທື່ອເພື່ອຄວບຄຸມການຊູມ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ບໍ່ສາມາດເພີ່ມວິດເຈັດໄດ້."</string>
<string name="ime_action_go" msgid="8320845651737369027">"ໄປ"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"ເລືອກປີ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ຖືກລຶບແລ້ວ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ບ່ອນເຮັດວຽກ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"ບ່ອນເຮັດວຽກທີ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"ບ່ອນເຮັດວຽກທີ 3 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ກົດປຸ່ມກັບຄືນຄ້າງໄວ້ເພື່ອເຊົາປັກໝຸດໜ້າຈໍນີ້."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ແອັບຖືກປັກໝຸດແລ້ວ: ບໍ່ອະນຸຍາດໃຫ້ຖອນປັກໝຸດຢູ່ເທິງອຸປະກອນນີ້."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ປັກໝຸດໜ້າຈໍແລ້ວ"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ຣີເຊັດດຽວນີ້"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ປິດການນຳໃຊ້ <xliff:g id="LABEL">%1$s</xliff:g> ແລ້ວ"</string>
<string name="conference_call" msgid="3751093130790472426">"ການປະຊຸມສາຍ"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ຄຳອະທິບາຍເຄື່ອງມື"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index f9293c4..3100570 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Programai leidžiama naudoti IMS paslaugą, kad būtų galima atlikti skambučius be jūsų įsikišimo."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"skaityti telefono būseną ir tapatybę"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Leidžiama programai pasiekti telefono funkcijas įrenginyje. Šis leidimas suteikia teisę programai nustatyti telefono numerį ir įrenginio ID, tai, ar skambutis aktyvus, ir skambučiu prijungtą nuotolinį numerį."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"skaityti telefono numerį"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Programai leidžiama pasiekti įrenginio telefono numerį."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"neleisti planšetiniam kompiuteriui užmigti"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"neleisti įjungti TV miego būsenos"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"neleisti telefonui snausti"</string>
@@ -1105,16 +1107,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Medijos garsumas"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Pranešimo apimtis"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Numatytasis skambėjimo tonas"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Numatytasis („<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>“)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Nėra"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Skambėjimo tonai"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Įspėjimų garsai"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Pranešimų garsai"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Nežinoma"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Pasiekiami „Wi-Fi“ tinklai</item>
<item quantity="few">Pasiekiami „Wi-Fi“ tinklai</item>
@@ -1264,6 +1262,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Leidžiama programai skaityti diegimo seansus. Leidžiama peržiūrėti išsamią aktyvių paketų diegimo informaciją."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"pateikti užklausą dėl diegimo paketų"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Programai leidžiama pateikti užklausą dėl paketų diegimo."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Bakstelėkite du kartus, kad valdytumėte mastelio keitimą"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nepavyko pridėti."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Pradėti"</string>
@@ -1618,10 +1620,8 @@
<string name="select_year" msgid="7952052866994196170">"Pasirinkite metus"</string>
<string name="deleted_key" msgid="7659477886625566590">"Ištrinta: <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-asis darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-iasis darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Kad atsegtumėte šį ekraną, palieskite ir palaikykite „Atgal“."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Programa prisegta: šiame įrenginyje negalima atsegti."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrano prisegtas"</string>
@@ -1759,6 +1759,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Nustatyti iš naujo dabar"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Išj. valdiklis „<xliff:g id="LABEL">%1$s</xliff:g>“"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferencinis skambutis"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Patarimas"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 04ea14e..5393e49 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Ļauj lietotnei izmantot tūlītējās ziņojumapmaiņas pakalpojumu, lai veiktu zvanus bez jūsu ziņas."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lasīt tālruņa statusu un identitāti"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ļauj lietotnei piekļūt ierīces tālruņa funkcijām. Ar šo atļauju lietotne var noteikt tālruņa numuru un ierīču ID, zvana statusu un attālo numuru, ar ko ir izveidots savienojums, veicot zvanu."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lasīt tālruņa numuru"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Ļauj lietotnei piekļūt ierīces tālruņa numuram."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"novērst planšetdatora pāriešanu miega režīmā"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"novērst televizora pāreju miega režīmā"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"novērst tālruņa pāriešanu miega režīmā"</string>
@@ -1082,16 +1084,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Multivides skaļums"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Paziņojumu skaļums"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Noklusējuma zvana signāls"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Noklusējuma (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Nav"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Zvana signāli"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Modinātāja signāla skaņas"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Paziņojumu skaņas"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Nezināms"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="zero">Pieejami Wi-Fi tīkli</item>
<item quantity="one">Pieejami Wi-Fi tīkli</item>
@@ -1239,6 +1237,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ļauj lietojumprogrammai lasīt instalēšanas sesijas. Tādējādi lietojumprogrammai ir pieejama informācija par aktīvajām pakotņu instalācijām."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"Pieprasīt pakotņu instalēšanu"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Ļauj lietojumprogrammai pieprasīt pakotņu instalēšanu."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Pieskarieties divreiz, lai kontrolētu tālummaiņu."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nevarēja pievienot logrīku."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Doties uz"</string>
@@ -1591,10 +1593,8 @@
<string name="select_year" msgid="7952052866994196170">"Atlasiet gadu."</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> tika dzēsts."</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbā: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. darba profils: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. darba profils: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Lai atspraustu šo ekrānu, pieskarieties pogai “Atpakaļ” un turiet to."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Lietotne ir piesprausta. Atspraušana šajā ierīcē nav atļauta."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrāns ir piesprausts"</string>
@@ -1723,6 +1723,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Atiestatīt tūlīt"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> atspējots"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferences zvans"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Rīka padoms"</string>
</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index aeb0c41..f0c9a8d 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Дозволува апликацијата да ја користи услугата IMS за повици без ваша интервенција."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"прочитај ги статусот и идентитетот на телефонот"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Овозможува апликацијата да пристапи кон карактеристиките на телефонот на уредот. Оваа дозвола овозможува апликацијата да ги утврди телефонскиот број и ID на уредот, дали повикот е активен и далечинскиот број поврзан со повикот."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"да го чита телефонскиот број"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Ѝ дозволува на апликацијата да пристапи до телефонскиот број на уредот."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"спречи режим на штедење кај таблет"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"спречи го телевизорот да премине во режим на мирување"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"спречи телефон од режим на штедење"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Дозволува апликација да чита сесии на инсталирање. Тоа овозможува апликацијата да гледа детали за активни инсталации на пакет."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"барање пакети за инсталирање"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Дозволува апликацијата да бара инсталација на пакети."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Допрете двапати за контрола на зумот"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Не можеше да се додаде виџет."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Оди"</string>
@@ -1562,10 +1568,8 @@
<string name="select_year" msgid="7952052866994196170">"Избери година"</string>
<string name="deleted_key" msgid="7659477886625566590">"Избришано <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Работа <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Втора деловна <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Трета деловна <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"За откачување на екранов, допрете и задржете Назад."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Апликацијата е закачена: откачување не е дозволено на уредов."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екранот е закачен"</string>
@@ -1685,5 +1689,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Ресетирај сега"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Оневозможен <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференциски повик"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Појавен прозорец на совет за алатка"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Совет за алатка"</string>
</resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 4193079..a1e7214 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -163,7 +163,7 @@
<string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g> എന്നതിൽ സൈൻ ഇൻ ചെയ്യുന്നതിൽ പിശക്"</string>
<string name="contentServiceSync" msgid="8353523060269335667">"സമന്വയിപ്പിക്കുക"</string>
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"സമന്വയിപ്പിക്കുക"</string>
- <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"വളരെയധികം <xliff:g id="CONTENT_TYPE">%s</xliff:g> ഇല്ലാതാക്കലുകൾ."</string>
+ <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"വളരെയധികം <xliff:g id="CONTENT_TYPE">%s</xliff:g> ഇല്ലാതാക്കുന്നു."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"ടാബ്ലെറ്റ് സ്റ്റോറേജ് കഴിഞ്ഞു. ഇടം ശൂന്യമാക്കാൻ ചില ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
<string name="low_memory" product="watch" msgid="4415914910770005166">"വാച്ചിലെ സ്റ്റോറേജ് നിറഞ്ഞു. ഇടം ശൂന്യമാക്കാൻ കുറച്ച് ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
<string name="low_memory" product="tv" msgid="516619861191025923">"ടിവി സ്റ്റോറേജ് നിറഞ്ഞു. ഇടം ശൂന്യമാക്കാൻ കുറച്ച് ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"നിങ്ങളുടെ ഇടപെടൽ ഇല്ലാതെ കോളുകൾ ചെയ്യാൻ IMS സേവനം ഉപയോഗിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ഫോൺ നിലയും ഐഡന്റിറ്റിയും റീഡുചെയ്യുക"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ഉപകരണത്തിന്റെ ഫോൺ സവിശേഷതകൾ ആക്സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഈ അനുമതി ഫോൺ നമ്പർ, ഉപകരണ ഐഡികൾ, ഒരു കോൾ സജീവമാണോയെന്നത്, ഒരു കോൾ കണക്റ്റുചെയ്ത വിദൂര നമ്പർ എന്നിവ നിർണ്ണയിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ഫോൺ നമ്പർ വായിക്കുക"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ഉപകരണത്തിന്റെ ഫോൺ നമ്പർ ആക്സസ്സ് ചെയ്യുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"സുഷുപ്തിയിലാകുന്നതിൽ നിന്ന് ടാബ്ലെറ്റിനെ തടയുക"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ടിവിയെ നിർജ്ജീവമാകുന്നതിൽ നിന്ന് തടയുക"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"സുഷുപ്തിയിലാകുന്നതിൽ നിന്ന് ഫോണിനെ തടയുക"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"മീഡിയ വോളിയം"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"അറിയിപ്പ് വോളിയം"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ഡിഫോൾട്ട് റിംഗ്ടോൺ"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ഡിഫോൾട്ട് (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ഒന്നും വേണ്ട"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"റിംഗ്ടോണുകൾ"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"അലാറം ശബ്ദങ്ങൾ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"അറിയിപ്പ് ശബ്ദങ്ങൾ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"അറിഞ്ഞുകൂടാത്തത്"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">വൈഫൈ നെറ്റ്വർക്കുകൾ ലഭ്യമാണ്</item>
<item quantity="one">വൈഫൈ നെറ്റ്വർക്ക് ലഭ്യമാണ്</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ഇൻസ്റ്റാൾ ചെയ്ത സെഷനുകൾ റീഡുചെയ്യുന്നതിന് ഒരു അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. സജീവ പാക്കേജ് ഇൻസ്റ്റാളേഷനുകളെക്കുറിച്ചുള്ള വിശദാംശങ്ങൾ കാണുന്നതിന് ഇത് അനുവദിക്കുന്നു."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"പാക്കേജുകൾ ഇൻസ്റ്റാൾ ചെയ്യാൻ അഭ്യർത്ഥിക്കുക"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"പാക്കേജുകളുടെ ഇൻസ്റ്റാളേഷൻ അഭ്യർത്ഥിക്കാൻ ഒരു അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"സൂം നിയന്ത്രണം ലഭിക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"വിജറ്റ് ചേർക്കാനായില്ല."</string>
<string name="ime_action_go" msgid="8320845651737369027">"പോവുക"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"വർഷം തിരഞ്ഞെടുക്കുക"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ഇല്ലാതാക്കി"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ഔദ്യോഗികം <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"രണ്ടാമത്തെ ഔദ്യോഗിക <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"മൂന്നാമത്തെ ഔദ്യോഗിക <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ഈ സ്ക്രീൻ അൺപിൻ ചെയ്യാൻ, ബാക്ക് ബട്ടൺ സ്പർശിച്ച് പിടിക്കുക"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"അപ്ലിക്കേഷൻ പിൻ ചെയ്തു: ഈ ഉപകരണത്തിൽ അൺപിൻ ചെയ്യാനാവില്ല."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"സ്ക്രീൻ പിൻ ചെയ്തു"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ഇപ്പോൾ പുനക്രമീകരിക്കുക"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="conference_call" msgid="3751093130790472426">"കോൺഫറൻസ് കോൾ"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ടൂൾ ടിപ്പ്"</string>
</resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 74006da..3f9618c 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Апп нь дуудлага хийхдээ таны оролцоогүйгээр IMS үйлчилгээг ашиглах боломжтой."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"утасны статус ба таниулбарыг унших"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Апп нь төхөөрөмжийн утасны функцд хандах боломжтой. Энэ зөвшөөрөл нь апп-д утасны дугаар болон төхөөрөмжийн ID-г, дуудлага идэвхтэй эсэх, холын дугаар дуудлагаар холбогдсон байгаа эсэхийг тогтоох боломжийг олгоно,"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"утасны дугаарыг харах"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Төхөөрөмжийн утасны дугаарт хандах зөвшөөрлийг аппд олгоно."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"таблетыг унтуулахгүй байлгах"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"Телевиз-ийн гэрэл унтрахаас сэргийл"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"утсыг унтуулахгүй байлгах"</string>
@@ -436,7 +438,7 @@
<string name="permlab_manageFingerprint" msgid="5640858826254575638">"хурууны хээний програм хангамжийг удирдах"</string>
<string name="permdesc_manageFingerprint" msgid="178208705828055464">"Хурууны хээний загварыг нэмэх эсвэл усгтах үйлдлийг хийх зөвшөөрлийг програмд олгодог."</string>
<string name="permlab_useFingerprint" msgid="3150478619915124905">"хурууны хээний програм хангамжийг ашиглах"</string>
- <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний програм хамгамжийг ашиглах зөвшөөрлийг програмд олгодог"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний апп хамгамжийг ашиглах зөвшөөрлийг аппд олгодог"</string>
<string name="fingerprint_acquired_partial" msgid="735082772341716043">"Хурууны хээг дутуу уншуулсан байна. Дахин оролдоно уу."</string>
<string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Хурууны хээ боловсруулж чадахгүй байна. Дахин оролдоно уу."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Хурууны хээ мэдрэгч бохирдсон байна. Та цэвэрлэсний дараагаар дахин оролдоно уу."</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Медиа дууны хэмжээ"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Мэдэгдлийн дууны хэмжээ"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Үндсэн хонхны ая"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Үндсэн (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Алийг нь ч биш"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Хонхны ая"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Сэрүүлгийн ая"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Мэдэгдлийн дуу"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Тодорхойгүй"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Wi-Fi сүлжээ ашиглах боломжтой</item>
<item quantity="one">Wi-Fi сүлжээ ашиглах боломжтой</item>
@@ -1208,12 +1206,16 @@
<string name="ext_media_status_formatting" msgid="1085079556538644861">"Хэлбэршүүлж байна..."</string>
<string name="ext_media_status_missing" msgid="5638633895221670766">"Оруулаагүй байна"</string>
<string name="activity_list_empty" msgid="1675388330786841066">"Таарах активити олдсонгүй."</string>
- <string name="permlab_route_media_output" msgid="6243022988998972085">"медиа гаралтын маршрут"</string>
+ <string name="permlab_route_media_output" msgid="6243022988998972085">"медиа гаралтын чиглэл"</string>
<string name="permdesc_route_media_output" msgid="4932818749547244346">"Аппликешн нь медиа гаралтыг бусад гадаад төхөөрөмжрүү чиглүүлэх боломжтой."</string>
<string name="permlab_readInstallSessions" msgid="3713753067455750349">"Суулгах харилцан үйлдлийг унших"</string>
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Аппликешн-д суулгах сешн уншихыг зөвшөөрнө. Энэ нь идэвхтэй багцуудыг суулгалтын талаар дэлгэрэнгүй мэдээллийг үзэх боломж олгоно."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"багц суулгахыг хүсэх"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Аппликейшн нь багц суулгахыг хүсэх боломжтой."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Өсгөх контрол дээр хоёр удаа товшино уу"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Виджет нэмж чадсангүй."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Очих"</string>
@@ -1240,7 +1242,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Ханын зураг"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Ханын зураг солих"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Мэдэгдэл сонсогч"</string>
- <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR сонсогч"</string>
+ <string name="vr_listener_binding_label" msgid="4316591939343607306">"Виртуал Орчин (VR) сонсогч"</string>
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Нөхцөл нийлүүлэгч"</string>
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Мэдэгдлийг ангилах үйлчилгээ"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN идэвхтэй болов"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Жилийг сонгоно уу"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> устсан"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ажлын <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Энэ дэлгэцийг эхэнд нээхийг болиулахын тулд Буцах товчлуурыг дараад, хүлээнэ үү."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App-ыг тусгайлан тэмдэглэсэн байна: Энэ төхөөрөмж дээр тусгайлан тэмдэглэсэн сонголтыг устгах боломжгүй."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Дэлгэцийг тогтоосон"</string>
@@ -1685,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Одоо шинэчлэх"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g>-г цуцалсан"</string>
<string name="conference_call" msgid="3751093130790472426">"Хурлын дуудлага"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Зөвлөмж"</string>
</resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index dd99f15..d5487e1 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"आपल्या हस्तक्षेपाशिवाय अॅपला कॉल करण्यासाठी IMS सेवा वापरण्याची अनुमती देते."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"फोन स्थिती आणि ओळख वाचा"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"डिव्हाइसच्या फोन वैशिष्ट्यांवर प्रवेश करण्यास अॅप ला अनुमती देते. ही परवानगी कॉल सक्रिय असला किंवा नसला तरीही, फोन नंबर आणि डिव्हाइस ID आणि कॉलद्वारे कनेक्ट केलेला रीमोट नंबर निर्धारित करण्यासाठी अॅप ला अनुमती देते."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"फोन नंबर वाचा"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"अॅपला डिव्हाइसच्या फोन नंबरमध्ये प्रवेश करण्याची अनुमती देते."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"टॅबलेट निष्क्रिय होण्यापासून प्रतिबंधित करा"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"निष्क्रिय होण्यापासून प्रतिबंध करा"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"फोन निष्क्रिय होण्यापासून प्रतिबंधित करा"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"अनुप्रयोगास स्थापना सत्र वाचण्याची अनुमती देते. हे सक्रिय पॅकेज स्थापनांविषयी तपशील पाहाण्याची यास अनुमती देते."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"पॅकेज स्थापित करण्यासाठी विनंती करा"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"पॅकेजच्या स्थापना करण्यासाठी अनुप्रयोगास अनुमती देते."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"झूम नियंत्रणासाठी दोनदा टॅप करा"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"विजेट जोडू शकलो नाही."</string>
<string name="ime_action_go" msgid="8320845651737369027">"जा"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"वर्ष निवडा"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> हटविली"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 रे कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 रे कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ही स्क्रीन अनपिन करण्यासाठी, परत ला स्पर्श करा आणि धरून ठेवा."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"अॅप पिन केलेला आहे: या डिव्हाइसवर अनपिन करण्यास अनुमती नाही."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"स्क्रीन पिन केली"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"आता रीसेट करा"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> अक्षम केले"</string>
<string name="conference_call" msgid="3751093130790472426">"परिषद कॉल"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"टूलटिप पॉपअप"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"टूलटिप"</string>
</resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 57edab8..1ef6493 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Membenarkan apl menggunakan perkhidmatan IMS untuk membuat panggilan tanpa campur tangan anda."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"baca status dan identiti telefon"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Membenarkan apl mengakses ciri telefon pada peranti. Kebenaran ini membolehkan apl menentukan nombor telefon dan ID peranti, sama ada panggilan aktif dan nombor jauh yang dihubungkan dengan panggilan."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"baca nombor telefon"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Membenarkan apl mengakses nombor telefon peranti."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"menghalang tablet daripada tidur"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"halang TV daripada tidur"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"halang telefon daripada tidur"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Kelantangan media"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Kelantangan pemberitahuan"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Nada dering lalai"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Lalai (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Tiada"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Nada dering"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Bunyi penggera"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Bunyi pemberitahuan"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Tidak diketahui"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Rangkaian Wi-Fi tersedia</item>
<item quantity="one">Rangkaian Wi-Fi tersedia</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Membenarkan aplikasi membaca sesi pemasangan Ini membenarkan apl melihat butiran mengenai pemasangan pakej yang aktif."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"minta pakej pemasangan"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Membenarkan aplikasi meminta pemasangan pakej."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ketik dua kali untuk mendapatkan kawalan zum"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Tidak dapat menambahkan widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Pergi"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Pilih tahun"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dipadamkan"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Kerja <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> kerja ke-2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> kerja ke-3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Untuk menyahsematkan skrin ni, ketik & tahan Kembali."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Apl disemat: Nyahsemat tidak dibenarkan pada peranti ini."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skrin disemat"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Tetapkan semula sekarang"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> dilumpuhkan"</string>
<string name="conference_call" msgid="3751093130790472426">"Panggilan Sidang"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Keterangan item"</string>
</resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 834a665..2117c56 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"သင့်ရဲ့ဝင်ရောက်စွက်ဖက်မှုမပါဘဲ IMS ဝန်ဆောင်မှုကိုအသုံးပြုပြီး ဖုန်းခေါ်ဆိုနိုင်ရန် အပ်ဖ်ကို ခွင့်ပြုထားပါ။"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ဖုန်းရဲ့ အခြေအနေ နှင့် အမှတ်သညာအား ဖတ်ခြင်း"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"အပလီကေးရှင်းအား ဖုန်းရဲ့ စွမ်းဆောင်ချက်များအား သုံးခွင့်ပြုပါ။ အပလီကေးရှင်းအနေဖြင့် ဖုန်းနံပါတ်၊ စက်နံပါတ်၊ ဖုန်းခေါ်နေမှု ရှိမရှိနှင့် တဖက်မှ ဖုန်းနံပါတ် များအား သိရှိနိုင်ပါသည်"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ဖုန်းနံပါတ်ကို ဖတ်ရန်"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"အက်ပ်ကို စက်ပစ္စည်း၏ ဖုန်းနံပါတ် အသုံးပြုခွင့်ပေးပါ။"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"တက်ပလက်အား ပိတ်ခြင်းမှ ကာကွယ်ခြင်း"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"တီဗွီအား နားနေခြင်းမှ ကာကွယ်ရန်"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ဖုန်းအနားယူခြင်းမပြုလုပ်စေရန်"</string>
@@ -643,7 +645,7 @@
<string name="relationTypeAssistant" msgid="6274334825195379076">"အထောက်အကူ"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"ညီအကို"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"သားသမီး"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"အတူနေအပေါင်းအဖော်"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"အတူနေအဖော်"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"ဖခင်"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"သူငယ်ချင်း"</string>
<string name="relationTypeManager" msgid="6365677861610137895">"မန်နေဂျာ"</string>
@@ -651,7 +653,7 @@
<string name="relationTypeParent" msgid="4755635567562925226">"မိဘ"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"လုပ်ဖော်ကိုင်ဖက်"</string>
<string name="relationTypeReferredBy" msgid="101573059844135524">"မှရည်ညွှန်းပေးသည်"</string>
- <string name="relationTypeRelative" msgid="1799819930085610271">"ဆွေးမျိုး"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"ဆွေမျိုး"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"ညီအမ"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"အိမ်ထောင်ဖက်"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"မိမိစိတ်ကြိုက်"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"အပလီကေးရှင်းအား တပ်ဆင်ရေး ချိတ်ဆက်မှုများကို ဖတ်ခွင့်ပြုသည်။ ၎င်းသည် ဖွင့်သုံးနေသည့် အထုပ်အား တပ်ဆင်မှုဆိုင်ရာ အသေးိစတ်များကို ကြည့်ရှုခွင့် ပြုသည်။"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"တပ်ဆင်ရေး အထုပ်များကို တောင်းဆိုပါ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ပက်ကေ့များ သွင်းယူခြင်းအတွက် တောင်းဆိုရန် အပလီကေးရှင်းအား ခွင့်ပြုပါ"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ဇူးမ်အသုံးပြုရန် နှစ်ချက်တို့ပါ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ဝဒ်ဂျက်ထည့်လို့ မရပါ"</string>
<string name="ime_action_go" msgid="8320845651737369027">"သွားပါ"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"ခုနှစ်ကို ရွေးပါ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ကို ဖျက်ပြီးပါပြီ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"အလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"ဒုတိယအလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"တတိယအလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ဤမျက်နှာပြင်ကို ပင်ဖြုတ်ရန် \"နောက်သို့\" ကိုထိပြီးဖိထားပါ။"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"အက်ပ်ကို ပင်ထိုးထားသည်။ ပင်ဖျက်ခြင်းကို ဒီစက်မှာ မရနိုင်ပါ။"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"မျက်နှာပြင်ကို ပင်ထိုးထား"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ယခုပြန်လည်သတ်မှတ်ပါ"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ပိတ်ထားသည့် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"လူအမြောက်အမြားတပြိုင်နက် ခေါ်ဆိုမှု"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"အကြံပြုချက်ပြ ပေါ့အပ်ဝင်းဒိုး"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"အကြံပြုချက်ပြ ပေါ့အပ် ဝင်းဒိုး"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 61e74a2..f2b11c9 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Lar appen bruke nettprattjenesten til å ringe uten at du gjør noe."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lese telefonstatus og -identitet"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lar appen bruke enhetens telefonfunksjoner. Med denne tillatelsen kan appen finne telefonnummer og enhets-ID-er, registrere om en samtale pågår, og se det eksterne nummeret det opprettes en forbindelse med via oppringing."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"les telefonnummeret"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Gir appen tilgang til telefonnummeret til enheten."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"hindre nettbrettet fra å gå over til sovemodus"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"hindre TV-en i å gå i hvilemodus"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"forhindre telefonen fra å sove"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Tillater en app å lese installeringsøkter. Dette gjør det mulig for den å se detaljer om aktive pakkeinstallasjoner."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"be om installasjon av pakker"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Lar apper be om installasjon av pakker."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Trykk to ganger for zoomkontroll"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Kunne ikke legge til modulen."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Utfør"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Velg året"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> er slettet"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Jobb-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Andre <xliff:g id="LABEL">%1$s</xliff:g> for jobben"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Tredje <xliff:g id="LABEL">%1$s</xliff:g> for jobben"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"For å løsne denne skjermen, trykk og hold inne Tilbake."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Appen er festet – du kan ikke løsne apper på denne enheten."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skjermen er festet"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Tilbakestill nå"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> er slått av"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferansesamtale"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Verktøytips i forgrunnen"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Verktøytips"</string>
</resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index d6c8612..15f787937 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"तपाईँको हस्तक्षेप बिना नै कल गर्न IMS सेवा प्रयोग गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"फोन स्थिति र पहिचान पढ्नुहोस्"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"उपकरणको फोन विशेषताहरूको पहुँच गर्न अनुप्रयोगलाई अनुमति दिन्छ। यस अनुमतिले फोन नम्बर र उपकरणको IDs, कल सक्षम छ कि छैन र कलद्वारा जोडिएको टाढाको नम्बर निर्धारण गर्न अनुमति दिन्छ।"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"फोन नम्बर पढ्ने"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"यस अनुप्रयोगलाई यस यन्त्रको फोन नम्बरमाथि पहुँच राख्न दिनुहोस्।"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ट्याब्लेटलाई निन्द्रामा जानबाट रोक्नुहोस्"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV निभ्नबाट जोगाउनुहोस्"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"फोनलाई निदाउनबाट रोक्नुहोस्"</string>
@@ -553,30 +555,30 @@
<item msgid="1735177144948329370">"घरको फ्याक्स"</item>
<item msgid="603878674477207394">"पेजर"</item>
<item msgid="1650824275177931637">"अन्य"</item>
- <item msgid="9192514806975898961">"अनुकूलन"</item>
+ <item msgid="9192514806975898961">"आफू अनुकूल"</item>
</string-array>
<string-array name="emailAddressTypes">
<item msgid="8073994352956129127">"गृह"</item>
<item msgid="7084237356602625604">"काम"</item>
<item msgid="1112044410659011023">"अन्य"</item>
- <item msgid="2374913952870110618">"अनुकूलन"</item>
+ <item msgid="2374913952870110618">"आफू अनुकूल"</item>
</string-array>
<string-array name="postalAddressTypes">
<item msgid="6880257626740047286">"गृह"</item>
<item msgid="5629153956045109251">"काम"</item>
<item msgid="4966604264500343469">"अन्य"</item>
- <item msgid="4932682847595299369">"अनुकूलन"</item>
+ <item msgid="4932682847595299369">"आफू अनुकूल"</item>
</string-array>
<string-array name="imAddressTypes">
<item msgid="1738585194601476694">"गृह"</item>
<item msgid="1359644565647383708">"काम"</item>
<item msgid="7868549401053615677">"अन्य"</item>
- <item msgid="3145118944639869809">"अनुकूलन"</item>
+ <item msgid="3145118944639869809">"आफू अनुकूल"</item>
</string-array>
<string-array name="organizationTypes">
<item msgid="7546335612189115615">"काम गर्नुहोस्"</item>
<item msgid="4378074129049520373">"अन्य"</item>
- <item msgid="3455047468583965104">"अनुकूलन"</item>
+ <item msgid="3455047468583965104">"आफू अनुकूल"</item>
</string-array>
<string-array name="imProtocols">
<item msgid="8595261363518459565">"AIM"</item>
@@ -588,7 +590,7 @@
<item msgid="2506857312718630823">"ICQ"</item>
<item msgid="1648797903785279353">"Jabber"</item>
</string-array>
- <string name="phoneTypeCustom" msgid="1644738059053355820">"अनुकूलन"</string>
+ <string name="phoneTypeCustom" msgid="1644738059053355820">"आफू अनुकूल"</string>
<string name="phoneTypeHome" msgid="2570923463033985887">"गृह"</string>
<string name="phoneTypeMobile" msgid="6501463557754751037">"मोबाइल"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"काम"</string>
@@ -609,24 +611,24 @@
<string name="phoneTypeWorkPager" msgid="649938731231157056">"कार्य पेजर"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"सहायक"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
- <string name="eventTypeCustom" msgid="7837586198458073404">"अनुकूलन"</string>
+ <string name="eventTypeCustom" msgid="7837586198458073404">"आफू अनुकूल"</string>
<string name="eventTypeBirthday" msgid="2813379844211390740">"जन्मदिन"</string>
<string name="eventTypeAnniversary" msgid="3876779744518284000">"वार्षिक समारोह"</string>
<string name="eventTypeOther" msgid="7388178939010143077">"अन्य"</string>
- <string name="emailTypeCustom" msgid="8525960257804213846">"अनुकूलन"</string>
+ <string name="emailTypeCustom" msgid="8525960257804213846">"आफू अनुकूल"</string>
<string name="emailTypeHome" msgid="449227236140433919">"गृह"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"काम"</string>
<string name="emailTypeOther" msgid="2923008695272639549">"अन्य"</string>
<string name="emailTypeMobile" msgid="119919005321166205">"मोबाइल"</string>
- <string name="postalTypeCustom" msgid="8903206903060479902">"अनुकूलन"</string>
+ <string name="postalTypeCustom" msgid="8903206903060479902">"आफू अनुकूल"</string>
<string name="postalTypeHome" msgid="8165756977184483097">"गृह"</string>
<string name="postalTypeWork" msgid="5268172772387694495">"काम"</string>
<string name="postalTypeOther" msgid="2726111966623584341">"अन्य"</string>
- <string name="imTypeCustom" msgid="2074028755527826046">"अनुकूलन"</string>
+ <string name="imTypeCustom" msgid="2074028755527826046">"आफू अनुकूल"</string>
<string name="imTypeHome" msgid="6241181032954263892">"गृह"</string>
<string name="imTypeWork" msgid="1371489290242433090">"काम"</string>
<string name="imTypeOther" msgid="5377007495735915478">"अन्य"</string>
- <string name="imProtocolCustom" msgid="6919453836618749992">"अनुकूलन"</string>
+ <string name="imProtocolCustom" msgid="6919453836618749992">"आफू अनुकूल"</string>
<string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
<string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
<string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string>
@@ -638,8 +640,8 @@
<string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
<string name="orgTypeWork" msgid="29268870505363872">"काम"</string>
<string name="orgTypeOther" msgid="3951781131570124082">"अन्य"</string>
- <string name="orgTypeCustom" msgid="225523415372088322">"अनुकूलन"</string>
- <string name="relationTypeCustom" msgid="3542403679827297300">"अनुकूलन"</string>
+ <string name="orgTypeCustom" msgid="225523415372088322">"आफू अनुकूल"</string>
+ <string name="relationTypeCustom" msgid="3542403679827297300">"आफू अनुकूल"</string>
<string name="relationTypeAssistant" msgid="6274334825195379076">"सहायक"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"भाइ"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"सन्तान"</string>
@@ -653,8 +655,8 @@
<string name="relationTypeReferredBy" msgid="101573059844135524">"द्वारा उल्लिखित"</string>
<string name="relationTypeRelative" msgid="1799819930085610271">"आफन्त"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"बहिनी"</string>
- <string name="relationTypeSpouse" msgid="394136939428698117">"पति-पत्नि"</string>
- <string name="sipAddressTypeCustom" msgid="2473580593111590945">"अनुकूलन"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"पति-पत्नी"</string>
+ <string name="sipAddressTypeCustom" msgid="2473580593111590945">"आफू अनुकूल"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"गृह"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"काम गर्नुहोस्"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"अन्य"</string>
@@ -1029,7 +1031,7 @@
<string name="smv_process" msgid="5120397012047462446">"प्रक्रिया <xliff:g id="PROCESS">%1$s</xliff:g> यसको आफ्नै कडामोड नीतिका कारण उल्लङ्घन गरिएको छ।"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"एन्ड्रोइड अपग्रेड हुँदैछ…"</string>
<string name="android_start_title" msgid="8418054686415318207">"Android शुरू हुँदैछ..."</string>
- <string name="android_upgrading_fstrim" msgid="8036718871534640010">"भण्डारण अनुकूलन गर्दै।"</string>
+ <string name="android_upgrading_fstrim" msgid="8036718871534640010">"भण्डारण आफू अनुकूल गर्दै।"</string>
<string name="android_upgrading_notification_title" msgid="8428357096969413169">"Android को अद्यावधिकलाई सम्पन्न गर्दै…"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"स्तरवृद्धि सम्पन्न नभएसम्म केही अनुप्रयोगहरू राम्ररी काम नगर्न सक्छन्"</string>
<string name="app_upgrading_toast" msgid="3008139776215597053">"<xliff:g id="APPLICATION">%1$s</xliff:g> को स्तरवृद्धि हुँदैछ…"</string>
@@ -1102,8 +1104,8 @@
<string name="wifi_connect_alert_message" msgid="6451273376815958922">"अनुप्रयोग %1$s Wifi सञ्जाल %2$s मा जडान गर्न चाहन्छ"</string>
<string name="wifi_connect_default_application" msgid="7143109390475484319">"एउटा अनुप्रयोग"</string>
<string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi प्रत्यक्ष"</string>
- <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi सिधा सुरु गर्नुहोस्। यसले Wi-Fi ग्राहक/हट्स्पटलाई बन्द गराउने छ।"</string>
- <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi सिधा सुरु हुन सकेन।"</string>
+ <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi सीधा सुरु गर्नुहोस्। यसले Wi-Fi ग्राहक/हट्स्पटलाई बन्द गराउने छ।"</string>
+ <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi सीधा सुरु हुन सकेन।"</string>
<string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi प्रत्यक्ष खुल्ला छ"</string>
<string name="wifi_p2p_enabled_notification_message" msgid="8064677407830620023">"सेटिङहरूका लागि ट्याप गर्नुहोस्"</string>
<string name="accept" msgid="1645267259272829559">"स्वीकार्नुहोस्"</string>
@@ -1216,6 +1218,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"स्थापित सत्र पढ्न अनुप्रयोगलाई अनुमति दिनुहोस्। यसले सक्रिय प्याकेज प्रतिष्ठानहरू बारेमा विवरण हेर्ने अनुमति दिन्छ।"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"स्थापना प्याकेजहरू अनुरोध गर्नुहोस्"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"प्याकेजहरूको स्थापना अनुरोध गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"जुम नियन्त्रणको लागि दुई चोटि ट्याप गर्नुहोस्"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"विजेट थप गर्न सकिँदैन।"</string>
<string name="ime_action_go" msgid="8320845651737369027">"जानुहोस्"</string>
@@ -1566,10 +1572,8 @@
<string name="select_year" msgid="7952052866994196170">"वर्ष चयन गर्नुहोस्"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> हटाइयो"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"कार्यालयको दोस्रो <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"कार्यालयको तेस्रो <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"यस स्क्रिनलाई अनपिन गर्न पछाडि बटनलाई छोइराख्नुहोस्।"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"अनुप्रयोग पिन गरियो: यस यन्त्रमा अनपिन गर्ने अनुमति छैन।"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"स्क्रिन पिन गरियो"</string>
@@ -1689,5 +1693,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"अहिले रिसेट गर्नुहोस्"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> लाई असक्षम गरियो"</string>
<string name="conference_call" msgid="3751093130790472426">"सम्मेलन कल"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"उपकरणको वर्णन गर्ने पपअप"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"उपकरणको वर्णन"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index f7c76cd..9112a8c 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Hiermee kan de app de IMS-service gebruiken om te bellen zonder je tussenkomst."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefoonstatus en -identiteit lezen"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Hiermee kan de app toegang krijgen tot de telefoonfuncties van het apparaat, Met deze toestemming kan de app het telefoonnummer en de apparaat-ID\'s bepalen, of een oproep actief is, en het andere telefoonnummer waarmee wordt gebeld."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"telefoonnummer lezen"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Hiermee kan de app toegang krijgen tot het telefoonnummer van het apparaat."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"voorkomen dat tablet overschakelt naar slaapmodus"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"voorkomen dat tv overschakelt naar slaapmodus"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"voorkomen dat telefoon overschakelt naar slaapmodus"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Hiermee wordt een app toegestaan installatiesessies te lezen. Zo kan de app informatie bekijken over actieve pakketinstallaties."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"installatiepakketten aanvragen"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Hiermee kan een app installatie van pakketten aanvragen."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tik twee keer voor zoomregeling"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Kan widget niet toevoegen."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ga"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Jaar selecteren"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> verwijderd"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e <xliff:g id="LABEL">%1$s</xliff:g>, werk"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e <xliff:g id="LABEL">%1$s</xliff:g>, werk"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Tik op Terug en houd vast om dit scherm los te maken."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is vastgezet: losmaken is niet toegestaan op dit apparaat."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Scherm vastgezet"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Nu resetten"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> uitgeschakeld"</string>
<string name="conference_call" msgid="3751093130790472426">"Telefonische vergadering"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Pop-up met knopinfo"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Knopinfo"</string>
</resources>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 39c5dfa..a3628cc 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -40,7 +40,7 @@
<string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> ਸਕਿੰਟ"</string>
<string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> ਸਕਿੰਟ"</string>
<string name="untitled" msgid="4638956954852782576">"<ਬਿਨਾਂ ਸਿਰਲੇਖ>"</string>
- <string name="emptyPhoneNumber" msgid="7694063042079676517">"(ਕੋਈ ਫੋਨ ਨੰਬਰ ਨਹੀਂ)"</string>
+ <string name="emptyPhoneNumber" msgid="7694063042079676517">"(ਕੋਈ ਫ਼ੋਨ ਨੰਬਰ ਨਹੀਂ)"</string>
<string name="unknownName" msgid="6867811765370350269">"ਅਗਿਆਤ"</string>
<string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"ਵੌਇਸਮੇਲ"</string>
<string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
@@ -252,7 +252,7 @@
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
<string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS ਸੁਨੇਹੇ ਭੇਜਣ ਅਤੇ ਦੇਖਣ"</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"ਸਟੋਰੇਜ"</string>
- <string name="permgroupdesc_storage" msgid="637758554581589203">"ਆਪਣੀ ਡੀਵਾਈਸ ’ਤੇ ਫੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਫਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
+ <string name="permgroupdesc_storage" msgid="637758554581589203">"ਆਪਣੀ ਡੀਵਾਈਸ ’ਤੇ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਫਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"ਮਾਈਕ੍ਰੋਫੋਨ"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"ਔਡੀਓ ਰਿਕਾਰਡ ਕਰਨ"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"ਕੈਮਰਾ"</string>
@@ -376,7 +376,9 @@
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS ਕਾਲ ਸੇਵਾ ਤੱਕ ਪਹੁੰਚ"</string>
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਕਾਲਾਂ ਕਰਨ ਲਈ IMS ਸੇਵਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ਫੋਨ ਸਥਿਤੀ ਅਤੇ ਪਛਾਣ ਪੜ੍ਹੋ"</string>
- <string name="permdesc_readPhoneState" msgid="1639212771826125528">"ਐਪ ਨੂੰ ਡੀਵਾਈਸ ਦੀਆਂ ਫੋਨ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਅਨੁਮਤੀ ਐਪ ਨੂੰ ਫੋਨ ਨੰਬਰ ਅਤੇ ਡੀਵਾਈਸ ID ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ, ਇੱਕ ਕਾਲ ਸਕਿਰਿਆ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਰਿਮੋਟ ਨੰਬਰ ਇੱਕ ਕਾਲ ਨਾਲ ਕਨੈਕਟ ਹੈ ਜਾਂ ਨਹੀਂ।"</string>
+ <string name="permdesc_readPhoneState" msgid="1639212771826125528">"ਐਪ ਨੂੰ ਡੀਵਾਈਸ ਦੀਆਂ ਫੋਨ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਅਨੁਮਤੀ ਐਪ ਨੂੰ ਫ਼ੋਨ ਨੰਬਰ ਅਤੇ ਡੀਵਾਈਸ ID ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ, ਇੱਕ ਕਾਲ ਸਕਿਰਿਆ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਰਿਮੋਟ ਨੰਬਰ ਇੱਕ ਕਾਲ ਨਾਲ ਕਨੈਕਟ ਹੈ ਜਾਂ ਨਹੀਂ।"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ਫ਼ੋਨ ਨੰਬਰ ਪੜ੍ਹੋ"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ਡੀਵਾਈਸ ਦੇ ਫ਼ੋਨ ਨੰਬਰ \'ਤੇ ਪਹੁੰਚ ਕਰਨ ਲਈ ਐਪ ਨੂੰ ਇਜਾਜ਼ਤ ਦਿੰਦੀ ਹੈ।"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ਟੈਬਲੇਟ ਨੂੰ ਸਲੀਪਿੰਗ ਤੋਂ ਰੋਕੋ"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV ਨੂੰ ਸਲੀਪਿੰਗ ਤੋਂ ਰੋਕੋ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ਫੋਨ ਨੂੰ ਸਲੀਪਿੰਗ ਤੋਂ ਰੋਕੋ"</string>
@@ -549,7 +551,7 @@
<item msgid="8901098336658710359">"ਘਰ"</item>
<item msgid="869923650527136615">"ਮੋਬਾਈਲ"</item>
<item msgid="7897544654242874543">"ਕੰਮ"</item>
- <item msgid="1103601433382158155">"ਦਫ਼ਤਰ ਦੀ ਫੈਕਸ"</item>
+ <item msgid="1103601433382158155">"ਕਾਰਜ-ਸਥਾਨ ਫੈਕਸ"</item>
<item msgid="1735177144948329370">"ਘਰ ਦੀ ਫੈਕਸ"</item>
<item msgid="603878674477207394">"ਪੇਜਰ"</item>
<item msgid="1650824275177931637">"ਹੋਰ"</item>
@@ -592,7 +594,7 @@
<string name="phoneTypeHome" msgid="2570923463033985887">"ਘਰ"</string>
<string name="phoneTypeMobile" msgid="6501463557754751037">"ਮੋਬਾਈਲ"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"ਕੰਮ"</string>
- <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ਦਫ਼ਤਰ ਦੀ ਫੈਕਸ"</string>
+ <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ਕਾਰਜ-ਸਥਾਨ ਫੈਕਸ"</string>
<string name="phoneTypeFaxHome" msgid="2067265972322971467">"ਘਰ ਦੀ ਫੈਕਸ"</string>
<string name="phoneTypePager" msgid="7582359955394921732">"ਪੇਜਰ"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"ਹੋਰ"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"ਮੀਡੀਆ ਵੌਲਿਊਮ"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"ਸੂਚਨਾ ਵੌਲਿਊਮ"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਰਿੰਗਟੋਨ"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ਪੂਰਵ-ਨਿਰਧਾਰਤ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ਕੋਈ ਨਹੀਂ"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ਰਿੰਗਟੋਨਾਂ"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"ਅਲਾਰਮ ਧੁਨੀਆਂ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"ਸੂਚਨਾ ਧੁਨੀਆਂ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"ਅਗਿਆਤ"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Wi-Fi ਨੈੱਟਵਰਕਸ ਉਪਲਬਧ</item>
<item quantity="other">Wi-Fi ਨੈੱਟਵਰਕਸ ਉਪਲਬਧ</item>
@@ -1152,7 +1150,7 @@
<string name="usb_charging_notification_title" msgid="6895185153353640787">"ਇਹ ਡੀਵਾਈਸ USB ਰਾਹੀਂ ਚਾਰਜ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
<string name="usb_supplying_notification_title" msgid="5310642257296510271">"ਨੱਥੀ ਕੀਤੀ ਡੀਵਾਈਸ ਨੂੰ USB ਰਾਹੀਂ ਪਾਵਰ ਮਿਲ ਰਹੀ ਹੈ"</string>
<string name="usb_mtp_notification_title" msgid="8396264943589760855">"ਫ਼ਾਈਲ ਟ੍ਰਾਂਸਫ਼ਰ ਲਈ USB"</string>
- <string name="usb_ptp_notification_title" msgid="1347328437083192112">"ਫੋਟੋ ਟ੍ਰਾਂਸਫ਼ਰ ਲਈ USB"</string>
+ <string name="usb_ptp_notification_title" msgid="1347328437083192112">"ਫ਼ੋਟੋ ਟ੍ਰਾਂਸਫ਼ਰ ਲਈ USB"</string>
<string name="usb_midi_notification_title" msgid="4850904915889144654">"MIDI ਲਈ USB"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"ਇੱਕ USB ਐਕਸੈਸਰੀ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="usb_notification_message" msgid="3370903770828407960">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ।"</string>
@@ -1174,7 +1172,7 @@
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ਤਿਆਰ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ਤਰੁੱਟੀਆਂ ਦੀ ਜਾਂਚ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"ਨਵੇਂ <xliff:g id="NAME">%s</xliff:g> ਦਾ ਪਤਾ ਲਗਾਇਆ ਗਿਆ"</string>
- <string name="ext_media_ready_notification_message" msgid="4083398150380114462">"ਫੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ ਨੂੰ ਟ੍ਰਾਂਸਫ਼ਰ ਕਰਨ ਲਈ"</string>
+ <string name="ext_media_ready_notification_message" msgid="4083398150380114462">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ ਨੂੰ ਟ੍ਰਾਂਸਫ਼ਰ ਕਰਨ ਲਈ"</string>
<string name="ext_media_unmountable_notification_title" msgid="8295123366236989588">"ਕਰਪਟਿਡ <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_message" msgid="2343202057122495773">"<xliff:g id="NAME">%s</xliff:g> ਗ਼ਲਤ ਹੈ। ਠੀਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"ਅਸਮਰਥਿਤ <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਇੰਸਟੌਲ ਸੈਸ਼ਨ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਇਸਨੂੰ ਸਕਿਰਿਆ ਪੈਕੇਜ ਇੰਸਟੌਲੇਸ਼ਨਾਂ ਬਾਰੇ ਵੇਰਵੇ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ਪੈਕੇਜ ਸਥਾਪਿਤ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕਰੋ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ਪੈਕੇਜ ਦੀ ਸਥਾਪਨਾ ਦੀ ਬੇਨਤੀ ਕਰਨ ਲਈ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਅਨੁਮਤੀ ਦਿੰਦਾ ਹੈ"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ਜ਼ੂਮ ਕੰਟਰੋਲ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ਵਿਜੇਟ ਨਹੀਂ ਜੋੜ ਸਕਿਆ।"</string>
<string name="ime_action_go" msgid="8320845651737369027">"ਜਾਓ"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"ਸਾਲ ਚੁਣੋ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ਹਟਾਇਆ ਗਿਆ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ਕੰਮ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"ਦੂਸਰੀ ਕਾਰਜ-ਸਥਾਨ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"ਤੀਸਰੀ ਕਾਰਜ-ਸਥਾਨ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ਇਸ ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਪਿੰਨ ਕਰਨ ਲਈ, ਸਪਰਸ਼ ਕਰੋ & ਦਬਾਈ ਰੱਖੋ।"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ਐਪ ਪਿੰਨਡ ਹੈ: ਇਸ ਡੀਵਾਈਸ ਤੇ ਅਨਪਿਨ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ।"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ਸਕ੍ਰੀਨ ਪਿੰਨ ਕੀਤੀ"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ਹੁਣੇ ਮੁੜ-ਸੈੱਟ ਕਰੋ"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"ਕਾਨਫਰੰਸ ਕਾਲ"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ਟੂਲਟਿਪ"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 4ffd963..bdd601a 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Zezwala aplikacji na korzystanie z usługi komunikatora, by nawiązywać połączenia bez Twojego udziału."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"odczytywanie stanu i informacji o telefonie"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Pozwala aplikacji na dostęp do funkcji telefonicznych urządzenia. Aplikacja z tym uprawnieniem może odczytać numer telefonu i identyfikator urządzenia, sprawdzić, czy połączenie jest aktywne, oraz poznać numer, z którym jest nawiązane połączenie."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"odczyt numeru telefonu"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Zezwala aplikacji na dostęp do numeru telefonu urządzenia."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zapobieganie przechodzeniu tabletu do trybu uśpienia"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"powstrzymywanie usypiania telewizora"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"zapobieganie przejściu telefonu w stan uśpienia"</string>
@@ -1260,6 +1262,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Pozwala aplikacji odczytywać sesje instalacji. Umożliwia to jej na poznanie szczegółów aktywnych instalacji pakietów."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"żądanie instalacji pakietów"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Zezwala aplikacji żądanie instalacji pakietów."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Dotknij dwukrotnie, aby sterować powiększeniem"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nie można dodać widżetu."</string>
<string name="ime_action_go" msgid="8320845651737369027">"OK"</string>
@@ -1614,10 +1620,8 @@
<string name="select_year" msgid="7952052866994196170">"Wybierz rok"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> usunięte"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (praca)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> – praca 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> – praca 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Aby odpiąć ten ekran, naciśnij i przytrzymaj Wstecz."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacja jest przypięta. Nie możesz jej odpiąć na tym urządzeniu."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran przypięty"</string>
@@ -1755,5 +1759,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Resetuj teraz"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Wyłączono: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Połączenie konferencyjne"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Wyskakujące okno z etykietką"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Etykietka"</string>
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 482c1e9..40bb94a 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que o app use o serviço de mensagens instantâneas para fazer chamadas sem sua intervenção."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ler status e identidade do telefone"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que o app acesse os recursos de telefonia do dispositivo. Esta permissão autoriza o app a determinar o número de telefone e IDs de dispositivo, quando uma chamada está ativa, e o número remoto conectado a uma chamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ler número de telefone"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que o app acesse o número de telefone do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir modo de inatividade do tablet"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"impedir a suspensão da TV"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir modo de inatividade do telefone"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que um app leia sessões de instalação. Isso permite que ele veja detalhes sobre as instalações de pacote ativas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar pacotes de instalação"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite que um app solicite a instalação de pacotes."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Toque duas vezes para ter controle do zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Não foi possível adicionar widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Selecione o ano"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> excluído"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Segundo <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Terceiro <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Para liberar esta tela, toque no botão \"Voltar\" e mantenha-o pressionado."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"O app está fixado. A liberação não é permitida neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Tela fixada"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reiniciar agora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Widget <xliff:g id="LABEL">%1$s</xliff:g> desativado"</string>
<string name="conference_call" msgid="3751093130790472426">"Teleconferência"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Pop-up de dica"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Dica"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3f9417e..6fdaa19 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que a aplicação utilize o serviço IMS para fazer chamadas sem a sua intervenção."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ler o estado e a identidade do telemóvel"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que a aplicação aceda às funcionalidades de telefone do dispositivo. Esta autorização permite que a aplicação determine o número de telefone e IDs do dispositivo, se alguma chamada está ativa e qual o número remoto ligado por uma chamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ler o número de telefone"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que a aplicação aceda ao número de telefone do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir que o tablet entre em inactividade"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"impedir a TV de entrar no modo de suspensão"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir modo de inactividade do telefone"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que uma aplicação leia sessões de instalação. Isto permite que veja detalhes acerca de instalações de pacotes ativas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar pacotes de instalação"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite que uma aplicação solicite a instalação de pacotes."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tocar duas vezes para controlar o zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Não foi possível adicionar widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Selecionar ano"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2.º <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3.º <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Para soltar este ecrã, toque sem soltar em Anterior."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"A aplicação está fixa: não é permitido soltá-la neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ecrã fixo"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Repor agora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> desativado"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferência"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Pop-up de sugestão"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Sugestão"</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 482c1e9..40bb94a 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que o app use o serviço de mensagens instantâneas para fazer chamadas sem sua intervenção."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ler status e identidade do telefone"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que o app acesse os recursos de telefonia do dispositivo. Esta permissão autoriza o app a determinar o número de telefone e IDs de dispositivo, quando uma chamada está ativa, e o número remoto conectado a uma chamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ler número de telefone"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que o app acesse o número de telefone do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir modo de inatividade do tablet"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"impedir a suspensão da TV"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir modo de inatividade do telefone"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que um app leia sessões de instalação. Isso permite que ele veja detalhes sobre as instalações de pacote ativas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar pacotes de instalação"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite que um app solicite a instalação de pacotes."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Toque duas vezes para ter controle do zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Não foi possível adicionar widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Selecione o ano"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> excluído"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Segundo <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Terceiro <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Para liberar esta tela, toque no botão \"Voltar\" e mantenha-o pressionado."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"O app está fixado. A liberação não é permitida neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Tela fixada"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reiniciar agora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Widget <xliff:g id="LABEL">%1$s</xliff:g> desativado"</string>
<string name="conference_call" msgid="3751093130790472426">"Teleconferência"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Pop-up de dica"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Dica"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 5735f7c..e732022 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite aplicației să folosească serviciul IMS pentru apeluri, fără intervenția dvs."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"citește starea și identitatea telefonului"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite aplicației să acceseze funcțiile de telefon ale dispozitivului. Cu această permisiune aplicația stabilește numărul de telefon și ID-urile de dispozitiv, dacă un apel este activ, precum și numărul de la distanță conectat printr-un apel."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"să citească numărul de telefon"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite aplicației să acceseze numărul de telefon al dispozitivului."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"împiedicarea computerului tablet PC să intre în repaus"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"împiedică intrarea televizorului în stare de inactivitate"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"împiedicare intrare telefon în repaus"</string>
@@ -1082,16 +1084,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Volumul media"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volum notificare"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Ton de apel prestabilit"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Prestabilit (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Niciunul"</string>
- <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonuri de sonerie"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonuri de apel"</string>
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Sunete de alarmă"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Sunete pentru notificare"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Necunoscut"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="few">Rețele Wi-Fi disponibile</item>
<item quantity="other">Rețele Wi-Fi disponibile</item>
@@ -1239,6 +1237,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite unei aplicații accesul la citirea sesiunilor de instalare. Aceasta poate vedea detalii despre instalările de pachete active."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"să solicite pachete de instalare"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite unei aplicații să solicite instalarea pachetelor."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Apăsați de două ori pentru a controla mărirea/micșorarea"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nu s-a putut adăuga widgetul."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Accesați"</string>
@@ -1591,10 +1593,8 @@
<string name="select_year" msgid="7952052866994196170">"Selectați anul"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> a fost șters"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de serviciu"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> pentru serviciu (2)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> pentru serviciu (3)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Pentru a anula fixarea acestui ecran, atingeți lung opțiunea Înapoi."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplicația este fixată: Anularea fixării nu este permisă pe acest dispozitiv."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ecran fixat"</string>
@@ -1723,6 +1723,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Resetați acum"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> a fost dezactivat"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferință telefonică"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Balon explicativ"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 0d6ca06..9c45d89 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -90,7 +90,7 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Идентификация абонента по умолчанию не запрещена. След. вызов: разрешена"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Услуга не предоставляется."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Невозможно изменить параметр идентификатора вызывающего абонента."</string>
- <string name="RestrictedOnData" msgid="8653794784690065540">"Служба данных заблокирована."</string>
+ <string name="RestrictedOnData" msgid="8653794784690065540">"Передача данных заблокирована."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Служба экстренной помощи заблокирована."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Служба передачи голосовых сообщений заблокирована."</string>
<string name="RestrictedOnAllVoice" msgid="3396963652108151260">"Все службы передачи голосовых сообщений заблокированы."</string>
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Позволяет приложению совершать звонки с помощью службы IMS без вашего вмешательства."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"Получение данных о статусе телефона"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Приложение получит доступ к функциям телефона на устройстве. Кроме того, оно сможет определять номера телефонов и серийные номера моделей, состояние активности вызова, а также удаленные номера, с которыми установлено соединение."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"Чтение номера телефона"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Приложение получит доступ к телефонному номеру устройства."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Отключение спящего режима"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"запрещать переход в спящий режим"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Отключение спящего режима"</string>
@@ -1260,6 +1262,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Чтение данных текущих сеансов установки пакетов."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"Запрос пакетов установки"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Приложение сможет запрашивать разрешения на установку пакетов."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Нажмите дважды для изменения масштаба"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Не удалось добавить виджет."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Выбрать"</string>
@@ -1614,10 +1620,8 @@
<string name="select_year" msgid="7952052866994196170">"Выберите год"</string>
<string name="deleted_key" msgid="7659477886625566590">"Цифра <xliff:g id="KEY">%1$s</xliff:g> удалена"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Рабочий <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Задача 2: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Задача 3: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Чтобы открепить экран, нажмите и удерживайте кнопку \"Назад\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Включена блокировка в приложении. Ее отключение запрещено правилами организации."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Блокировка включена"</string>
@@ -1755,5 +1759,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Сбросить"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Виджет <xliff:g id="LABEL">%1$s</xliff:g> отключен"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференц-связь"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Подсказка"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Подсказка"</string>
</resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 7526c1e..87a277b 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -284,7 +284,7 @@
<string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"කෙටිමං අස්ථාපනය කරන්න"</string>
<string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"පරිශීලක මැදිහත්වීමෙන් තොරව මුල්තිර කෙටිමං එක් කිරීමට යෙදුමකට අවසර දෙයි."</string>
<string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"පිටවන ඇමතුම් වල මග වෙනස් කිරීම"</string>
- <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ඇමතුම වෙනත් අංකයකට හරවා යැවීම හෝ ඇමතුම මුළුමනින්ම නැවත් වීම වැනි විකල්ප සමඟ පිටතට යන ඇමතුමකදී ඩයල් කළ අංකය බැලීමට යෙදුමට ඉඩ දෙන්න."</string>
+ <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ඇමතුම වෙනත් අංකයකට හරවා යැවීම හෝ ඇමතුම මුළුමනින්ම නැවත්වීම වැනි විකල්ප සමඟ පිටතට යන ඇමතුමකදී අංකනය කළ අංකය බැලීමට යෙදුමට ඉඩ දෙයි."</string>
<string name="permlab_receiveSms" msgid="8673471768947895082">"කෙටි පණිවිඩ ලබාගැනීම (SMS)"</string>
<string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS පණිවිඩ ලැබීමට සහ ක්රියාත්මක කිරීමට යෙදුමට අවසර දෙන්න. මෙහි තේරුම යෙදුමට ඔබගේ උපාංගයට ලැබෙන පණිවිඩ අධීක්ෂණය කිරීමට හැකිවීම වන අතර, ඒවා ඔබට නොපෙන්වා මකා දැමීමටද හැකි වීමයි."</string>
<string name="permlab_receiveMms" msgid="1821317344668257098">"පෙළ පණිවුඩ ලබාගන්න (MMS)"</string>
@@ -376,7 +376,9 @@
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS ඇමතුම් සේවාවට පිවිසෙන්න"</string>
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"ඔබේ මැදිහත්වීමකින් තොරව ඇමතුම් සිදු කිරීමට IMS සේවාව භාවිතයට යෙදුමට ඉඩ දෙන්න."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"දුරකථනයේ තත්වය සහ අනන්යතාවය කියවීම"</string>
- <string name="permdesc_readPhoneState" msgid="1639212771826125528">"උපාංගයේ දුරකථන විශේෂාංග වෙත පිවිසීමට යෙදුමට අවසර දෙන්න. ඇමතුම සක්රිය වුවත් සහ ඇමතුමකින් දුරස්ථ අංකය සම්බන්ධ වුවත් දුරකථන අංකය සහ උපාංග ID හඳුනා ගැනීමට මෙම අවසරය යෙදුමට අවසර දෙයි."</string>
+ <string name="permdesc_readPhoneState" msgid="1639212771826125528">"උපාංගයේ දුරකථන විශේෂාංග වෙත ප්රවේශයට යෙදුමට ඉඩ දෙයි. ඇමතුම සක්රිය වුවත්, සහ ඇමතුමකින් දුරස්ථ අංකය සම්බන්ධ වුවත් දුරකථන අංකය සහ උපාංග ID හඳුනා ගැනීමට මෙම අවසරය යෙදුමට ඉඩ දෙයි."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"දුරකථන අංකය කියවන්න"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"උපාංගයේ දුරකථන අංකය වෙත පිවිසීමට යෙදුමට ඉඩ දෙන්න."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ටැබ්ලටය නින්දෙන් වැළක්වීම"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"රූපවාහිනිය නින්දට යාමෙන් නවත්වන්න"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"දුරකථනය නින්දට යාමෙන් වළකන්න"</string>
@@ -1061,16 +1063,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"මාධ්ය ශබ්දය"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"දැනුම්දීමේ ශබ්ද ත්රීවතාව"</string>
<string name="ringtone_default" msgid="3789758980357696936">"සුපුරුදු රින්ටෝනය සකසන්න"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"පෙරනිමි (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"කිසිවක් නැත"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"රිගින්ටෝන"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"එලාම හඬ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"දැනුම්දීම් හඬ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"නොදනී"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Wi-Fi ජාල තිබේ</item>
<item quantity="other">Wi-Fi ජාල තිබේ</item>
@@ -1216,6 +1214,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ස්ථාපන සැසිය කියවීමට යෙදුමට ඉඩ දෙන්න. සක්රිය පැකේජ ස්ථාපනය පිළිබඳ විස්තර බැලීමට එයට මෙයින් ඉඩ දෙයි."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ස්ථාපන පැකේජ ඉල්ලීම"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ස්ථාපන පැකේජ ඉල්ලීමට යෙදුමකට අවසර දීම."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"විශාලන පාලක සඳහා දෙවතාවක් තට්ටු කරන්න"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"විජටය එකතු කිරීමට නොහැකි විය."</string>
<string name="ime_action_go" msgid="8320845651737369027">"යන්න"</string>
@@ -1566,10 +1568,8 @@
<string name="select_year" msgid="7952052866994196170">"වසර තෝරන්න"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> මකා දමන ලදි"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2වන වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3වන වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"මෙම තිරය ඇමුණුම් ඉවත් කිරීමට, ස්පර්ශ කර අල්ලා ගෙන සිටින්න."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"යෙදුම අමුණා ඇත: ගැලවීමට මෙම උපාංගය මත ඉඩ දිය නොහැකිය."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"තිරය අගුළු දමා ඇත"</string>
@@ -1689,6 +1689,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"දැන් යළි සකසන්න"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"අබල කළ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"සම්මන්ත්රණ ඇමතුම"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"මෙවලම් ඉඟිය"</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 7ff3ce2..7811a46 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Umožňuje aplikácii používať službu okamžitých správ (IMS) na volanie bez intervencie používateľa."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čítať stav a identitu telefónu"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Umožňuje aplikácii pristupovať k telefónnym funkciám zariadenia. Aplikácia s týmto povolením môže určiť telefónne číslo a ID zariadenia, či práve prebieha hovor, a vzdialené číslo, s ktorým je prostredníctvom hovoru nadviazané spojenie."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"čítanie telefónneho čísla"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Umožňuje aplikácii pristupovať k telefónnemu číslu daného zariadenia."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zabránenie prechodu tabletu do režimu spánku"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"zabránenie televízoru v prechode do režimu spánku"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"deaktivovať režim spánku"</string>
@@ -649,10 +651,10 @@
<string name="relationTypeAssistant" msgid="6274334825195379076">"Asistent"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"Brat"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"Dieťa"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Partner(ka)"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Druh(-žka)"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"Otec"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"Kamarát(ka)"</string>
- <string name="relationTypeManager" msgid="6365677861610137895">"Manažér"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"Vedúci(-a)"</string>
<string name="relationTypeMother" msgid="4578571352962758304">"Matka"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Rodič"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Partner(ka)"</string>
@@ -1260,6 +1262,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Toto povolenie umožňuje aplikácii čítať relácie inštalácií a zobraziť tak podrobnosti o aktívnych inštaláciách balíkov."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"odosielanie žiadostí o inštaláciu balíkov"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Umožňuje aplikácii vyžiadať inštaláciu balíkov."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Dvojitým klepnutím môžete ovládať priblíženie"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Miniaplikáciu sa nepodarilo pridať."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Hľadať"</string>
@@ -1614,10 +1620,8 @@
<string name="select_year" msgid="7952052866994196170">"Vyberte rok"</string>
<string name="deleted_key" msgid="7659477886625566590">"Číslo <xliff:g id="KEY">%1$s</xliff:g> bolo odstránené"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Práca – <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Ak chcete uvoľniť túto obrazovku, klepnite na tlačidlo Späť a podržte ho."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikácia je pripnutá. Uvoľnenie nie je na tomto zariadení povolené."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Obrazovka bola pripnutá"</string>
@@ -1755,5 +1759,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Resetovať"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Deaktivovaná miniaplikácia <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferenčný hovor"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Kontextové okno s popisom"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Popis"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index f7b8096..5cdbefb 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Aplikaciji dovoljuje uporabo storitev IMS za opravljanje klicev brez vašega posredovanja."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"branje stanja in identitete telefona"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Aplikaciji omogoča dostop do funkcij telefona v napravi. S tem dovoljenjem lahko aplikacija določi telefonsko številko in ID-je naprave, določi lahko tudi, ali je klic aktiven, in oddaljeno številko, s katero je klic povezan."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"branje telefonske številke"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Aplikaciji dovoljuje dostop do telefonske številke naprave."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"preprečitev prehoda tabličnega računalnika v stanje pripravljenosti"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"preprečevanje preklopa televizorja v stanje pripravljenosti"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"preprečevanje prehoda v stanje pripravljenosti telefona"</string>
@@ -1105,16 +1107,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Glasnost predstavnosti"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Glasnost obvestila"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Privzeta melodija zvonjenja"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Privzeto (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Brez"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Melodije zvonjenja"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Zvoki alarma"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Zvoki obvestil"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Neznano"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Na voljo so omrežja Wi-Fi</item>
<item quantity="two">Na voljo so omrežja Wi-Fi</item>
@@ -1264,6 +1262,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Aplikaciji omogoča branje sej namestitev. Tako lahko bere podrobnosti o aktivnih namestitvah paketov."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"zahtevanje paketov za namestitev"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Aplikaciji omogoča zahtevanje namestitve paketov."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tapnite dvakrat za nadzor povečave/pomanjšave"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Pripomočka ni bilo mogoče dodati."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Pojdi"</string>
@@ -1618,10 +1620,8 @@
<string name="select_year" msgid="7952052866994196170">"Izberite leto"</string>
<string name="deleted_key" msgid="7659477886625566590">"Številka <xliff:g id="KEY">%1$s</xliff:g> je izbrisana"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za delo"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. službeni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. službeni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Če želite odpeti ta zaslon, se dotaknite tipke za nazaj in jo pridržite."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je pripeta: v tej napravi odpenjanje ni dovoljeno."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Zaslon je pripet"</string>
@@ -1759,6 +1759,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Ponastavi"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – onemogočeno"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferenčni klic"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Opis orodja"</string>
</resources>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index c3ccaca..ea33fff 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Lejon aplikacionin të përdorë shërbimin IMS për të kryer telefonata pa ndërhyrjen tënde."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lexo statusin e telefonit dhe identitetin"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lejon aplikacionin të hyjë në funksionet telefonike të pajisjes. Kjo leje i mundëson aplikacionit të përcaktojë numrin e telefonit dhe ID-të e pajisjes, nëse një telefonatë është aktive apo nëse numri në distancë është i lidhur me një telefonatë."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lexo numrin e telefonit"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Lejon që aplikacioni të ketë qasje te numri i telefonit i pajisjes."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"parandalo kalimin e tabletit në fjetje"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"parandalo kalimin e televizorit në fjetje"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"parandalo kalimin e telefonit në fjetje"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"volumi i klipit \"media\""</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volumi i njoftimeve"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Zile e paracaktuar."</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"I parazgjedhur (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Asnjë"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Zilet"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Tingujt e alarmeve"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Tingujt e njoftimeve"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"E panjohur"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Rrjete Wi-Fi ofrohen për përdorim</item>
<item quantity="one">Një rrjet Wi-Fi ofrohet për përdorim</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Lejon një aplikacion të lexojë sesionet e instalimit. Kjo e lejon atë të shohë detaje rreth instalimeve të paketave aktive."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"kërko paketat e instalimit"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Lejon që një aplikacion të kërkojë instalimin e paketave."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Trokit dy herë për të kontrolluar zmadhimin"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nuk mundi të shtonte miniaplikacion."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Shko"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Përzgjidh vitin"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> u fshi"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Puna <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> i dytë i punës"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> i tretë i punës"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Për të hequr gozhdimin e ekranit, prek dhe mbaj të shtypur \"Prapa\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ekrani është i gozhduar. Anulimi i mbërthimit nuk lejohet nga organizata jote."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrani u gozhdua"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Rivendos tani"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> u çaktivizua"</string>
<string name="conference_call" msgid="3751093130790472426">"Telefonatë konferencë"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Këshilla për veglën"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index da44a65..19a1140 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Дозвољава апликацији да користи услугу размене тренутних порука да би упућивала позиве без ваше интервенције."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"читање статуса и идентитета телефона"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Дозвољава апликацији да приступа функцијама телефона на уређају. Ова дозвола омогућава апликацији да утврди број телефона и ИД-ове уређаја, затим да ли је позив активан, као и број даљинског уређаја са којим је успостављен позив."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"читање броја телефона"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Дозвољава апликацији да приступа броју телефона на уређају."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"спречавање преласка таблета у стање спавања"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"спречавање ТВ-а да пређе у стање спавања"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"спречавање преласка телефона у стање спавања"</string>
@@ -1235,6 +1237,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Дозвољава апликацији да чита сесије инсталирања. То јој дозвољава да види детаље о активним инсталацијама пакета."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"захтевање пакета за инсталирање"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Омогућава да апликација захтева инсталацију пакета."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Додирните двапут за контролу зумирања"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Није могуће додати виџет."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Иди"</string>
@@ -1587,10 +1593,8 @@
<string name="select_year" msgid="7952052866994196170">"Изаберите годину"</string>
<string name="deleted_key" msgid="7659477886625566590">"Избрисали сте <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> на послу"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. пословни <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. пословни имејл <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Да бисте откачили овај екран, додирните и задржите Назад."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Апликација је закачена: откачињање није дозвољено на овом уређају."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екран је закачен"</string>
@@ -1719,5 +1723,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Ресетуј"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Виџет <xliff:g id="LABEL">%1$s</xliff:g> је онемогућен"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференцијски позив"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Искачуће објашњење"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Објашњење"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 1bf5196..3a4fee3 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -82,10 +82,10 @@
<string name="RuacMmi" msgid="7827887459138308886">"Avvisande av oönskade irriterande samtal"</string>
<string name="CndMmi" msgid="3116446237081575808">"Leverans av nummer för inkommande samtal"</string>
<string name="DndMmi" msgid="1265478932418334331">"Stör ej"</string>
- <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Nummerpresentatören är begränsad som standard. Nästa samtal: Begränsad"</string>
- <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Nummerpresentatörens standardinställning är begränsad. Nästa samtal: Inte begränsad"</string>
- <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Nummerpresentatörens standardinställning är inte begränsad. Nästa samtal: Begränsad"</string>
- <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Nummerpresentatörens standardinställning är inte begränsad. Nästa samtal: Inte begränsad"</string>
+ <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Nummerpresentatören är blockerad som standard. Nästa samtal: Blockerad"</string>
+ <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Nummerpresentatörens standardinställning är blockerad. Nästa samtal: Inte blockerad"</string>
+ <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Nummerpresentatörens standardinställning är inte blockerad. Nästa samtal: Blockerad"</string>
+ <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Nummerpresentatörens standardinställning är inte blockerad. Nästa samtal: Inte blockerad"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Tjänsten är inte etablerad."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Det går inte att ändra inställningen för nummerpresentatör."</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Datatjänsten är blockerad."</string>
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Tillåter att appen använder tjänsten för snabbmeddelanden för att ringa samtal utan åtgärd från dig."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"läsa telefonens status och identitet"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Tillåter att appen kommer åt enhetens telefonfunktioner. Med den här behörigheten tillåts appen att identifiera mobilens telefonnummer och enhets-ID, om ett samtal pågår och vilket nummer samtalet är kopplat till."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"läsa telefonnumret"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Ger appen åtkomst till mobilnumret på enheten."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"förhindra att surfplattan går in i viloläge"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"förhindra att TV:n försätts i viloläge"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"förhindra att telefonen sätts i viloläge"</string>
@@ -650,7 +652,7 @@
<string name="relationTypeMother" msgid="4578571352962758304">"Mamma"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Förälder"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Partner"</string>
- <string name="relationTypeReferredBy" msgid="101573059844135524">"Genom"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"Känner genom"</string>
<string name="relationTypeRelative" msgid="1799819930085610271">"Släkting"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Syster"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"Make/maka"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Tillåt appen att läsa installationssessioner. Det ger den tillgång till uppgifter om aktiva paketinstallationer."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"begära installationspaket"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Tillåter att en app begär paketinstallation."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Peka två gånger för zoomkontroll"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Det gick inte att lägga till widgeten."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Kör"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Välj år"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> har tagits bort"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> för arbetet"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Andra <xliff:g id="LABEL">%1$s</xliff:g> för jobbet"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Tredje <xliff:g id="LABEL">%1$s</xliff:g> för jobbet"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Om du vill lossa skärmen trycker du länge på Tillbaka."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Appen är fäst. Att lossa den är inte tillåtet på den här enheten."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skärmen är fäst"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Återställ nu"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> har inaktiverats"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferenssamtal"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Popup-fönster med beskrivning"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Beskrivning"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 1d3c7ac..4b75ff1 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -375,6 +375,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Huruhusu programu kutumia huduma ya IMS kupiga simu bila udhibiti wako."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"kusoma hali na kitambulisho cha simu"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Huruhusu programu kufikia vipengele vya simu vilivyo kwenye kifaa. Idhini hii inaruhusu programu kutambua nambari ya simu na kifaa, kama kuna simu inayopigwa, na nambari ya mbali iliyounganishwa kwenye simu."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"kusoma nambari ya simu"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Inaruhusu programu kufikia nambari ya simu ya kifaa."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zuia kompyuta ndogo dhidi ya kulala"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"zuia runinga isiingie katika hali tuli"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"kuzuia simu isilale"</string>
@@ -1208,6 +1210,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Huruhusu programu kusoma vipindi vya kusanikisha. Hii huiruhusu kuona maelezo kuhusu usanikishaji wa programu unaoendelea."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"omba ruhusa ya kusakinisha vifurushi"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Huruhusu programu kuomba idhini ya kusakinisha vifurushi."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Gonga mara mbili kwa udhibiti wa kuza"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Haikuweza kuongeza wijeti."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Nenda"</string>
@@ -1558,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Chagua mwaka"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> kimefutwa"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ya kazini <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> ya 2 ya Kazini"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> ya 3 ya Kazini"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Ili kubandua skrini hii, gusa na ushikilie Nyuma."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Programu imebanwa: Kubanuliwa hakuruhusiwi kwenye kifaa hiki."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skrini imebandikwa"</string>
@@ -1681,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Weka upya sasa"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> imezimwa"</string>
<string name="conference_call" msgid="3751093130790472426">"Simu ya Kongamano"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Kidirisha Ibukizi cha vidokezo"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Kidirisha cha vidokezo"</string>
</resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 46a4589..6a54f82 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"உங்கள் குறுக்கீடின்றி IMS சேவையைப் பயன்படுத்தி அழைப்பதற்கு, பயன்பாட்டை அனுமதிக்கும்."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"மொபைல் நிலை மற்றும் அடையாளத்தைப் படித்தல்"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"சாதனத்தின் மொபைல் அம்சங்களை அணுகப் பயன்பாட்டை அனுமதிக்கிறது. மொபைல் மற்றும் சாதன ஐடிகள், அழைப்பு செயலில் உள்ளதா மற்றும் அழைப்பு மூலம் இணைக்கப்பட்ட தொலைக் கட்டுப்பாட்டு எண் ஆகியவற்றைத் தீர்மானிக்க இந்த அனுமதி பயன்பாட்டை அனுமதிக்கிறது."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"மொபைல் எண்ணைப் படி"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"சாதனத்தின் மொபைல் எண்ணை அணுக, பயன்பாட்டை அனுமதிக்கும்."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"டேப்லெட் உறக்க நிலைக்குச் செல்வதைத் தடுத்தல்"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"டிவி உறக்கநிலைக்குச் செல்வதைத் தடுத்தல்"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"தொலைபேசி உறக்கநிலைக்குச் செல்வதைத் தடுத்தல்"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"மீடியாவின் ஒலியளவு"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"அறிவிப்பின் ஒலியளவு"</string>
<string name="ringtone_default" msgid="3789758980357696936">"இயல்புநிலை ரிங்டோன்"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"இயல்பு (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ஏதுமில்லை"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ரிங்டோன்கள்"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"அலார ஒலிகள்"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"அறிவிப்பு ஒலிகள்"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"தெரியாதது"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">வைஃபை நெட்வொர்க்குகள் உள்ளன</item>
<item quantity="one">வைஃபை நெட்வொர்க் உள்ளது</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"நிறுவல் அமர்வுகளைப் படிக்க, பயன்பாட்டை அனுமதிக்கிறது. இது செயல்படும் தொகுப்பு நிறுவல்களைப் பற்றிய விவரங்களைப் பார்க்க அனுமதிக்கிறது."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"நிறுவல் தொகுப்புகளைக் கோருதல்"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"தொகுப்புகளின் நிறுவலைக் கோர, பயன்பாட்டை அனுமதிக்கும்."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"அளவை மாற்றுவதற்கான கட்டுப்பாட்டிற்கு, இருமுறை தட்டவும்"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"விட்ஜெட்டைச் சேர்க்க முடியவில்லை."</string>
<string name="ime_action_go" msgid="8320845651737369027">"செல்"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"ஆண்டைத் தேர்ந்தெடுக்கவும்"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> நீக்கப்பட்டது"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"பணியிடம் <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2வது பணி <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3வது பணி <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"இந்தத் திரையை விலக்க, \"முந்தையது\" பொத்தானைத் தொட்டுப் பிடிக்கவும்."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"பயன்பாடு பொருத்தப்பட்டது: பொருத்தியதை நீக்குவதற்கு இந்தச் சாதனத்தில் அனுமதியில்லை."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"திரை பின் செய்யப்பட்டது"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"இப்போதே மீட்டமை"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"முடக்கப்பட்டது: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"குழு அழைப்பு"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"உதவிக்குறிப்பு"</string>
</resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index c6722ee..49b509c 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"మీ ప్రమేయం లేకుండా కాల్లు చేయడం కోసం IMS సేవను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ఫోన్ స్థితి మరియు గుర్తింపుని చదవడం"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"పరికరం యొక్క ఫోన్ లక్షణాలను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి ఫోన్ నంబర్ మరియు పరికరం IDలను, కాల్ సక్రియంగా ఉందా లేదా అనే విషయాన్ని మరియు కాల్ ద్వారా కనెక్ట్ చేయబడిన రిమోట్ నంబర్ను కనుగొనడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ఫోన్ నంబర్ను చదవడం"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"పరికరం యొక్క ఫోన్ నంబర్ను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"టాబ్లెట్ను నిద్రావస్థకు వెళ్లనీయకుండా నిరోధించడం"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"టీవీ నిద్రావస్థకు వెళ్లకుండా నిరోధించడం"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ఫోన్ను నిద్రావస్థకు వెళ్లనీయకుండా నిరోధించడం"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"మీడియా వాల్యూమ్"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"నోటిఫికేషన్ వాల్యూమ్"</string>
<string name="ringtone_default" msgid="3789758980357696936">"డిఫాల్ట్ రింగ్టోన్"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"డిఫాల్ట్ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ఏదీ వద్దు"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"రింగ్టోన్లు"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"అలారం ధ్వనులు"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"నోటిఫికేషన్ ధ్వనులు"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"తెలియదు"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Wi-Fi నెట్వర్క్లు అందుబాటులో ఉన్నాయి</item>
<item quantity="one">Wi-Fi నెట్వర్క్ అందుబాటులో ఉంది</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ఇన్స్టాల్ సెషన్లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది సక్రియ ప్యాకేజీ ఇన్స్టాలేషన్ల గురించి వివరాలను చూడటానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ఇన్స్టాల్ ప్యాకేజీలను అభ్యర్థించడం"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ప్యాకేజీల ఇన్స్టాలేషన్ అభ్యర్థించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"జూమ్ నియంత్రణ కోసం రెండుసార్లు నొక్కండి"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"విడ్జెట్ను జోడించడం సాధ్యపడలేదు."</string>
<string name="ime_action_go" msgid="8320845651737369027">"వెళ్లు"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"సంవత్సరాన్ని ఎంచుకోండి"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> తొలగించబడింది"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2వ కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3వ కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ఈ స్క్రీన్ని అన్పిన్ చేయడానికి, వెనుకకు తాకి & అలాగే పట్టుకోండి."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"అనువర్తనం పిన్ చేయబడింది: ఈ పరికరంలో అన్పిన్ చేయడానికి అనుమతి లేదు."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"స్క్రీన్ పిన్ చేయబడింది"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ఇప్పుడే రీసెట్ చేయి"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> నిలిపివేయబడింది"</string>
<string name="conference_call" msgid="3751093130790472426">"కాన్ఫరెన్స్ కాల్"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"సాధనం చిట్కా"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ab04bec..c4d72ab 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"อนุญาตให้แอปใช้บริการ IMS เพื่อโทรออกโดยคุณไม่ต้องดำเนินการใดๆ เลย"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"อ่านสถานะและข้อมูลระบุตัวตนของโทรศัพท์"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"อนุญาตให้แอปพลิเคชันเข้าถึงคุณลักษณะโทรศัพท์ของอุปกรณ์ การอนุญาตนี้ทำให้แอปพลิเคชันสามารถตรวจสอบหมายเลขโทรศัพท์และรหัสอุปกรณ์ ตรวจสอบว่ามีการโทรที่ทำงานอยู่หรือไม่ และตรวจสอบหมายเลขระยะไกลที่เชื่อมต่อด้วยการโทร"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"อ่านหมายเลขโทรศัพท์"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"อนุญาตให้แอปเข้าถึงหมายเลขโทรศัพท์ของอุปกรณ์"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ป้องกันไม่ให้แท็บเล็ตเข้าสู่โหมดสลีป"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ป้องกันไม่ให้ทีวีเข้าสู่โหมดสลีป"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ป้องกันไม่ให้โทรศัพท์เข้าโหมดสลีป"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"ระดับเสียงของสื่อ"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"ระดับเสียงของการแจ้งเตือน"</string>
<string name="ringtone_default" msgid="3789758980357696936">"เสียงเรียกเข้าเริ่มต้น"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ค่าเริ่มต้น (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ไม่มี"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"เสียงเรียกเข้า"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"เสียงปลุก"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"เสียงการแจ้งเตือน"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"ไม่รู้จัก"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">มีหลายเครือข่าย Wi-Fi ที่ใช้งานได้</item>
<item quantity="one">มี 1 เครือข่าย Wi-Fi ที่ใช้งานได้</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"อนุญาตให้แอปพลิเคชันอ่านเซสชันการติดตั้ง ซึ่งจะอนุญาตให้อ่านรายละเอียดเกี่ยวกับการติดตั้งแพ็กเกจที่ใช้งาน"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ขอติดตั้งแพ็กเกจ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"อนุญาตให้แอปพลิเคชันขอการติดตั้งแพ็กเกจ"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"แตะสองครั้งเพื่อควบคุมการซูม"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ไม่สามารถเพิ่มวิดเจ็ต"</string>
<string name="ime_action_go" msgid="8320845651737369027">"ไป"</string>
@@ -1553,7 +1555,7 @@
</plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"ลองอีกครั้งในภายหลัง"</string>
<string name="immersive_cling_title" msgid="8394201622932303336">"กำลังดูแบบเต็มหน้าจอ"</string>
- <string name="immersive_cling_description" msgid="3482371193207536040">"หากต้องการออกไป ให้เลื่อนลงจากด้านบน"</string>
+ <string name="immersive_cling_description" msgid="3482371193207536040">"หากต้องการออก ให้เลื่อนลงจากด้านบน"</string>
<string name="immersive_cling_positive" msgid="5016839404568297683">"รับทราบ"</string>
<string name="done_label" msgid="2093726099505892398">"เสร็จสิ้น"</string>
<string name="hour_picker_description" msgid="6698199186859736512">"ตัวเลื่อนหมุนระบุชั่วโมง"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"เลือกปี"</string>
<string name="deleted_key" msgid="7659477886625566590">"ลบ <xliff:g id="KEY">%1$s</xliff:g> แล้ว"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g>ที่ทำงาน"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> งานที่ 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> งานที่ 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"หากต้องการเลิกตรึงหน้าจอนี้ แตะ \"กลับ\" ค้างไว้"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"มีการตรึงแอป: ไม่อนุญาตให้เลิกตรึงบนอุปกรณ์นี้"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ตรึงหน้าจอแล้ว"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"รีเซ็ตทันที"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ปิดใช้ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"การประชุมสาย"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"เคล็ดลับเครื่องมือ"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e7cec56..a4e1b26 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Pinapahintulutan ang app na gamitin ang serbisyo ng IMS upang tumawag nang walang pahintulot mo."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"basahin ang katayuan at pagkakakilanlan ng telepono"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Pinapayagan ang app na i-access ang mga tampok ng telepono ng device. Pinapayagan ng pahintulot na ito ang app na tukuyin ang numero ng telepono at mga ID ng device, kung aktibo man ang isang tawag, at ang malayuang numerong ikinonekta ng isang tawag."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"basahin ang numero ng telepono"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Binibigyang-daan ang app na i-access ang numero ng telepono ng device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"pigilan ang tablet mula sa pag-sleep"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"pigilan ang TV sa pag-sleep"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"pigilan ang telepono mula sa paghinto"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Volume ng media"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume ng notification"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Default na ringtone"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Default (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Wala"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Mga Ringtone"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Mga tunog ng alarm"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Mga tunog ng notification"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Hindi Alam"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Available ang mga Wi-Fi network</item>
<item quantity="other">Available ang mga Wi-Fi network</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Pinapayagan ang isang application na magbasa ng mga session ng pag-install. Nagbibigay-daan ito upang makita ang mga detalye tungkol sa mga aktibong pag-install ng package."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"humiling ng mga package sa pag-install"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Pinapayagan ang isang application na hilingin ang pag-install ng mga package."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tapikin ng dalawang beses para sa pagkontrol ng zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Hindi maidagdag ang widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Pumunta"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Pumili ng taon"</string>
<string name="deleted_key" msgid="7659477886625566590">"Tinanggal ang <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Pangalawang <xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Pangatlong <xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Upang i-unpin ang screen na ito, pindutin nang matagal ang Bumalik."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Naka-pin ang app: Hindi pinapayagan ang pag-a-unpin sa device na ito."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Naka-pin ang screen"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"I-reset ngayon"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Na-disable ang <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conference Call"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tooltip"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 59dc68e..eacf16e 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Uygulamanın, sizin müdahaleniz olmadan telefon etmek için IMS hizmetini kullanmasına izin verir."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefonun durumunu ve kimliğini okuma"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Uygulamaya cihazdaki telefon özelliklerine erişme izni verir. Bu izin, uygulamanın telefon numarasını ve cihaz kimliğini, etkin bir çağrı olup olmadığını ve çağrıda bağlanılan karşı tarafın numarasını öğrenmesine olanak sağlar."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"telefon numarasını oku"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Uygulamanın cihazın telefon numarasına erişmesine izin verir."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"tabletin uykuya geçmesini önle"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV\'nin uyku moduna geçmesini önleme"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"telefonun uykuya geçmesini önleme"</string>
@@ -605,7 +607,7 @@
<string name="phoneTypeRadio" msgid="4093738079908667513">"Telsiz"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"Teleks"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
- <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"İş Cep Telefonu"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"İş Mobil"</string>
<string name="phoneTypeWorkPager" msgid="649938731231157056">"İş Çağrı Cihazı"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Yardımcı"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
@@ -649,7 +651,7 @@
<string name="relationTypeManager" msgid="6365677861610137895">"Yönetici"</string>
<string name="relationTypeMother" msgid="4578571352962758304">"Anne"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Ebeveyn"</string>
- <string name="relationTypePartner" msgid="7266490285120262781">"Hayat Arkadaşı"</string>
+ <string name="relationTypePartner" msgid="7266490285120262781">"Ortak"</string>
<string name="relationTypeReferredBy" msgid="101573059844135524">"Öneren"</string>
<string name="relationTypeRelative" msgid="1799819930085610271">"Akraba"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Kız Kardeş"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Medya ses düzeyi"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Bildirim ses düzeyi"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Varsayılan zil sesi"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Varsayılan (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Yok"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Zil sesleri"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Alarm sesleri"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Bildirim sesleri"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Bilinmiyor"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Kablosuz ağlar var</item>
<item quantity="one">Kablosuz ağ var</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Bir uygulamanın yükleme oturumlarını okumasına izin verir. Bu, etkin paket yüklemeleriyle ilgili ayrıntıların görülmesine olanak tanır."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"paket yükleme isteğinde bulunma"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Uygulamaya, paketleri yükleme isteğinde bulunma izni verir."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Zum denetimi için iki kez dokun"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget eklenemedi."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Git"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Yılı seçin"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> silindi"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (İş)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"İş için 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"İş için 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Bu ekranın sabitlemesini kaldırmak için Geri\'ye dokunup basılı tutun."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Uygulama sabitlendi. Bu cihazda sabitlemenin kaldırılmasına izin verilmiyor."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran sabitlendi"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Şimdi sıfırla"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> devre dışı"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferans Çağrısı"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"İpucu"</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 0ac3b80..4dbeb0d 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Додаток зможе телефонувати за допомогою служби IMS без вашого відома."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"читати статус та ідентифікаційну інформацію телефону"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Дозволяє програмі отримувати доступ до телефонних функцій пристрою. Такий дозвіл дає програмі змогу визначати номер телефону й ідентифікатори пристрою, активність виклику, а також віддалений номер, на який здійснюється виклик."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"переглядати номер телефону"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Дозволяє додатку отримувати доступ до номера телефону на пристрої."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"не доп.перехід пристр.в реж.сну"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"не допускати перехід телевізора в режим сну"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Вимкнення режиму сну"</string>
@@ -1260,6 +1262,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Дозволяє додатку читати дані сеансів встановлення. Додаток може бачити деталі про активні встановлення пакетів."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"запитувати дані про пакети встановлення"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Додаток зможе надсилати запити на встановлення пакетів."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Двічі натис. для кер. масшт."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Не вдалося додати віджет."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Йти"</string>
@@ -1614,10 +1620,8 @@
<string name="select_year" msgid="7952052866994196170">"Виберіть рік"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> видалено"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Робоча <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-а робота: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-я робота: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Щоб відкріпити цей екран, натисніть і утримуйте кнопку \"Назад\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Додаток закріплено. Його не можна відкріпити на цьому пристрої."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екран закріплено"</string>
@@ -1755,5 +1759,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Скинути"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> вимкнено"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференц-виклик"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Спливаюча підказка"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Спливаюча підказка"</string>
</resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 715dbed..82253ac 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -265,7 +265,7 @@
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"کسی ایسی ونڈو کے مواد کا معائنہ کریں جس کے ساتھ آپ تعامل کر رہے ہیں۔"</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"ٹچ کے ذریعے دریافت کریں کو آن کرنے کی"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"تھپتھپائے گئے آئٹمز کو باآواز بلند بولا جائے گا اور اشاروں کا استعمال کرکے اسکرین کو دریافت کیا جا سکتا ہے۔"</string>
- <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"بہتر ویب accessibility کو آن کرنے کی"</string>
+ <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"بہتر ویب ایکسیسبیلٹی کو آن کرنے کی"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"ایپ کا مواد مزید قابل رسائی بنانے کیلئے اسکرپٹس کو انسٹال کیا جا سکتا ہے۔"</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"آپکے ٹائپ کردہ متن کا مشاہدہ کرنے کی"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"اس میں ذاتی ڈیٹا جیسے کریڈٹ کارڈ نمبرز اور پاس ورڈز شامل ہیں۔"</string>
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"آپ کی مداخلت کے بغیر کالیں کرنے کیلئے ایپ کو IMS سروس استعمال کرنے کی اجازت دیتی ہے۔"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"فون کے اسٹیٹس اور شناخت کو پڑھیں"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ایپ کو آلے کی فون والی خصوصیات تک رسائی حاصل کرنے کی اجازت دیتا ہے۔ یہ اجازت ایپ کو فون نمبر اور آلے کے IDs کا تعین کرنے، آیا کوئی کال فعال ہے، اور کال کے ذریعہ مربوط ریموٹ نمبر کا تعین کرنے دیتی ہے۔"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"فون نمبر پڑھے"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ایپ کو آلہ کے فون نمبر تک رسائی کرنے دیتا ہے۔"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ٹیبلیٹ کو سلیپ وضع میں جانے سے روکیں"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV کو سلیپ وضع میں جانے سے روکیں"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"فون کو سلیپ وضع میں جانے سے روکیں"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"میڈیا والیوم"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"اطلاع کا والیوم"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ڈیفالٹ رنگ ٹون"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ڈیفالٹ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"کوئی نہیں"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"رنگ ٹونز"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"الارم کی آوازیں"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"اطلاعات کی آوازیں"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"نامعلوم"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Wi-Fi نیٹ ورکس دستیاب ہیں</item>
<item quantity="one">Wi-Fi نیٹ ورک دستیاب ہے</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ایک ایپلیکیشن کو انسٹال سیشنز پڑھنے کی اجازت دیتا ہے۔ یہ اسے فعال پیکیج انسٹالیشنز کے بارے میں تفصیلات دیکھنے کی اجازت دیتا ہے۔"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"پیکجز انسٹال کرنے کی درخواست کریں"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ایک ایپلیکیشن کو پیکجز انسٹال کرنے کی اجازت دیتی ہے۔"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"زوم کنٹرول کیلئے دوبار تھپتھپائیں"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ویجٹس کو شامل نہیں کرسکا۔"</string>
<string name="ime_action_go" msgid="8320845651737369027">"جائیں"</string>
@@ -1236,7 +1238,7 @@
<string name="forward_intent_to_work" msgid="621480743856004612">"آپ اس ایپ کو اپنے دفتری پروفائل میں استعمال کر رہے ہیں"</string>
<string name="input_method_binding_label" msgid="1283557179944992649">"اندراج کا طریقہ"</string>
<string name="sync_binding_label" msgid="3687969138375092423">"مطابقت پذیری کریں"</string>
- <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibility"</string>
+ <string name="accessibility_binding_label" msgid="4148120742096474641">"ایکسیسبیلٹی"</string>
<string name="wallpaper_binding_label" msgid="1240087844304687662">"وال پیپر"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"وال پیپر تبدیل کریں"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"اطلاع سننے والا"</string>
@@ -1438,9 +1440,9 @@
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"ہٹائیں"</string>
<string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"والیوم کو تجویز کردہ سطح سے زیادہ کریں؟\n\nزیادہ وقت تک اونچی آواز میں سننے سے آپ کی سماعت کو نقصان پہنچ سکتا ہے۔"</string>
- <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"accessibility فعال کرنے کیلئے دو انگلیاں نیچے دبائے رکھیں۔"</string>
- <string name="accessibility_enabled" msgid="1381972048564547685">"Accessibility فعال۔"</string>
- <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accessibility منسوخ ہوگئی۔"</string>
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"ایکسیسبیلٹی فعال کرنے کیلئے دو انگلیاں نیچے دبائے رکھیں۔"</string>
+ <string name="accessibility_enabled" msgid="1381972048564547685">"ایکسیسبیلٹی فعال۔"</string>
+ <string name="enable_accessibility_canceled" msgid="3833923257966635673">"ایکسیسبیلٹی منسوخ ہوگئی۔"</string>
<string name="user_switched" msgid="3768006783166984410">"موجودہ صارف <xliff:g id="NAME">%1$s</xliff:g>۔"</string>
<string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g> پر سوئچ کیا جا رہا ہے…"</string>
<string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> لاگ آؤٹ ہو رہا ہے…"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"سال منتخب کریں"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> کو حذف کر دیا گیا"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"دفتر <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"دوسرا کام <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"تیسرا کام <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"اس اسکرین سے پن ہٹانے کیلئے، پیچھے کو تھپتھپائیں اور دبا کر رکھیں۔"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ایپ کو پن کر دیا گیا ہے: اس آلہ پر پن ہٹانے کی اجازت نہیں ہے۔"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"اسکرین کو پن کر دیا گیا"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ابھی ری سیٹ کریں"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"غیر فعال کردہ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"کانفرنس کال"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ٹول ٹپ"</string>
</resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 255982c..f44a6c9 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Ilovaga sizning ishtirokingizsiz qo‘ng‘iroqlarni amalga oshirish uchun IMS xizmatidan foydalanishga ruxsat beradi."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefon holati haqidagi ma’lumotlarni olish"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ilovaga qurilmangizdagi telefon xususiyatlariga kirishga ruxsat beradi. Bu ruxsat ilovaga telefon raqami va qurilma nomlari, qo‘ng‘iroq faol yoki faolsizligi va masofadagi raqam qo‘ng‘rioq orqali bog‘langanligini aniqlashga imkon beradi."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"telefon raqamini o‘qish"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Ilovaga qurilmaning telefon raqamidan foydalanishiga ruxsat beradi."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"planshetni uyquga ketishiga yo‘l qo‘ymaslik"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"televizorning uyqu rejimiga o‘tishining oldini olish"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"telefonni uxlashiga yo‘l qo‘ymaslik"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ilovaga o‘rnatilgan seanslarni o‘qish uchun ruxsat beradi. Bu unga faol paket o‘rnatmalari haqidagi ma’lumotlarni ko‘rish imkonini beradi."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"paketlarni o‘rnatish so‘rovini yuborish"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Ilovaga paketlarni o‘rnatish so‘rovini yuborish imkonini beradi."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ko‘lamini o‘zgartirish uchun ikki marta bosing"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Vidjet qo‘shilmadi."</string>
<string name="ime_action_go" msgid="8320845651737369027">"O‘tish"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Yilni tanlash"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> raqami o‘chirib tashlandi"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ish <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-ishxona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-ishxona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Bu ekrandan chiqish uchun “Orqaga” tugmasini bosib turing."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ilova qadab qo‘yilgan. Uni ekrandan yechish ushbu qurilmada ta’qiqlangan."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran qadab qo‘yildi"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Asl holatga qaytarish"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> vidjeti o‘chirilgan"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferens-aloqa"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Qalqib chiquvchi maslahat oynasi"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Maslahat oynasi"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 1f6a1cd..21ad11c4 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Cho phép ứng dụng sử dụng dịch vụ IMS để thực hiện cuộc gọi mà không có sự can thiệp của bạn."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"đọc trạng thái và nhận dạng của điện thoại"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Cho phép ứng dụng truy cập vào các tính năng điện thoại của thiết bị. Quyền này cho phép ứng dụng xác định số điện thoại và ID thiết bị, cho dù cuộc gọi có hiện hoạt hay không và số từ xa có được kết nối bằng một cuộc gọi hay không."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"đọc số điện thoại"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Cho phép ứng dụng truy cập số điện thoại của thiết bị."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ngăn máy tính bảng chuyển sang chế độ ngủ"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ngăn TV chuyển sang chế độ ngủ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ngăn điện thoại chuyển sang chế độ ngủ"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Âm lượng phương tiện"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Âm lượng thông báo"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Nhạc chuông mặc định"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Mặc định (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Không"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Nhạc chuông"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Âm thanh báo thức"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Âm thanh thông báo"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Không xác định"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Các mạng Wi-Fi khả dụng</item>
<item quantity="one">Mạng Wi-Fi khả dụng</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Cho phép ứng dụng đọc phiên cài đặt. Thao tác này sẽ cho phép ứng dụng xem chi tiết về gói cài đặt đang hoạt động."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"yêu cầu gói cài đặt"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Cho phép ứng dụng yêu cầu cài đặt gói."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Nhấn hai lần để kiểm soát thu phóng"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Không thể thêm tiện ích."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Đến"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Chọn năm"</string>
<string name="deleted_key" msgid="7659477886625566590">"Đã xóa <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> làm việc"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Công việc thứ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Công việc thứ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Để bỏ ghim màn hình này, nhấn và giữ Quay lại."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ứng dụng được ghim: Không được phép bỏ ghim trên thiết bị này."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Đã ghim màn hình"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Đặt lại ngay bây giờ"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Đã tắt <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Cuộc gọi nhiều bên"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Chú giải công cụ"</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 5991f54..68fec51 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -278,7 +278,7 @@
<string name="permlab_statusBarService" msgid="4826835508226139688">"用作状态栏"</string>
<string name="permdesc_statusBarService" msgid="716113660795976060">"允许以状态栏形式显示应用。"</string>
<string name="permlab_expandStatusBar" msgid="1148198785937489264">"展开/收拢状态栏"</string>
- <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"允许应用展开或折叠状态栏。"</string>
+ <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"允许应用展开或收起状态栏。"</string>
<string name="permlab_install_shortcut" msgid="4279070216371564234">"安装快捷方式"</string>
<string name="permdesc_install_shortcut" msgid="8341295916286736996">"允许应用自行添加主屏幕快捷方式。"</string>
<string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"卸载快捷方式"</string>
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"允许应用自行使用即时通讯服务拨打电话。"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"读取手机状态和身份"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"允许该应用访问设备的电话功能。此权限可让该应用确定本机号码和设备 ID、是否正处于通话状态以及拨打的号码。"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"读取电话号码"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"允许该应用访问该设备的电话号码。"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"阻止平板电脑进入休眠状态"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"阻止电视进入休眠状态"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"防止手机休眠"</string>
@@ -738,7 +740,7 @@
<string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"添加小部件。"</string>
<string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"空白"</string>
<string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"已展开解锁区域。"</string>
- <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"已折叠解锁区域。"</string>
+ <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"已收起解锁区域。"</string>
<string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>小部件。"</string>
<string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"用户选择器"</string>
<string name="keyguard_accessibility_status" msgid="8008264603935930611">"状态"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"媒体音量"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
<string name="ringtone_default" msgid="3789758980357696936">"默认铃声"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"默认铃声(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"无"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"铃声"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"闹钟提示音"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"通知提示音"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"未知"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">有可用的 WLAN 网络</item>
<item quantity="one">有可用的 WLAN 网络</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"允许应用读取安装会话。这样,应用将可以查看有关当前软件包安装的详情。"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"请求安装文件包"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"允许应用请求安装文件包。"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"双击可以进行缩放控制"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"无法添加小部件。"</string>
<string name="ime_action_go" msgid="8320845651737369027">"开始"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"选择年份"</string>
<string name="deleted_key" msgid="7659477886625566590">"已删除<xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"第二个工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"第三个工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"要取消固定此屏幕,请触摸并按住“返回”按钮。"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"应用处于固定状态:在此设备上不允许退出该模式。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"已固定屏幕"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"立即重置"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"已停用的<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"电话会议"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"提示"</string>
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 7191a3d..d6b4cf7 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"允許應用程式自行使用 IMS 服務撥打電話。"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"讀取手機狀態和識別碼"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"允許應用程式使用裝置的電話功能。這項權限允許應用程式確定手機號碼和裝置編號、是否正在通話中,以及所撥打的對方號碼。"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"讀取電話號碼"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"允許應用程式存取裝置的電話號碼。"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"防止平板電腦進入休眠狀態"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"阻止電視進入休眠狀態"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"防止手機進入休眠狀態"</string>
@@ -646,7 +648,7 @@
<string name="relationTypeDomesticPartner" msgid="6904807112121122133">"同居伴侶"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"父親"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"朋友"</string>
- <string name="relationTypeManager" msgid="6365677861610137895">"管理員"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"主管"</string>
<string name="relationTypeMother" msgid="4578571352962758304">"母親"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"父母"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"夥伴"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"媒體音量"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
<string name="ringtone_default" msgid="3789758980357696936">"預設鈴聲"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"預設 (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"無"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"鈴聲"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"鬧鐘音效"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"通知音效"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"不明"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">有可用的 Wi-Fi 網絡</item>
<item quantity="one">有可用的 Wi-Fi 網絡</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"允許應用程式讀取安裝工作階段。應用程式將可查看目前安裝套裝的詳細資料。"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"要求安裝套件"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"允許應用程式要求安裝套件"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"輕觸兩下控制縮放"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"無法新增小工具。"</string>
<string name="ime_action_go" msgid="8320845651737369027">"開始"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"選取年份"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> 已刪除"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"第二個工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"第三個工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"如要取消固定這個畫面,請按住 [返回]。"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"應用程式已固定:不允許在此裝置上取消固定。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"螢幕已固定"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"立即重設"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"「<xliff:g id="LABEL">%1$s</xliff:g>」已停用"</string>
<string name="conference_call" msgid="3751093130790472426">"會議通話"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"提示"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9e37672..74b149d 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"允許應用程式自動使用 IMS 服務撥打電話。"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"讀取手機狀態和識別碼"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"允許應用程式使用裝置的電話功能。這項權限可讓應用程式判讀手機號碼和裝置 ID、是否正在通話中,以及所撥打的對方號碼。"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"讀取電話號碼"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"允許應用程式存取裝置的電話號碼。"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"防止平板電腦進入休眠狀態"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"防止電視進入休眠狀態"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"防止手機進入待命狀態"</string>
@@ -605,7 +607,7 @@
<string name="phoneTypeRadio" msgid="4093738079908667513">"無線電"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"電報"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY/TDD"</string>
- <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"公司行動電話"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"公司手機"</string>
<string name="phoneTypeWorkPager" msgid="649938731231157056">"公司呼叫器"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"助理"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"多媒體簡訊"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"媒體音量"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
<string name="ringtone_default" msgid="3789758980357696936">"預設鈴聲"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"預設 (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"無"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"鈴聲"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"鬧鐘音效"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"通知音效"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"不明"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">有多個可用的 Wi-Fi 網路</item>
<item quantity="one">有一個可用的 Wi-Fi 網路</item>
@@ -1214,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"允許應用程式讀取安裝工作階段。應用程式將可查看目前的套件安裝詳細資料。"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"要求安裝套件"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"允許應用程式要求安裝套件。"</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"點兩下以進行縮放控制"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"無法新增小工具。"</string>
<string name="ime_action_go" msgid="8320845651737369027">"開始"</string>
@@ -1564,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"選取年份"</string>
<string name="deleted_key" msgid="7659477886625566590">"已刪除 <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"第 2 項工作:<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"第 3 項工作:<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"如要取消固定這個畫面,請按住「返回」按鈕。"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"應用程式已固定:無法在這部裝置取消固定。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"已固定螢幕"</string>
@@ -1687,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"立即重設"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"已停用的<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"電話會議"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"工具提示"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 66d1010..d36b7fb 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Ivumela uhlelo lokusebenza ukuthi lusebenzise isevisi ye-IMS ukuze yenze amakholi ngaphandle kokungenelela kwakho."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"funda isimo sefoni kanye nesazisi"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ivumela uhlelo lokusebenza ukufinyelela izici zefoni zedivayisi. Le mvume ivumela uhlelo lokusebenza ukucacisa inombolo yefoni nobunikazi bedivayisi, ukuthi noma ikholi iyasebenza, futhi nenombolo yesilawuli kude zixhunywe ngekholi."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"funda inombolo yefoni"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Ivumela uhlelo lokusebenza ukuthi lifinyelele kunombolo yefoni yedivayisi."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"gwema ithebhulethi ukuba ingalali"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"vimbela i-TV kusukela ekulaleni"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"gwema ifoni ukuba ingalali"</string>
@@ -1210,6 +1212,10 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ivumela uhlelo lokusebenza ukufunda izikhathi. Lokhu kuzolivumela ukubona imininingwane mayelana nokufaka kwephakethi esebenzayo."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"cela amaphakheji wokufaka"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Ivumela uhlelo lokusebenza ukucela ukufakwa kwamaphakheji."</string>
+ <!-- no translation found for permlab_requestIgnoreBatteryOptimizations (8021256345643918264) -->
+ <skip />
+ <!-- no translation found for permdesc_requestIgnoreBatteryOptimizations (8359147856007447638) -->
+ <skip />
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Thepha kabili ukuthola ukulawula ukusondeza"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Yehlulekile ukwengeza i-widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Iya"</string>
@@ -1560,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Khetha unyaka"</string>
<string name="deleted_key" msgid="7659477886625566590">"I-<xliff:g id="KEY">%1$s</xliff:g> isusiwe"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Umsebenzi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Umsebenzi wesibili <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Umsebenzi wesithathu <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Ukuze ususe ukuphina lesi sikrini, thinta futhi ubambe okuthi Emuva."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Uhlelo lokusebenza luphiniwe: Ukususa ukuphina akuvunyelwe kule divayisi."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Isikrini siphiniwe"</string>
@@ -1683,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Setha kabusha manje"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"I-<xliff:g id="LABEL">%1$s</xliff:g> ekhutshaziwe"</string>
<string name="conference_call" msgid="3751093130790472426">"Ikholi yengqungquthela"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Okuzivelelayo kwe-tooltip"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Ithulithiphu"</string>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7045eaf..8c64484 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7508,6 +7508,8 @@
<attr name="title" />
<!-- @SystemApi Summary for the same preference as the title. @hide -->
<attr name="summary" />
+ <!-- @SystemApi Whether trust agent can unlock a user profile @hide -->
+ <attr name="unlockProfile" format="boolean"/>
</declare-styleable>
<!-- =============================== -->
@@ -8378,13 +8380,13 @@
<attr name="color" />
</declare-styleable>
- <!-- @hide Attributes which will be read by the Activity to intialize the
+ <!-- @hide Attributes which will be read by the Activity to intialize the
base activity TaskDescription. -->
<declare-styleable name="ActivityTaskDescription">
<!-- @hide From Theme.colorPrimary, used for the TaskDescription primary
color. -->
<attr name="colorPrimary" />
- <!-- @hide From Theme.colorBackground, used for the TaskDescription background
+ <!-- @hide From Theme.colorBackground, used for the TaskDescription background
color. -->
<attr name="colorBackground" />
</declare-styleable>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a7c5b2a..9e75ff9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -422,6 +422,9 @@
<!-- Boolean indicating whether Hotspot 2.0/Passpoint and ANQP queries is enabled -->
<bool translatable="false" name="config_wifi_hotspot2_enabled">false</bool>
+ <!-- Boolean indicating whether 802.11r Fast BSS Transition is enabled on this platform -->
+ <bool translatable="false" name="config_wifi_fast_bss_transition_enabled">false</bool>
+
<!-- Device type information conforming to Annex B format in WiFi Direct specification.
The default represents a dual-mode smartphone -->
<string translatable="false" name="config_wifi_p2p_device_type">10-0050F204-5</string>
@@ -1254,6 +1257,19 @@
config_enableFusedLocationOverlay is false. -->
<string name="config_fusedLocationProviderPackageName" translatable="false">com.android.location.fused</string>
+ <!-- A list of potential packages, in priority order, that may contain a
+ network recommendation provider. A network recommendation provider must:
+ * Be granted the SCORE_NETWORKS permission.
+ * Include a Receiver for the android.net.scoring.SCORE_NETWORKS action guarded by the
+ BROADCAST_NETWORK_PRIVILEGED permission.
+ * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action.
+
+ This may be empty if network scoring and recommending isn't supported.
+ -->
+ <string-array name="config_networkRecommendationPackageNames" translatable="false">
+ <!-- Add packages here -->
+ </string-array>
+
<!-- Whether to enable Hardware FLP overlay which allows Hardware FLP to be
replaced by an app at run-time. When disabled, only the
config_hardwareFlpPackageName package will be searched for Hardware Flp,
@@ -1650,7 +1666,7 @@
<bool name="config_actionMenuItemAllCaps">true</bool>
<!-- Remote server that can provide NTP responses. -->
- <string translatable="false" name="config_ntpServer">2.android.pool.ntp.org</string>
+ <string translatable="false" name="config_ntpServer">time.android.com</string>
<!-- Normal polling frequency in milliseconds -->
<integer name="config_ntpPollingInterval">86400000</integer>
<!-- Try-again polling interval in milliseconds, in case the network request failed -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index af77b1f..87f38c1 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3248,6 +3248,11 @@
<!-- Description of an application permission that lets it read install sessions. -->
<string name="permdesc_requestInstallPackages">Allows an application to request installation of packages.</string>
+ <!-- Title of an application permission that lets it ask user to ignore battery optimizations for that app. -->
+ <string name="permlab_requestIgnoreBatteryOptimizations">ask to ignore battery optimizations</string>
+ <!-- Description of an application permission that lets it ask user to ignore battery optimizations for that app-->
+ <string name="permdesc_requestIgnoreBatteryOptimizations">Allows an app to ask for permission to ignore battery optimizations for that app.</string>
+
<!-- Shown in the tutorial for tap twice for zoom control. -->
<string name="tutorial_double_tap_to_zoom_message_short">Tap twice for zoom control</string>
@@ -4453,6 +4458,6 @@
<!-- Label used by Telephony code, assigned as the display name for conference calls [CHAR LIMIT=60] -->
<string name="conference_call">Conference Call</string>
- <!-- Title for a tooltip popup window [CHAR LIMIT=NONE] -->
- <string name="tooltip_popup_title">Tooltip Popup</string>
+ <!-- Window title for a tooltip [CHAR LIMIT=NONE] -->
+ <string name="tooltip_popup_title">Tooltip</string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f6fd64b..a85ddf1 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1716,6 +1716,7 @@
<java-symbol type="bool" name="config_wifi_background_scan_support" />
<java-symbol type="bool" name="config_wifi_dual_band_support" />
<java-symbol type="bool" name="config_wifi_hotspot2_enabled" />
+ <java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" />
<java-symbol type="bool" name="config_wimaxEnabled" />
<java-symbol type="bool" name="show_ongoing_ime_switcher" />
<java-symbol type="color" name="config_defaultNotificationColor" />
@@ -2751,4 +2752,7 @@
<java-symbol type="integer" name="date_picker_mode" />
<java-symbol type="dimen" name="config_appTransitionAnimationDurationScaleDefault" />
+
+<!-- Network Recommendation -->
+ <java-symbol type="array" name="config_networkRecommendationPackageNames" />
</resources>
diff --git a/core/tests/coretests/res/layout/messaging_linear_layout_test.xml b/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
new file mode 100644
index 0000000..8ba3e07
--- /dev/null
+++ b/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<com.android.internal.widget.MessagingLinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:maxHeight="300px"
+ android:spacing="5px">
+
+</com.android.internal.widget.MessagingLinearLayout>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/provider/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
index 0a32e43..b0ce2c8 100644
--- a/core/tests/coretests/src/android/provider/SettingsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
@@ -351,6 +351,10 @@
assertCanBeHandled(new Intent(Settings.ACTION_WIFI_SETTINGS));
assertCanBeHandled(new Intent(Settings.ACTION_WIFI_SAVED_NETWORK_SETTINGS));
assertCanBeHandled(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
+
+ if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) {
+ assertCanBeHandled(new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS));
+ }
}
private void assertCanBeHandled(final Intent intent) {
diff --git a/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
new file mode 100644
index 0000000..5dc07c2
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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 com.android.internal.widget;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.view.View.MeasureSpec;
+import android.widget.TextView;
+
+import org.junit.Before;
+import org.junit.Test;
+
+@SmallTest
+public class ImageFloatingTextViewTest {
+
+ private Context mContext;
+ private ImageFloatingTextView mView;
+ private TextView mTextView;
+
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mView = new ImageFloatingTextView(mContext, null, 0, 0);
+ mTextView = new TextView(mContext, null, 0, 0);
+ mTextView.setMaxLines(9);
+ }
+
+ @Test
+ public void testEmpty() {
+ parametrizedTest("");
+ }
+
+ @Test
+ public void testSingleLine() {
+ parametrizedTest("Hello, World!");
+ }
+
+ @Test
+ public void testTwoLine() {
+ parametrizedTest("Hello, World!\nWhat a nice day!");
+ }
+
+ @Test
+ public void testShort() {
+ parametrizedTest("Hello, World! What a nice day! Let's try some more text. "
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet.");
+ }
+
+ @Test
+ public void testLong() {
+ parametrizedTest("Hello, World! What a nice day! Let's try some more text. "
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet.");
+ }
+
+ private void parametrizedTest(CharSequence text) {
+ int heightMeasureSpec = MeasureSpec.makeMeasureSpec(500, MeasureSpec.AT_MOST);
+ int widthMeasureSpec = MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY);
+
+ mTextView.setText(text);
+ mView.setText(text);
+
+ mTextView.measure(widthMeasureSpec, heightMeasureSpec);
+ mView.measure(widthMeasureSpec, heightMeasureSpec);
+
+ assertEquals(mTextView.getMeasuredHeight(), mView.getMeasuredHeight());
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
new file mode 100644
index 0000000..75b2c1d
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
@@ -0,0 +1,223 @@
+/*
+ * 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 com.android.internal.widget;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.os.Debug;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.espresso.core.deps.guava.base.Function;
+import android.support.test.filters.SmallTest;
+import android.view.LayoutInflater;
+import android.view.View.MeasureSpec;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+
+@SmallTest
+public class MessagingLinearLayoutTest {
+
+ public static final int WIDTH_SPEC = MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY);
+ public static final int HEIGHT_SPEC = MeasureSpec.makeMeasureSpec(400, MeasureSpec.AT_MOST);
+ private Context mContext;
+ private MessagingLinearLayout mView;
+
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ // maxHeight: 300px
+ // spacing: 50px
+ mView = (MessagingLinearLayout) LayoutInflater.from(mContext).inflate(
+ R.layout.messaging_linear_layout_test, null);
+ }
+
+ @Test
+ public void testSingleChild() {
+ FakeImageFloatingTextView child = fakeChild((i) -> 3);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertEquals(3, child.getNumIndentLines());
+ assertFalse(child.isHidden());
+ assertEquals(150, mView.getMeasuredHeight());
+ }
+
+ @Test
+ public void testLargeSmall() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> 3);
+ FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child1);
+ mView.addView(child2);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertEquals(3, child1.getNumIndentLines());
+ assertEquals(0, child2.getNumIndentLines());
+ assertFalse(child1.isHidden());
+ assertFalse(child2.isHidden());
+ assertEquals(205, mView.getMeasuredHeight());
+ }
+
+ @Test
+ public void testSmallSmall() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> 1);
+ FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child1);
+ mView.addView(child2);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertEquals(2, child1.getNumIndentLines());
+ assertEquals(1, child2.getNumIndentLines());
+ assertFalse(child1.isHidden());
+ assertFalse(child2.isHidden());
+ assertEquals(105, mView.getMeasuredHeight());
+ }
+
+ @Test
+ public void testLargeLarge() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> 7);
+ FakeImageFloatingTextView child2 = fakeChild((i) -> 7);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child1);
+ mView.addView(child2);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertEquals(3, child2.getNumIndentLines());
+ assertTrue(child1.isHidden());
+ assertFalse(child2.isHidden());
+ assertEquals(300, mView.getMeasuredHeight());
+ }
+
+ @Test
+ public void testLargeSmall_largeWrapsWith3indentbutnot3_andHitsMax() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> i > 2 ? 5 : 4);
+ FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child1);
+ mView.addView(child2);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertTrue(child1.isHidden());
+ assertFalse(child2.isHidden());
+ assertEquals(50, mView.getMeasuredHeight());
+ assertEquals(2, child2.getNumIndentLines());
+ }
+
+ @Test
+ public void testLargeSmall_largeWrapsWith3indentbutnot3() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> i > 2 ? 4 : 3);
+ FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child1);
+ mView.addView(child2);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertFalse(child1.isHidden());
+ assertFalse(child2.isHidden());
+ assertEquals(255, mView.getMeasuredHeight());
+ assertEquals(3, child1.getNumIndentLines());
+ assertEquals(0, child2.getNumIndentLines());
+ }
+
+ private class FakeImageFloatingTextView extends ImageFloatingTextView {
+
+ public static final int LINE_HEIGHT = 50;
+ private final Function<Integer, Integer> mLinesForIndent;
+ private int mNumIndentLines;
+
+ public FakeImageFloatingTextView(Context context,
+ Function<Integer, Integer> linesForIndent) {
+ super(context, null, 0, 0);
+ mLinesForIndent = linesForIndent;
+ }
+
+ @Override
+ public boolean setNumIndentLines(int lines) {
+ boolean changed = (mNumIndentLines != lines);
+ mNumIndentLines = lines;
+ return changed;
+ }
+
+ public int getNumIndentLines() {
+ return mNumIndentLines;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(
+ getDefaultSize(500, widthMeasureSpec),
+ resolveSize(getDesiredHeight(), heightMeasureSpec));
+ }
+
+ @Override
+ public int getLineCount() {
+ return mLinesForIndent.apply(mNumIndentLines);
+ }
+
+ public int getDesiredHeight() {
+ return LINE_HEIGHT * getLineCount();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ // swallow
+ }
+
+ public boolean isHidden() {
+ MessagingLinearLayout.LayoutParams lp =
+ (MessagingLinearLayout.LayoutParams) getLayoutParams();
+ try {
+ Field hide = MessagingLinearLayout.LayoutParams.class.getDeclaredField("hide");
+ hide.setAccessible(true);
+ return hide.getBoolean(lp);
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private FakeImageFloatingTextView fakeChild(Function<Integer,Integer> linesForIndent) {
+ return new FakeImageFloatingTextView(mContext, linesForIndent);
+ }
+}
diff --git a/core/tests/utiltests/Android.mk b/core/tests/utiltests/Android.mk
index 6e415f4..46a0d9b 100644
--- a/core/tests/utiltests/Android.mk
+++ b/core/tests/utiltests/Android.mk
@@ -12,6 +12,8 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SRC_FILES += src/android/util/IRemoteMemoryIntArray.aidl
+LOCAL_JNI_SHARED_LIBRARIES := libmemoryintarraytest libcutils libc++
+
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
frameworks-base-testutils \
diff --git a/core/tests/utiltests/jni/Android.bp b/core/tests/utiltests/jni/Android.bp
new file mode 100644
index 0000000..e9a4144
--- /dev/null
+++ b/core/tests/utiltests/jni/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+cc_library_shared {
+ name: "libmemoryintarraytest",
+ shared_libs: [
+ "libcutils",
+ ],
+ clang: true,
+ stl: "libc++",
+ srcs: [
+ "registration.cpp",
+ "android_util_MemoryIntArrayTest.cpp",
+ ],
+ cflags: ["-Werror"],
+}
\ No newline at end of file
diff --git a/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
new file mode 100644
index 0000000..57ee2d5
--- /dev/null
+++ b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#include <atomic>
+#include <jni.h>
+#include <cutils/ashmem.h>
+#include <linux/ashmem.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+jint android_util_MemoryIntArrayTest_createAshmem(__attribute__((unused)) JNIEnv* env,
+ __attribute__((unused)) jobject clazz,
+ jstring name, jint size)
+{
+
+ if (name == NULL) {
+ return -1;
+ }
+
+ if (size < 0) {
+ return -1;
+ }
+
+ const char* nameStr = env->GetStringUTFChars(name, NULL);
+ const int ashmemSize = sizeof(std::atomic_int) * size;
+ int fd = ashmem_create_region(nameStr, ashmemSize);
+ env->ReleaseStringUTFChars(name, nameStr);
+
+ if (fd < 0) {
+ return -1;
+ }
+
+ int setProtResult = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
+ if (setProtResult < 0) {
+ return -1;
+ }
+
+ return fd;
+}
+
+void android_util_MemoryIntArrayTest_setAshmemSize(__attribute__((unused)) JNIEnv* env,
+ __attribute__((unused)) jobject clazz, jint fd, jint size)
+{
+ if (fd < 0) {
+ return;
+ }
+
+ if (size < 0) {
+ return;
+ }
+
+ ioctl(fd, ASHMEM_SET_SIZE, size);
+}
diff --git a/core/tests/utiltests/jni/registration.cpp b/core/tests/utiltests/jni/registration.cpp
new file mode 100644
index 0000000..0c84d98
--- /dev/null
+++ b/core/tests/utiltests/jni/registration.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+
+extern jint android_util_MemoryIntArrayTest_createAshmem(JNIEnv* env,
+ jobject clazz, jstring name, jint size);
+extern void android_util_MemoryIntArrayTest_setAshmemSize(JNIEnv* env,
+ jobject clazz, jint fd, jint size);
+
+extern "C" {
+ JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
+ JNIEnv * env, jobject obj, jstring name, jint size);
+ JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
+ JNIEnv * env, jobject obj, jint fd, jint size);
+};
+
+JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
+ __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
+ jstring name, jint size)
+{
+ return android_util_MemoryIntArrayTest_createAshmem(env, obj, name, size);
+}
+
+JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
+ __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
+ jint fd, jint size)
+{
+ android_util_MemoryIntArrayTest_setAshmemSize(env, obj, fd, size);
+}
diff --git a/core/tests/utiltests/src/android/util/IRemoteMemoryIntArray.aidl b/core/tests/utiltests/src/android/util/IRemoteMemoryIntArray.aidl
index 0a65fff2..10d14f1 100644
--- a/core/tests/utiltests/src/android/util/IRemoteMemoryIntArray.aidl
+++ b/core/tests/utiltests/src/android/util/IRemoteMemoryIntArray.aidl
@@ -20,11 +20,12 @@
interface IRemoteMemoryIntArray {
MemoryIntArray peekInstance();
- void create(int size, boolean clientWritable);
+ void create(int size);
boolean isWritable();
int get(int index);
void set(int index, int value);
int size();
void close();
boolean isClosed();
+ void accessLastElementInRemoteProcess(in MemoryIntArray array);
}
diff --git a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
index 129e6b7..85817bb 100644
--- a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
+++ b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
@@ -28,14 +28,22 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.lang.reflect.Field;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
@RunWith(AndroidJUnit4.class)
public class MemoryIntArrayTest {
+ static {
+ System.loadLibrary("cutils");
+ System.loadLibrary("memoryintarraytest");
+ }
@Test
public void testSize() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, false);
+ array = new MemoryIntArray(3);
assertEquals("size must be three", 3, array.size());
} finally {
IoUtils.closeQuietly(array);
@@ -46,7 +54,7 @@
public void testGetSet() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, false);
+ array = new MemoryIntArray(3);
array.set(0, 1);
array.set(1, 2);
@@ -64,7 +72,7 @@
public void testWritable() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, true);
+ array = new MemoryIntArray(3);
assertTrue("Must be mutable", array.isWritable());
} finally {
IoUtils.closeQuietly(array);
@@ -75,7 +83,7 @@
public void testClose() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, false);
+ array = new MemoryIntArray(3);
array.close();
assertTrue("Must be closed", array.isClosed());
} finally {
@@ -90,7 +98,7 @@
MemoryIntArray firstArray = null;
MemoryIntArray secondArray = null;
try {
- firstArray = new MemoryIntArray(3, false);
+ firstArray = new MemoryIntArray(3);
firstArray.set(0, 1);
firstArray.set(1, 2);
@@ -117,7 +125,7 @@
public void testInteractOnceClosed() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, false);
+ array = new MemoryIntArray(3);
array.close();
array.close();
@@ -160,7 +168,7 @@
public void testInteractPutOfBounds() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, false);
+ array = new MemoryIntArray(3);
try {
array.get(-1);
@@ -198,7 +206,7 @@
public void testOverMaxSize() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(MemoryIntArray.getMaxSize() + 1, false);
+ array = new MemoryIntArray(MemoryIntArray.getMaxSize() + 1);
fail("Cannot use over max size");
} catch (IllegalArgumentException e) {
/* expected */
@@ -209,7 +217,7 @@
@Test
public void testNotMutableByUnprivilegedClients() throws Exception {
- RemoteIntArray remoteIntArray = new RemoteIntArray(1, false);
+ RemoteIntArray remoteIntArray = new RemoteIntArray(1);
try {
assertNotNull("Couldn't get remote instance", remoteIntArray);
MemoryIntArray localIntArray = remoteIntArray.peekInstance();
@@ -230,4 +238,64 @@
remoteIntArray.destroy();
}
}
+
+ @Test
+ public void testAshmemSizeMatchesMemoryIntArraySize() throws Exception {
+ boolean success = false;
+
+ // Get a handle to a remote process to send the fd
+ RemoteIntArray remoteIntArray = new RemoteIntArray(1);
+ try {
+ // Let us try 100 times
+ for (int i = 0; i < 100; i++) {
+ // Create a MemoryIntArray to muck with
+ MemoryIntArray array = new MemoryIntArray(1);
+
+ // Create the fd to stuff in the MemoryIntArray
+ final int fd = nativeCreateAshmem("foo", 1);
+
+ // Replace the fd with our ahsmem region
+ Field fdFiled = MemoryIntArray.class.getDeclaredField("mFd");
+ fdFiled.setAccessible(true);
+ fdFiled.set(array, fd);
+
+ CountDownLatch countDownLatch = new CountDownLatch(2);
+
+ new Thread() {
+ @Override
+ public void run() {
+ for (int i = 2; i < Integer.MAX_VALUE; i++) {
+ if (countDownLatch.getCount() == 1) {
+ countDownLatch.countDown();
+ return;
+ }
+ nativeSetAshmemSize(fd, i);
+ }
+ }
+ }.start();
+
+ try {
+ remoteIntArray.accessLastElementInRemoteProcess(array);
+ } catch (IllegalArgumentException e) {
+ success = true;
+ }
+
+ countDownLatch.countDown();
+ countDownLatch.await(1000, TimeUnit.MILLISECONDS);
+
+ if (success) {
+ break;
+ }
+ }
+ } finally {
+ remoteIntArray.destroy();
+ }
+
+ if (!success) {
+ fail("MemoryIntArray should catch ahshmem size changing under it");
+ }
+ }
+
+ private native int nativeCreateAshmem(String name, int size);
+ private native void nativeSetAshmemSize(int fd, int size);
}
diff --git a/core/tests/utiltests/src/android/util/RemoteIntArray.java b/core/tests/utiltests/src/android/util/RemoteIntArray.java
index 10c325f..7dc3400 100644
--- a/core/tests/utiltests/src/android/util/RemoteIntArray.java
+++ b/core/tests/utiltests/src/android/util/RemoteIntArray.java
@@ -40,7 +40,7 @@
private android.util.IRemoteMemoryIntArray mRemoteInstance;
- public RemoteIntArray(int size, boolean clientWritable) throws IOException, TimeoutException {
+ public RemoteIntArray(int size) throws IOException, TimeoutException {
mIntent.setComponent(new ComponentName(InstrumentationRegistry.getContext(),
RemoteMemoryIntArrayService.class));
synchronized (mLock) {
@@ -48,7 +48,7 @@
bindLocked();
}
try {
- mRemoteInstance.create(size, clientWritable);
+ mRemoteInstance.create(size);
} catch (RemoteException e) {
throw new IOException(e);
}
@@ -148,6 +148,14 @@
}
}
+ public void accessLastElementInRemoteProcess(MemoryIntArray array) {
+ try {
+ mRemoteInstance.accessLastElementInRemoteProcess(array);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mLock) {
diff --git a/core/tests/utiltests/src/android/util/RemoteMemoryIntArrayService.java b/core/tests/utiltests/src/android/util/RemoteMemoryIntArrayService.java
index 35ae9a7..9264c6c 100644
--- a/core/tests/utiltests/src/android/util/RemoteMemoryIntArrayService.java
+++ b/core/tests/utiltests/src/android/util/RemoteMemoryIntArrayService.java
@@ -35,10 +35,10 @@
return new android.util.IRemoteMemoryIntArray.Stub() {
@Override
- public void create(int size, boolean clientWritable) {
+ public void create(int size) {
synchronized (mLock) {
try {
- mArray = new MemoryIntArray(size, clientWritable);
+ mArray = new MemoryIntArray(size);
} catch (IOException e) {
throw new IllegalStateException(e);
}
@@ -109,6 +109,15 @@
return mArray.isClosed();
}
}
+
+ @Override
+ public void accessLastElementInRemoteProcess(MemoryIntArray array) {
+ try {
+ array.get(array.size() - 1);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
};
}
}
diff --git a/docs/html/reference/packages-wearable-support.html b/docs/html/reference/packages-wearable-support.html
index aff2e34..a8d9446 100644
--- a/docs/html/reference/packages-wearable-support.html
+++ b/docs/html/reference/packages-wearable-support.html
@@ -113,7 +113,7 @@
<!-- JAVASCRIPT -->
-<script src="http://www.google.com/jsapi" type="text/javascript"></script>
+<script src="//www.google.com/jsapi" type="text/javascript"></script>
<script src="../assets/js/android_3p-bundle.js" type="text/javascript"></script>
<script type="text/javascript">
var toRoot = "../";
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes.html
new file mode 100644
index 0000000..cd9b0a5
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<!-- on Fri Nov 11 17:08:02 EST 2016 -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Support Library API Differences Report
+</TITLE>
+<link href="../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</head>
+<frameset cols="242,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9">
+<frameset rows="174,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9">
+ <frame src="changes/jdiff_topleftframe.html" scrolling="no" name="topleftframe" frameborder="1">
+ <frame src="changes/alldiffs_index_all.html" scrolling="auto" name="bottomleftframe" frameborder="1">
+ </frameset>
+ <frame src="changes/changes-summary.html" scrolling="auto" name="rightframe" frameborder="1">
+</frameset>
+<noframes>
+<h2>
+Frame Alert
+</h2>
+
+<p>
+This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+<br>
+Link to <a href="changes/changes-summary.html" target="_top">Non-frame version.</A>
+</noframes>
+</html>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_additions.html
new file mode 100644
index 0000000..369d9b1
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_additions.html
@@ -0,0 +1,252 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+ <br>
+<A HREF="alldiffs_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Constructor ActivityCompat -->
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v13.app.ActivityCompat.html#android.support.v13.app.ActivityCompat.ctor_added()" class="hiddenlink" target="rightframe"><b>ActivityCompat</b>
+()</A></nobr> constructor<br>
+<!-- Package android.support.v13.view.inputmethod -->
+<A HREF="changes-summary.html#android.support.v13.view.inputmethod" class="hiddenlink" target="rightframe"><b>android.support.v13.view.inputmethod</b></A><br>
+<!-- Class BottomNavigationView -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView" class="hiddenlink" target="rightframe"><b>BottomNavigationView</b></A><br>
+<!-- Class BottomNavigationView.OnNavigationItemSelectedListener -->
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView.OnNavigationItemSelectedListener" class="hiddenlink" target="rightframe"><b><i>BottomNavigationView.OnNavigationItemSelectedListener</i></b></A><br>
+<!-- Class DividerItemDecoration -->
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#DividerItemDecoration" class="hiddenlink" target="rightframe"><b>DividerItemDecoration</b></A><br>
+<!-- Method getBridgeTag -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()" class="hiddenlink" target="rightframe"><b>getBridgeTag</b>
+()</A></nobr><br>
+<!-- Method getDecoratedBoundsWithMargins -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getDecoratedBoundsWithMargins</b>
+(<code>View, Rect</code>)</A></nobr><br>
+<!-- Method getDisplay -->
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)" class="hiddenlink" target="rightframe"><b>getDisplay</b>
+(<code>View</code>)</A></nobr><br>
+<!-- Method getProgressViewEndOffset -->
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewEndOffset</b>
+()</A></nobr><br>
+<!-- Method getProgressViewStartOffset -->
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewStartOffset</b>
+()</A></nobr><br>
+<!-- Method getRestrictBackgroundStatus -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)" class="hiddenlink" target="rightframe"><b>getRestrictBackgroundStatus</b>
+(<code>ConnectivityManager</code>)</A></nobr><br>
+<!-- Method getRippleColor -->
+<nobr><A HREF="android.support.design.widget.FloatingActionButton.html#android.support.design.widget.FloatingActionButton.getRippleColor_added()" class="hiddenlink" target="rightframe"><b>getRippleColor</b>
+()</A></nobr><br>
+<!-- Method isItemPrefetchEnabled -->
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()" class="hiddenlink" target="rightframe"><b>isItemPrefetchEnabled</b>
+()</A></nobr><br>
+<!-- Method isRtl -->
+<nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>isRtl</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<!-- Class NotificationCompat.DecoratedCustomViewStyle -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedCustomViewStyle</b></A><br>
+<!-- Class NotificationCompat.DecoratedMediaCustomViewStyle -->
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedMediaCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedMediaCustomViewStyle</b></A><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_DISABLED -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_DISABLED</A>
+</nobr><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_ENABLED -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_ENABLED</A>
+</nobr><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_WHITELISTED -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_WHITELISTED</A>
+</nobr><br>
+<!-- Method setBackground -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe"><b>setBackground</b>
+(<code>View, Drawable</code>)</A></nobr><br>
+<!-- Method setBridgeTag -->
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)" class="hiddenlink" target="rightframe"><b>setBridgeTag</b>
+(<code>String</code>)</A></nobr><br>
+<!-- Method setItemPrefetchEnabled -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)" class="hiddenlink" target="rightframe"><b>setItemPrefetchEnabled</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setPageTransformer -->
+<nobr><A HREF="android.support.v4.view.ViewPager.html#android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)" class="hiddenlink" target="rightframe"><b>setPageTransformer</b>
+(<code>boolean, PageTransformer, int</code>)</A></nobr><br>
+<!-- Method startActivity -->
+<nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>startActivity</b>
+(<code>Context, Intent, Bundle</code>)</A></nobr><br>
+<!-- Method unicodeWrap -->
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>unicodeWrap</i><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_all.html
new file mode 100644
index 0000000..9396e52
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_all.html
@@ -0,0 +1,422 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>All Differences</b>
+ <br>
+<A HREF="alldiffs_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Class ActivityCompat -->
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>ActivityCompat</i><br>
+ <A HREF="android.support.v13.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<!-- Class ActivityCompat -->
+ <A HREF="android.support.v4.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<!-- Constructor ActivityCompat -->
+ <nobr><A HREF="android.support.v13.app.ActivityCompat.html#android.support.v13.app.ActivityCompat.ctor_added()" class="hiddenlink" target="rightframe"><b>ActivityCompat</b>
+()</A></nobr> constructor<br>
+<!-- Constructor ActivityCompat -->
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.ctor_changed()" class="hiddenlink" target="rightframe">ActivityCompat
+()</A></nobr> constructor<br>
+<!-- Package android.support.customtabs -->
+<A HREF="pkg_android.support.customtabs.html" class="hiddenlink" target="rightframe">android.support.customtabs</A><br>
+<!-- Package android.support.design.widget -->
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<!-- Package android.support.v13.app -->
+<A HREF="pkg_android.support.v13.app.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<!-- Package android.support.v13.view.inputmethod -->
+<A HREF="changes-summary.html#android.support.v13.view.inputmethod" class="hiddenlink" target="rightframe"><b>android.support.v13.view.inputmethod</b></A><br>
+<!-- Package android.support.v4.app -->
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<!-- Package android.support.v4.content -->
+<A HREF="pkg_android.support.v4.content.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<!-- Package android.support.v4.net -->
+<A HREF="pkg_android.support.v4.net.html" class="hiddenlink" target="rightframe">android.support.v4.net</A><br>
+<!-- Package android.support.v4.text -->
+<A HREF="pkg_android.support.v4.text.html" class="hiddenlink" target="rightframe">android.support.v4.text</A><br>
+<!-- Package android.support.v4.view -->
+<A HREF="pkg_android.support.v4.view.html" class="hiddenlink" target="rightframe">android.support.v4.view</A><br>
+<!-- Package android.support.v4.widget -->
+<A HREF="pkg_android.support.v4.widget.html" class="hiddenlink" target="rightframe">android.support.v4.widget</A><br>
+<!-- Package android.support.v7.app -->
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<!-- Package android.support.v7.widget -->
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<!-- Class BidiFormatter -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.text.BidiFormatter.html" class="hiddenlink" target="rightframe">BidiFormatter</A><br>
+<!-- Class BottomNavigationView -->
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView" class="hiddenlink" target="rightframe"><b>BottomNavigationView</b></A><br>
+<!-- Class BottomNavigationView.OnNavigationItemSelectedListener -->
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView.OnNavigationItemSelectedListener" class="hiddenlink" target="rightframe"><b><i>BottomNavigationView.OnNavigationItemSelectedListener</i></b></A><br>
+<!-- Class ConnectivityManagerCompat -->
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.net.ConnectivityManagerCompat.html" class="hiddenlink" target="rightframe">ConnectivityManagerCompat</A><br>
+<!-- Class ContextCompat -->
+<i>ContextCompat</i><br>
+ <A HREF="android.support.v4.content.ContextCompat.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<!-- Constructor ContextCompat -->
+ <nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.ctor_changed()" class="hiddenlink" target="rightframe">ContextCompat
+()</A></nobr> constructor<br>
+<!-- Class CustomTabsIntent -->
+<A HREF="android.support.customtabs.CustomTabsIntent.html" class="hiddenlink" target="rightframe">CustomTabsIntent</A><br>
+<!-- Class DividerItemDecoration -->
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#DividerItemDecoration" class="hiddenlink" target="rightframe"><b>DividerItemDecoration</b></A><br>
+<!-- Class FloatingActionButton -->
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.FloatingActionButton.html" class="hiddenlink" target="rightframe">FloatingActionButton</A><br>
+<!-- Method getBridgeTag -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()" class="hiddenlink" target="rightframe"><b>getBridgeTag</b>
+()</A></nobr><br>
+<!-- Method getDecoratedBoundsWithMargins -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getDecoratedBoundsWithMargins</b>
+(<code>View, Rect</code>)</A></nobr><br>
+<!-- Method getDisplay -->
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)" class="hiddenlink" target="rightframe"><b>getDisplay</b>
+(<code>View</code>)</A></nobr><br>
+<!-- Method getProgressViewEndOffset -->
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewEndOffset</b>
+()</A></nobr><br>
+<!-- Method getProgressViewStartOffset -->
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewStartOffset</b>
+()</A></nobr><br>
+<!-- Method getReferrer -->
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)" class="hiddenlink" target="rightframe">getReferrer
+(<code>Activity</code>)</A></nobr><br>
+<!-- Method getRestrictBackgroundStatus -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)" class="hiddenlink" target="rightframe"><b>getRestrictBackgroundStatus</b>
+(<code>ConnectivityManager</code>)</A></nobr><br>
+<!-- Method getRippleColor -->
+<nobr><A HREF="android.support.design.widget.FloatingActionButton.html#android.support.design.widget.FloatingActionButton.getRippleColor_added()" class="hiddenlink" target="rightframe"><b>getRippleColor</b>
+()</A></nobr><br>
+<!-- Method isItemPrefetchEnabled -->
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()" class="hiddenlink" target="rightframe"><b>isItemPrefetchEnabled</b>
+()</A></nobr><br>
+<!-- Method isRtl -->
+<nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>isRtl</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<!-- Method launchUrl -->
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.customtabs.CustomTabsIntent.html#android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)" class="hiddenlink" target="rightframe">launchUrl
+(<code>Context, Uri</code>)</A></nobr><br>
+<!-- Class NotificationCompat.DecoratedCustomViewStyle -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedCustomViewStyle</b></A><br>
+<!-- Class NotificationCompat.DecoratedMediaCustomViewStyle -->
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedMediaCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedMediaCustomViewStyle</b></A><br>
+<!-- Class NotificationCompat.WearableExtender -->
+<A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html" class="hiddenlink" target="rightframe">NotificationCompat.WearableExtender</A><br>
+<!-- Class RecyclerView -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<!-- Class RecyclerView.LayoutManager -->
+<A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html" class="hiddenlink" target="rightframe">RecyclerView.LayoutManager</A><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_DISABLED -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_DISABLED</A>
+</nobr><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_ENABLED -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_ENABLED</A>
+</nobr><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_WHITELISTED -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_WHITELISTED</A>
+</nobr><br>
+<!-- Method setBackground -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe"><b>setBackground</b>
+(<code>View, Drawable</code>)</A></nobr><br>
+<!-- Method setBridgeTag -->
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)" class="hiddenlink" target="rightframe"><b>setBridgeTag</b>
+(<code>String</code>)</A></nobr><br>
+<!-- Method setItemPrefetchEnabled -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)" class="hiddenlink" target="rightframe"><b>setItemPrefetchEnabled</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setPageTransformer -->
+<nobr><A HREF="android.support.v4.view.ViewPager.html#android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)" class="hiddenlink" target="rightframe"><b>setPageTransformer</b>
+(<code>boolean, PageTransformer, int</code>)</A></nobr><br>
+<!-- Class Space -->
+<A HREF="pkg_android.support.v7.widget.html#Space" class="hiddenlink" target="rightframe"><strike>Space</strike></A><br>
+<!-- Method startActivity -->
+<i>startActivity</i><br>
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">type
+(<code>Context, Intent, Bundle</code>) in android.support.v4.app.ActivityCompat
+</A></nobr><br>
+<!-- Method startActivity -->
+ <nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">type <b>
+(<code>Context, Intent, Bundle</code>)</b> in android.support.v4.content.ContextCompat
+</A></nobr><br>
+<!-- Class SwipeRefreshLayout -->
+<A HREF="android.support.v4.widget.SwipeRefreshLayout.html" class="hiddenlink" target="rightframe">SwipeRefreshLayout</A><br>
+<!-- Method unicodeWrap -->
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>unicodeWrap</i><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Class ViewCompat -->
+<A NAME="V"></A>
+<br><font size="+2">V</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
+<!-- Class ViewPager -->
+<A HREF="android.support.v4.view.ViewPager.html" class="hiddenlink" target="rightframe">ViewPager</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_changes.html
new file mode 100644
index 0000000..e0c9f1e
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_changes.html
@@ -0,0 +1,256 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+ <br>
+<A HREF="alldiffs_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Class ActivityCompat -->
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>ActivityCompat</i><br>
+ <A HREF="android.support.v13.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<!-- Class ActivityCompat -->
+ <A HREF="android.support.v4.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<!-- Constructor ActivityCompat -->
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.ctor_changed()" class="hiddenlink" target="rightframe">ActivityCompat
+()</A></nobr> constructor<br>
+<!-- Package android.support.customtabs -->
+<A HREF="pkg_android.support.customtabs.html" class="hiddenlink" target="rightframe">android.support.customtabs</A><br>
+<!-- Package android.support.design.widget -->
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<!-- Package android.support.v13.app -->
+<A HREF="pkg_android.support.v13.app.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<!-- Package android.support.v4.app -->
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<!-- Package android.support.v4.content -->
+<A HREF="pkg_android.support.v4.content.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<!-- Package android.support.v4.net -->
+<A HREF="pkg_android.support.v4.net.html" class="hiddenlink" target="rightframe">android.support.v4.net</A><br>
+<!-- Package android.support.v4.text -->
+<A HREF="pkg_android.support.v4.text.html" class="hiddenlink" target="rightframe">android.support.v4.text</A><br>
+<!-- Package android.support.v4.view -->
+<A HREF="pkg_android.support.v4.view.html" class="hiddenlink" target="rightframe">android.support.v4.view</A><br>
+<!-- Package android.support.v4.widget -->
+<A HREF="pkg_android.support.v4.widget.html" class="hiddenlink" target="rightframe">android.support.v4.widget</A><br>
+<!-- Package android.support.v7.app -->
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<!-- Package android.support.v7.widget -->
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<!-- Class BidiFormatter -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.text.BidiFormatter.html" class="hiddenlink" target="rightframe">BidiFormatter</A><br>
+<!-- Class ConnectivityManagerCompat -->
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.net.ConnectivityManagerCompat.html" class="hiddenlink" target="rightframe">ConnectivityManagerCompat</A><br>
+<!-- Class ContextCompat -->
+<i>ContextCompat</i><br>
+ <A HREF="android.support.v4.content.ContextCompat.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<!-- Constructor ContextCompat -->
+ <nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.ctor_changed()" class="hiddenlink" target="rightframe">ContextCompat
+()</A></nobr> constructor<br>
+<!-- Class CustomTabsIntent -->
+<A HREF="android.support.customtabs.CustomTabsIntent.html" class="hiddenlink" target="rightframe">CustomTabsIntent</A><br>
+<!-- Class FloatingActionButton -->
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.FloatingActionButton.html" class="hiddenlink" target="rightframe">FloatingActionButton</A><br>
+<!-- Method getReferrer -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)" class="hiddenlink" target="rightframe">getReferrer
+(<code>Activity</code>)</A></nobr><br>
+<!-- Method launchUrl -->
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.customtabs.CustomTabsIntent.html#android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)" class="hiddenlink" target="rightframe">launchUrl
+(<code>Context, Uri</code>)</A></nobr><br>
+<!-- Class NotificationCompat.WearableExtender -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html" class="hiddenlink" target="rightframe">NotificationCompat.WearableExtender</A><br>
+<!-- Class RecyclerView -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<!-- Class RecyclerView.LayoutManager -->
+<A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html" class="hiddenlink" target="rightframe">RecyclerView.LayoutManager</A><br>
+<!-- Method startActivity -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">startActivity
+(<code>Context, Intent, Bundle</code>)</A></nobr><br>
+<!-- Class SwipeRefreshLayout -->
+<A HREF="android.support.v4.widget.SwipeRefreshLayout.html" class="hiddenlink" target="rightframe">SwipeRefreshLayout</A><br>
+<!-- Class ViewCompat -->
+<A NAME="V"></A>
+<br><font size="+2">V</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
+<!-- Class ViewPager -->
+<A HREF="android.support.v4.view.ViewPager.html" class="hiddenlink" target="rightframe">ViewPager</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_removals.html
new file mode 100644
index 0000000..76010db1
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_removals.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+ <br>
+<b>Removals</b>
+ <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Class Space -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#Space" class="hiddenlink" target="rightframe"><strike>Space</strike></A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.customtabs.CustomTabsIntent.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.customtabs.CustomTabsIntent.html
new file mode 100644
index 0000000..891be3d
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.customtabs.CustomTabsIntent.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.customtabs.CustomTabsIntent
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.customtabs.<A HREF="../../../../reference/android/support/customtabs/CustomTabsIntent.html" target="_top"><font size="+2"><code>CustomTabsIntent</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/customtabs/CustomTabsIntent.html#launchUrl(android.content.Context, android.net.Uri)" target="_top"><code>launchUrl</code></A>(<code>Context,</nobr> Uri<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change in signature from (<code>Activity, Uri</code>) to (<code>Context, Uri</code>).<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.design.widget.FloatingActionButton.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.design.widget.FloatingActionButton.html
new file mode 100644
index 0000000..d048222
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.design.widget.FloatingActionButton.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.design.widget.FloatingActionButton
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.design.widget.<A HREF="../../../../reference/android/support/design/widget/FloatingActionButton.html" target="_top"><font size="+2"><code>FloatingActionButton</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.FloatingActionButton.getRippleColor_added()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/design/widget/FloatingActionButton.html#getRippleColor()" target="_top"><code>getRippleColor</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v13.app.ActivityCompat.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v13.app.ActivityCompat.html
new file mode 100644
index 0000000..c11dce2
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v13.app.ActivityCompat.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v13.app.ActivityCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v13.app.<A HREF="../../../../reference/android/support/v13/app/ActivityCompat.html" target="_top"><font size="+2"><code>ActivityCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Constructors" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Constructors</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v13.app.ActivityCompat.ctor_added()"></A>
+ <nobr><A HREF="../../../../reference/android/support/v13/app/ActivityCompat.html#ActivityCompat()" target="_top"><code>ActivityCompat</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.ActivityCompat.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.ActivityCompat.html
new file mode 100644
index 0000000..e728c87
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.ActivityCompat.html
@@ -0,0 +1,154 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app.ActivityCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.app.<A HREF="../../../../reference/android/support/v4/app/ActivityCompat.html" target="_top"><font size="+2"><code>ActivityCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Constructors" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Constructors</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.ActivityCompat.ctor_changed()"></A>
+ <nobr><A HREF="../../../../reference/android/support/v4/app/ActivityCompat.html#ActivityCompat()" target="_top"><code>ActivityCompat</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change from deprecated to undeprecated.<br> Change of visibility from public to protected.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)"></A>
+ <nobr><code>Uri</code> <A HREF="../../../../reference/android/support/v4/app/ActivityCompat.html#getReferrer(android.app.Activity)" target="_top"><code>getReferrer</code></A>(<code>Activity</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change from non-static to static.<br> Change from deprecated to undeprecated.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.ActivityCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/content/ContextCompat.html#startActivity(android.content.Context, android.content.Intent, android.os.Bundle)" target="_top"><code>startActivity</code></A>(<code>Context,</nobr> Intent<nobr>,</nobr> Bundle<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change in signature from (<code>Activity, Intent, Bundle</code>) to (<code>Context, Intent, Bundle</code>).<br>
+ Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v4/content/ContextCompat.html#startActivity(android.content.Context, android.content.Intent, android.os.Bundle)" target="_top"><code>ContextCompat</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.NotificationCompat.WearableExtender.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.NotificationCompat.WearableExtender.html
new file mode 100644
index 0000000..fb9d1fc
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.NotificationCompat.WearableExtender.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app.NotificationCompat.WearableExtender
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.app.<A HREF="../../../../reference/android/support/v4/app/NotificationCompat.WearableExtender.html" target="_top"><font size="+2"><code>NotificationCompat.WearableExtender</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()"></A>
+ <nobr><code>String</code> <A HREF="../../../../reference/android/support/v4/app/NotificationCompat.WearableExtender.html#getBridgeTag()" target="_top"><code>getBridgeTag</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)"></A>
+ <nobr><code>WearableExtender</code> <A HREF="../../../../reference/android/support/v4/app/NotificationCompat.WearableExtender.html#setBridgeTag(java.lang.String)" target="_top"><code>setBridgeTag</code></A>(<code>String</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.content.ContextCompat.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.content.ContextCompat.html
new file mode 100644
index 0000000..ffcebd0
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.content.ContextCompat.html
@@ -0,0 +1,140 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.content.ContextCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.content.<A HREF="../../../../reference/android/support/v4/content/ContextCompat.html" target="_top"><font size="+2"><code>ContextCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Constructors" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Constructors</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.content.ContextCompat.ctor_changed()"></A>
+ <nobr><A HREF="../../../../reference/android/support/v4/content/ContextCompat.html#ContextCompat()" target="_top"><code>ContextCompat</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change from deprecated to undeprecated.<br> Change of visibility from public to protected.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/content/ContextCompat.html#startActivity(android.content.Context, android.content.Intent, android.os.Bundle)" target="_top"><code>startActivity</code></A>(<code>Context,</nobr> Intent<nobr>,</nobr> Bundle<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.net.ConnectivityManagerCompat.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.net.ConnectivityManagerCompat.html
new file mode 100644
index 0000000..f9ca4c0
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.net.ConnectivityManagerCompat.html
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.net.ConnectivityManagerCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.net.<A HREF="../../../../reference/android/support/v4/net/ConnectivityManagerCompat.html" target="_top"><font size="+2"><code>ConnectivityManagerCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/net/ConnectivityManagerCompat.html#getRestrictBackgroundStatus(android.net.ConnectivityManager)" target="_top"><code>getRestrictBackgroundStatus</code></A>(<code>ConnectivityManager</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/net/ConnectivityManagerCompat.html#RESTRICT_BACKGROUND_STATUS_DISABLED" target="_top"><code>RESTRICT_BACKGROUND_STATUS_DISABLED</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/net/ConnectivityManagerCompat.html#RESTRICT_BACKGROUND_STATUS_ENABLED" target="_top"><code>RESTRICT_BACKGROUND_STATUS_ENABLED</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/net/ConnectivityManagerCompat.html#RESTRICT_BACKGROUND_STATUS_WHITELISTED" target="_top"><code>RESTRICT_BACKGROUND_STATUS_WHITELISTED</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.text.BidiFormatter.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.text.BidiFormatter.html
new file mode 100644
index 0000000..63ee221
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.text.BidiFormatter.html
@@ -0,0 +1,150 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.text.BidiFormatter
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.text.<A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html" target="_top"><font size="+2"><code>BidiFormatter</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html#isRtl(java.lang.CharSequence)" target="_top"><code>isRtl</code></A>(<code>CharSequence</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html#unicodeWrap(java.lang.CharSequence)" target="_top"><code>unicodeWrap</code></A>(<code>CharSequence</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html#unicodeWrap(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)" target="_top"><code>unicodeWrap</code></A>(<code>CharSequence,</nobr> TextDirectionHeuristicCompat<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html#unicodeWrap(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)" target="_top"><code>unicodeWrap</code></A>(<code>CharSequence,</nobr> TextDirectionHeuristicCompat<nobr>,</nobr> boolean<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html#unicodeWrap(java.lang.CharSequence, boolean)" target="_top"><code>unicodeWrap</code></A>(<code>CharSequence,</nobr> boolean<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewCompat.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewCompat.html
new file mode 100644
index 0000000..9e99e73
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewCompat.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.view.ViewCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.view.<A HREF="../../../../reference/android/support/v4/view/ViewCompat.html" target="_top"><font size="+2"><code>ViewCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)"></A>
+ <nobr><code>Display</code> <A HREF="../../../../reference/android/support/v4/view/ViewCompat.html#getDisplay(android.view.View)" target="_top"><code>getDisplay</code></A>(<code>View</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/view/ViewCompat.html#setBackground(android.view.View, android.graphics.drawable.Drawable)" target="_top"><code>setBackground</code></A>(<code>View,</nobr> Drawable<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewPager.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewPager.html
new file mode 100644
index 0000000..ca17f87
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewPager.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.view.ViewPager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.view.<A HREF="../../../../reference/android/support/v4/view/ViewPager.html" target="_top"><font size="+2"><code>ViewPager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/view/ViewPager.html#setPageTransformer(boolean, android.support.v4.view.ViewPager.PageTransformer, int)" target="_top"><code>setPageTransformer</code></A>(<code>boolean,</nobr> PageTransformer<nobr>,</nobr> int<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.widget.SwipeRefreshLayout.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.widget.SwipeRefreshLayout.html
new file mode 100644
index 0000000..aca6ab9
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.widget.SwipeRefreshLayout.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.widget.SwipeRefreshLayout
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.widget.<A HREF="../../../../reference/android/support/v4/widget/SwipeRefreshLayout.html" target="_top"><font size="+2"><code>SwipeRefreshLayout</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/widget/SwipeRefreshLayout.html#getProgressViewEndOffset()" target="_top"><code>getProgressViewEndOffset</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/widget/SwipeRefreshLayout.html#getProgressViewStartOffset()" target="_top"><code>getProgressViewStartOffset</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.LayoutManager.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.LayoutManager.html
new file mode 100644
index 0000000..7a5df64
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.LayoutManager.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget.RecyclerView.LayoutManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.widget.<A HREF="../../../../reference/android/support/v7/widget/RecyclerView.LayoutManager.html" target="_top"><font size="+2"><code>RecyclerView.LayoutManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v7/widget/RecyclerView.LayoutManager.html#isItemPrefetchEnabled()" target="_top"><code>isItemPrefetchEnabled</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v7/widget/RecyclerView.LayoutManager.html#setItemPrefetchEnabled(boolean)" target="_top"><code>setItemPrefetchEnabled</code></A>(<code>boolean</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.html
new file mode 100644
index 0000000..af4c24d
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget.RecyclerView
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.widget.<A HREF="../../../../reference/android/support/v7/widget/RecyclerView.html" target="_top"><font size="+2"><code>RecyclerView</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v7/widget/RecyclerView.html#getDecoratedBoundsWithMargins(android.view.View, android.graphics.Rect)" target="_top"><code>getDecoratedBoundsWithMargins</code></A>(<code>View,</nobr> Rect<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/changes-summary.html b/docs/html/sdk/support_api_diff/25.0.0/changes/changes-summary.html
new file mode 100644
index 0000000..d8bd829
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/changes-summary.html
@@ -0,0 +1,220 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Support Library API Differences Report
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<body class="gc-documentation">
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+ <div id="docTitleContainer">
+ <h1>Support Library API Differences Report</h1>
+<p>This report details the changes in the core Android framework API between two <a
+href="https://developer.android.com/guide/appendix/api-levels.html" target="_top">API Level</a>
+specifications. It shows additions, modifications, and removals for packages, classes, methods, and fields.
+The report also includes general statistics that characterize the extent and type of the differences.</p>
+<p>This report is based a comparison of the Android API specifications
+whose API Level identifiers are given in the upper-right corner of this page. It compares a
+newer "to" API to an older "from" API, noting all changes relative to the
+older API. So, for example, API elements marked as removed are no longer present in the "to"
+API specification.</p>
+<p>To navigate the report, use the "Select a Diffs Index" and "Filter the Index"
+controls on the left. The report uses text formatting to indicate <em>interface names</em>,
+<a href= ><code>links to reference documentation</code></a>, and <a href= >links to change
+description</a>. The statistics are accessible from the "Statistics" link in the upper-right corner.</p>
+<p>For more information about the Android framework API and SDK,
+see the <a href="https://developer.android.com/index.html" target="_top">Android Developers site</a>.</p>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Packages" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Packages</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v13.view.inputmethod"></A>
+ <nobr><A HREF="../../../../reference/android/support/v13/view/inputmethod/package-summary.html" target="_top"><code>android.support.v13.view.inputmethod</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Packages" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Packages</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.customtabs"></A>
+ <nobr><A HREF="pkg_android.support.customtabs.html">android.support.customtabs</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget"></A>
+ <nobr><A HREF="pkg_android.support.design.widget.html">android.support.design.widget</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v13.app"></A>
+ <nobr><A HREF="pkg_android.support.v13.app.html">android.support.v13.app</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app"></A>
+ <nobr><A HREF="pkg_android.support.v4.app.html">android.support.v4.app</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.content"></A>
+ <nobr><A HREF="pkg_android.support.v4.content.html">android.support.v4.content</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.net"></A>
+ <nobr><A HREF="pkg_android.support.v4.net.html">android.support.v4.net</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text"></A>
+ <nobr><A HREF="pkg_android.support.v4.text.html">android.support.v4.text</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.view"></A>
+ <nobr><A HREF="pkg_android.support.v4.view.html">android.support.v4.view</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.widget"></A>
+ <nobr><A HREF="pkg_android.support.v4.widget.html">android.support.v4.widget</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.app"></A>
+ <nobr><A HREF="pkg_android.support.v7.app.html">android.support.v7.app</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget"></A>
+ <nobr><A HREF="pkg_android.support.v7.widget.html">android.support.v7.widget</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<!-- End of API section -->
+<!-- Start of packages section -->
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_additions.html
new file mode 100644
index 0000000..c3286a8
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_additions.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+ <br>
+<A HREF="classes_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#N"><font size="-2">N</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView" class="hiddenlink" target="rightframe"><b>BottomNavigationView</b></A><br>
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView.OnNavigationItemSelectedListener" class="hiddenlink" target="rightframe"><b><i>BottomNavigationView.OnNavigationItemSelectedListener</i></b></A><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#N"><font size="-2">N</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#DividerItemDecoration" class="hiddenlink" target="rightframe"><b>DividerItemDecoration</b></A><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedCustomViewStyle</b></A><br>
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedMediaCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedMediaCustomViewStyle</b></A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_all.html
new file mode 100644
index 0000000..6a862ff
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_all.html
@@ -0,0 +1,189 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Classes</b>
+ <br>
+<A HREF="classes_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>ActivityCompat</i><br>
+ <A HREF="android.support.v13.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+ <A HREF="android.support.v4.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.text.BidiFormatter.html" class="hiddenlink" target="rightframe">BidiFormatter</A><br>
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView" class="hiddenlink" target="rightframe"><b>BottomNavigationView</b></A><br>
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView.OnNavigationItemSelectedListener" class="hiddenlink" target="rightframe"><b><i>BottomNavigationView.OnNavigationItemSelectedListener</i></b></A><br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.net.ConnectivityManagerCompat.html" class="hiddenlink" target="rightframe">ConnectivityManagerCompat</A><br>
+<A HREF="android.support.v4.content.ContextCompat.html" class="hiddenlink" target="rightframe">ContextCompat</A><br>
+<A HREF="android.support.customtabs.CustomTabsIntent.html" class="hiddenlink" target="rightframe">CustomTabsIntent</A><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#DividerItemDecoration" class="hiddenlink" target="rightframe"><b>DividerItemDecoration</b></A><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.FloatingActionButton.html" class="hiddenlink" target="rightframe">FloatingActionButton</A><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedCustomViewStyle</b></A><br>
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedMediaCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedMediaCustomViewStyle</b></A><br>
+<A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html" class="hiddenlink" target="rightframe">NotificationCompat.WearableExtender</A><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html" class="hiddenlink" target="rightframe">RecyclerView.LayoutManager</A><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#Space" class="hiddenlink" target="rightframe"><strike>Space</strike></A><br>
+<A HREF="android.support.v4.widget.SwipeRefreshLayout.html" class="hiddenlink" target="rightframe">SwipeRefreshLayout</A><br>
+<A NAME="V"></A>
+<br><font size="+2">V</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
+<A HREF="android.support.v4.view.ViewPager.html" class="hiddenlink" target="rightframe">ViewPager</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_changes.html
new file mode 100644
index 0000000..9881ce6
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_changes.html
@@ -0,0 +1,163 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+ <br>
+<A HREF="classes_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>ActivityCompat</i><br>
+ <A HREF="android.support.v13.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+ <A HREF="android.support.v4.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.text.BidiFormatter.html" class="hiddenlink" target="rightframe">BidiFormatter</A><br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.net.ConnectivityManagerCompat.html" class="hiddenlink" target="rightframe">ConnectivityManagerCompat</A><br>
+<A HREF="android.support.v4.content.ContextCompat.html" class="hiddenlink" target="rightframe">ContextCompat</A><br>
+<A HREF="android.support.customtabs.CustomTabsIntent.html" class="hiddenlink" target="rightframe">CustomTabsIntent</A><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.FloatingActionButton.html" class="hiddenlink" target="rightframe">FloatingActionButton</A><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html" class="hiddenlink" target="rightframe">NotificationCompat.WearableExtender</A><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html" class="hiddenlink" target="rightframe">RecyclerView.LayoutManager</A><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.widget.SwipeRefreshLayout.html" class="hiddenlink" target="rightframe">SwipeRefreshLayout</A><br>
+<A NAME="V"></A>
+<br><font size="+2">V</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
+<A HREF="android.support.v4.view.ViewPager.html" class="hiddenlink" target="rightframe">ViewPager</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_removals.html
new file mode 100644
index 0000000..65dc88b
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_removals.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+ <br>
+<b>Removals</b>
+ <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#Space" class="hiddenlink" target="rightframe"><strike>Space</strike></A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_additions.html
new file mode 100644
index 0000000..b119899
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_additions.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="constructors_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v13.app.ActivityCompat.html#android.support.v13.app.ActivityCompat.ctor_added()" class="hiddenlink" target="rightframe"><b>ActivityCompat</b>
+()</A></nobr> constructor<br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_all.html
new file mode 100644
index 0000000..d19abe3
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_all.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Constructors</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="constructors_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="constructors_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#C"><font size="-2">C</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>ActivityCompat</i><br>
+ <nobr><A HREF="android.support.v13.app.ActivityCompat.html#android.support.v13.app.ActivityCompat.ctor_added()" class="hiddenlink" target="rightframe"><b>ActivityCompat</b>
+()</A></nobr> constructor<br>
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.ctor_changed()" class="hiddenlink" target="rightframe">ActivityCompat
+()</A></nobr> constructor<br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.ctor_changed()" class="hiddenlink" target="rightframe">ContextCompat
+()</A></nobr> constructor<br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_changes.html
new file mode 100644
index 0000000..9c48ca4
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_changes.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="constructors_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#C"><font size="-2">C</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.ctor_changed()" class="hiddenlink" target="rightframe">ActivityCompat
+()</A></nobr> constructor<br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.ctor_changed()" class="hiddenlink" target="rightframe">ContextCompat
+()</A></nobr> constructor<br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_removals.html
new file mode 100644
index 0000000..55afb30
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="constructors_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="constructors_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_additions.html
new file mode 100644
index 0000000..19d2189
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_additions.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<b>Additions</b>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_DISABLED</A>
+</nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_ENABLED</A>
+</nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_WHITELISTED</A>
+</nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_all.html
new file mode 100644
index 0000000..2f658ab
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_all.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Fields</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_DISABLED</A>
+</nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_ENABLED</A>
+</nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_WHITELISTED</A>
+</nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_changes.html
new file mode 100644
index 0000000..f6d9158
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_changes.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_removals.html
new file mode 100644
index 0000000..b16c79f
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_help.html b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_help.html
new file mode 100644
index 0000000..0f826e3
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_help.html
@@ -0,0 +1,134 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+JDiff Help
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<TABLE summary="Navigation bar" BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+ <TABLE summary="Navigation bar" BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../reference/index.html" target="_top"><FONT CLASS="NavBarFont1"><B><code>25.0.0</code></B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="changes-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="jdiff_statistics.html"><FONT CLASS="NavBarFont1"><B>Statistics</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT> </TD>
+ </TR>
+ </TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM><b>Generated by<br><a href="http://www.jdiff.org" class="staysblack" target="_top">JDiff</a></b></EM></TD>
+</TR>
+<TR>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell2"><FONT SIZE="-2"></FONT>
+</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../changes.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="jdiff_help.html" TARGET="_top"><B>NO FRAMES</B></A></FONT></TD>
+</TR>
+</TABLE>
+<HR>
+<!-- End of nav bar -->
+<center>
+<H1>JDiff Documentation</H1>
+</center>
+<BLOCKQUOTE>
+JDiff is a <a href="http://java.sun.com/j2se/javadoc/" target="_top">Javadoc</a> doclet which generates a report of the API differences between two versions of a product. It does not report changes in Javadoc comments, or changes in what a class or method does.
+This help page describes the different parts of the output from JDiff.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+ See the reference page in the <a href="http://www.jdiff.org">source for JDiff</a> for information about how to generate a report like this one.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+The indexes shown in the top-left frame help show each type of change in more detail. The index "All Differences" contains all the differences between the APIs, in alphabetical order.
+These indexes all use the same format:
+<ul>
+<li>Removed packages, classes, constructors, methods and fields are <strike>struck through</strike>.</li>
+<li>Added packages, classes, constructors, methods and fields appear in <b>bold</b>.</li>
+<li>Changed packages, classes, constructors, methods and fields appear in normal text.</li>
+</ul>
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+You can always tell when you are reading a JDiff page, rather than a Javadoc page, by the color of the index bar and the color of the background.
+Links which take you to a Javadoc page are always in a <code>typewriter</code> font.
+Just like Javadoc, all interface names are in <i>italic</i>, and class names are not italicized. Where there are multiple entries in an index with the same name, the heading for them is also in italics, but is not a link.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3><b><code>Javadoc</code></b></H3>
+This is a link to the <a href="../../../../reference/index.html" target="_top">top-level</a> Javadoc page for the new version of the product.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Overview</H3>
+The <a href="changes-summary.html">overview</a> is the top-level summary of what was removed, added and changed between versions.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Package</H3>
+This is a link to the package containing the current changed class or interface.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Class</H3>
+This is highlighted when you are looking at the changed class or interface.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Text Changes</H3>
+This is a link to the top-level index of all documentation changes for the current package or class.
+If it is not present, then there are no documentation changes for the current package or class.
+This link can be removed entirely by not using the <code>-docchanges</code> option.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Statistics</H3>
+This is a link to a page which shows statistics about the changes between the two APIs.
+This link can be removed entirely by not using the <code>-stats</code> option.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Help</H3>
+A link to this Help page for JDiff.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Prev/Next</H3>
+These links take you to the previous and next changed package or class.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Frames/No Frames</H3>
+These links show and hide the HTML frames. All pages are available with or without frames.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H2>Complex Changes</H2>
+There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass.
+In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes.
+</BLOCKQUOTE>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_statistics.html b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_statistics.html
new file mode 100644
index 0000000..de60506
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_statistics.html
@@ -0,0 +1,302 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+API Change Statistics
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<body class="gc-documentation">
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;xborder-bottom:none;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="../changes.html" target="_top">Top of Report</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<h1>API Change Statistics</h1>
+<p>The overall difference between API Levels 24.2.0 and 25.0.0 is approximately <span style="color:222;font-weight:bold;">1.82%</span>.
+</p>
+<br>
+<a name="numbers"></a>
+<h2>Total of Differences, by Number and Type</h2>
+<p>
+The table below lists the numbers of program elements (packages, classes, constructors, methods, and fields) that were added, changed, or removed. The table includes only the highest-level program elements — that is, if a class with two methods was added, the number of methods added does not include those two methods, but the number of classes added does include that class.
+</p>
+<TABLE summary="Number of differences" WIDTH="100%">
+<TR>
+ <th>Type</th>
+ <TH ALIGN="center"><b>Additions</b></TH>
+ <TH ALIGN="center"><b>Changes</b></TH>
+ <TH ALIGN="center">Removals</TH>
+ <TH ALIGN="center"><b>Total</b></TH>
+</TR>
+<TR>
+ <TD>Packages</TD>
+ <TD ALIGN="right">1</TD>
+ <TD ALIGN="right">11</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">12</TD>
+</TR>
+<TR>
+ <TD>Classes and <i>Interfaces</i></TD>
+ <TD ALIGN="right">5</TD>
+ <TD ALIGN="right">13</TD>
+ <TD ALIGN="right">1</TD>
+ <TD ALIGN="right">19</TD>
+</TR>
+<TR>
+ <TD>Constructors</TD>
+ <TD ALIGN="right">1</TD>
+ <TD ALIGN="right">2</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">3</TD>
+</TR>
+<TR>
+ <TD>Methods</TD>
+ <TD ALIGN="right">18</TD>
+ <TD ALIGN="right">3</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">21</TD>
+</TR>
+<TR>
+ <TD>Fields</TD>
+ <TD ALIGN="right">3</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">3</TD>
+</TR>
+<TR>
+ <TD style="background-color:#FAFAFA"><b>Total</b></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>28</strong></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>29</strong></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>1</strong></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>58</strong></TD>
+</TR>
+</TABLE>
+<br>
+<a name="packages"></a>
+<h2>Changed Packages, Sorted by Percentage Difference</h2>
+<TABLE summary="Packages sorted by percentage difference" WIDTH="100%">
+<TR>
+ <TH WIDTH="10%">Percentage Difference*</TH>
+ <TH>Package</TH>
+</TR>
+<TR>
+ <TD ALIGN="center">25</TD>
+ <TD><A HREF="pkg_android.support.v4.net.html">android.support.v4.net</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="pkg_android.support.v13.app.html">android.support.v13.app</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">3</TD>
+ <TD><A HREF="pkg_android.support.v7.app.html">android.support.v7.app</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">3</TD>
+ <TD><A HREF="pkg_android.support.v4.text.html">android.support.v4.text</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="pkg_android.support.design.widget.html">android.support.design.widget</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="pkg_android.support.v7.widget.html">android.support.v7.widget</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v4.content.html">android.support.v4.content</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v4.app.html">android.support.v4.app</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.customtabs.html">android.support.customtabs</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v4.widget.html">android.support.v4.widget</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v4.view.html">android.support.v4.view</A></TD>
+</TR>
+</TABLE>
+<p style="font-size:10px">* See <a href="#calculation">Calculation of Change Percentages</a>, below.</p>
+<br>
+<a name="classes"></a>
+<h2>Changed Classes and <i>Interfaces</i>, Sorted by Percentage Difference</h2>
+<TABLE summary="Classes sorted by percentage difference" WIDTH="100%">
+<TR WIDTH="20%">
+ <TH WIDTH="10%">Percentage<br>Difference*</TH>
+ <TH><b>Class or <i>Interface</i></b></TH>
+</TR>
+<TR>
+ <TD ALIGN="center">50</TD>
+ <TD><A HREF="android.support.v4.net.ConnectivityManagerCompat.html">
+android.support.v4.net.ConnectivityManagerCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">33</TD>
+ <TD><A HREF="android.support.v13.app.ActivityCompat.html">
+android.support.v13.app.ActivityCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">20</TD>
+ <TD><A HREF="android.support.v4.text.BidiFormatter.html">
+android.support.v4.text.BidiFormatter</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">11</TD>
+ <TD><A HREF="android.support.v4.app.ActivityCompat.html">
+android.support.v4.app.ActivityCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">6</TD>
+ <TD><A HREF="android.support.v4.content.ContextCompat.html">
+android.support.v4.content.ContextCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">4</TD>
+ <TD><A HREF="android.support.v4.widget.SwipeRefreshLayout.html">
+android.support.v4.widget.SwipeRefreshLayout</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="android.support.design.widget.FloatingActionButton.html">
+android.support.design.widget.FloatingActionButton</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html">
+android.support.v4.app.NotificationCompat.WearableExtender</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.customtabs.CustomTabsIntent.html">
+android.support.customtabs.CustomTabsIntent</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.v4.view.ViewPager.html">
+android.support.v4.view.ViewPager</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html">
+android.support.v7.widget.RecyclerView.LayoutManager</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="android.support.v4.view.ViewCompat.html">
+android.support.v4.view.ViewCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="android.support.v7.widget.RecyclerView.html">
+android.support.v7.widget.RecyclerView</A></TD>
+</TR>
+</TABLE>
+<p style="font-size:10px">* See <a href="#calculation">Calculation of Change Percentages</a>, below.</p>
+<br>
+<h2 id="calculation">Calculation of Change Percentages</h2>
+<p>
+The percent change statistic reported for all elements in the "to" API Level specification is defined recursively as follows:</p>
+<pre>
+Percentage difference = 100 * (added + removed + 2*changed)
+ -----------------------------------
+ sum of public elements in BOTH APIs
+</pre>
+<p>where <code>added</code> is the number of packages added, <code>removed</code> is the number of packages removed, and <code>changed</code> is the number of packages changed.
+This definition is applied recursively for the classes and their program elements, so the value for a changed package will be less than 1, unless every class in that package has changed.
+The definition ensures that if all packages are removed and all new packages are
+added, the change will be 100%.</p>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY></HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_topleftframe.html b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_topleftframe.html
new file mode 100644
index 0000000..4368791
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_topleftframe.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Android API Version Differences
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<table class="jdiffIndex" summary="Links to diff index files" BORDER="0" WIDTH="100%" cellspacing="0" cellpadding="0" style="margin:0">
+<TR>
+ <th class="indexHeader" nowrap>
+ Select a Diffs Index:</th>
+</TR>
+<TR>
+ <TD><FONT CLASS="indexText" size="-2"><A HREF="alldiffs_index_all.html" TARGET="bottomleftframe">All Differences</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="packages_index_all.html" TARGET="bottomleftframe">By Package</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="classes_index_all.html" TARGET="bottomleftframe">By Class</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="constructors_index_all.html" TARGET="bottomleftframe">By Constructor</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="methods_index_all.html" TARGET="bottomleftframe">By Method</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="fields_index_all.html" TARGET="bottomleftframe">By Field</A></FONT><br></TD>
+</TR>
+</TABLE>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_additions.html
new file mode 100644
index 0000000..0ef8e0d
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_additions.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()" class="hiddenlink" target="rightframe"><b>getBridgeTag</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getDecoratedBoundsWithMargins</b>
+(<code>View, Rect</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)" class="hiddenlink" target="rightframe"><b>getDisplay</b>
+(<code>View</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewEndOffset</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewStartOffset</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)" class="hiddenlink" target="rightframe"><b>getRestrictBackgroundStatus</b>
+(<code>ConnectivityManager</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.FloatingActionButton.html#android.support.design.widget.FloatingActionButton.getRippleColor_added()" class="hiddenlink" target="rightframe"><b>getRippleColor</b>
+()</A></nobr><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()" class="hiddenlink" target="rightframe"><b>isItemPrefetchEnabled</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>isRtl</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe"><b>setBackground</b>
+(<code>View, Drawable</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)" class="hiddenlink" target="rightframe"><b>setBridgeTag</b>
+(<code>String</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)" class="hiddenlink" target="rightframe"><b>setItemPrefetchEnabled</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.view.ViewPager.html#android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)" class="hiddenlink" target="rightframe"><b>setPageTransformer</b>
+(<code>boolean, PageTransformer, int</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>startActivity</b>
+(<code>Context, Intent, Bundle</code>)</A></nobr><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>unicodeWrap</i><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_all.html
new file mode 100644
index 0000000..08df085
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_all.html
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Methods</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()" class="hiddenlink" target="rightframe"><b>getBridgeTag</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getDecoratedBoundsWithMargins</b>
+(<code>View, Rect</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)" class="hiddenlink" target="rightframe"><b>getDisplay</b>
+(<code>View</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewEndOffset</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewStartOffset</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)" class="hiddenlink" target="rightframe">getReferrer
+(<code>Activity</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)" class="hiddenlink" target="rightframe"><b>getRestrictBackgroundStatus</b>
+(<code>ConnectivityManager</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.FloatingActionButton.html#android.support.design.widget.FloatingActionButton.getRippleColor_added()" class="hiddenlink" target="rightframe"><b>getRippleColor</b>
+()</A></nobr><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()" class="hiddenlink" target="rightframe"><b>isItemPrefetchEnabled</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>isRtl</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.customtabs.CustomTabsIntent.html#android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)" class="hiddenlink" target="rightframe">launchUrl
+(<code>Context, Uri</code>)</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe"><b>setBackground</b>
+(<code>View, Drawable</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)" class="hiddenlink" target="rightframe"><b>setBridgeTag</b>
+(<code>String</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)" class="hiddenlink" target="rightframe"><b>setItemPrefetchEnabled</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.view.ViewPager.html#android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)" class="hiddenlink" target="rightframe"><b>setPageTransformer</b>
+(<code>boolean, PageTransformer, int</code>)</A></nobr><br>
+<i>startActivity</i><br>
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">type
+(<code>Context, Intent, Bundle</code>) in android.support.v4.app.ActivityCompat
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">type <b>
+(<code>Context, Intent, Bundle</code>)</b> in android.support.v4.content.ContextCompat
+</A></nobr><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>unicodeWrap</i><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_changes.html
new file mode 100644
index 0000000..b2aae91
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_changes.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)" class="hiddenlink" target="rightframe">getReferrer
+(<code>Activity</code>)</A></nobr><br>
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.customtabs.CustomTabsIntent.html#android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)" class="hiddenlink" target="rightframe">launchUrl
+(<code>Context, Uri</code>)</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">startActivity
+(<code>Context, Intent, Bundle</code>)</A></nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_removals.html
new file mode 100644
index 0000000..d88010f
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_additions.html
new file mode 100644
index 0000000..bcbbaf0
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_additions.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<A NAME="A"></A>
+<A HREF="changes-summary.html#android.support.v13.view.inputmethod" class="hiddenlink" target="rightframe"><b>android.support.v13.view.inputmethod</b></A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_all.html
new file mode 100644
index 0000000..bfadc87
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_all.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Packages</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="packages_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<A NAME="A"></A>
+<A HREF="pkg_android.support.customtabs.html" class="hiddenlink" target="rightframe">android.support.customtabs</A><br>
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<A HREF="pkg_android.support.v13.app.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<A HREF="changes-summary.html#android.support.v13.view.inputmethod" class="hiddenlink" target="rightframe"><b>android.support.v13.view.inputmethod</b></A><br>
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<A HREF="pkg_android.support.v4.content.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<A HREF="pkg_android.support.v4.net.html" class="hiddenlink" target="rightframe">android.support.v4.net</A><br>
+<A HREF="pkg_android.support.v4.text.html" class="hiddenlink" target="rightframe">android.support.v4.text</A><br>
+<A HREF="pkg_android.support.v4.view.html" class="hiddenlink" target="rightframe">android.support.v4.view</A><br>
+<A HREF="pkg_android.support.v4.widget.html" class="hiddenlink" target="rightframe">android.support.v4.widget</A><br>
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_changes.html
new file mode 100644
index 0000000..df27300
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_changes.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="packages_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<A NAME="A"></A>
+<A HREF="pkg_android.support.customtabs.html" class="hiddenlink" target="rightframe">android.support.customtabs</A><br>
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<A HREF="pkg_android.support.v13.app.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<A HREF="pkg_android.support.v4.content.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<A HREF="pkg_android.support.v4.net.html" class="hiddenlink" target="rightframe">android.support.v4.net</A><br>
+<A HREF="pkg_android.support.v4.text.html" class="hiddenlink" target="rightframe">android.support.v4.text</A><br>
+<A HREF="pkg_android.support.v4.view.html" class="hiddenlink" target="rightframe">android.support.v4.view</A><br>
+<A HREF="pkg_android.support.v4.widget.html" class="hiddenlink" target="rightframe">android.support.v4.widget</A><br>
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_removals.html
new file mode 100644
index 0000000..c91155c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_removals.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="packages_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.customtabs.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.customtabs.html
new file mode 100644
index 0000000..7e1276d
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.customtabs.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.customtabs
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/customtabs/package-summary.html" target="_top"><font size="+1"><code>android.support.customtabs</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="CustomTabsIntent"></A>
+ <nobr><A HREF="android.support.customtabs.CustomTabsIntent.html">CustomTabsIntent</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.design.widget.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.design.widget.html
new file mode 100644
index 0000000..e7326e7
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.design.widget.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.design.widget
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/design/widget/package-summary.html" target="_top"><font size="+1"><code>android.support.design.widget</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes and Interfaces" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes and Interfaces</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BottomNavigationView"></A>
+ <nobr><A HREF="../../../../reference/android/support/design/widget/BottomNavigationView.html" target="_top"><code>BottomNavigationView</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BottomNavigationView.OnNavigationItemSelectedListener"></A>
+ <nobr><A HREF="../../../../reference/android/support/design/widget/BottomNavigationView.OnNavigationItemSelectedListener.html" target="_top"><code><I>BottomNavigationView.<br>OnNavigationItemSelectedListener</I></code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="FloatingActionButton"></A>
+ <nobr><A HREF="android.support.design.widget.FloatingActionButton.html">FloatingActionButton</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v13.app.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v13.app.html
new file mode 100644
index 0000000..5f9d84e
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v13.app.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v13.app
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v13/app/package-summary.html" target="_top"><font size="+1"><code>android.support.v13.app</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ActivityCompat"></A>
+ <nobr><A HREF="android.support.v13.app.ActivityCompat.html">ActivityCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.app.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.app.html
new file mode 100644
index 0000000..4ebfbdd
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.app.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/app/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.app</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ActivityCompat"></A>
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html">ActivityCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="NotificationCompat.WearableExtender"></A>
+ <nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html">NotificationCompat.WearableExtender</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.content.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.content.html
new file mode 100644
index 0000000..a5e7ef8
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.content.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.content
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/content/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.content</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ContextCompat"></A>
+ <nobr><A HREF="android.support.v4.content.ContextCompat.html">ContextCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.net.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.net.html
new file mode 100644
index 0000000..978acb2
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.net.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.net
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/net/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.net</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ConnectivityManagerCompat"></A>
+ <nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html">ConnectivityManagerCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.text.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.text.html
new file mode 100644
index 0000000..821ac23
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.text.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.text
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/text/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.text</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BidiFormatter"></A>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html">BidiFormatter</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.view.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.view.html
new file mode 100644
index 0000000..062bb90
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.view.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.view
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/view/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.view</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ViewCompat"></A>
+ <nobr><A HREF="android.support.v4.view.ViewCompat.html">ViewCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ViewPager"></A>
+ <nobr><A HREF="android.support.v4.view.ViewPager.html">ViewPager</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.widget.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.widget.html
new file mode 100644
index 0000000..7c6be7a
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.widget.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.widget
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/widget/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.widget</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="SwipeRefreshLayout"></A>
+ <nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html">SwipeRefreshLayout</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.app.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.app.html
new file mode 100644
index 0000000..eaf702c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.app.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.app
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v7/app/package-summary.html" target="_top"><font size="+1"><code>android.support.v7.app</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="NotificationCompat.DecoratedCustomViewStyle"></A>
+ <nobr><A HREF="../../../../reference/android/support/v7/app/NotificationCompat.DecoratedCustomViewStyle.html" target="_top"><code>NotificationCompat.DecoratedCustomViewStyle</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="NotificationCompat.DecoratedMediaCustomViewStyle"></A>
+ <nobr><A HREF="../../../../reference/android/support/v7/app/NotificationCompat.DecoratedMediaCustomViewStyle.html" target="_top"><code>NotificationCompat.DecoratedMediaCustomViewStyle</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.widget.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.widget.html
new file mode 100644
index 0000000..d6c4f12
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.widget.html
@@ -0,0 +1,156 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v7/widget/package-summary.html" target="_top"><font size="+1"><code>android.support.v7.widget</code></font></A>
+</H2>
+<p>
+<a NAME="Removed"></a>
+<TABLE summary="Removed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Removed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="Space"></A>
+ Space
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="DividerItemDecoration"></A>
+ <nobr><A HREF="../../../../reference/android/support/v7/widget/DividerItemDecoration.html" target="_top"><code>DividerItemDecoration</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="RecyclerView"></A>
+ <nobr><A HREF="android.support.v7.widget.RecyclerView.html">RecyclerView</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="RecyclerView.LayoutManager"></A>
+ <nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html">RecyclerView.LayoutManager</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/missingSinces.txt b/docs/html/sdk/support_api_diff/25.0.0/missingSinces.txt
new file mode 100644
index 0000000..5d93bd9
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/missingSinces.txt
@@ -0,0 +1,27 @@
+NO DOC BLOCK: android.support.design.widget.BottomNavigationView Class
+NO DOC BLOCK: android.support.design.widget.BottomNavigationView.OnNavigationItemSelectedListener Interface
+NO DOC BLOCK: android.support.v7.widget.DividerItemDecoration Class
+NO DOC BLOCK: android.support.v7.app.NotificationCompat.DecoratedCustomViewStyle Class
+NO DOC BLOCK: android.support.v7.app.NotificationCompat.DecoratedMediaCustomViewStyle Class
+NO DOC BLOCK: android.support.v13.app.ActivityCompat Constructor ()
+NO DOC BLOCK: android.support.v4.app.NotificationCompat.WearableExtender Method getBridgeTag()
+NO DOC BLOCK: android.support.v7.widget.RecyclerView Method getDecoratedBoundsWithMargins(android.view.View, android.graphics.Rect)
+NO DOC BLOCK: android.support.v4.view.ViewCompat Method getDisplay(android.view.View)
+NO DOC BLOCK: android.support.v4.widget.SwipeRefreshLayout Method getProgressViewEndOffset()
+NO DOC BLOCK: android.support.v4.widget.SwipeRefreshLayout Method getProgressViewStartOffset()
+NO DOC BLOCK: android.support.v4.net.ConnectivityManagerCompat Method getRestrictBackgroundStatus(android.net.ConnectivityManager)
+NO DOC BLOCK: android.support.design.widget.FloatingActionButton Method getRippleColor()
+NO DOC BLOCK: android.support.v7.widget.RecyclerView.LayoutManager Method isItemPrefetchEnabled()
+NO DOC BLOCK: android.support.v4.text.BidiFormatter Method isRtl(java.lang.CharSequence)
+NO DOC BLOCK: android.support.v4.view.ViewCompat Method setBackground(android.view.View, android.graphics.drawable.Drawable)
+NO DOC BLOCK: android.support.v4.app.NotificationCompat.WearableExtender Method setBridgeTag(java.lang.String)
+NO DOC BLOCK: android.support.v7.widget.RecyclerView.LayoutManager Method setItemPrefetchEnabled(boolean)
+NO DOC BLOCK: android.support.v4.view.ViewPager Method setPageTransformer(boolean, android.support.v4.view.ViewPager.PageTransformer, int)
+NO DOC BLOCK: android.support.v4.content.ContextCompat Method startActivity(android.content.Context, android.content.Intent, android.os.Bundle)
+NO DOC BLOCK: android.support.v4.text.BidiFormatter Method unicodeWrap(java.lang.CharSequence)
+NO DOC BLOCK: android.support.v4.text.BidiFormatter Method unicodeWrap(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)
+NO DOC BLOCK: android.support.v4.text.BidiFormatter Method unicodeWrap(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)
+NO DOC BLOCK: android.support.v4.text.BidiFormatter Method unicodeWrap(java.lang.CharSequence, boolean)
+NO DOC BLOCK: android.support.v4.net.ConnectivityManagerCompat Field RESTRICT_BACKGROUND_STATUS_DISABLED
+NO DOC BLOCK: android.support.v4.net.ConnectivityManagerCompat Field RESTRICT_BACKGROUND_STATUS_ENABLED
+NO DOC BLOCK: android.support.v4.net.ConnectivityManagerCompat Field RESTRICT_BACKGROUND_STATUS_WHITELISTED
diff --git a/docs/html/sdk/support_api_diff/25.0.0/stylesheet-jdiff.css b/docs/html/sdk/support_api_diff/25.0.0/stylesheet-jdiff.css
new file mode 100644
index 0000000..edafaa3
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/stylesheet-jdiff.css
@@ -0,0 +1,44 @@
+
+/* (http://www.jdiff.org) */
+
+div.and-diff-id {border: 1px solid #eee;position:relative;float:right;clear:both;padding:0px;}
+table.diffspectable {border:1px;padding:0px;margin:0px;}
+.diffspechead {background-color:#eee;}
+.diffspectable tr {border:0px;padding:0px;}
+.diffspectable td {background-color:eee;border:0px;font-size:90%;font-weight:normal;padding:0px;padding-left:1px;padding-right:1px;text-align:center;color:777;}
+td.diffvalueold {color:orange;background-color:white;border:0px;font-size:80%;font-style:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffvaluenew {color:green;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffvalue {color:444;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffspec {background-color:white;border:0px;font-size:80%;font-weight:normal;padding:1px;color:444;text-align:right;padding-right:.5em;line-height:.95em;}
+tt {font-size:11pt;font-family:monospace;}
+.indexHeader {
+ font-size:96%;
+ line-height:.8em;}
+.jdiffIndex td {
+ font-size:96%;
+ xline-height:.8em;
+ padding:2px;
+ padding-left:1em;}
+.indexText {
+ font-size:100%;
+ padding-left:1em;}
+#indexTableCaption {
+ font-size:96%;
+ margin-top:.25em;
+ margin-bottom:0;
+ }
+.hiddenlink {
+ font-size:96%;
+ line-height:.8em;
+ text-decoration:none;}
+a {
+ text-decoration:none;}
+a:hover {
+ text-decoration:underline;}
+.indexBox {
+ border: 1px solid red;
+ margin:1em 0 0 0;}
+.letterIndexHead {
+ font-size: 1.5em;font-weight:9;
+ margin:0 0 0em 0;
+ border: 1px solid red;}
diff --git a/docs/html/sdk/support_api_diff/25.0.0/user_comments_for_24.2.0_to_25.0.0.xml b/docs/html/sdk/support_api_diff/25.0.0/user_comments_for_24.2.0_to_25.0.0.xml
new file mode 100644
index 0000000..9091eb6
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/user_comments_for_24.2.0_to_25.0.0.xml
@@ -0,0 +1,379 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
+<comments
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xsi:noNamespaceSchemaLocation='comments.xsd'
+ name="24.2.0_to_25.0.0"
+ jdversion="1.1.0">
+
+<!-- Use this file to enter an API change description. For example, when you remove a class,
+ you can enter a comment for that class that points developers to the replacement class.
+ You can also provide a change summary for modified API, to give an overview of the changes
+ why they were made, workarounds, etc. -->
+
+<!-- When the API diffs report is generated, the comments in this file get added to the tables of
+ removed, added, and modified packages, classes, methods, and fields. This file does not ship
+ with the final report. -->
+
+<!-- The id attribute in an identifier element identifies the change as noted in the report.
+ An id has the form package[.class[.[ctor|method|field].signature]], where [] indicates optional
+ text. A comment element can have multiple identifier elements, which will will cause the same
+ text to appear at each place in the report, but will be converted to separate comments when the
+ comments file is used. -->
+
+<!-- HTML tags in the text field will appear in the report. You also need to close p HTML elements,
+ used for paragraphs - see the top-level documentation. -->
+
+<!-- You can include standard javadoc links in your change descriptions. You can use the @first command
+ to cause jdiff to include the first line of the API documentation. You also need to close p HTML
+ elements, used for paragraphs - see the top-level documentation. -->
+
+<comment>
+ <identifier id="android.support.customtabs"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.customtabs.CustomTabsIntent"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BottomNavigationView"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BottomNavigationView.OnNavigationItemSelectedListener"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.FloatingActionButton"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.FloatingActionButton.getRippleColor_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v13.app"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v13.app.ActivityCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v13.app.ActivityCompat.ctor_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v13.view.inputmethod"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.ActivityCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.ActivityCompat.ctor_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.NotificationCompat.WearableExtender"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.content"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.content.ContextCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.content.ContextCompat.ctor_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.content.ContextCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net.ConnectivityManagerCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view.ViewCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view.ViewPager"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.widget"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.widget.SwipeRefreshLayout"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.app"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.app.NotificationCompat.DecoratedCustomViewStyle"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.app.NotificationCompat.DecoratedMediaCustomViewStyle"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.DividerItemDecoration"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.LayoutManager"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.Space"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+
+</comments>
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 069f81b..9490436 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -155,7 +155,7 @@
@VisibleForTesting
public static int makeTag(char c1, char c2, char c3, char c4) {
- return (c1 << 24) + (c2 << 16) + (c3 << 8) + c4;
+ return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4;
}
private static boolean isSpacer(char c) {
@@ -228,8 +228,10 @@
return new Font(fullFilename, index, axes, weight, isItalic);
}
- /** The 'tag' attribute value is read as four character values between 0 and 255 inclusive. */
- private static final Pattern TAG_PATTERN = Pattern.compile("[\\x00-\\xFF]{4}");
+ /** The 'tag' attribute value is read as four character values between U+0020 and U+007E
+ * inclusive.
+ */
+ private static final Pattern TAG_PATTERN = Pattern.compile("[\\x20-\\x7E]{4}");
/** The 'styleValue' attribute has an optional leading '-', followed by '<digits>',
* '<digits>.<digits>', or '.<digits>' where '<digits>' is one or more of [0-9].
diff --git a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
index e4d6aa8..d046c11 100644
--- a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
+++ b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
@@ -105,9 +105,18 @@
}
@SmallTest
+ public void testInvalidTagCharacters() {
+ FontListParser.Axis[] axis =
+ FontListParser.parseFontVariationSettings("'\u0000\u0000\u0000\u0000' 10");
+ assertEquals(0, axis.length);
+ axis = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10");
+ assertEquals(0, axis.length);
+ }
+
+ @SmallTest
public void testMakeTag() {
assertEquals(0x77647468, FontListParser.makeTag('w', 'd', 't', 'h'));
assertEquals(0x41582020, FontListParser.makeTag('A', 'X', ' ', ' '));
assertEquals(0x20202020, FontListParser.makeTag(' ', ' ', ' ', ' '));
}
-}
\ No newline at end of file
+}
diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk
index fe5d8ca..7bab189 100644
--- a/legacy-test/Android.mk
+++ b/legacy-test/Android.mk
@@ -21,9 +21,22 @@
# This contains the junit.framework classes that were in Android API level 25.
include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_MODULE := legacy-test
LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
LOCAL_STATIC_JAVA_LIBRARIES := core-junit-static
-LOCAL_MODULE := legacy-test
-
include $(BUILD_JAVA_LIBRARY)
+
+ifeq ($(HOST_OS),linux)
+# Build the legacy-performance-test-hostdex library
+# =================================================
+# This contains the android.test.PerformanceTestCase class only
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := src/android/test/PerformanceTestCase.java
+LOCAL_MODULE := legacy-performance-test-hostdex
+
+include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
+endif # HOST_OS == linux
diff --git a/core/java/android/test/AndroidTestCase.java b/legacy-test/src/android/test/AndroidTestCase.java
similarity index 100%
rename from core/java/android/test/AndroidTestCase.java
rename to legacy-test/src/android/test/AndroidTestCase.java
diff --git a/core/java/android/test/FlakyTest.java b/legacy-test/src/android/test/FlakyTest.java
similarity index 100%
rename from core/java/android/test/FlakyTest.java
rename to legacy-test/src/android/test/FlakyTest.java
diff --git a/core/java/android/test/InstrumentationTestCase.java b/legacy-test/src/android/test/InstrumentationTestCase.java
similarity index 100%
rename from core/java/android/test/InstrumentationTestCase.java
rename to legacy-test/src/android/test/InstrumentationTestCase.java
diff --git a/core/java/android/test/InstrumentationTestSuite.java b/legacy-test/src/android/test/InstrumentationTestSuite.java
similarity index 100%
rename from core/java/android/test/InstrumentationTestSuite.java
rename to legacy-test/src/android/test/InstrumentationTestSuite.java
diff --git a/core/java/android/test/PerformanceTestCase.java b/legacy-test/src/android/test/PerformanceTestCase.java
similarity index 100%
rename from core/java/android/test/PerformanceTestCase.java
rename to legacy-test/src/android/test/PerformanceTestCase.java
diff --git a/core/java/android/test/RepetitiveTest.java b/legacy-test/src/android/test/RepetitiveTest.java
similarity index 100%
rename from core/java/android/test/RepetitiveTest.java
rename to legacy-test/src/android/test/RepetitiveTest.java
diff --git a/core/java/android/test/UiThreadTest.java b/legacy-test/src/android/test/UiThreadTest.java
similarity index 100%
rename from core/java/android/test/UiThreadTest.java
rename to legacy-test/src/android/test/UiThreadTest.java
diff --git a/core/java/android/test/package.html b/legacy-test/src/android/test/package.html
similarity index 100%
rename from core/java/android/test/package.html
rename to legacy-test/src/android/test/package.html
diff --git a/core/java/android/test/suitebuilder/annotation/LargeTest.java b/legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java
similarity index 100%
rename from core/java/android/test/suitebuilder/annotation/LargeTest.java
rename to legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java
diff --git a/core/java/android/test/suitebuilder/annotation/MediumTest.java b/legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java
similarity index 100%
rename from core/java/android/test/suitebuilder/annotation/MediumTest.java
rename to legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java
diff --git a/core/java/android/test/suitebuilder/annotation/SmallTest.java b/legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java
similarity index 100%
rename from core/java/android/test/suitebuilder/annotation/SmallTest.java
rename to legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java
diff --git a/core/java/android/test/suitebuilder/annotation/Smoke.java b/legacy-test/src/android/test/suitebuilder/annotation/Smoke.java
similarity index 100%
rename from core/java/android/test/suitebuilder/annotation/Smoke.java
rename to legacy-test/src/android/test/suitebuilder/annotation/Smoke.java
diff --git a/core/java/android/test/suitebuilder/annotation/Suppress.java b/legacy-test/src/android/test/suitebuilder/annotation/Suppress.java
similarity index 100%
rename from core/java/android/test/suitebuilder/annotation/Suppress.java
rename to legacy-test/src/android/test/suitebuilder/annotation/Suppress.java
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
new file mode 100644
index 0000000..d501d25
--- /dev/null
+++ b/libs/androidfw/Android.bp
@@ -0,0 +1,74 @@
+// Copyright (C) 2010 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.
+
+// libandroidfw is partially built for the host (used by obbtool, aapt, and others)
+
+cc_library {
+ name: "libandroidfw",
+ host_supported: true,
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+ srcs: [
+ "Asset.cpp",
+ "AssetDir.cpp",
+ "AssetManager.cpp",
+ "AttributeResolution.cpp",
+ "LocaleData.cpp",
+ "misc.cpp",
+ "ObbFile.cpp",
+ "ResourceTypes.cpp",
+ "StreamingZipInflater.cpp",
+ "TypeWrappers.cpp",
+ "ZipFileRO.cpp",
+ "ZipUtils.cpp",
+ ],
+ export_include_dirs: ["include"],
+ target: {
+ android: {
+ srcs: [
+ "BackupData.cpp",
+ "BackupHelpers.cpp",
+ "CursorWindow.cpp",
+ "DisplayEventDispatcher.cpp",
+ ],
+ shared_libs: [
+ "libziparchive",
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libcutils",
+ "libgui",
+ "libutils",
+ "libz",
+ ],
+ static: {
+ enabled: false,
+ },
+ },
+ host: {
+ cflags: ["-DSTATIC_ANDROIDFW_FOR_TOOLS"],
+ shared: {
+ enabled: false,
+ },
+ shared_libs: ["libz-host"],
+ },
+ windows: {
+ enabled: true,
+ },
+ },
+}
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk
index 7689256..68c51ef 100644
--- a/libs/androidfw/Android.mk
+++ b/libs/androidfw/Android.mk
@@ -14,74 +14,6 @@
LOCAL_PATH:= $(call my-dir)
-# libandroidfw is partially built for the host (used by obbtool, aapt, and others)
-# These files are common to host and target builds.
-
-commonSources := \
- Asset.cpp \
- AssetDir.cpp \
- AssetManager.cpp \
- AttributeResolution.cpp \
- LocaleData.cpp \
- misc.cpp \
- ObbFile.cpp \
- ResourceTypes.cpp \
- StreamingZipInflater.cpp \
- TypeWrappers.cpp \
- ZipFileRO.cpp \
- ZipUtils.cpp
-
-deviceSources := \
- $(commonSources) \
- BackupData.cpp \
- BackupHelpers.cpp \
- CursorWindow.cpp \
- DisplayEventDispatcher.cpp
-
-hostSources := $(commonSources)
-
-# For the host
-# =====================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= libandroidfw
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-LOCAL_SRC_FILES:= $(hostSources)
-LOCAL_C_INCLUDES := external/zlib
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-
-# For the device
-# =====================================================
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= libandroidfw
-LOCAL_SRC_FILES:= $(deviceSources)
-LOCAL_C_INCLUDES := \
- system/core/include
-LOCAL_SHARED_LIBRARIES := \
- libziparchive \
- libbase \
- libbinder \
- liblog \
- libcutils \
- libgui \
- libutils \
- libz
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_SHARED_LIBRARY)
-
-
# Include subdirectory makefiles
# ============================================================
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index 00f7a42..f5aef05 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -14,34 +14,41 @@
* limitations under the License.
*/
-#include "AttributeFinder.h"
-
#include "androidfw/AttributeResolution.h"
-#include "androidfw/ResourceTypes.h"
+
+#include <cstdint>
#include <android/log.h>
-#include <cstdint>
+
+#include "androidfw/AttributeFinder.h"
+#include "androidfw/ResourceTypes.h"
constexpr bool kDebugStyles = false;
namespace android {
-class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, size_t> {
+class XmlAttributeFinder
+ : public BackTrackingAttributeFinder<XmlAttributeFinder, size_t> {
public:
explicit XmlAttributeFinder(const ResXMLParser* parser)
- : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0),
+ : BackTrackingAttributeFinder(
+ 0, parser != nullptr ? parser->getAttributeCount() : 0),
parser_(parser) {}
- inline uint32_t GetAttribute(size_t index) const { return parser_->getAttributeNameResID(index); }
+ inline uint32_t GetAttribute(size_t index) const {
+ return parser_->getAttributeNameResID(index);
+ }
private:
const ResXMLParser* parser_;
};
class BagAttributeFinder
- : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
+ : public BackTrackingAttributeFinder<BagAttributeFinder,
+ const ResTable::bag_entry*> {
public:
- BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
+ BagAttributeFinder(const ResTable::bag_entry* start,
+ const ResTable::bag_entry* end)
: BackTrackingAttributeFinder(start, end) {}
inline uint32_t GetAttribute(const ResTable::bag_entry* entry) const {
@@ -49,12 +56,14 @@
}
};
-bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr, uint32_t def_style_res,
- uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
- size_t attrs_length, uint32_t* out_values, uint32_t* out_indices) {
+bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
+ uint32_t def_style_res, uint32_t* src_values,
+ size_t src_values_length, uint32_t* attrs,
+ size_t attrs_length, uint32_t* out_values,
+ uint32_t* out_indices) {
if (kDebugStyles) {
- ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme, def_style_attr,
- def_style_res);
+ ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme,
+ def_style_attr, def_style_res);
}
const ResTable& res = theme->getResTable();
@@ -67,7 +76,8 @@
uint32_t def_style_bag_type_set_flags = 0;
if (def_style_attr != 0) {
Res_value value;
- if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) {
+ if (theme->getAttribute(def_style_attr, &value,
+ &def_style_bag_type_set_flags) >= 0) {
if (value.dataType == Res_value::TYPE_REFERENCE) {
def_style_res = value.data;
}
@@ -78,14 +88,15 @@
res.lock();
// Retrieve the default style bag, if requested.
- const ResTable::bag_entry* def_style_start = NULL;
+ const ResTable::bag_entry* def_style_start = nullptr;
uint32_t def_style_type_set_flags = 0;
- ssize_t bag_off =
- def_style_res != 0
- ? res.getBagLocked(def_style_res, &def_style_start, &def_style_type_set_flags)
- : -1;
+ ssize_t bag_off = def_style_res != 0
+ ? res.getBagLocked(def_style_res, &def_style_start,
+ &def_style_type_set_flags)
+ : -1;
def_style_type_set_flags |= def_style_bag_type_set_flags;
- const ResTable::bag_entry* const def_style_end = def_style_start + (bag_off >= 0 ? bag_off : 0);
+ const ResTable::bag_entry* const def_style_end =
+ def_style_start + (bag_off >= 0 ? bag_off : 0);
BagAttributeFinder def_style_attr_finder(def_style_start, def_style_end);
// Now iterate through all of the attributes that the client has requested,
@@ -113,18 +124,21 @@
value.dataType = Res_value::TYPE_ATTRIBUTE;
value.data = src_values[ii];
if (kDebugStyles) {
- ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
if (value.dataType == Res_value::TYPE_NULL) {
- const ResTable::bag_entry* const def_style_entry = def_style_attr_finder.Find(cur_ident);
+ const ResTable::bag_entry* const def_style_entry =
+ def_style_attr_finder.Find(cur_ident);
if (def_style_entry != def_style_end) {
block = def_style_entry->stringBlock;
type_set_flags = def_style_type_set_flags;
value = def_style_entry->map.value;
if (kDebugStyles) {
- ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
}
@@ -132,24 +146,29 @@
uint32_t resid = 0;
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
- ssize_t new_block =
- theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
+ ssize_t new_block = theme->resolveAttributeReference(
+ &value, block, &resid, &type_set_flags, &config);
if (new_block >= 0) block = new_block;
if (kDebugStyles) {
- ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
} else {
// If we still don't have a value for this attribute, try to find
// it in the theme!
- ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
+ ssize_t new_block =
+ theme->getAttribute(cur_ident, &value, &type_set_flags);
if (new_block >= 0) {
if (kDebugStyles) {
- ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
- new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
+ new_block = res.resolveReference(&value, new_block, &resid,
+ &type_set_flags, &config);
if (new_block >= 0) block = new_block;
if (kDebugStyles) {
- ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
}
@@ -165,19 +184,21 @@
}
if (kDebugStyles) {
- ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
+ ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident,
+ value.dataType, value.data);
}
// Write the final value back to Java.
out_values[STYLE_TYPE] = value.dataType;
out_values[STYLE_DATA] = value.data;
out_values[STYLE_ASSET_COOKIE] =
- block != -1 ? static_cast<uint32_t>(res.getTableCookie(block)) : static_cast<uint32_t>(-1);
+ block != -1 ? static_cast<uint32_t>(res.getTableCookie(block))
+ : static_cast<uint32_t>(-1);
out_values[STYLE_RESOURCE_ID] = resid;
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
- if (out_indices != NULL && value.dataType != Res_value::TYPE_NULL) {
+ if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
indices_idx++;
out_indices[indices_idx] = ii;
}
@@ -187,18 +208,18 @@
res.unlock();
- if (out_indices != NULL) {
+ if (out_indices != nullptr) {
out_indices[0] = indices_idx;
}
return true;
}
-bool ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
- uint32_t def_style_res, uint32_t* attrs, size_t attrs_length, uint32_t* out_values,
- uint32_t* out_indices) {
+void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
+ uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
+ uint32_t* out_values, uint32_t* out_indices) {
if (kDebugStyles) {
- ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p", theme,
- def_style_attr, def_style_res, xml_parser);
+ ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p",
+ theme, def_style_attr, def_style_res, xml_parser);
}
const ResTable& res = theme->getResTable();
@@ -211,7 +232,8 @@
uint32_t def_style_bag_type_set_flags = 0;
if (def_style_attr != 0) {
Res_value value;
- if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) {
+ if (theme->getAttribute(def_style_attr, &value,
+ &def_style_bag_type_set_flags) >= 0) {
if (value.dataType == Res_value::TYPE_REFERENCE) {
def_style_res = value.data;
}
@@ -221,11 +243,12 @@
// Retrieve the style class associated with the current XML tag.
int style = 0;
uint32_t style_bag_type_set_flags = 0;
- if (xml_parser != NULL) {
+ if (xml_parser != nullptr) {
ssize_t idx = xml_parser->indexOfStyle();
if (idx >= 0 && xml_parser->getAttributeValue(idx, &value) >= 0) {
if (value.dataType == value.TYPE_ATTRIBUTE) {
- if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) < 0) {
+ if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) <
+ 0) {
value.dataType = Res_value::TYPE_NULL;
}
}
@@ -239,29 +262,35 @@
res.lock();
// Retrieve the default style bag, if requested.
- const ResTable::bag_entry* def_style_attr_start = NULL;
+ const ResTable::bag_entry* def_style_attr_start = nullptr;
uint32_t def_style_type_set_flags = 0;
- ssize_t bag_off =
- def_style_res != 0
- ? res.getBagLocked(def_style_res, &def_style_attr_start, &def_style_type_set_flags)
- : -1;
+ ssize_t bag_off = def_style_res != 0
+ ? res.getBagLocked(def_style_res, &def_style_attr_start,
+ &def_style_type_set_flags)
+ : -1;
def_style_type_set_flags |= def_style_bag_type_set_flags;
const ResTable::bag_entry* const def_style_attr_end =
def_style_attr_start + (bag_off >= 0 ? bag_off : 0);
- BagAttributeFinder def_style_attr_finder(def_style_attr_start, def_style_attr_end);
+ BagAttributeFinder def_style_attr_finder(def_style_attr_start,
+ def_style_attr_end);
// Retrieve the style class bag, if requested.
- const ResTable::bag_entry* style_attr_start = NULL;
+ const ResTable::bag_entry* style_attr_start = nullptr;
uint32_t style_type_set_flags = 0;
- bag_off = style != 0 ? res.getBagLocked(style, &style_attr_start, &style_type_set_flags) : -1;
+ bag_off =
+ style != 0
+ ? res.getBagLocked(style, &style_attr_start, &style_type_set_flags)
+ : -1;
style_type_set_flags |= style_bag_type_set_flags;
- const ResTable::bag_entry* const style_attr_end = style_attr_start + (bag_off >= 0 ? bag_off : 0);
+ const ResTable::bag_entry* const style_attr_end =
+ style_attr_start + (bag_off >= 0 ? bag_off : 0);
BagAttributeFinder style_attr_finder(style_attr_start, style_attr_end);
// Retrieve the XML attributes, if requested.
static const ssize_t kXmlBlock = 0x10000000;
XmlAttributeFinder xml_attr_finder(xml_parser);
- const size_t xml_attr_end = xml_parser != NULL ? xml_parser->getAttributeCount() : 0;
+ const size_t xml_attr_end =
+ xml_parser != nullptr ? xml_parser->getAttributeCount() : 0;
// Now iterate through all of the attributes that the client has requested,
// filling in each with whatever data we can find.
@@ -289,34 +318,41 @@
// We found the attribute we were looking for.
xml_parser->getAttributeValue(xml_attr_idx, &value);
if (kDebugStyles) {
- ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
if (value.dataType == Res_value::TYPE_NULL) {
- // Walk through the style class values looking for the requested attribute.
- const ResTable::bag_entry* const style_attr_entry = style_attr_finder.Find(cur_ident);
+ // Walk through the style class values looking for the requested
+ // attribute.
+ const ResTable::bag_entry* const style_attr_entry =
+ style_attr_finder.Find(cur_ident);
if (style_attr_entry != style_attr_end) {
// We found the attribute we were looking for.
block = style_attr_entry->stringBlock;
type_set_flags = style_type_set_flags;
value = style_attr_entry->map.value;
if (kDebugStyles) {
- ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
}
if (value.dataType == Res_value::TYPE_NULL) {
- // Walk through the default style values looking for the requested attribute.
- const ResTable::bag_entry* const def_style_attr_entry = def_style_attr_finder.Find(cur_ident);
+ // Walk through the default style values looking for the requested
+ // attribute.
+ const ResTable::bag_entry* const def_style_attr_entry =
+ def_style_attr_finder.Find(cur_ident);
if (def_style_attr_entry != def_style_attr_end) {
// We found the attribute we were looking for.
block = def_style_attr_entry->stringBlock;
type_set_flags = style_type_set_flags;
value = def_style_attr_entry->map.value;
if (kDebugStyles) {
- ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
}
@@ -324,30 +360,35 @@
uint32_t resid = 0;
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
- ssize_t new_block =
- theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
+ ssize_t new_block = theme->resolveAttributeReference(
+ &value, block, &resid, &type_set_flags, &config);
if (new_block >= 0) {
block = new_block;
}
if (kDebugStyles) {
- ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
} else {
// If we still don't have a value for this attribute, try to find
// it in the theme!
- ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
+ ssize_t new_block =
+ theme->getAttribute(cur_ident, &value, &type_set_flags);
if (new_block >= 0) {
if (kDebugStyles) {
- ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
- new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
+ new_block = res.resolveReference(&value, new_block, &resid,
+ &type_set_flags, &config);
if (new_block >= 0) {
block = new_block;
}
if (kDebugStyles) {
- ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
}
@@ -363,20 +404,21 @@
}
if (kDebugStyles) {
- ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
+ ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident,
+ value.dataType, value.data);
}
// Write the final value back to Java.
out_values[STYLE_TYPE] = value.dataType;
out_values[STYLE_DATA] = value.data;
- out_values[STYLE_ASSET_COOKIE] = block != kXmlBlock
- ? static_cast<uint32_t>(res.getTableCookie(block))
- : static_cast<uint32_t>(-1);
+ out_values[STYLE_ASSET_COOKIE] =
+ block != kXmlBlock ? static_cast<uint32_t>(res.getTableCookie(block))
+ : static_cast<uint32_t>(-1);
out_values[STYLE_RESOURCE_ID] = resid;
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
- if (out_indices != NULL && value.dataType != Res_value::TYPE_NULL) {
+ if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
indices_idx++;
out_indices[indices_idx] = ii;
}
@@ -386,14 +428,14 @@
res.unlock();
- if (out_indices != NULL) {
+ if (out_indices != nullptr) {
out_indices[0] = indices_idx;
}
- return true;
}
-bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, uint32_t* attrs,
- size_t attrs_length, uint32_t* out_values, uint32_t* out_indices) {
+bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser,
+ uint32_t* attrs, size_t attrs_length,
+ uint32_t* out_values, uint32_t* out_indices) {
ResTable_config config;
Res_value value;
@@ -437,7 +479,8 @@
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
// printf("Resolving attribute reference\n");
- ssize_t new_block = res->resolveReference(&value, block, &resid, &type_set_flags, &config);
+ ssize_t new_block = res->resolveReference(&value, block, &resid,
+ &type_set_flags, &config);
if (new_block >= 0) block = new_block;
}
@@ -451,14 +494,14 @@
// Write the final value back to Java.
out_values[STYLE_TYPE] = value.dataType;
out_values[STYLE_DATA] = value.data;
- out_values[STYLE_ASSET_COOKIE] = block != kXmlBlock
- ? static_cast<uint32_t>(res->getTableCookie(block))
- : static_cast<uint32_t>(-1);
+ out_values[STYLE_ASSET_COOKIE] =
+ block != kXmlBlock ? static_cast<uint32_t>(res->getTableCookie(block))
+ : static_cast<uint32_t>(-1);
out_values[STYLE_RESOURCE_ID] = resid;
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
- if (out_indices != NULL && value.dataType != Res_value::TYPE_NULL) {
+ if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
indices_idx++;
out_indices[indices_idx] = ii;
}
@@ -468,7 +511,7 @@
res->unlock();
- if (out_indices != NULL) {
+ if (out_indices != nullptr) {
out_indices[0] = indices_idx;
}
return true;
diff --git a/libs/androidfw/AttributeFinder.h b/libs/androidfw/include/androidfw/AttributeFinder.h
similarity index 100%
rename from libs/androidfw/AttributeFinder.h
rename to libs/androidfw/include/androidfw/AttributeFinder.h
diff --git a/libs/androidfw/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h
index 3ed8bce..8d5ff46 100644
--- a/libs/androidfw/include/androidfw/AttributeResolution.h
+++ b/libs/androidfw/include/androidfw/AttributeResolution.h
@@ -44,9 +44,9 @@
uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
-bool ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
- uint32_t def_style_res, uint32_t* attrs, size_t attrs_length, uint32_t* out_values,
- uint32_t* out_indices);
+void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
+ uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
+ uint32_t* out_values, uint32_t* out_indices);
bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, uint32_t* attrs,
size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index d18cb8f..d91a133 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -24,6 +24,7 @@
AppAsLib_test.cpp \
Asset_test.cpp \
AttributeFinder_test.cpp \
+ AttributeResolution_test.cpp \
ByteBucketArray_test.cpp \
Config_test.cpp \
ConfigLocale_test.cpp \
@@ -53,14 +54,15 @@
LOCAL_MODULE := libandroidfw_tests
LOCAL_CFLAGS := $(androidfw_test_cflags)
-LOCAL_SRC_FILES := $(testFiles) AttributeResolution_test.cpp
+LOCAL_SRC_FILES := $(testFiles)
LOCAL_STATIC_LIBRARIES := \
libandroidfw \
libbase \
libutils \
libcutils \
liblog \
- libz
+ libz \
+ libziparchive
LOCAL_PICKUP_FILES := $(LOCAL_PATH)/data
include $(BUILD_HOST_NATIVE_TEST)
@@ -82,7 +84,8 @@
libbase \
libcutils \
libutils \
- libui
+ libui \
+ libziparchive
LOCAL_PICKUP_FILES := $(LOCAL_PATH)/data
include $(BUILD_NATIVE_TEST)
diff --git a/libs/androidfw/tests/AppAsLib_test.cpp b/libs/androidfw/tests/AppAsLib_test.cpp
index 8489acf..ddaa46d 100644
--- a/libs/androidfw/tests/AppAsLib_test.cpp
+++ b/libs/androidfw/tests/AppAsLib_test.cpp
@@ -14,55 +14,69 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/ResourceTypes.h"
+#include "TestHelpers.h"
#include "data/appaslib/R.h"
-#include <gtest/gtest.h>
+namespace app = com::android::appaslib::app;
+namespace lib = com::android::appaslib::lib;
-using namespace android;
-
-namespace {
-
-#include "data/appaslib/appaslib_arsc.h"
-#include "data/appaslib/appaslib_lib_arsc.h"
+namespace android {
// This tests the app resources loaded as app.
-TEST(AppAsLibTest, loadedAsApp) {
+TEST(AppAsLibTest, LoadedAsApp) {
+ std::string contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib.apk",
+ "resources.arsc", &contents));
+
ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(appaslib_arsc, appaslib_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
Res_value val;
- ssize_t block = table.getResource(appaslib::R::app::integer::number1, &val);
+ ssize_t block = table.getResource(app::R::integer::number1, &val);
ASSERT_GE(block, 0);
ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(appaslib::R::app::array::integerArray1, val.data);
+ ASSERT_EQ(app::R::array::integerArray1, val.data);
}
// This tests the app resources loaded as shared-lib.
-TEST(AppAsLibTest, loadedAsSharedLib) {
+TEST(AppAsLibTest, LoadedAsSharedLib) {
+ std::string contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib.apk",
+ "resources.arsc", &contents));
+
ResTable table;
// Load as shared library.
- ASSERT_EQ(NO_ERROR, table.add(appaslib_arsc, appaslib_arsc_len, NULL, 0, -1, false, true));
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size(), NULL, 0, -1,
+ false, true));
Res_value val;
- ssize_t block = table.getResource(appaslib::R::lib::integer::number1, &val);
+ ssize_t block = table.getResource(lib::R::integer::number1, &val);
ASSERT_GE(block, 0);
ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(appaslib::R::lib::array::integerArray1, val.data);
+ ASSERT_EQ(lib::R::array::integerArray1, val.data);
}
// This tests the shared-lib loaded with appAsLib as true.
-TEST(AppAsLibTest, loadedSharedLib) {
+TEST(AppAsLibTest, LoadedSharedLib) {
+ std::string contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib_lib.apk",
+ "resources.arsc", &contents));
+
ResTable table;
// Load shared library with appAsLib as true.
- ASSERT_EQ(NO_ERROR, table.add(appaslib_lib_arsc, appaslib_lib_arsc_len, NULL, 0, -1, false, true));
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size(), NULL, 0, -1,
+ false, true));
Res_value val;
- ssize_t block = table.getResource(appaslib::R::lib::integer::number1, &val);
+ ssize_t block = table.getResource(lib::R::integer::number1, &val);
ASSERT_GE(block, 0);
ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(appaslib::R::lib::array::integerArray1, val.data);
+ ASSERT_EQ(lib::R::array::integerArray1, val.data);
}
-}
+} // namespace android
diff --git a/libs/androidfw/tests/Asset_test.cpp b/libs/androidfw/tests/Asset_test.cpp
index 45c8cef..5018218 100644
--- a/libs/androidfw/tests/Asset_test.cpp
+++ b/libs/androidfw/tests/Asset_test.cpp
@@ -14,24 +14,26 @@
* limitations under the License.
*/
-#include <androidfw/Asset.h>
+#include "androidfw/Asset.h"
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
-using namespace android;
+namespace android {
TEST(AssetTest, FileAssetRegistersItself) {
- const int32_t count = Asset::getGlobalCount();
- Asset* asset = new _FileAsset();
- EXPECT_EQ(count + 1, Asset::getGlobalCount());
- delete asset;
- EXPECT_EQ(count, Asset::getGlobalCount());
+ const int32_t count = Asset::getGlobalCount();
+ Asset* asset = new _FileAsset();
+ EXPECT_EQ(count + 1, Asset::getGlobalCount());
+ delete asset;
+ EXPECT_EQ(count, Asset::getGlobalCount());
}
TEST(AssetTest, CompressedAssetRegistersItself) {
- const int32_t count = Asset::getGlobalCount();
- Asset* asset = new _CompressedAsset();
- EXPECT_EQ(count + 1, Asset::getGlobalCount());
- delete asset;
- EXPECT_EQ(count, Asset::getGlobalCount());
+ const int32_t count = Asset::getGlobalCount();
+ Asset* asset = new _CompressedAsset();
+ EXPECT_EQ(count + 1, Asset::getGlobalCount());
+ delete asset;
+ EXPECT_EQ(count, Asset::getGlobalCount());
}
+
+} // nameapce android
diff --git a/libs/androidfw/tests/AttributeFinder_test.cpp b/libs/androidfw/tests/AttributeFinder_test.cpp
index d9ed48e..7264b81 100644
--- a/libs/androidfw/tests/AttributeFinder_test.cpp
+++ b/libs/androidfw/tests/AttributeFinder_test.cpp
@@ -14,16 +14,18 @@
* limitations under the License.
*/
-#include "../AttributeFinder.h"
+#include "androidfw/AttributeFinder.h"
-#include <android-base/macros.h>
-#include <gtest/gtest.h>
+#include "android-base/macros.h"
+#include "gtest/gtest.h"
-using android::BackTrackingAttributeFinder;
+namespace android {
-class MockAttributeFinder : public BackTrackingAttributeFinder<MockAttributeFinder, int> {
+class MockAttributeFinder
+ : public BackTrackingAttributeFinder<MockAttributeFinder, int> {
public:
- MockAttributeFinder(const uint32_t* attrs, int len) : BackTrackingAttributeFinder(0, len) {
+ MockAttributeFinder(const uint32_t* attrs, int len)
+ : BackTrackingAttributeFinder(0, len) {
attrs_ = new uint32_t[len];
memcpy(attrs_, attrs, sizeof(*attrs) * len);
}
@@ -36,13 +38,16 @@
uint32_t* attrs_;
};
-static const uint32_t kSortedAttributes[] = {0x01010000, 0x01010001, 0x01010002, 0x01010004,
- 0x02010001, 0x02010010, 0x7f010001};
+static const uint32_t kSortedAttributes[] = {0x01010000, 0x01010001, 0x01010002,
+ 0x01010004, 0x02010001, 0x02010010,
+ 0x7f010001};
static const uint32_t kPackageUnsortedAttributes[] = {
- 0x02010001, 0x02010010, 0x01010000, 0x01010001, 0x01010002, 0x01010004, 0x7f010001};
+ 0x02010001, 0x02010010, 0x01010000, 0x01010001,
+ 0x01010002, 0x01010004, 0x7f010001};
-static const uint32_t kSinglePackageAttributes[] = {0x7f010007, 0x7f01000a, 0x7f01000d, 0x00000000};
+static const uint32_t kSinglePackageAttributes[] = {0x7f010007, 0x7f01000a,
+ 0x7f01000d, 0x00000000};
TEST(AttributeFinderTest, IteratesSequentially) {
const int end = arraysize(kSortedAttributes);
@@ -116,3 +121,5 @@
EXPECT_EQ(end, finder.Find(0x010100fa));
EXPECT_EQ(0, finder.Find(0x7f010007));
}
+
+} // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp
index d6d7890..d417aba 100644
--- a/libs/androidfw/tests/AttributeResolution_test.cpp
+++ b/libs/androidfw/tests/AttributeResolution_test.cpp
@@ -30,12 +30,11 @@
class AttributeResolutionTest : public ::testing::Test {
public:
virtual void SetUp() override {
- std::string test_source_dir = GetTestDataPath();
std::string contents;
- CHECK(base::ReadFileToString(test_source_dir + "/styles/resources.arsc",
- &contents));
- CHECK(table_.add(contents.data(), contents.size(), 1 /*cookie*/,
- true /*copyData*/) == NO_ERROR);
+ ASSERT_TRUE(ReadFileFromZipToString(
+ GetTestDataPath() + "/styles/styles.apk", "resources.arsc", &contents));
+ ASSERT_EQ(NO_ERROR, table_.add(contents.data(), contents.size(),
+ 1 /*cookie*/, true /*copyData*/));
}
protected:
@@ -46,12 +45,14 @@
public:
virtual void SetUp() override {
AttributeResolutionTest::SetUp();
- std::string test_source_dir = GetTestDataPath();
+
std::string contents;
- CHECK(base::ReadFileToString(test_source_dir + "/styles/layout.xml",
- &contents));
- CHECK(xml_parser_.setTo(contents.data(), contents.size(),
- true /*copyData*/) == NO_ERROR);
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk",
+ "res/layout/layout.xml", &contents));
+
+ ASSERT_EQ(NO_ERROR, xml_parser_.setTo(contents.data(), contents.size(),
+ true /*copyData*/));
// Skip to the first tag.
while (xml_parser_.next() != ResXMLParser::START_TAG) {
@@ -161,9 +162,9 @@
std::vector<uint32_t> values;
values.resize(arraysize(attrs) * 6);
- ASSERT_TRUE(ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/,
- 0 /*def_style_res*/, attrs, arraysize(attrs),
- values.data(), nullptr /*out_indices*/));
+ ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/,
+ 0 /*def_style_res*/, attrs, arraysize(attrs),
+ values.data(), nullptr /*out_indices*/);
const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
diff --git a/libs/androidfw/tests/ByteBucketArray_test.cpp b/libs/androidfw/tests/ByteBucketArray_test.cpp
index 376e79c..5d464c7 100644
--- a/libs/androidfw/tests/ByteBucketArray_test.cpp
+++ b/libs/androidfw/tests/ByteBucketArray_test.cpp
@@ -14,28 +14,42 @@
* limitations under the License.
*/
-#include <androidfw/ByteBucketArray.h>
+#include "androidfw/ByteBucketArray.h"
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
-using android::ByteBucketArray;
+namespace android {
TEST(ByteBucketArrayTest, TestSparseInsertion) {
- ByteBucketArray<int> bba;
- ASSERT_TRUE(bba.set(0, 1));
- ASSERT_TRUE(bba.set(10, 2));
- ASSERT_TRUE(bba.set(26, 3));
- ASSERT_TRUE(bba.set(129, 4));
- ASSERT_TRUE(bba.set(234, 5));
+ ByteBucketArray<int> bba;
+ ASSERT_TRUE(bba.set(0, 1));
+ ASSERT_TRUE(bba.set(10, 2));
+ ASSERT_TRUE(bba.set(26, 3));
+ ASSERT_TRUE(bba.set(129, 4));
+ ASSERT_TRUE(bba.set(234, 5));
- for (size_t i = 0; i < bba.size(); i++) {
- switch (i) {
- case 0: EXPECT_EQ(1, bba[i]); break;
- case 10: EXPECT_EQ(2, bba[i]); break;
- case 26: EXPECT_EQ(3, bba[i]); break;
- case 129: EXPECT_EQ(4, bba[i]); break;
- case 234: EXPECT_EQ(5, bba[i]); break;
- default: EXPECT_EQ(0, bba[i]); break;
- }
+ for (size_t i = 0; i < bba.size(); i++) {
+ switch (i) {
+ case 0:
+ EXPECT_EQ(1, bba[i]);
+ break;
+ case 10:
+ EXPECT_EQ(2, bba[i]);
+ break;
+ case 26:
+ EXPECT_EQ(3, bba[i]);
+ break;
+ case 129:
+ EXPECT_EQ(4, bba[i]);
+ break;
+ case 234:
+ EXPECT_EQ(5, bba[i]);
+ break;
+ default:
+ EXPECT_EQ(0, bba[i]);
+ break;
}
+ }
}
+
+} // namespace android
diff --git a/libs/androidfw/tests/Config_test.cpp b/libs/androidfw/tests/Config_test.cpp
index 738947a..778c7bf 100644
--- a/libs/androidfw/tests/Config_test.cpp
+++ b/libs/androidfw/tests/Config_test.cpp
@@ -14,168 +14,172 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
+#include "androidfw/ResourceTypes.h"
+
+#include "utils/Log.h"
+#include "utils/String8.h"
+#include "utils/Vector.h"
#include "TestHelpers.h"
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
namespace android {
static ResTable_config selectBest(const ResTable_config& target,
- const Vector<ResTable_config>& configs) {
- ResTable_config bestConfig;
- memset(&bestConfig, 0, sizeof(bestConfig));
- const size_t configCount = configs.size();
- for (size_t i = 0; i < configCount; i++) {
- const ResTable_config& thisConfig = configs[i];
- if (!thisConfig.match(target)) {
- continue;
- }
-
- if (thisConfig.isBetterThan(bestConfig, &target)) {
- bestConfig = thisConfig;
- }
+ const Vector<ResTable_config>& configs) {
+ ResTable_config bestConfig;
+ memset(&bestConfig, 0, sizeof(bestConfig));
+ const size_t configCount = configs.size();
+ for (size_t i = 0; i < configCount; i++) {
+ const ResTable_config& thisConfig = configs[i];
+ if (!thisConfig.match(target)) {
+ continue;
}
- return bestConfig;
+
+ if (thisConfig.isBetterThan(bestConfig, &target)) {
+ bestConfig = thisConfig;
+ }
+ }
+ return bestConfig;
}
static ResTable_config buildDensityConfig(int density) {
- ResTable_config config;
- memset(&config, 0, sizeof(config));
- config.density = uint16_t(density);
- config.sdkVersion = 4;
- return config;
+ ResTable_config config;
+ memset(&config, 0, sizeof(config));
+ config.density = uint16_t(density);
+ config.sdkVersion = 4;
+ return config;
}
TEST(ConfigTest, shouldSelectBestDensity) {
- ResTable_config deviceConfig;
- memset(&deviceConfig, 0, sizeof(deviceConfig));
- deviceConfig.density = ResTable_config::DENSITY_XHIGH;
- deviceConfig.sdkVersion = 21;
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
+ deviceConfig.density = ResTable_config::DENSITY_XHIGH;
+ deviceConfig.sdkVersion = 21;
- Vector<ResTable_config> configs;
+ Vector<ResTable_config> configs;
- ResTable_config expectedBest = buildDensityConfig(ResTable_config::DENSITY_HIGH);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ ResTable_config expectedBest =
+ buildDensityConfig(ResTable_config::DENSITY_HIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- expectedBest = buildDensityConfig(ResTable_config::DENSITY_XXHIGH);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_XXHIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- expectedBest = buildDensityConfig(int(ResTable_config::DENSITY_XXHIGH) - 20);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ expectedBest = buildDensityConfig(int(ResTable_config::DENSITY_XXHIGH) - 20);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- configs.add(buildDensityConfig(int(ResTable_config::DENSITY_HIGH) + 20));
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ configs.add(buildDensityConfig(int(ResTable_config::DENSITY_HIGH) + 20));
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- expectedBest = buildDensityConfig(ResTable_config::DENSITY_XHIGH);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_XHIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
- expectedBest.sdkVersion = 21;
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
+ expectedBest.sdkVersion = 21;
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
}
TEST(ConfigTest, shouldSelectBestDensityWhenNoneSpecified) {
- ResTable_config deviceConfig;
- memset(&deviceConfig, 0, sizeof(deviceConfig));
- deviceConfig.sdkVersion = 21;
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
+ deviceConfig.sdkVersion = 21;
- Vector<ResTable_config> configs;
- configs.add(buildDensityConfig(ResTable_config::DENSITY_HIGH));
+ Vector<ResTable_config> configs;
+ configs.add(buildDensityConfig(ResTable_config::DENSITY_HIGH));
- ResTable_config expectedBest = buildDensityConfig(ResTable_config::DENSITY_MEDIUM);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ ResTable_config expectedBest =
+ buildDensityConfig(ResTable_config::DENSITY_MEDIUM);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
}
TEST(ConfigTest, shouldMatchRoundQualifier) {
- ResTable_config deviceConfig;
- memset(&deviceConfig, 0, sizeof(deviceConfig));
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
- ResTable_config roundConfig;
- memset(&roundConfig, 0, sizeof(roundConfig));
- roundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ ResTable_config roundConfig;
+ memset(&roundConfig, 0, sizeof(roundConfig));
+ roundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
- EXPECT_FALSE(roundConfig.match(deviceConfig));
+ EXPECT_FALSE(roundConfig.match(deviceConfig));
- deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
- EXPECT_TRUE(roundConfig.match(deviceConfig));
+ EXPECT_TRUE(roundConfig.match(deviceConfig));
- deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_NO;
+ deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_NO;
- EXPECT_FALSE(roundConfig.match(deviceConfig));
+ EXPECT_FALSE(roundConfig.match(deviceConfig));
- ResTable_config notRoundConfig;
- memset(¬RoundConfig, 0, sizeof(notRoundConfig));
- notRoundConfig.screenLayout2 = ResTable_config::SCREENROUND_NO;
+ ResTable_config notRoundConfig;
+ memset(¬RoundConfig, 0, sizeof(notRoundConfig));
+ notRoundConfig.screenLayout2 = ResTable_config::SCREENROUND_NO;
- EXPECT_TRUE(notRoundConfig.match(deviceConfig));
+ EXPECT_TRUE(notRoundConfig.match(deviceConfig));
}
TEST(ConfigTest, RoundQualifierShouldHaveStableSortOrder) {
- ResTable_config defaultConfig;
- memset(&defaultConfig, 0, sizeof(defaultConfig));
+ ResTable_config defaultConfig;
+ memset(&defaultConfig, 0, sizeof(defaultConfig));
- ResTable_config longConfig = defaultConfig;
- longConfig.screenLayout = ResTable_config::SCREENLONG_YES;
+ ResTable_config longConfig = defaultConfig;
+ longConfig.screenLayout = ResTable_config::SCREENLONG_YES;
- ResTable_config longRoundConfig = longConfig;
- longRoundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ ResTable_config longRoundConfig = longConfig;
+ longRoundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
- ResTable_config longRoundPortConfig = longConfig;
- longRoundPortConfig.orientation = ResTable_config::ORIENTATION_PORT;
+ ResTable_config longRoundPortConfig = longConfig;
+ longRoundPortConfig.orientation = ResTable_config::ORIENTATION_PORT;
- EXPECT_TRUE(longConfig.compare(longRoundConfig) < 0);
- EXPECT_TRUE(longConfig.compareLogical(longRoundConfig) < 0);
- EXPECT_TRUE(longRoundConfig.compare(longConfig) > 0);
- EXPECT_TRUE(longRoundConfig.compareLogical(longConfig) > 0);
+ EXPECT_TRUE(longConfig.compare(longRoundConfig) < 0);
+ EXPECT_TRUE(longConfig.compareLogical(longRoundConfig) < 0);
+ EXPECT_TRUE(longRoundConfig.compare(longConfig) > 0);
+ EXPECT_TRUE(longRoundConfig.compareLogical(longConfig) > 0);
- EXPECT_TRUE(longRoundConfig.compare(longRoundPortConfig) < 0);
- EXPECT_TRUE(longRoundConfig.compareLogical(longRoundPortConfig) < 0);
- EXPECT_TRUE(longRoundPortConfig.compare(longRoundConfig) > 0);
- EXPECT_TRUE(longRoundPortConfig.compareLogical(longRoundConfig) > 0);
+ EXPECT_TRUE(longRoundConfig.compare(longRoundPortConfig) < 0);
+ EXPECT_TRUE(longRoundConfig.compareLogical(longRoundPortConfig) < 0);
+ EXPECT_TRUE(longRoundPortConfig.compare(longRoundConfig) > 0);
+ EXPECT_TRUE(longRoundPortConfig.compareLogical(longRoundConfig) > 0);
}
TEST(ConfigTest, ScreenShapeHasCorrectDiff) {
- ResTable_config defaultConfig;
- memset(&defaultConfig, 0, sizeof(defaultConfig));
+ ResTable_config defaultConfig;
+ memset(&defaultConfig, 0, sizeof(defaultConfig));
- ResTable_config roundConfig = defaultConfig;
- roundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ ResTable_config roundConfig = defaultConfig;
+ roundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
- EXPECT_EQ(defaultConfig.diff(roundConfig), ResTable_config::CONFIG_SCREEN_ROUND);
+ EXPECT_EQ(defaultConfig.diff(roundConfig),
+ ResTable_config::CONFIG_SCREEN_ROUND);
}
TEST(ConfigTest, RoundIsMoreSpecific) {
- ResTable_config deviceConfig;
- memset(&deviceConfig, 0, sizeof(deviceConfig));
- deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
- deviceConfig.screenLayout = ResTable_config::SCREENLONG_YES;
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
+ deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ deviceConfig.screenLayout = ResTable_config::SCREENLONG_YES;
- ResTable_config targetConfigA;
- memset(&targetConfigA, 0, sizeof(targetConfigA));
+ ResTable_config targetConfigA;
+ memset(&targetConfigA, 0, sizeof(targetConfigA));
- ResTable_config targetConfigB = targetConfigA;
- targetConfigB.screenLayout = ResTable_config::SCREENLONG_YES;
+ ResTable_config targetConfigB = targetConfigA;
+ targetConfigB.screenLayout = ResTable_config::SCREENLONG_YES;
- ResTable_config targetConfigC = targetConfigB;
- targetConfigC.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ ResTable_config targetConfigC = targetConfigB;
+ targetConfigC.screenLayout2 = ResTable_config::SCREENROUND_YES;
- EXPECT_TRUE(targetConfigB.isBetterThan(targetConfigA, &deviceConfig));
- EXPECT_TRUE(targetConfigC.isBetterThan(targetConfigB, &deviceConfig));
+ EXPECT_TRUE(targetConfigB.isBetterThan(targetConfigA, &deviceConfig));
+ EXPECT_TRUE(targetConfigC.isBetterThan(targetConfigB, &deviceConfig));
}
} // namespace android.
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index f50c178..0928b1b 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -14,102 +14,102 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/ResourceTypes.h"
-#include <utils/String8.h>
-#include <utils/String16.h>
+#include "utils/String16.h"
+#include "utils/String8.h"
+
#include "TestHelpers.h"
#include "data/basic/R.h"
-#include <gtest/gtest.h>
+using com::android::basic::R;
-using namespace android;
-
-namespace {
-
-/**
- * Include a binary resource table.
- *
- * Package: com.android.test.basic
- */
-#include "data/basic/basic_arsc.h"
-
-/**
- * Include a binary resource table.
- * This table is an overlay.
- *
- * Package: com.android.test.basic
- */
-#include "data/overlay/overlay_arsc.h"
-
-enum { MAY_NOT_BE_BAG = false };
+namespace android {
class IdmapTest : public ::testing::Test {
-protected:
- virtual void SetUp() {
- ASSERT_EQ(NO_ERROR, mTargetTable.add(basic_arsc, basic_arsc_len));
- ASSERT_EQ(NO_ERROR, mOverlayTable.add(overlay_arsc, overlay_arsc_len));
- char targetName[256] = "com.android.test.basic";
- ASSERT_EQ(NO_ERROR, mTargetTable.createIdmap(mOverlayTable, 0, 0,
- targetName, targetName, &mData, &mDataSize));
- }
+ protected:
+ void SetUp() override {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
+ ASSERT_EQ(NO_ERROR,
+ target_table_.add(contents.data(), contents.size(), 0, true));
- virtual void TearDown() {
- free(mData);
- }
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk",
+ "resources.arsc", &overlay_data_));
+ ResTable overlay_table;
+ ASSERT_EQ(NO_ERROR,
+ overlay_table.add(overlay_data_.data(), overlay_data_.size()));
- ResTable mTargetTable;
- ResTable mOverlayTable;
- void* mData;
- size_t mDataSize;
+ char target_name[256] = "com.android.basic";
+ ASSERT_EQ(NO_ERROR,
+ target_table_.createIdmap(overlay_table, 0, 0, target_name,
+ target_name, &data_, &data_size_));
+ }
+
+ void TearDown() override { ::free(data_); }
+
+ ResTable target_table_;
+ std::string overlay_data_;
+ void* data_ = nullptr;
+ size_t data_size_ = 0;
};
TEST_F(IdmapTest, canLoadIdmap) {
- ASSERT_EQ(NO_ERROR, mTargetTable.add(overlay_arsc, overlay_arsc_len, mData, mDataSize));
+ ASSERT_EQ(NO_ERROR,
+ target_table_.add(overlay_data_.data(), overlay_data_.size(), data_,
+ data_size_));
}
TEST_F(IdmapTest, overlayOverridesResourceValue) {
- Res_value val;
- ssize_t block = mTargetTable.getResource(base::R::string::test2, &val, false);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
- const ResStringPool* pool = mTargetTable.getTableStringBlock(block);
- ASSERT_TRUE(pool != NULL);
- ASSERT_LT(val.data, pool->size());
+ Res_value val;
+ ssize_t block = target_table_.getResource(R::string::test2, &val, false);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
+ const ResStringPool* pool = target_table_.getTableStringBlock(block);
+ ASSERT_TRUE(pool != NULL);
+ ASSERT_LT(val.data, pool->size());
- size_t strLen;
- const char16_t* targetStr16 = pool->stringAt(val.data, &strLen);
- ASSERT_TRUE(targetStr16 != NULL);
- ASSERT_EQ(String16("test2"), String16(targetStr16, strLen));
+ size_t strLen;
+ const char16_t* targetStr16 = pool->stringAt(val.data, &strLen);
+ ASSERT_TRUE(targetStr16 != NULL);
+ ASSERT_EQ(String16("test2"), String16(targetStr16, strLen));
- ASSERT_EQ(NO_ERROR, mTargetTable.add(overlay_arsc, overlay_arsc_len, mData, mDataSize));
+ ASSERT_EQ(NO_ERROR,
+ target_table_.add(overlay_data_.data(), overlay_data_.size(), data_,
+ data_size_));
- ssize_t newBlock = mTargetTable.getResource(base::R::string::test2, &val, false);
- ASSERT_GE(newBlock, 0);
- ASSERT_NE(block, newBlock);
- ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
- pool = mTargetTable.getTableStringBlock(newBlock);
- ASSERT_TRUE(pool != NULL);
- ASSERT_LT(val.data, pool->size());
+ ssize_t newBlock = target_table_.getResource(R::string::test2, &val, false);
+ ASSERT_GE(newBlock, 0);
+ ASSERT_NE(block, newBlock);
+ ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
+ pool = target_table_.getTableStringBlock(newBlock);
+ ASSERT_TRUE(pool != NULL);
+ ASSERT_LT(val.data, pool->size());
- targetStr16 = pool->stringAt(val.data, &strLen);
- ASSERT_TRUE(targetStr16 != NULL);
- ASSERT_EQ(String16("test2-overlay"), String16(targetStr16, strLen));
+ targetStr16 = pool->stringAt(val.data, &strLen);
+ ASSERT_TRUE(targetStr16 != NULL);
+ ASSERT_EQ(String16("test2-overlay"), String16(targetStr16, strLen));
}
TEST_F(IdmapTest, overlaidResourceHasSameName) {
- ASSERT_EQ(NO_ERROR, mTargetTable.add(overlay_arsc, overlay_arsc_len, mData, mDataSize));
+ ASSERT_EQ(NO_ERROR,
+ target_table_.add(overlay_data_.data(), overlay_data_.size(), data_,
+ data_size_));
- ResTable::resource_name resName;
- ASSERT_TRUE(mTargetTable.getResourceName(base::R::array::integerArray1, false, &resName));
+ ResTable::resource_name resName;
+ ASSERT_TRUE(
+ target_table_.getResourceName(R::array::integerArray1, false, &resName));
- ASSERT_TRUE(resName.package != NULL);
- ASSERT_TRUE(resName.type != NULL);
- ASSERT_TRUE(resName.name != NULL);
+ ASSERT_TRUE(resName.package != NULL);
+ ASSERT_TRUE(resName.type != NULL);
+ ASSERT_TRUE(resName.name != NULL);
- EXPECT_EQ(String16("com.android.test.basic"), String16(resName.package, resName.packageLen));
- EXPECT_EQ(String16("array"), String16(resName.type, resName.typeLen));
- EXPECT_EQ(String16("integerArray1"), String16(resName.name, resName.nameLen));
+ EXPECT_EQ(String16("com.android.basic"),
+ String16(resName.package, resName.packageLen));
+ EXPECT_EQ(String16("array"), String16(resName.type, resName.typeLen));
+ EXPECT_EQ(String16("integerArray1"), String16(resName.name, resName.nameLen));
}
-} // namespace
+} // namespace
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index 9e53dd2..b151f3f 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -14,352 +14,386 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/ResourceTypes.h"
#include <codecvt>
#include <locale>
#include <string>
-#include <utils/String8.h>
-#include <utils/String16.h>
+#include "utils/String16.h"
+#include "utils/String8.h"
+
#include "TestHelpers.h"
#include "data/basic/R.h"
#include "data/lib/R.h"
-#include <gtest/gtest.h>
+namespace basic = com::android::basic;
+namespace lib = com::android::lib;
-using namespace android;
+namespace android {
-namespace {
+TEST(ResTableTest, ShouldLoadSuccessfully) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
-/**
- * Include a binary resource table.
- *
- * Package: com.android.test.basic
- */
-#include "data/basic/basic_arsc.h"
-
-/**
- * Include a binary library resource table.
- *
- * Package: com.android.test.basic
- */
-#include "data/lib/lib_arsc.h"
-
-/**
- * Include a system resource table.
- *
- * Package: android
- */
-#include "data/system/system_arsc.h"
-
-TEST(ResTableTest, shouldLoadSuccessfully) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
}
-TEST(ResTableTest, simpleTypeIsRetrievedCorrectly) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, SimpleTypeIsRetrievedCorrectly) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- EXPECT_TRUE(IsStringEqual(table, base::R::string::test1, "test1"));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
+
+ EXPECT_TRUE(IsStringEqual(table, basic::R::string::test1, "test1"));
}
-TEST(ResTableTest, resourceNameIsResolved) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, ResourceNameIsResolved) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- String16 defPackage("com.android.test.basic");
- String16 testName("@string/test1");
- uint32_t resID = table.identifierForName(testName.string(), testName.size(),
- 0, 0,
- defPackage.string(), defPackage.size());
- ASSERT_NE(uint32_t(0x00000000), resID);
- ASSERT_EQ(base::R::string::test1, resID);
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
+
+ String16 defPackage("com.android.basic");
+ String16 testName("@string/test1");
+ uint32_t resID =
+ table.identifierForName(testName.string(), testName.size(), 0, 0,
+ defPackage.string(), defPackage.size());
+ ASSERT_NE(uint32_t(0x00000000), resID);
+ ASSERT_EQ(basic::R::string::test1, resID);
}
-TEST(ResTableTest, noParentThemeIsAppliedCorrectly) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, NoParentThemeIsAppliedCorrectly) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- ResTable::Theme theme(table);
- ASSERT_EQ(NO_ERROR, theme.applyStyle(base::R::style::Theme1));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- Res_value val;
- uint32_t specFlags = 0;
- ssize_t index = theme.getAttribute(base::R::attr::attr1, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(100), val.data);
+ ResTable::Theme theme(table);
+ ASSERT_EQ(NO_ERROR, theme.applyStyle(basic::R::style::Theme1));
- index = theme.getAttribute(base::R::attr::attr2, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(base::R::integer::number1, val.data);
+ Res_value val;
+ uint32_t specFlags = 0;
+ ssize_t index = theme.getAttribute(basic::R::attr::attr1, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(100), val.data);
+
+ index = theme.getAttribute(basic::R::attr::attr2, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
+ ASSERT_EQ(basic::R::integer::number1, val.data);
}
-TEST(ResTableTest, parentThemeIsAppliedCorrectly) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, ParentThemeIsAppliedCorrectly) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- ResTable::Theme theme(table);
- ASSERT_EQ(NO_ERROR, theme.applyStyle(base::R::style::Theme2));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- Res_value val;
- uint32_t specFlags = 0;
- ssize_t index = theme.getAttribute(base::R::attr::attr1, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(300), val.data);
+ ResTable::Theme theme(table);
+ ASSERT_EQ(NO_ERROR, theme.applyStyle(basic::R::style::Theme2));
- index = theme.getAttribute(base::R::attr::attr2, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(base::R::integer::number1, val.data);
+ Res_value val;
+ uint32_t specFlags = 0;
+ ssize_t index = theme.getAttribute(basic::R::attr::attr1, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(300), val.data);
+
+ index = theme.getAttribute(basic::R::attr::attr2, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
+ ASSERT_EQ(basic::R::integer::number1, val.data);
}
-TEST(ResTableTest, libraryThemeIsAppliedCorrectly) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(lib_arsc, lib_arsc_len));
+TEST(ResTableTest, LibraryThemeIsAppliedCorrectly) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib/lib.apk",
+ "resources.arsc", &contents));
- ResTable::Theme theme(table);
- ASSERT_EQ(NO_ERROR, theme.applyStyle(lib::R::style::Theme));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- Res_value val;
- uint32_t specFlags = 0;
- ssize_t index = theme.getAttribute(lib::R::attr::attr1, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(700), val.data);
+ ResTable::Theme theme(table);
+ ASSERT_EQ(NO_ERROR, theme.applyStyle(lib::R::style::Theme));
- index = theme.getAttribute(lib::R::attr::attr2, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(700), val.data);
+ Res_value val;
+ uint32_t specFlags = 0;
+ ssize_t index = theme.getAttribute(lib::R::attr::attr1, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(700), val.data);
+
+ index = theme.getAttribute(lib::R::attr::attr2, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(700), val.data);
}
-TEST(ResTableTest, referenceToBagIsNotResolved) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, ReferenceToBagIsNotResolved) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- Res_value val;
- ssize_t block = table.getResource(base::R::integer::number2, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(base::R::array::integerArray1, val.data);
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- ssize_t newBlock = table.resolveReference(&val, block);
- EXPECT_EQ(block, newBlock);
- EXPECT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- EXPECT_EQ(base::R::array::integerArray1, val.data);
+ Res_value val;
+ ssize_t block =
+ table.getResource(basic::R::integer::number2, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
+ ASSERT_EQ(basic::R::array::integerArray1, val.data);
+
+ ssize_t newBlock = table.resolveReference(&val, block);
+ EXPECT_EQ(block, newBlock);
+ EXPECT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
+ EXPECT_EQ(basic::R::array::integerArray1, val.data);
}
-TEST(ResTableTest, resourcesStillAccessibleAfterParameterChange) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, ResourcesStillAccessibleAfterParameterChange) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- Res_value val;
- ssize_t block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- const ResTable::bag_entry* entry;
- ssize_t count = table.lockBag(base::R::array::integerArray1, &entry);
- ASSERT_GE(count, 0);
- table.unlockBag(entry);
+ Res_value val;
+ ssize_t block =
+ table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ResTable_config param;
- memset(¶m, 0, sizeof(param));
- param.density = 320;
- table.setParameters(¶m);
+ const ResTable::bag_entry* entry;
+ ssize_t count = table.lockBag(basic::R::array::integerArray1, &entry);
+ ASSERT_GE(count, 0);
+ table.unlockBag(entry);
- block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ResTable_config param;
+ memset(¶m, 0, sizeof(param));
+ param.density = 320;
+ table.setParameters(¶m);
- count = table.lockBag(base::R::array::integerArray1, &entry);
- ASSERT_GE(count, 0);
- table.unlockBag(entry);
+ block = table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+
+ count = table.lockBag(basic::R::array::integerArray1, &entry);
+ ASSERT_GE(count, 0);
+ table.unlockBag(entry);
}
-TEST(ResTableTest, resourceIsOverridenWithBetterConfig) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, ResourceIsOverridenWithBetterConfig) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- Res_value val;
- ssize_t block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(200), val.data);
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- ResTable_config param;
- memset(¶m, 0, sizeof(param));
- param.language[0] = 's';
- param.language[1] = 'v';
- param.country[0] = 'S';
- param.country[1] = 'E';
- table.setParameters(¶m);
+ Res_value val;
+ ssize_t block =
+ table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(200), val.data);
- block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(400), val.data);
+ ResTable_config param;
+ memset(¶m, 0, sizeof(param));
+ param.language[0] = 's';
+ param.language[1] = 'v';
+ param.country[0] = 'S';
+ param.country[1] = 'E';
+ table.setParameters(¶m);
+
+ block = table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(400), val.data);
}
TEST(ResTableTest, emptyTableHasSensibleDefaults) {
- const int32_t assetCookie = 1;
+ const int32_t assetCookie = 1;
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.addEmpty(assetCookie));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.addEmpty(assetCookie));
- // Adding an empty table gives us one table!
- ASSERT_EQ(uint32_t(1), table.getTableCount());
+ // Adding an empty table gives us one table!
+ ASSERT_EQ(uint32_t(1), table.getTableCount());
- // Adding an empty table doesn't mean we get packages.
- ASSERT_EQ(uint32_t(0), table.getBasePackageCount());
+ // Adding an empty table doesn't mean we get packages.
+ ASSERT_EQ(uint32_t(0), table.getBasePackageCount());
- Res_value val;
- ASSERT_LT(table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG), 0);
+ Res_value val;
+ ASSERT_LT(table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG),
+ 0);
}
void testU16StringToInt(const char16_t* str, uint32_t expectedValue,
bool expectSuccess, bool expectHex) {
- size_t len = std::char_traits<char16_t>::length(str);
+ size_t len = std::char_traits<char16_t>::length(str);
- // Gtest can't print UTF-16 strings, so we have to convert to UTF-8 :(
- std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
- std::string s = convert.to_bytes(std::u16string(str, len));
+ // Gtest can't print UTF-16 strings, so we have to convert to UTF-8 :(
+ std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
+ std::string s = convert.to_bytes(std::u16string(str, len));
- Res_value out = {};
- ASSERT_EQ(expectSuccess, U16StringToInt(str, len, &out))
- << "Failed with " << s;
+ Res_value out = {};
+ ASSERT_EQ(expectSuccess, U16StringToInt(str, len, &out)) << "Failed with "
+ << s;
- if (!expectSuccess) {
- ASSERT_EQ(out.TYPE_NULL, out.dataType) << "Failed with " << s;
- return;
- }
+ if (!expectSuccess) {
+ ASSERT_EQ(out.TYPE_NULL, out.dataType) << "Failed with " << s;
+ return;
+ }
- if (expectHex) {
- ASSERT_EQ(out.TYPE_INT_HEX, out.dataType) << "Failed with " << s;
- } else {
- ASSERT_EQ(out.TYPE_INT_DEC, out.dataType) << "Failed with " << s;
- }
+ if (expectHex) {
+ ASSERT_EQ(out.TYPE_INT_HEX, out.dataType) << "Failed with " << s;
+ } else {
+ ASSERT_EQ(out.TYPE_INT_DEC, out.dataType) << "Failed with " << s;
+ }
- ASSERT_EQ(expectedValue, out.data) << "Failed with " << s;
+ ASSERT_EQ(expectedValue, out.data) << "Failed with " << s;
}
TEST(ResTableTest, U16StringToInt) {
- testU16StringToInt(u"", 0U, false, false);
- testU16StringToInt(u" ", 0U, false, false);
- testU16StringToInt(u"\t\n", 0U, false, false);
+ testU16StringToInt(u"", 0U, false, false);
+ testU16StringToInt(u" ", 0U, false, false);
+ testU16StringToInt(u"\t\n", 0U, false, false);
- testU16StringToInt(u"abcd", 0U, false, false);
- testU16StringToInt(u"10abcd", 0U, false, false);
- testU16StringToInt(u"42 42", 0U, false, false);
- testU16StringToInt(u"- 42", 0U, false, false);
- testU16StringToInt(u"-", 0U, false, false);
+ testU16StringToInt(u"abcd", 0U, false, false);
+ testU16StringToInt(u"10abcd", 0U, false, false);
+ testU16StringToInt(u"42 42", 0U, false, false);
+ testU16StringToInt(u"- 42", 0U, false, false);
+ testU16StringToInt(u"-", 0U, false, false);
- testU16StringToInt(u"0x", 0U, false, true);
- testU16StringToInt(u"0xnope", 0U, false, true);
- testU16StringToInt(u"0X42", 0U, false, true);
- testU16StringToInt(u"0x42 0x42", 0U, false, true);
- testU16StringToInt(u"-0x0", 0U, false, true);
- testU16StringToInt(u"-0x42", 0U, false, true);
- testU16StringToInt(u"- 0x42", 0U, false, true);
+ testU16StringToInt(u"0x", 0U, false, true);
+ testU16StringToInt(u"0xnope", 0U, false, true);
+ testU16StringToInt(u"0X42", 0U, false, true);
+ testU16StringToInt(u"0x42 0x42", 0U, false, true);
+ testU16StringToInt(u"-0x0", 0U, false, true);
+ testU16StringToInt(u"-0x42", 0U, false, true);
+ testU16StringToInt(u"- 0x42", 0U, false, true);
- // Note that u" 42" would pass. This preserves the old behavior, but it may
- // not be desired.
- testU16StringToInt(u"42 ", 0U, false, false);
- testU16StringToInt(u"0x42 ", 0U, false, true);
+ // Note that u" 42" would pass. This preserves the old behavior, but it may
+ // not be desired.
+ testU16StringToInt(u"42 ", 0U, false, false);
+ testU16StringToInt(u"0x42 ", 0U, false, true);
- // Decimal cases.
- testU16StringToInt(u"0", 0U, true, false);
- testU16StringToInt(u"-0", 0U, true, false);
- testU16StringToInt(u"42", 42U, true, false);
- testU16StringToInt(u" 42", 42U, true, false);
- testU16StringToInt(u"-42", static_cast<uint32_t>(-42), true, false);
- testU16StringToInt(u" -42", static_cast<uint32_t>(-42), true, false);
- testU16StringToInt(u"042", 42U, true, false);
- testU16StringToInt(u"-042", static_cast<uint32_t>(-42), true, false);
+ // Decimal cases.
+ testU16StringToInt(u"0", 0U, true, false);
+ testU16StringToInt(u"-0", 0U, true, false);
+ testU16StringToInt(u"42", 42U, true, false);
+ testU16StringToInt(u" 42", 42U, true, false);
+ testU16StringToInt(u"-42", static_cast<uint32_t>(-42), true, false);
+ testU16StringToInt(u" -42", static_cast<uint32_t>(-42), true, false);
+ testU16StringToInt(u"042", 42U, true, false);
+ testU16StringToInt(u"-042", static_cast<uint32_t>(-42), true, false);
- // Hex cases.
- testU16StringToInt(u"0x0", 0x0, true, true);
- testU16StringToInt(u"0x42", 0x42, true, true);
- testU16StringToInt(u" 0x42", 0x42, true, true);
+ // Hex cases.
+ testU16StringToInt(u"0x0", 0x0, true, true);
+ testU16StringToInt(u"0x42", 0x42, true, true);
+ testU16StringToInt(u" 0x42", 0x42, true, true);
- // Just before overflow cases:
- testU16StringToInt(u"2147483647", INT_MAX, true, false);
- testU16StringToInt(u"-2147483648", static_cast<uint32_t>(INT_MIN), true,
- false);
- testU16StringToInt(u"0xffffffff", UINT_MAX, true, true);
+ // Just before overflow cases:
+ testU16StringToInt(u"2147483647", INT_MAX, true, false);
+ testU16StringToInt(u"-2147483648", static_cast<uint32_t>(INT_MIN), true,
+ false);
+ testU16StringToInt(u"0xffffffff", UINT_MAX, true, true);
- // Overflow cases:
- testU16StringToInt(u"2147483648", 0U, false, false);
- testU16StringToInt(u"-2147483649", 0U, false, false);
- testU16StringToInt(u"0x1ffffffff", 0U, false, true);
+ // Overflow cases:
+ testU16StringToInt(u"2147483648", 0U, false, false);
+ testU16StringToInt(u"-2147483649", 0U, false, false);
+ testU16StringToInt(u"0x1ffffffff", 0U, false, true);
}
TEST(ResTableTest, ShareButDontModifyResTable) {
- ResTable sharedTable;
- ASSERT_EQ(NO_ERROR, sharedTable.add(basic_arsc, basic_arsc_len));
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- ResTable_config param;
- memset(¶m, 0, sizeof(param));
- param.language[0] = 'v';
- param.language[1] = 's';
- sharedTable.setParameters(¶m);
+ ResTable sharedTable;
+ ASSERT_EQ(NO_ERROR, sharedTable.add(contents.data(), contents.size()));
- // Check that we get the default value for @integer:number1
- Res_value val;
- ssize_t block = sharedTable.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(600), val.data);
+ ResTable_config param;
+ memset(¶m, 0, sizeof(param));
+ param.language[0] = 'v';
+ param.language[1] = 's';
+ sharedTable.setParameters(¶m);
- // Create a new table that shares the entries of the shared table.
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(&sharedTable, false));
+ // Check that we get the default value for @integer:number1
+ Res_value val;
+ ssize_t block =
+ sharedTable.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(600), val.data);
- // Set a new configuration on the new table.
- memset(¶m, 0, sizeof(param));
- param.language[0] = 's';
- param.language[1] = 'v';
- param.country[0] = 'S';
- param.country[1] = 'E';
- table.setParameters(¶m);
+ // Create a new table that shares the entries of the shared table.
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(&sharedTable, false));
- // Check that we get a new value in the new table.
- block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(400), val.data);
+ // Set a new configuration on the new table.
+ memset(¶m, 0, sizeof(param));
+ param.language[0] = 's';
+ param.language[1] = 'v';
+ param.country[0] = 'S';
+ param.country[1] = 'E';
+ table.setParameters(¶m);
- // Check that we still get the old value in the shared table.
- block = sharedTable.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(600), val.data);
+ // Check that we get a new value in the new table.
+ block = table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(400), val.data);
+
+ // Check that we still get the old value in the shared table.
+ block =
+ sharedTable.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(600), val.data);
}
TEST(ResTableTest, GetConfigurationsReturnsUniqueList) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(system_arsc, system_arsc_len));
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- ResTable_config configSv;
- memset(&configSv, 0, sizeof(configSv));
- configSv.language[0] = 's';
- configSv.language[1] = 'v';
+ std::string system_contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/system/system.apk",
+ "resources.arsc", &system_contents));
- Vector<ResTable_config> configs;
- table.getConfigurations(&configs);
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(system_contents.data(), system_contents.size()));
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- EXPECT_EQ(1, std::count(configs.begin(), configs.end(), configSv));
+ ResTable_config configSv;
+ memset(&configSv, 0, sizeof(configSv));
+ configSv.language[0] = 's';
+ configSv.language[1] = 'v';
- Vector<String8> locales;
- table.getLocales(&locales);
+ Vector<ResTable_config> configs;
+ table.getConfigurations(&configs);
- EXPECT_EQ(1, std::count(locales.begin(), locales.end(), String8("sv")));
+ EXPECT_EQ(1, std::count(configs.begin(), configs.end(), configSv));
+
+ Vector<String8> locales;
+ table.getLocales(&locales);
+
+ EXPECT_EQ(1, std::count(locales.begin(), locales.end(), String8("sv")));
}
-} // namespace
+} // namespace android
diff --git a/libs/androidfw/tests/Split_test.cpp b/libs/androidfw/tests/Split_test.cpp
index b69d685..1f207e2 100644
--- a/libs/androidfw/tests/Split_test.cpp
+++ b/libs/androidfw/tests/Split_test.cpp
@@ -14,233 +14,254 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/ResourceTypes.h"
-#include <utils/String8.h>
-#include <utils/String16.h>
+#include "utils/String16.h"
+#include "utils/String8.h"
+
#include "TestHelpers.h"
#include "data/basic/R.h"
-#include <gtest/gtest.h>
+using com::android::basic::R;
-using namespace android;
+namespace android {
-namespace {
-
-/**
- * Include a binary resource table. This table
- * is a base table for an APK split.
- *
- * Package: com.android.test.basic
- */
-#include "data/basic/basic_arsc.h"
-
-/**
- * Include a binary resource table. This table
- * is a configuration split table for an APK split.
- *
- * Package: com.android.test.basic
- */
-#include "data/basic/split_de_fr_arsc.h"
-#include "data/basic/split_hdpi_v4_arsc.h"
-#include "data/basic/split_xhdpi_v4_arsc.h"
-#include "data/basic/split_xxhdpi_v4_arsc.h"
-
-/**
- * Include a binary resource table. This table
- * is a feature split table for an APK split.
- *
- * Package: com.android.test.basic
- */
-#include "data/feature/feature_arsc.h"
-
-enum { MAY_NOT_BE_BAG = false };
-
-void makeConfigFrench(ResTable_config* config) {
- memset(config, 0, sizeof(*config));
- config->language[0] = 'f';
- config->language[1] = 'r';
+static void makeConfigFrench(ResTable_config* config) {
+ memset(config, 0, sizeof(*config));
+ config->language[0] = 'f';
+ config->language[1] = 'r';
}
-TEST(SplitTest, TestLoadBase) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+class SplitTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &basic_contents_));
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic_de_fr.apk",
+ "resources.arsc", &basic_de_fr_contents_));
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic_hdpi-v4.apk",
+ "resources.arsc", &basic_hdpi_contents_));
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic_xhdpi-v4.apk",
+ "resources.arsc", &basic_xhdpi_contents_));
+ ASSERT_TRUE(ReadFileFromZipToString(
+ GetTestDataPath() + "/basic/basic_xxhdpi-v4.apk", "resources.arsc",
+ &basic_xxhdpi_contents_));
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk",
+ "resources.arsc", &feature_contents_));
+ }
+
+ protected:
+ std::string basic_contents_;
+ std::string basic_de_fr_contents_;
+ std::string basic_hdpi_contents_;
+ std::string basic_xhdpi_contents_;
+ std::string basic_xxhdpi_contents_;
+ std::string feature_contents_;
+};
+
+TEST_F(SplitTest, TestLoadBase) {
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
}
-TEST(SplitTest, TestGetResourceFromBase) {
- ResTable_config frenchConfig;
- makeConfigFrench(&frenchConfig);
+TEST_F(SplitTest, TestGetResourceFromBase) {
+ ResTable_config frenchConfig;
+ makeConfigFrench(&frenchConfig);
- ResTable table;
- table.setParameters(&frenchConfig);
+ ResTable table;
+ table.setParameters(&frenchConfig);
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
- ResTable_config expectedConfig;
- memset(&expectedConfig, 0, sizeof(expectedConfig));
+ ResTable_config expectedConfig;
+ memset(&expectedConfig, 0, sizeof(expectedConfig));
- Res_value val;
- ResTable_config config;
- ssize_t block = table.getResource(base::R::string::test1, &val, MAY_NOT_BE_BAG, 0, NULL, &config);
+ Res_value val;
+ ResTable_config config;
+ ssize_t block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
+ NULL, &config);
- // The returned block should tell us which string pool to get the value, if it is a string.
- EXPECT_GE(block, 0);
+ // The returned block should tell us which string pool to get the value, if it
+ // is a string.
+ EXPECT_GE(block, 0);
- // We expect the default resource to be selected since it is the only resource configuration.
- EXPECT_EQ(0, expectedConfig.compare(config));
+ // We expect the default resource to be selected since it is the only resource
+ // configuration.
+ EXPECT_EQ(0, expectedConfig.compare(config));
- EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
+ EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
}
-TEST(SplitTest, TestGetResourceFromSplit) {
- ResTable_config expectedConfig;
- makeConfigFrench(&expectedConfig);
+TEST_F(SplitTest, TestGetResourceFromSplit) {
+ ResTable_config expectedConfig;
+ makeConfigFrench(&expectedConfig);
- ResTable table;
- table.setParameters(&expectedConfig);
+ ResTable table;
+ table.setParameters(&expectedConfig);
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
- ASSERT_EQ(NO_ERROR, table.add(split_de_fr_arsc, split_de_fr_arsc_len));
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
+ ASSERT_EQ(NO_ERROR, table.add(basic_de_fr_contents_.data(),
+ basic_de_fr_contents_.size()));
- Res_value val;
- ResTable_config config;
- ssize_t block = table.getResource(base::R::string::test1, &val, MAY_NOT_BE_BAG, 0, NULL, &config);
+ Res_value val;
+ ResTable_config config;
+ ssize_t block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
+ NULL, &config);
- EXPECT_GE(block, 0);
+ EXPECT_GE(block, 0);
- EXPECT_EQ(0, expectedConfig.compare(config));
+ EXPECT_EQ(0, expectedConfig.compare(config));
- EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
+ EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
}
-TEST(SplitTest, ResourcesFromBaseAndSplitHaveSameNames) {
- ResTable_config expectedConfig;
- makeConfigFrench(&expectedConfig);
+TEST_F(SplitTest, ResourcesFromBaseAndSplitHaveSameNames) {
+ ResTable_config expectedConfig;
+ makeConfigFrench(&expectedConfig);
- ResTable table;
- table.setParameters(&expectedConfig);
+ ResTable table;
+ table.setParameters(&expectedConfig);
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
- ResTable::resource_name baseName;
- EXPECT_TRUE(table.getResourceName(base::R::string::test1, false, &baseName));
+ ResTable::resource_name baseName;
+ EXPECT_TRUE(table.getResourceName(R::string::test1, false, &baseName));
- ASSERT_EQ(NO_ERROR, table.add(split_de_fr_arsc, split_de_fr_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(basic_de_fr_contents_.data(),
+ basic_de_fr_contents_.size()));
- ResTable::resource_name frName;
- EXPECT_TRUE(table.getResourceName(base::R::string::test1, false, &frName));
+ ResTable::resource_name frName;
+ EXPECT_TRUE(table.getResourceName(R::string::test1, false, &frName));
- EXPECT_EQ(
- String16(baseName.package, baseName.packageLen),
+ EXPECT_EQ(String16(baseName.package, baseName.packageLen),
String16(frName.package, frName.packageLen));
- EXPECT_EQ(
- String16(baseName.type, baseName.typeLen),
+ EXPECT_EQ(String16(baseName.type, baseName.typeLen),
String16(frName.type, frName.typeLen));
- EXPECT_EQ(
- String16(baseName.name, baseName.nameLen),
+ EXPECT_EQ(String16(baseName.name, baseName.nameLen),
String16(frName.name, frName.nameLen));
}
-TEST(SplitTest, TypeEntrySpecFlagsAreUpdated) {
- ResTable_config defaultConfig;
- memset(&defaultConfig, 0, sizeof(defaultConfig));
+TEST_F(SplitTest, TypeEntrySpecFlagsAreUpdated) {
+ ResTable_config defaultConfig;
+ memset(&defaultConfig, 0, sizeof(defaultConfig));
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
- Res_value val;
- uint32_t specFlags = 0;
- ssize_t block = table.getResource(base::R::string::test1, &val, MAY_NOT_BE_BAG, 0, &specFlags, NULL);
- EXPECT_GE(block, 0);
+ Res_value val;
+ uint32_t specFlags = 0;
+ ssize_t block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
+ &specFlags, NULL);
+ EXPECT_GE(block, 0);
- EXPECT_EQ(static_cast<uint32_t>(0), specFlags);
+ EXPECT_EQ(static_cast<uint32_t>(0), specFlags);
- ASSERT_EQ(NO_ERROR, table.add(split_de_fr_arsc, split_de_fr_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(basic_de_fr_contents_.data(),
+ basic_de_fr_contents_.size()));
- uint32_t frSpecFlags = 0;
- block = table.getResource(base::R::string::test1, &val, MAY_NOT_BE_BAG, 0, &frSpecFlags, NULL);
- EXPECT_GE(block, 0);
+ uint32_t frSpecFlags = 0;
+ block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
+ &frSpecFlags, NULL);
+ EXPECT_GE(block, 0);
- EXPECT_EQ(ResTable_config::CONFIG_LOCALE, frSpecFlags);
+ EXPECT_EQ(ResTable_config::CONFIG_LOCALE, frSpecFlags);
}
-TEST(SplitTest, SelectBestDensity) {
- ResTable_config baseConfig;
- memset(&baseConfig, 0, sizeof(baseConfig));
- baseConfig.density = ResTable_config::DENSITY_XHIGH;
- baseConfig.sdkVersion = 21;
+TEST_F(SplitTest, SelectBestDensity) {
+ ResTable_config baseConfig;
+ memset(&baseConfig, 0, sizeof(baseConfig));
+ baseConfig.density = ResTable_config::DENSITY_XHIGH;
+ baseConfig.sdkVersion = 21;
- ResTable table;
- table.setParameters(&baseConfig);
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
- ASSERT_EQ(NO_ERROR, table.add(split_hdpi_v4_arsc, split_hdpi_v4_arsc_len));
+ ResTable table;
+ table.setParameters(&baseConfig);
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
+ ASSERT_EQ(NO_ERROR, table.add(basic_hdpi_contents_.data(),
+ basic_hdpi_contents_.size()));
- EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "hdpi"));
+ EXPECT_TRUE(IsStringEqual(table, R::string::density, "hdpi"));
- ASSERT_EQ(NO_ERROR, table.add(split_xhdpi_v4_arsc, split_xhdpi_v4_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(basic_xhdpi_contents_.data(),
+ basic_xhdpi_contents_.size()));
- EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xhdpi"));
+ EXPECT_TRUE(IsStringEqual(table, R::string::density, "xhdpi"));
- ASSERT_EQ(NO_ERROR, table.add(split_xxhdpi_v4_arsc, split_xxhdpi_v4_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(basic_xxhdpi_contents_.data(),
+ basic_xxhdpi_contents_.size()));
- EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xhdpi"));
+ EXPECT_TRUE(IsStringEqual(table, R::string::density, "xhdpi"));
- baseConfig.density = ResTable_config::DENSITY_XXHIGH;
- table.setParameters(&baseConfig);
+ baseConfig.density = ResTable_config::DENSITY_XXHIGH;
+ table.setParameters(&baseConfig);
- EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xxhdpi"));
+ EXPECT_TRUE(IsStringEqual(table, R::string::density, "xxhdpi"));
}
-TEST(SplitFeatureTest, TestNewResourceIsAccessible) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST_F(SplitTest, TestNewResourceIsAccessible) {
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
- Res_value val;
- ssize_t block = table.getResource(base::R::string::test3, &val, MAY_NOT_BE_BAG);
- EXPECT_LT(block, 0);
+ Res_value val;
+ ssize_t block = table.getResource(R::string::test3, &val, MAY_NOT_BE_BAG);
+ EXPECT_LT(block, 0);
- ASSERT_EQ(NO_ERROR, table.add(feature_arsc, feature_arsc_len));
+ ASSERT_EQ(NO_ERROR,
+ table.add(feature_contents_.data(), feature_contents_.size()));
- block = table.getResource(base::R::string::test3, &val, MAY_NOT_BE_BAG);
- EXPECT_GE(block, 0);
+ block = table.getResource(R::string::test3, &val, MAY_NOT_BE_BAG);
+ EXPECT_GE(block, 0);
- EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
+ EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
}
-TEST(SplitFeatureTest, TestNewResourceNameHasCorrectName) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST_F(SplitTest, TestNewResourceNameHasCorrectName) {
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
- ResTable::resource_name name;
- EXPECT_FALSE(table.getResourceName(base::R::string::test3, false, &name));
+ ResTable::resource_name name;
+ EXPECT_FALSE(table.getResourceName(R::string::test3, false, &name));
- ASSERT_EQ(NO_ERROR, table.add(feature_arsc, feature_arsc_len));
+ ASSERT_EQ(NO_ERROR,
+ table.add(feature_contents_.data(), feature_contents_.size()));
- ASSERT_TRUE(table.getResourceName(base::R::string::test3, false, &name));
+ ASSERT_TRUE(table.getResourceName(R::string::test3, false, &name));
- EXPECT_EQ(String16("com.android.test.basic"),
+ EXPECT_EQ(String16("com.android.basic"),
String16(name.package, name.packageLen));
- EXPECT_EQ(String16("string"),
- String16(name.type, name.typeLen));
+ EXPECT_EQ(String16("string"), String16(name.type, name.typeLen));
- EXPECT_EQ(String16("test3"),
- String16(name.name, name.nameLen));
+ EXPECT_EQ(String16("test3"), String16(name.name, name.nameLen));
}
-TEST(SplitFeatureTest, TestNewResourceIsAccessibleByName) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
- ASSERT_EQ(NO_ERROR, table.add(feature_arsc, feature_arsc_len));
+TEST_F(SplitTest, TestNewResourceIsAccessibleByName) {
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
+ ASSERT_EQ(NO_ERROR,
+ table.add(feature_contents_.data(), feature_contents_.size()));
- const String16 name("test3");
- const String16 type("string");
- const String16 package("com.android.test.basic");
- ASSERT_EQ(base::R::string::test3, table.identifierForName(name.string(), name.size(),
- type.string(), type.size(),
- package.string(), package.size()));
+ const String16 name("test3");
+ const String16 type("string");
+ const String16 package("com.android.basic");
+ ASSERT_EQ(
+ R::string::test3,
+ table.identifierForName(name.string(), name.size(), type.string(),
+ type.size(), package.string(), package.size()));
}
-} // namespace
+} // namespace
diff --git a/libs/androidfw/tests/TestHelpers.cpp b/libs/androidfw/tests/TestHelpers.cpp
index 702ee5c..2c834b1 100644
--- a/libs/androidfw/tests/TestHelpers.cpp
+++ b/libs/androidfw/tests/TestHelpers.cpp
@@ -19,6 +19,7 @@
#include <unistd.h>
#include "android-base/logging.h"
+#include "ziparchive/zip_archive.h"
namespace android {
@@ -31,8 +32,41 @@
return sTestDataPath;
}
-::testing::AssertionResult IsStringEqual(const ResTable& table,
- uint32_t resource_id,
+::testing::AssertionResult ReadFileFromZipToString(const std::string& zip_path,
+ const std::string& file,
+ std::string* out_contents) {
+ out_contents->clear();
+ ::ZipArchiveHandle handle;
+ int32_t result = OpenArchive(zip_path.c_str(), &handle);
+ if (result != 0) {
+ return ::testing::AssertionFailure() << "Failed to open zip '" << zip_path
+ << "': " << ::ErrorCodeString(result);
+ }
+
+ ::ZipString name(file.c_str());
+ ::ZipEntry entry;
+ result = ::FindEntry(handle, name, &entry);
+ if (result != 0) {
+ ::CloseArchive(handle);
+ return ::testing::AssertionFailure() << "Could not find file '" << file << "' in zip '"
+ << zip_path << "' : " << ::ErrorCodeString(result);
+ }
+
+ out_contents->resize(entry.uncompressed_length);
+ result = ::ExtractToMemory(
+ handle, &entry, const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(out_contents->data())),
+ out_contents->size());
+ if (result != 0) {
+ ::CloseArchive(handle);
+ return ::testing::AssertionFailure() << "Failed to extract file '" << file << "' from zip '"
+ << zip_path << "': " << ::ErrorCodeString(result);
+ }
+
+ ::CloseArchive(handle);
+ return ::testing::AssertionSuccess();
+}
+
+::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resource_id,
const char* expected_str) {
Res_value val;
ssize_t block = table.getResource(resource_id, &val, MAY_NOT_BE_BAG);
@@ -46,8 +80,7 @@
const ResStringPool* pool = table.getTableStringBlock(block);
if (pool == NULL) {
- return ::testing::AssertionFailure()
- << "table has no string pool for block " << block;
+ return ::testing::AssertionFailure() << "table has no string pool for block " << block;
}
const String8 actual_str = pool->string8ObjectAt(val.data);
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index c1e349f..d9cee22 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -25,13 +25,11 @@
#include "utils/String16.h"
#include "utils/String8.h"
-static inline ::std::ostream& operator<<(::std::ostream& out,
- const android::String8& str) {
+static inline ::std::ostream& operator<<(::std::ostream& out, const android::String8& str) {
return out << str.string();
}
-static inline ::std::ostream& operator<<(::std::ostream& out,
- const android::String16& str) {
+static inline ::std::ostream& operator<<(::std::ostream& out, const android::String16& str) {
return out << android::String8(str).string();
}
@@ -43,18 +41,19 @@
const std::string& GetTestDataPath();
-static inline bool operator==(const ResTable_config& a,
- const ResTable_config& b) {
+::testing::AssertionResult ReadFileFromZipToString(const std::string& zip_path,
+ const std::string& file,
+ std::string* out_contents);
+
+static inline bool operator==(const ResTable_config& a, const ResTable_config& b) {
return a.compare(b) == 0;
}
-static inline ::std::ostream& operator<<(::std::ostream& out,
- const ResTable_config& c) {
+static inline ::std::ostream& operator<<(::std::ostream& out, const ResTable_config& c) {
return out << c.toString().string();
}
-::testing::AssertionResult IsStringEqual(const ResTable& table,
- uint32_t resource_id,
+::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resource_id,
const char* expected_str);
} // namespace android
diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp
index 4d07130..3774657 100644
--- a/libs/androidfw/tests/Theme_test.cpp
+++ b/libs/androidfw/tests/Theme_test.cpp
@@ -14,55 +14,59 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/ResourceTypes.h"
-#include <utils/String8.h>
-#include <utils/String16.h>
+#include "utils/String16.h"
+#include "utils/String8.h"
+
#include "TestHelpers.h"
-#include "data/system/R.h"
#include "data/app/R.h"
+#include "data/system/R.h"
-#include <gtest/gtest.h>
+namespace app = com::android::app;
-using namespace android;
-
-namespace {
-
-#include "data/system/system_arsc.h"
-#include "data/app/app_arsc.h"
-
-enum { MAY_NOT_BE_BAG = false };
+namespace android {
/**
* TODO(adamlesinski): Enable when fixed.
*/
TEST(ThemeTest, DISABLED_shouldCopyThemeFromDifferentResTable) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(system_arsc, system_arsc_len));
- ASSERT_EQ(NO_ERROR, table.add(app_arsc, app_arsc_len));
+ ResTable table;
- ResTable::Theme theme1(table);
- ASSERT_EQ(NO_ERROR, theme1.applyStyle(app::R::style::Theme_One));
- Res_value val;
- ASSERT_GE(theme1.getAttribute(android::R::attr::background, &val), 0);
- ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
- ASSERT_EQ(uint32_t(0xffff0000), val.data);
- ASSERT_GE(theme1.getAttribute(app::R::attr::number, &val), 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(1), val.data);
+ std::string system_contents;
+ ASSERT_TRUE(ReadFileFromZipToString("/system/system.apk", "resources.arsc",
+ &system_contents));
+ ASSERT_EQ(NO_ERROR,
+ table.add(system_contents.data(), system_contents.size()));
- ResTable table2;
- ASSERT_EQ(NO_ERROR, table2.add(system_arsc, system_arsc_len));
- ASSERT_EQ(NO_ERROR, table2.add(app_arsc, app_arsc_len));
+ std::string app_contents;
+ ASSERT_TRUE(ReadFileFromZipToString("/basic/basic.apk", "resources.arsc",
+ &app_contents));
+ ASSERT_EQ(NO_ERROR, table.add(app_contents.data(), app_contents.size()));
- ResTable::Theme theme2(table2);
- ASSERT_EQ(NO_ERROR, theme2.setTo(theme1));
- ASSERT_GE(theme2.getAttribute(android::R::attr::background, &val), 0);
- ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
- ASSERT_EQ(uint32_t(0xffff0000), val.data);
- ASSERT_GE(theme2.getAttribute(app::R::attr::number, &val), 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(1), val.data);
+ ResTable::Theme theme1(table);
+ ASSERT_EQ(NO_ERROR, theme1.applyStyle(app::R::style::Theme_One));
+ Res_value val;
+ ASSERT_GE(theme1.getAttribute(android::R::attr::background, &val), 0);
+ ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
+ ASSERT_EQ(uint32_t(0xffff0000), val.data);
+ ASSERT_GE(theme1.getAttribute(app::R::attr::number, &val), 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(1), val.data);
+
+ ResTable table2;
+ ASSERT_EQ(NO_ERROR,
+ table2.add(system_contents.data(), system_contents.size()));
+ ASSERT_EQ(NO_ERROR, table2.add(app_contents.data(), app_contents.size()));
+
+ ResTable::Theme theme2(table2);
+ ASSERT_EQ(NO_ERROR, theme2.setTo(theme1));
+ ASSERT_GE(theme2.getAttribute(android::R::attr::background, &val), 0);
+ ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
+ ASSERT_EQ(uint32_t(0xffff0000), val.data);
+ ASSERT_GE(theme2.getAttribute(app::R::attr::number, &val), 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(1), val.data);
}
-}
+} // namespace android
diff --git a/libs/androidfw/tests/data/app/R.h b/libs/androidfw/tests/data/app/R.h
index 23e68e3..5be2eee 100644
--- a/libs/androidfw/tests/data/app/R.h
+++ b/libs/androidfw/tests/data/app/R.h
@@ -14,25 +14,31 @@
* limitations under the License.
*/
-#ifndef __APP_R_H
-#define __APP_R_H
+#ifndef TEST_DATA_APP_R_H_
+#define TEST_DATA_APP_R_H_
+#include <cstdint>
+
+namespace com {
+namespace android {
namespace app {
-namespace R {
-namespace attr {
- enum {
- number = 0x7f010000, // default
+struct R {
+ struct attr {
+ enum : uint32_t {
+ number = 0x7f010000, // default
};
-}
+ };
-namespace style {
- enum {
- Theme_One = 0x7f020000, // default
+ struct style {
+ enum : uint32_t {
+ Theme_One = 0x7f020000, // default
};
-}
+ };
+};
-} // namespace R
-} // namespace app
+} // namespace app
+} // namespace android
+} // namespace com
-#endif // __APP_R_H
+#endif // TEST_DATA_APP_R_H_
diff --git a/libs/androidfw/tests/data/app/app.apk b/libs/androidfw/tests/data/app/app.apk
new file mode 100644
index 0000000..ccb0824
--- /dev/null
+++ b/libs/androidfw/tests/data/app/app.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/app/app_arsc.h b/libs/androidfw/tests/data/app/app_arsc.h
deleted file mode 100644
index d5d9a3b..0000000
--- a/libs/androidfw/tests/data/app/app_arsc.h
+++ /dev/null
@@ -1,62 +0,0 @@
-unsigned char app_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0xc4, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x9c, 0x02, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00,
- 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6e, 0x00,
- 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00,
- 0x2e, 0x00, 0x4f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00
-};
-unsigned int app_arsc_len = 708;
diff --git a/libs/androidfw/tests/data/app/build b/libs/androidfw/tests/data/app/build
index 62257bc..d418158 100755
--- a/libs/androidfw/tests/data/app/build
+++ b/libs/androidfw/tests/data/app/build
@@ -15,7 +15,6 @@
# limitations under the License.
#
-aapt package -v -I ../system/bundle.apk -M AndroidManifest.xml -S res -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc app.arsc && \
-xxd -i app.arsc > app_arsc.h
+set -e
+
+aapt package -I ../system/system.apk -M AndroidManifest.xml -S res -F app.apk -f
diff --git a/libs/androidfw/tests/data/appaslib/R.h b/libs/androidfw/tests/data/appaslib/R.h
index 3af921a..5a21327 100644
--- a/libs/androidfw/tests/data/appaslib/R.h
+++ b/libs/androidfw/tests/data/appaslib/R.h
@@ -14,39 +14,53 @@
* limitations under the License.
*/
-#ifndef __APPASLIB_R_H
-#define __APPASLIB_R_H
+#ifndef DATA_APPASLIB_R_H_
+#define DATA_APPASLIB_R_H_
+#include <cstdint>
+
+namespace com {
+namespace android {
namespace appaslib {
-namespace R {
-namespace lib {
-namespace integer {
- enum {
- number1 = 0x02020000, // default
- };
-}
-namespace array {
- enum {
- integerArray1 = 0x02030000, // default
+namespace lib {
+
+struct R {
+ struct integer {
+ enum : uint32_t {
+ number1 = 0x02020000, // default
};
-}
-} // namespace lib
+ };
+
+ struct array {
+ enum : uint32_t {
+ integerArray1 = 0x02030000, // default
+ };
+ };
+};
+
+} // namespace lib
namespace app {
-namespace integer {
- enum {
- number1 = 0x7f020000, // default
- };
-}
-namespace array {
- enum {
- integerArray1 = 0x7f030000, // default
+struct R {
+ struct integer {
+ enum : uint32_t {
+ number1 = 0x7f020000, // default
};
-}
-} // namespace app
-} // namespace R
-} // namespace appaslib
+ };
-#endif // __APPASLIB_R_H
+ struct array {
+ enum : uint32_t {
+ integerArray1 = 0x7f030000, // default
+ };
+ };
+};
+
+} // namespace app
+
+} // namespace appaslib
+} // namespace android
+} // namespace com
+
+#endif // DATA_APPASLIB_R_H_
diff --git a/libs/androidfw/tests/data/appaslib/appaslib.apk b/libs/androidfw/tests/data/appaslib/appaslib.apk
new file mode 100644
index 0000000..6ebd823
--- /dev/null
+++ b/libs/androidfw/tests/data/appaslib/appaslib.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/appaslib/appaslib_arsc.h b/libs/androidfw/tests/data/appaslib/appaslib_arsc.h
deleted file mode 100644
index be176ab..0000000
--- a/libs/androidfw/tests/data/appaslib/appaslib_arsc.h
+++ /dev/null
@@ -1,68 +0,0 @@
-unsigned char appaslib_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x04, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xdc, 0x02, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
- 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00,
- 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00,
- 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0d, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00,
- 0x72, 0x00, 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x7f,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x03, 0x00, 0x00, 0x00
-};
-unsigned int appaslib_arsc_len = 772;
diff --git a/libs/androidfw/tests/data/appaslib/appaslib_lib.apk b/libs/androidfw/tests/data/appaslib/appaslib_lib.apk
new file mode 100644
index 0000000..ee1521c
--- /dev/null
+++ b/libs/androidfw/tests/data/appaslib/appaslib_lib.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/appaslib/appaslib_lib_arsc.h b/libs/androidfw/tests/data/appaslib/appaslib_lib_arsc.h
deleted file mode 100644
index 099285a..0000000
--- a/libs/androidfw/tests/data/appaslib/appaslib_lib_arsc.h
+++ /dev/null
@@ -1,68 +0,0 @@
-unsigned char appaslib_lib_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x04, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xdc, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
- 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00,
- 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00,
- 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0d, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00,
- 0x72, 0x00, 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x03, 0x00, 0x00, 0x00
-};
-unsigned int appaslib_lib_arsc_len = 772;
diff --git a/libs/androidfw/tests/data/appaslib/build b/libs/androidfw/tests/data/appaslib/build
index e4bd88b..baaf700 100755
--- a/libs/androidfw/tests/data/appaslib/build
+++ b/libs/androidfw/tests/data/appaslib/build
@@ -15,14 +15,9 @@
# limitations under the License.
#
+set -e
+
PATH_TO_FRAMEWORK_RES=$(gettop)/prebuilts/sdk/current/android.jar
-aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc appaslib.arsc && \
-xxd -i appaslib.arsc > appaslib_arsc.h && \
-aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES -F bundle.apk -f --shared-lib && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc appaslib_lib.arsc && \
-xxd -i appaslib_lib.arsc > appaslib_lib_arsc.h \
-
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES -F appaslib.apk -f
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES -F appaslib_lib.apk -f --shared-lib
diff --git a/libs/androidfw/tests/data/basic/AndroidManifest.xml b/libs/androidfw/tests/data/basic/AndroidManifest.xml
index a56ac18..b117882 100644
--- a/libs/androidfw/tests/data/basic/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/basic/AndroidManifest.xml
@@ -15,7 +15,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.test.basic">
- <application>
- </application>
+ package="com.android.basic">
+ <application />
</manifest>
diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h
index 6694dd0..9352b5c 100644
--- a/libs/androidfw/tests/data/basic/R.h
+++ b/libs/androidfw/tests/data/basic/R.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,59 +14,67 @@
* limitations under the License.
*/
-#ifndef __BASE_R_H
-#define __BASE_R_H
+#ifndef TESTS_DATA_BASIC_R_H_
+#define TESTS_DATA_BASIC_R_H_
-namespace base {
-namespace R {
+#include <cstdint>
-namespace attr {
- enum {
- attr1 = 0x7f010000, // default
- attr2 = 0x7f010001, // default
+namespace com {
+namespace android {
+namespace basic {
+
+struct R {
+ struct attr {
+ enum : uint32_t {
+ attr1 = 0x7f010000,
+ attr2 = 0x7f010001,
};
-}
+ };
-namespace layout {
- enum {
- main = 0x7f020000, // default, fr-sw600dp-v13
+ struct layout {
+ enum : uint32_t {
+ main = 0x7f020000,
};
-}
+ };
-namespace string {
- enum {
- test1 = 0x7f030000, // default
- test2 = 0x7f030001, // default
- density = 0x7f030002, // default
+ struct string {
+ enum : uint32_t {
+ test1 = 0x7f030000,
+ test2 = 0x7f030001,
+ density = 0x7f030002,
- test3 = 0x7f080000, // default (in feature)
- test4 = 0x7f080001, // default (in feature)
+ // From feature
+ test3 = 0x7f080000,
+ test4 = 0x7f080001,
};
-}
+ };
-namespace integer {
- enum {
- number1 = 0x7f040000, // default, sv, vs
- number2 = 0x7f040001, // default
+ struct integer {
+ enum : uint32_t {
+ number1 = 0x7f040000,
+ number2 = 0x7f040001,
- test3 = 0x7f090000, // default (in feature)
+ // From feature
+ number3 = 0x7f090000,
};
-}
+ };
-namespace style {
- enum {
- Theme1 = 0x7f050000, // default
- Theme2 = 0x7f050001, // default
+ struct style {
+ enum : uint32_t {
+ Theme1 = 0x7f050000,
+ Theme2 = 0x7f050001,
};
-}
+ };
-namespace array {
- enum {
- integerArray1 = 0x7f060000, // default
+ struct array {
+ enum : uint32_t {
+ integerArray1 = 0x7f060000,
};
-}
+ };
+};
-} // namespace R
-} // namespace base
+} // namespace basic
+} // namespace android
+} // namespace com
-#endif // __BASE_R_H
+#endif /* TESTS_DATA_BASIC_R_H_ */
diff --git a/libs/androidfw/tests/data/basic/basic.apk b/libs/androidfw/tests/data/basic/basic.apk
new file mode 100644
index 0000000..2d71f5b
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/basic.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_arsc.h b/libs/androidfw/tests/data/basic/basic_arsc.h
deleted file mode 100644
index e497401..0000000
--- a/libs/androidfw/tests/data/basic/basic_arsc.h
+++ /dev/null
@@ -1,175 +0,0 @@
-unsigned char basic_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x13, 0x00, 0x72, 0x00,
- 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x2f, 0x00, 0x6d, 0x00, 0x61, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c, 0x00,
- 0x00, 0x00, 0x22, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00,
- 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00,
- 0x2d, 0x00, 0x66, 0x00, 0x72, 0x00, 0x2d, 0x00, 0x73, 0x00, 0x77, 0x00,
- 0x36, 0x00, 0x30, 0x00, 0x30, 0x00, 0x64, 0x00, 0x70, 0x00, 0x2d, 0x00,
- 0x76, 0x00, 0x31, 0x00, 0x33, 0x00, 0x2f, 0x00, 0x6d, 0x00, 0x61, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
- 0x44, 0x07, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
- 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
- 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
- 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00,
- 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00,
- 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00,
- 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0xec, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
- 0x88, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x74, 0x00,
- 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6d, 0x00,
- 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00,
- 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00,
- 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00,
- 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x32, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00,
- 0x6d, 0x00, 0x65, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x31, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x8c, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x08, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x04, 0x24, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x4c, 0x00, 0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x4c, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
- 0xc8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x4c, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x76, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x58, 0x02, 0x00, 0x00,
- 0x01, 0x02, 0x4c, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
- 0x90, 0x01, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x98, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f,
- 0x08, 0x00, 0x00, 0x10, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f,
- 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x7f, 0x10, 0x00, 0x01, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7f, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x2c, 0x01, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x84, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
- 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02,
- 0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02,
- 0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00
-};
-unsigned int basic_arsc_len = 2060;
diff --git a/libs/androidfw/tests/data/basic/basic_de_fr.apk b/libs/androidfw/tests/data/basic/basic_de_fr.apk
new file mode 100644
index 0000000..69a2f30
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/basic_de_fr.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_hdpi-v4.apk b/libs/androidfw/tests/data/basic/basic_hdpi-v4.apk
new file mode 100644
index 0000000..011808b
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/basic_hdpi-v4.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_xhdpi-v4.apk b/libs/androidfw/tests/data/basic/basic_xhdpi-v4.apk
new file mode 100644
index 0000000..6d4353c
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/basic_xhdpi-v4.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_xxhdpi-v4.apk b/libs/androidfw/tests/data/basic/basic_xxhdpi-v4.apk
new file mode 100644
index 0000000..e3bda88
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/basic_xxhdpi-v4.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/build b/libs/androidfw/tests/data/basic/build
index fd289fa..68b911a 100755
--- a/libs/androidfw/tests/data/basic/build
+++ b/libs/androidfw/tests/data/basic/build
@@ -15,25 +15,8 @@
# limitations under the License.
#
+set -e
+
PATH_TO_FRAMEWORK_RES=$(gettop)/prebuilts/sdk/current/android.jar
-aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --split hdpi --split xhdpi --split xxhdpi --split fr,de -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc basic.arsc && \
-xxd -i basic.arsc > basic_arsc.h && \
-\
-unzip bundle_de_fr.apk resources.arsc && \
-mv resources.arsc split_de_fr.arsc && \
-xxd -i split_de_fr.arsc > split_de_fr_arsc.h && \
-\
-unzip bundle_hdpi-v4.apk resources.arsc && \
-mv resources.arsc split_hdpi_v4.arsc && \
-xxd -i split_hdpi_v4.arsc > split_hdpi_v4_arsc.h && \
-\
-unzip bundle_xhdpi-v4.apk resources.arsc && \
-mv resources.arsc split_xhdpi_v4.arsc && \
-xxd -i split_xhdpi_v4.arsc > split_xhdpi_v4_arsc.h && \
-\
-unzip bundle_xxhdpi-v4.apk resources.arsc && \
-mv resources.arsc split_xxhdpi_v4.arsc && \
-xxd -i split_xxhdpi_v4.arsc > split_xxhdpi_v4_arsc.h \
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --split hdpi --split xhdpi --split xxhdpi --split fr,de -F basic.apk -f
diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml
index a010cca..75e0435 100644
--- a/libs/androidfw/tests/data/basic/res/values/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values/values.xml
@@ -25,12 +25,12 @@
<integer name="number2">@array/integerArray1</integer>
<style name="Theme1">
- <item name="com.android.test.basic:attr1">100</item>
- <item name="com.android.test.basic:attr2">@integer/number1</item>
+ <item name="com.android.basic:attr1">100</item>
+ <item name="com.android.basic:attr2">@integer/number1</item>
</style>
- <style name="Theme2" parent="@com.android.test.basic:style/Theme1">
- <item name="com.android.test.basic:attr1">300</item>
+ <style name="Theme2" parent="@com.android.basic:style/Theme1">
+ <item name="com.android.basic:attr1">300</item>
</style>
<integer-array name="integerArray1">
diff --git a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h b/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
deleted file mode 100644
index a2aa598..0000000
--- a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
+++ /dev/null
@@ -1,88 +0,0 @@
-unsigned char split_de_fr_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0xf4, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x76, 0x00,
- 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x75, 0x00, 0x63, 0x00, 0x68, 0x00,
- 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x09, 0x00, 0x76, 0x00, 0x65, 0x00,
- 0x72, 0x00, 0x73, 0x00, 0x75, 0x00, 0x63, 0x00, 0x68, 0x00, 0x20, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x07, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00,
- 0x61, 0x00, 0x69, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00,
- 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x20, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x6c, 0x03, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x90, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
- 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00,
- 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00,
- 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00,
- 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00,
- 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
- 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-unsigned int split_de_fr_arsc_len = 1012;
diff --git a/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
deleted file mode 100644
index 0cc3915..0000000
--- a/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-unsigned char split_hdpi_v4_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x10, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00,
- 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
- 0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
- 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
- 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
- 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00,
- 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00,
- 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00,
- 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00,
- 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-unsigned int split_hdpi_v4_arsc_len = 784;
diff --git a/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
deleted file mode 100644
index d44ba96..0000000
--- a/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-unsigned char split_xhdpi_v4_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x14, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x78, 0x00,
- 0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x20, 0x01, 0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
- 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00,
- 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00,
- 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xb0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00,
- 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00,
- 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00,
- 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-unsigned int split_xhdpi_v4_arsc_len = 788;
diff --git a/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
deleted file mode 100644
index 2f3f682..0000000
--- a/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-unsigned char split_xxhdpi_v4_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x14, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x78, 0x00,
- 0x78, 0x00, 0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x20, 0x01, 0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
- 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00,
- 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00,
- 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xb0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00,
- 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00,
- 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00,
- 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-unsigned int split_xxhdpi_v4_arsc_len = 788;
diff --git a/libs/androidfw/tests/data/feature/AndroidManifest.xml b/libs/androidfw/tests/data/feature/AndroidManifest.xml
index c2343b7..c972372 100644
--- a/libs/androidfw/tests/data/feature/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/feature/AndroidManifest.xml
@@ -15,5 +15,5 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.test.basic">
+ package="com.android.basic">
</manifest>
diff --git a/libs/androidfw/tests/data/feature/build b/libs/androidfw/tests/data/feature/build
index 0f3307f..3316e41 100755
--- a/libs/androidfw/tests/data/feature/build
+++ b/libs/androidfw/tests/data/feature/build
@@ -15,7 +15,6 @@
# limitations under the License.
#
-aapt package -M AndroidManifest.xml -S res --feature-of ../basic/bundle.apk -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc feature.arsc && \
-xxd -i feature.arsc > feature_arsc.h
+set -e
+
+aapt package -M AndroidManifest.xml -S res --feature-of ../basic/basic.apk -F feature.apk -f
diff --git a/libs/androidfw/tests/data/feature/feature.apk b/libs/androidfw/tests/data/feature/feature.apk
new file mode 100644
index 0000000..1e65c27
--- /dev/null
+++ b/libs/androidfw/tests/data/feature/feature.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/feature/feature_arsc.h b/libs/androidfw/tests/data/feature/feature_arsc.h
deleted file mode 100644
index cd29910..0000000
--- a/libs/androidfw/tests/data/feature/feature_arsc.h
+++ /dev/null
@@ -1,73 +0,0 @@
-unsigned char feature_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x44, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x33, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xf8, 0x02, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x3c, 0x00,
- 0x65, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x74, 0x00, 0x79, 0x00, 0x3e, 0x00,
- 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x33, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x73, 0x00, 0x74, 0x00, 0x34, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00,
- 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x33, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x10, 0xc8, 0x00, 0x00, 0x00
-};
-unsigned int feature_arsc_len = 836;
diff --git a/libs/androidfw/tests/data/lib/AndroidManifest.xml b/libs/androidfw/tests/data/lib/AndroidManifest.xml
index a56ac18..02f5d3e 100644
--- a/libs/androidfw/tests/data/lib/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/lib/AndroidManifest.xml
@@ -15,7 +15,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.test.basic">
- <application>
- </application>
+ package="com.android.lib">
+ <application />
</manifest>
diff --git a/libs/androidfw/tests/data/lib/R.h b/libs/androidfw/tests/data/lib/R.h
index 6013973..bb22d22 100644
--- a/libs/androidfw/tests/data/lib/R.h
+++ b/libs/androidfw/tests/data/lib/R.h
@@ -14,26 +14,32 @@
* limitations under the License.
*/
-#ifndef __LIB_R_H
-#define __LIB_R_H
+#ifndef TEST_DATA_LIB_R_H_
+#define TEST_DATA_LIB_R_H_
+#include <cstdint>
+
+namespace com {
+namespace android {
namespace lib {
-namespace R {
-namespace attr {
- enum {
- attr1 = 0x02010000, // default
- attr2 = 0x02010001, // default
+struct R {
+ struct attr {
+ enum : uint32_t {
+ attr1 = 0x02010000, // default
+ attr2 = 0x02010001, // default
};
-}
+ };
-namespace style {
- enum {
- Theme = 0x02020000, // default
+ struct style {
+ enum : uint32_t {
+ Theme = 0x02020000, // default
};
-}
+ };
+};
-} // namespace R
-} // namespace lib
+} // namespace lib
+} // namespace android
+} // namespace com
-#endif // __LIB_R_H
+#endif // TEST_DATA_R_H_
diff --git a/libs/androidfw/tests/data/lib/build b/libs/androidfw/tests/data/lib/build
index 4102903..5c3d02c 100755
--- a/libs/androidfw/tests/data/lib/build
+++ b/libs/androidfw/tests/data/lib/build
@@ -15,7 +15,6 @@
# limitations under the License.
#
-aapt package -M AndroidManifest.xml -S res -F bundle.apk -f --shared-lib && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc lib.arsc && \
-xxd -i lib.arsc > lib_arsc.h
+set -e
+
+aapt package -M AndroidManifest.xml -S res -F lib.apk -f --shared-lib
diff --git a/libs/androidfw/tests/data/lib/lib.apk b/libs/androidfw/tests/data/lib/lib.apk
new file mode 100644
index 0000000..44c27c7
--- /dev/null
+++ b/libs/androidfw/tests/data/lib/lib.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/lib/lib_arsc.h b/libs/androidfw/tests/data/lib/lib_arsc.h
deleted file mode 100644
index 62bed65..0000000
--- a/libs/androidfw/tests/data/lib/lib_arsc.h
+++ /dev/null
@@ -1,68 +0,0 @@
-unsigned char lib_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xe4, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00,
- 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x05, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00,
- 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
- 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x4c, 0x00, 0x78, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x10, 0xbc, 0x02, 0x00, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00
-};
-unsigned int lib_arsc_len = 780;
diff --git a/libs/androidfw/tests/data/lib/res/values/values.xml b/libs/androidfw/tests/data/lib/res/values/values.xml
index ec8117a7..51e3a40 100644
--- a/libs/androidfw/tests/data/lib/res/values/values.xml
+++ b/libs/androidfw/tests/data/lib/res/values/values.xml
@@ -19,7 +19,7 @@
<attr name="attr2" format="integer" />
<style name="Theme">
- <item name="com.android.test.basic:attr1">700</item>
- <item name="com.android.test.basic:attr2">?com.android.test.basic:attr1</item>
+ <item name="com.android.lib:attr1">700</item>
+ <item name="com.android.lib:attr2">?com.android.lib:attr1</item>
</style>
</resources>
diff --git a/libs/androidfw/tests/data/overlay/build b/libs/androidfw/tests/data/overlay/build
index f737677..112f373 100755
--- a/libs/androidfw/tests/data/overlay/build
+++ b/libs/androidfw/tests/data/overlay/build
@@ -15,7 +15,6 @@
# limitations under the License.
#
-aapt package -M AndroidManifest.xml -S res -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc overlay.arsc && \
-xxd -i overlay.arsc > overlay_arsc.h
+set -e
+
+aapt package -M AndroidManifest.xml -S res -F overlay.apk -f
diff --git a/libs/androidfw/tests/data/overlay/overlay.apk b/libs/androidfw/tests/data/overlay/overlay.apk
new file mode 100644
index 0000000..e0e0543
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/overlay_arsc.h b/libs/androidfw/tests/data/overlay/overlay_arsc.h
deleted file mode 100644
index 5bd98b2..0000000
--- a/libs/androidfw/tests/data/overlay/overlay_arsc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-unsigned char overlay_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x10, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x74, 0x00,
- 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x6f, 0x00,
- 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xc4, 0x02, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
- 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x50, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x69, 0x00, 0x6e, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x41, 0x00,
- 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x0b, 0x00, 0x00, 0x00
-};
-unsigned int overlay_arsc_len = 784;
diff --git a/libs/androidfw/tests/data/styles/R.h b/libs/androidfw/tests/data/styles/R.h
index 6dc6ede..4127aa0 100644
--- a/libs/androidfw/tests/data/styles/R.h
+++ b/libs/androidfw/tests/data/styles/R.h
@@ -1,3 +1,22 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_DATA_STYLES_R_H_
+#define TEST_DATA_STYLES_R_H_
+
#include <cstdint>
namespace com {
@@ -17,9 +36,9 @@
};
struct string {
- enum : uint32_t {
- string_one = 0x7f030000u,
- };
+ enum : uint32_t {
+ string_one = 0x7f030000u,
+ };
};
struct style {
@@ -33,3 +52,5 @@
} // namespace app
} // namespace android
} // namespace com
+
+#endif // TEST_DATA_STYLES_R_H_
diff --git a/libs/androidfw/tests/data/styles/build b/libs/androidfw/tests/data/styles/build
new file mode 100755
index 0000000..81f78b1
--- /dev/null
+++ b/libs/androidfw/tests/data/styles/build
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+set -e
+
+aapt package -F styles.apk -M AndroidManifest.xml -S res -f
diff --git a/libs/androidfw/tests/data/styles/build.sh b/libs/androidfw/tests/data/styles/build.sh
deleted file mode 100755
index e763421..0000000
--- a/libs/androidfw/tests/data/styles/build.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-set -e
-
-aapt package -F package.apk -M AndroidManifest.xml -S res
-unzip -j package.apk resources.arsc res/layout/layout.xml
-rm package.apk
diff --git a/libs/androidfw/tests/data/styles/layout.xml b/libs/androidfw/tests/data/styles/layout.xml
deleted file mode 100644
index 4997e71..0000000
--- a/libs/androidfw/tests/data/styles/layout.xml
+++ /dev/null
Binary files differ
diff --git a/libs/androidfw/tests/data/styles/resources.arsc b/libs/androidfw/tests/data/styles/resources.arsc
deleted file mode 100644
index 8f65c9a..0000000
--- a/libs/androidfw/tests/data/styles/resources.arsc
+++ /dev/null
Binary files differ
diff --git a/libs/androidfw/tests/data/styles/styles.apk b/libs/androidfw/tests/data/styles/styles.apk
new file mode 100644
index 0000000..6064c48
--- /dev/null
+++ b/libs/androidfw/tests/data/styles/styles.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/system/R.h b/libs/androidfw/tests/data/system/R.h
index 6a31fb8..becb388 100644
--- a/libs/androidfw/tests/data/system/R.h
+++ b/libs/androidfw/tests/data/system/R.h
@@ -14,32 +14,34 @@
* limitations under the License.
*/
-#ifndef __ANDROID_R_H
-#define __ANDROID_R_H
+#ifndef TEST_DATA_SYSTEM_R_H_
+#define TEST_DATA_SYSTEM_R_H_
+
+#include <cstdint>
namespace android {
-namespace R {
-namespace attr {
- enum {
- background = 0x01010000, // default
- foreground = 0x01010001, // default
+struct R {
+ struct attr {
+ enum : uint32_t {
+ background = 0x01010000, // default
+ foreground = 0x01010001, // default
};
-}
+ };
-namespace style {
- enum {
- Theme_One = 0x01020000, // default
+ struct style {
+ enum : uint32_t {
+ Theme_One = 0x01020000, // default
};
-}
+ };
-namespace integer {
- enum {
- number = 0x01030000, // sv
+ struct integer {
+ enum : uint32_t {
+ number = 0x01030000, // sv
};
-}
+ };
+};
-} // namespace R
-} // namespace android
+} // namespace android
-#endif // __ANDROID_R_H
+#endif // TEST_DATA_SYSTEM_R_H_
diff --git a/libs/androidfw/tests/data/system/build b/libs/androidfw/tests/data/system/build
index 1a70e84..bfbdf4c 100755
--- a/libs/androidfw/tests/data/system/build
+++ b/libs/androidfw/tests/data/system/build
@@ -15,7 +15,6 @@
# limitations under the License.
#
-aapt package -x -M AndroidManifest.xml -S res -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc system.arsc && \
-xxd -i system.arsc > system_arsc.h
+set -e
+
+aapt package -x -M AndroidManifest.xml -S res -F system.apk -f
diff --git a/libs/androidfw/tests/data/system/system.apk b/libs/androidfw/tests/data/system/system.apk
new file mode 100644
index 0000000..1299016
--- /dev/null
+++ b/libs/androidfw/tests/data/system/system.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/system/system_arsc.h b/libs/androidfw/tests/data/system/system_arsc.h
deleted file mode 100644
index b0dab6b..0000000
--- a/libs/androidfw/tests/data/system/system_arsc.h
+++ /dev/null
@@ -1,88 +0,0 @@
-unsigned char system_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0xf8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xd0, 0x03, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
- 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x78, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00,
- 0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x5e, 0x00,
- 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x2d, 0x00, 0x70, 0x00,
- 0x72, 0x00, 0x69, 0x00, 0x76, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x84, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x62, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x67, 0x00,
- 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x67, 0x00,
- 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00,
- 0x2e, 0x00, 0x4f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00,
- 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x4c, 0x00, 0x8c, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x08, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x4c, 0x00,
- 0x78, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
- 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x01, 0x01,
- 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x4c, 0x00, 0x60, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-unsigned int system_arsc_len = 1016;
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index cf571e9..21ebe5f 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -46,6 +46,7 @@
renderthread/RenderTask.cpp \
renderthread/RenderThread.cpp \
renderthread/TimeLord.cpp \
+ renderthread/Frame.cpp \
thread/TaskManager.cpp \
utils/Blur.cpp \
utils/GLUtils.cpp \
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index 7e2c28c..489039c2 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -202,17 +202,17 @@
// Clip
///////////////////////////////////////////////////////////////////////////////
-bool CanvasState::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+bool CanvasState::clipRect(float left, float top, float right, float bottom, SkClipOp op) {
mSnapshot->clip(Rect(left, top, right, bottom), op);
return !mSnapshot->clipIsEmpty();
}
-bool CanvasState::clipPath(const SkPath* path, SkRegion::Op op) {
+bool CanvasState::clipPath(const SkPath* path, SkClipOp op) {
mSnapshot->clipPath(*path, op);
return !mSnapshot->clipIsEmpty();
}
-bool CanvasState::clipRegion(const SkRegion* region, SkRegion::Op op) {
+bool CanvasState::clipRegion(const SkRegion* region, SkClipOp op) {
mSnapshot->clipRegionTransformed(*region, op);
return !mSnapshot->clipIsEmpty();
}
@@ -225,7 +225,7 @@
bool outlineIsRounded = MathUtils::isPositive(radius);
if (!outlineIsRounded || currentTransform()->isSimple()) {
// TODO: consider storing this rect separately, so that this can't be replaced with clip ops
- clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkRegion::kIntersect_Op);
+ clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, kIntersect_SkClipOp);
}
if (outlineIsRounded) {
setClippingRoundRect(allocator, bounds, radius, false);
diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h
index 22c7e8a..a805597 100644
--- a/libs/hwui/CanvasState.h
+++ b/libs/hwui/CanvasState.h
@@ -18,6 +18,7 @@
#include "Snapshot.h"
+#include <SkClipOp.h>
#include <SkMatrix.h>
#include <SkPath.h>
#include <SkRegion.h>
@@ -121,9 +122,9 @@
bool quickRejectConservative(float left, float top, float right, float bottom) const;
- bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- bool clipPath(const SkPath* path, SkRegion::Op op);
- bool clipRegion(const SkRegion* region, SkRegion::Op op);
+ bool clipRect(float left, float top, float right, float bottom, SkClipOp op);
+ bool clipPath(const SkPath* path, SkClipOp op);
+ bool clipRegion(const SkRegion* region, SkClipOp op);
/**
* Sets a "clipping outline", which is independent from the regular clip.
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 245db1d..5b683e0 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -120,7 +120,7 @@
mCanvasState.save(SaveFlags::MatrixClip);
mCanvasState.translate(tx, ty);
mCanvasState.clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
- SkRegion::kIntersect_Op);
+ kIntersect_SkClipOp);
deferNodePropsAndOps(renderNode);
mCanvasState.restore();
}
@@ -262,7 +262,7 @@
Rect clipRect;
properties.getClippingRectForFlags(clipFlags, &clipRect);
mCanvasState.clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
- SkRegion::kIntersect_Op);
+ kIntersect_SkClipOp);
}
if (properties.getRevealClip().willClip()) {
diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp
index 408159b..74a8395 100644
--- a/libs/hwui/OpenGLReadback.cpp
+++ b/libs/hwui/OpenGLReadback.cpp
@@ -82,8 +82,15 @@
return CopyResult::UnknownError;
}
- CopyResult copyResult = copyImageInto(sourceImage, texTransform, graphicBuffer->getWidth(),
- graphicBuffer->getHeight(), srcRect, bitmap);
+ uint32_t width = graphicBuffer->getWidth();
+ uint32_t height = graphicBuffer->getHeight();
+ // If this is a 90 or 270 degree rotation we need to swap width/height
+ // This is a fuzzy way of checking that.
+ if (texTransform[Matrix4::kSkewX] >= 0.5f || texTransform[Matrix4::kSkewX] <= -0.5f) {
+ std::swap(width, height);
+ }
+ CopyResult copyResult = copyImageInto(sourceImage, texTransform, width, height,
+ srcRect, bitmap);
// All we're flushing & finishing is the deletion of the texture since
// copyImageInto already did a major flush & finish as an implicit
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 9d18484..96c6d29 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -234,13 +234,13 @@
SkRect bounds = path.getBounds();
return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
}
-bool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+bool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkClipOp op) {
return mState.clipRect(left, top, right, bottom, op);
}
-bool RecordingCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
+bool RecordingCanvas::clipPath(const SkPath* path, SkClipOp op) {
return mState.clipPath(path, op);
}
-bool RecordingCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
+bool RecordingCanvas::clipRegion(const SkRegion* region, SkClipOp op) {
return mState.clipRegion(region, op);
}
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index f93e8b8..5d49385 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -131,9 +131,10 @@
virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
virtual bool quickRejectPath(const SkPath& path) const override;
- virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) override;
- virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
- virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
+ virtual bool clipRect(float left, float top, float right, float bottom,
+ SkClipOp op) override;
+ virtual bool clipPath(const SkPath* path, SkClipOp op) override;
+ virtual bool clipRegion(const SkRegion* region, SkClipOp op) override;
// Misc
virtual SkDrawFilter* getDrawFilter() override { return mDrawFilter.get(); }
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 6786a69..8ab57c9d 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -78,13 +78,13 @@
public:
explicit ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
- virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
+ virtual void clipRect(const SkRect& rect, SkClipOp op, bool antialias) {
m_dstCanvas->clipRect(rect, op, antialias);
}
- virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
+ virtual void clipRRect(const SkRRect& rrect, SkClipOp op, bool antialias) {
m_dstCanvas->clipRRect(rrect, op, antialias);
}
- virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
+ virtual void clipPath(const SkPath& path, SkClipOp op, bool antialias) {
m_dstCanvas->clipPath(path, op, antialias);
}
@@ -218,11 +218,11 @@
class SkiaCanvas::Clip {
public:
- Clip(const SkRect& rect, SkRegion::Op op, const SkMatrix& m)
+ Clip(const SkRect& rect, SkClipOp op, const SkMatrix& m)
: mType(Type::Rect), mOp(op), mMatrix(m), mRRect(SkRRect::MakeRect(rect)) {}
- Clip(const SkRRect& rrect, SkRegion::Op op, const SkMatrix& m)
+ Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m)
: mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
- Clip(const SkPath& path, SkRegion::Op op, const SkMatrix& m)
+ Clip(const SkPath& path, SkClipOp op, const SkMatrix& m)
: mType(Type::Path), mOp(op), mMatrix(m), mPath(&path) {}
void apply(SkCanvas* canvas) const {
@@ -247,9 +247,9 @@
Path,
};
- Type mType;
- SkRegion::Op mOp;
- SkMatrix mMatrix;
+ Type mType;
+ SkClipOp mOp;
+ SkMatrix mMatrix;
// These are logically a union (tracked separately due to non-POD path).
SkTLazy<SkPath> mPath;
@@ -293,7 +293,7 @@
}
template <typename T>
-void SkiaCanvas::recordClip(const T& clip, SkRegion::Op op) {
+void SkiaCanvas::recordClip(const T& clip, SkClipOp op) {
// Only need tracking when in a partial save frame which
// doesn't restore the clip.
const SaveRec* rec = this->currentSaveRec();
@@ -397,14 +397,14 @@
return mCanvas->quickReject(path);
}
-bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkClipOp op) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
this->recordClip(rect, op);
mCanvas->clipRect(rect, op);
return !mCanvas->isClipEmpty();
}
-bool SkiaCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
+bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) {
SkRRect roundRect;
if (path->isRRect(&roundRect)) {
this->recordClip(roundRect, op);
@@ -416,7 +416,7 @@
return !mCanvas->isClipEmpty();
}
-bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
+bool SkiaCanvas::clipRegion(const SkRegion* region, SkClipOp op) {
SkPath rgnPath;
if (region->getBoundaryPath(&rgnPath)) {
// The region is specified in device space.
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 4f1d857..9639ebd 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -92,9 +92,9 @@
virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
virtual bool quickRejectPath(const SkPath& path) const override;
virtual bool clipRect(float left, float top, float right, float bottom,
- SkRegion::Op op) override;
- virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
- virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
+ SkClipOp op) override;
+ virtual bool clipPath(const SkPath* path, SkClipOp op) override;
+ virtual bool clipRegion(const SkRegion* region, SkClipOp op) override;
virtual SkDrawFilter* getDrawFilter() override;
virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
@@ -174,7 +174,7 @@
void recordPartialSave(SaveFlags::Flags flags);
template<typename T>
- void recordClip(const T&, SkRegion::Op);
+ void recordClip(const T&, SkClipOp);
void applyPersistentClips(size_t clipStartIndex);
void drawPoints(const float* points, int count, const SkPaint& paint,
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 5978abc..75396f7 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -430,21 +430,21 @@
}
}
-void SkiaCanvasProxy::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle) {
+void SkiaCanvasProxy::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle) {
mCanvas->clipRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, op);
}
-void SkiaCanvasProxy::onClipRRect(const SkRRect& roundRect, SkRegion::Op op, ClipEdgeStyle) {
+void SkiaCanvasProxy::onClipRRect(const SkRRect& roundRect, SkClipOp op, ClipEdgeStyle) {
SkPath path;
path.addRRect(roundRect);
mCanvas->clipPath(&path, op);
}
-void SkiaCanvasProxy::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle) {
+void SkiaCanvasProxy::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle) {
mCanvas->clipPath(&path, op);
}
-void SkiaCanvasProxy::onClipRegion(const SkRegion& region, SkRegion::Op op) {
+void SkiaCanvasProxy::onClipRegion(const SkRegion& region, SkClipOp op) {
mCanvas->clipRegion(®ion, op);
}
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index 0111815..badcc1d 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -90,10 +90,10 @@
const SkPoint texCoords[4], SkBlendMode,
const SkPaint& paint) override;
- virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override;
- virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override;
- virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override;
- virtual void onClipRegion(const SkRegion&, SkRegion::Op) override;
+ virtual void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
+ virtual void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
+ virtual void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;
+ virtual void onClipRegion(const SkRegion&, SkClipOp) override;
private:
Canvas* mCanvas;
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index f61c3e9..3f08009 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -72,19 +72,19 @@
// Clipping
///////////////////////////////////////////////////////////////////////////////
-void Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
+void Snapshot::clipRegionTransformed(const SkRegion& region, SkClipOp op) {
flags |= Snapshot::kFlagClipSet;
- mClipArea->clipRegion(region, op);
+ mClipArea->clipRegion(region, static_cast<SkRegion::Op>(op));
}
-void Snapshot::clip(const Rect& localClip, SkRegion::Op op) {
+void Snapshot::clip(const Rect& localClip, SkClipOp op) {
flags |= Snapshot::kFlagClipSet;
- mClipArea->clipRectWithTransform(localClip, transform, op);
+ mClipArea->clipRectWithTransform(localClip, transform, static_cast<SkRegion::Op>(op));
}
-void Snapshot::clipPath(const SkPath& path, SkRegion::Op op) {
+void Snapshot::clipPath(const SkPath& path, SkClipOp op) {
flags |= Snapshot::kFlagClipSet;
- mClipArea->clipPathWithTransform(path, transform, op);
+ mClipArea->clipPathWithTransform(path, transform, static_cast<SkRegion::Op>(op));
}
void Snapshot::setClip(float left, float top, float right, float bottom) {
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 4ab5830..287e58a 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -23,6 +23,7 @@
#include <utils/RefBase.h>
#include <ui/Region.h>
+#include <SkClipOp.h>
#include <SkRegion.h>
#include "ClipArea.h"
@@ -107,25 +108,25 @@
* the specified operation. The specified rectangle is transformed
* by this snapshot's trasnformation.
*/
- void clip(const Rect& localClip, SkRegion::Op op);
+ void clip(const Rect& localClip, SkClipOp op);
/**
* Modifies the current clip with the new clip rectangle and
* the specified operation. The specified rectangle is considered
* already transformed.
*/
- void clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op);
+ void clipTransformed(const Rect& r, SkClipOp op = kIntersect_SkClipOp);
/**
* Modifies the current clip with the specified region and operation.
* The specified region is considered already transformed.
*/
- void clipRegionTransformed(const SkRegion& region, SkRegion::Op op);
+ void clipRegionTransformed(const SkRegion& region, SkClipOp op);
/**
* Modifies the current clip with the specified path and operation.
*/
- void clipPath(const SkPath& path, SkRegion::Op op);
+ void clipPath(const SkPath& path, SkClipOp op);
/**
* Sets the current clip.
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 97b7dd7..208107f 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -308,7 +308,7 @@
void ClipPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath,
float strokeScale, const SkMatrix& matrix, bool useStagingData){
- outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
+ outCanvas->clipPath(renderPath);
}
Group::Group(const Group& group) : Node(group) {
@@ -574,7 +574,7 @@
}
bool Tree::canReuseBitmap(Bitmap* bitmap, int width, int height) {
- return bitmap && width == bitmap->width() && height == bitmap->height();
+ return bitmap && width <= bitmap->width() && height <= bitmap->height();
}
void Tree::onPropertyChanged(TreeProperties* prop) {
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index e9a9c71..8244a39 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -630,10 +630,15 @@
}
void setScaledSize(int width, int height) {
- if (mNonAnimatableProperties.scaledWidth != width
- || mNonAnimatableProperties.scaledHeight != height) {
- mNonAnimatableProperties.scaledWidth = width;
- mNonAnimatableProperties.scaledHeight = height;
+ // If the requested size is bigger than what the bitmap was, then
+ // we increase the bitmap size to match. The width and height
+ // are bound by MAX_CACHED_BITMAP_SIZE.
+ if (mNonAnimatableProperties.scaledWidth < width
+ || mNonAnimatableProperties.scaledHeight < height) {
+ mNonAnimatableProperties.scaledWidth = std::max(width,
+ mNonAnimatableProperties.scaledWidth);
+ mNonAnimatableProperties.scaledHeight = std::max(height,
+ mNonAnimatableProperties.scaledHeight);
mNonAnimatablePropertiesDirty = true;
mTree->onPropertyChanged(this);
}
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index d3e765d..64ef866 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -16,6 +16,7 @@
#include "Bitmap.h"
#include "Caches.h"
+#include "renderthread/EglManager.h"
#include "renderthread/RenderThread.h"
#include "renderthread/RenderProxy.h"
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index d7839b4..e7b6b2d 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -182,9 +182,9 @@
virtual bool quickRejectPath(const SkPath& path) const = 0;
virtual bool clipRect(float left, float top, float right, float bottom,
- SkRegion::Op op = SkRegion::kIntersect_Op) = 0;
- virtual bool clipPath(const SkPath* path, SkRegion::Op op) = 0;
- virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0;
+ SkClipOp op) = 0;
+ virtual bool clipPath(const SkPath* path, SkClipOp op) = 0;
+ virtual bool clipRegion(const SkRegion* region, SkClipOp op) = 0;
// filters
virtual SkDrawFilter* getDrawFilter() = 0;
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 4b34c7c..14cc449 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -68,7 +68,7 @@
if (pendingClip && !pendingClip->contains(rect)) {
canvas->clipRect(*pendingClip);
}
- canvas->clipRRect(SkRRect::MakeRectXY(rect, radius, radius), SkRegion::kIntersect_Op, true);
+ canvas->clipRRect(SkRRect::MakeRectXY(rect, radius, radius), kIntersect_SkClipOp, true);
} else {
if (pendingClip) {
(void)rect.intersect(*pendingClip);
@@ -263,7 +263,7 @@
}
if (properties.getRevealClip().willClip()) {
- canvas->clipPath(*properties.getRevealClip().getPath(), SkRegion::kIntersect_Op, true);
+ canvas->clipPath(*properties.getRevealClip().getPath(), kIntersect_SkClipOp, true);
} else if (properties.getOutline().willClip()) {
clipOutline(properties.getOutline(), canvas, pendingClip);
pendingClip = nullptr;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 7f3474a..c8258f7 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -19,6 +19,7 @@
#include "DeferredLayerUpdater.h"
#include "LayerDrawable.h"
#include "renderthread/EglManager.h"
+#include "renderthread/Frame.h"
#include "renderstate/RenderState.h"
#include "SkiaPipeline.h"
#include "SkiaProfileRenderer.h"
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 0f2d09d..d77aa48 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -17,6 +17,7 @@
#include "SkiaPipeline.h"
#include "utils/TraceUtils.h"
+#include <SkImageEncoder.h>
#include <SkOSFile.h>
#include <SkOverdrawCanvas.h>
#include <SkOverdrawColorFilter.h>
@@ -98,7 +99,7 @@
int saveCount = layerCanvas->save();
SkASSERT(saveCount == 1);
- layerCanvas->clipRect(layerDamage.toSkRect(), SkRegion::kReplace_Op);
+ layerCanvas->clipRect(layerDamage.toSkRect(), kReplace_SkClipOp);
auto savedLightCenter = mLightCenter;
// map current light center into RenderNode's coordinate space
@@ -166,8 +167,10 @@
public:
bool onUseEncodedData(const void*, size_t) override { return true; }
SkData* onEncode(const SkPixmap& pixmap) override {
- return SkImageEncoder::EncodeData(pixmap.info(), pixmap.addr(), pixmap.rowBytes(),
- SkImageEncoder::kPNG_Type, 100);
+ SkDynamicMemoryWStream buf;
+ return SkEncodeImage(&buf, pixmap, SkEncodedImageFormat::kPNG, 100)
+ ? buf.detachAsData().release()
+ : nullptr;
}
};
@@ -222,7 +225,7 @@
const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
SkCanvas* canvas) {
- canvas->clipRect(clip, SkRegion::kReplace_Op);
+ canvas->clipRect(clip, kReplace_SkClipOp);
if (!opaque) {
canvas->clear(SK_ColorTRANSPARENT);
@@ -272,7 +275,7 @@
const float dy = backdropBounds.top - contentDrawBounds.top;
canvas->translate(dx, dy);
// It gets cropped against the bounds of the backdrop to stay inside.
- canvas->clipRect(clip, SkRegion::kIntersect_Op);
+ canvas->clipRect(clip);
}
RenderNodeDrawable root(node.get(), canvas);
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index ca394b2..0d3f4ef 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -17,7 +17,7 @@
#include "SkiaVulkanPipeline.h"
#include "DeferredLayerUpdater.h"
-#include "renderthread/EglManager.h" // needed for Frame
+#include "renderthread/Frame.h"
#include "Readback.h"
#include "renderstate/RenderState.h"
#include "SkiaPipeline.h"
@@ -58,8 +58,7 @@
return Frame(-1, -1, 0);
}
- // TODO: support buffer age if Vulkan API can do it
- Frame frame(backBuffer->width(), backBuffer->height(), 0);
+ Frame frame(backBuffer->width(), backBuffer->height(), mVkManager.getAge(mVkSurface));
return frame;
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c561c86..1b3bf96 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -20,6 +20,7 @@
#include "AnimationContext.h"
#include "Caches.h"
#include "EglManager.h"
+#include "Frame.h"
#include "LayerUpdateQueue.h"
#include "Properties.h"
#include "RenderThread.h"
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index de95bee..02021fc 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -19,6 +19,7 @@
#include "Texture.h"
#include "Caches.h"
#include "DeviceInfo.h"
+#include "Frame.h"
#include "Properties.h"
#include "RenderThread.h"
#include "renderstate/RenderState.h"
@@ -74,24 +75,6 @@
bool setDamage = false;
} EglExtensions;
-void Frame::map(const SkRect& in, EGLint* out) const {
- /* The rectangles are specified relative to the bottom-left of the surface
- * and the x and y components of each rectangle specify the bottom-left
- * position of that rectangle.
- *
- * HWUI does everything with 0,0 being top-left, so need to map
- * the rect
- */
- SkIRect idirty;
- in.roundOut(&idirty);
- EGLint y = mHeight - (idirty.y() + idirty.height());
- // layout: {x, y, width, height}
- out[0] = idirty.x();
- out[1] = y;
- out[2] = idirty.width();
- out[3] = idirty.height();
-}
-
EglManager::EglManager(RenderThread& thread)
: mRenderThread(thread)
, mEglDisplay(EGL_NO_DISPLAY)
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index b12522e..0251925 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -26,36 +26,8 @@
namespace uirenderer {
namespace renderthread {
+class Frame;
class RenderThread;
-class EglManager;
-
-class Frame {
-public:
- Frame(EGLint width, EGLint height, EGLint bufferAge)
- : mWidth(width)
- , mHeight(height)
- , mBufferAge(bufferAge) { }
-
- EGLint width() const { return mWidth; }
- EGLint height() const { return mHeight; }
-
- // See: https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_buffer_age.txt
- // for what this means
- EGLint bufferAge() const { return mBufferAge; }
-
-private:
- Frame() {}
- friend class EglManager;
-
- EGLSurface mSurface;
- EGLint mWidth;
- EGLint mHeight;
- EGLint mBufferAge;
-
- // Maps from 0,0 in top-left to 0,0 in bottom-left
- // If out is not an EGLint[4] you're going to have a bad time
- void map(const SkRect& in, EGLint* out) const;
-};
// This class contains the shared global EGL objects, such as EGLDisplay
// and EGLConfig, which are re-used by CanvasContext
diff --git a/libs/hwui/renderthread/Frame.cpp b/libs/hwui/renderthread/Frame.cpp
new file mode 100644
index 0000000..126bb09
--- /dev/null
+++ b/libs/hwui/renderthread/Frame.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include "Frame.h"
+#include <SkRect.h>
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+void Frame::map(const SkRect& in, int32_t* out) const {
+ /* The rectangles are specified relative to the bottom-left of the surface
+ * and the x and y components of each rectangle specify the bottom-left
+ * position of that rectangle.
+ *
+ * HWUI does everything with 0,0 being top-left, so need to map
+ * the rect
+ */
+ SkIRect idirty;
+ in.roundOut(&idirty);
+ int32_t y = mHeight - (idirty.y() + idirty.height());
+ // layout: {x, y, width, height}
+ out[0] = idirty.x();
+ out[1] = y;
+ out[2] = idirty.width();
+ out[3] = idirty.height();
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/Frame.h b/libs/hwui/renderthread/Frame.h
new file mode 100644
index 0000000..99996fe
--- /dev/null
+++ b/libs/hwui/renderthread/Frame.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+struct SkRect;
+typedef void *EGLSurface;
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+class Frame {
+public:
+ Frame(int32_t width, int32_t height, int32_t bufferAge)
+ : mWidth(width)
+ , mHeight(height)
+ , mBufferAge(bufferAge) { }
+
+ int32_t width() const { return mWidth; }
+ int32_t height() const { return mHeight; }
+
+ // See: https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_buffer_age.txt
+ // for what this means
+ int32_t bufferAge() const { return mBufferAge; }
+
+private:
+ Frame() {}
+ friend class EglManager;
+
+ int32_t mWidth;
+ int32_t mHeight;
+ int32_t mBufferAge;
+
+ EGLSurface mSurface;
+
+ // Maps from 0,0 in top-left to 0,0 in bottom-left
+ // If out is not an int32_t[4] you're going to have a bad time
+ void map(const SkRect& in, int32_t* out) const;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 0e4000b..45f6718 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -17,7 +17,6 @@
#pragma once
#include "FrameInfoVisualizer.h"
-#include "EglManager.h"
#include <SkRect.h>
#include <utils/RefBase.h>
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
index 9dc2b59..df08599 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.cpp
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -18,6 +18,7 @@
#include "DeferredLayerUpdater.h"
#include "EglManager.h"
+#include "Frame.h"
#include "ProfileRenderer.h"
#include "renderstate/RenderState.h"
#include "OpenGLReadback.h"
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 4d239bc..68c04af 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -17,6 +17,7 @@
#include "VulkanManager.h"
#include "DeviceInfo.h"
+#include "Properties.h"
#include "RenderThread.h"
#include <GrContext.h>
@@ -100,6 +101,10 @@
mRenderThread.setGrContext(GrContext::Create(kVulkan_GrBackend,
(GrBackendContext) mBackendContext.get()));
DeviceInfo::initialize(mRenderThread.getGrContext()->caps()->maxRenderTargetSize());
+
+ if (Properties::enablePartialUpdates && Properties::useBufferAge) {
+ mSwapBehavior = SwapBehavior::BufferAge;
+ }
}
// Returns the next BackbufferInfo to use for the next draw. The function will make sure all
@@ -162,7 +167,7 @@
}
// set up layout transfer from initial to color attachment
- VkImageLayout layout = surface->mImageLayouts[backbuffer->mImageIndex];
+ VkImageLayout layout = surface->mImageInfos[backbuffer->mImageIndex].mImageLayout;
SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout || VK_IMAGE_LAYOUT_PRESENT_SRC_KHR == layout);
VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT :
@@ -215,7 +220,7 @@
// We need to notify Skia that we changed the layout of the wrapped VkImage
GrVkImageInfo* imageInfo;
- sk_sp<SkSurface> skSurface = surface->mSurfaces[backbuffer->mImageIndex];
+ sk_sp<SkSurface> skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface;
skSurface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
SkSurface::kFlushRead_BackendHandleAccess);
imageInfo->updateImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@@ -243,10 +248,8 @@
delete[] surface->mBackbuffers;
surface->mBackbuffers = nullptr;
- delete[] surface->mSurfaces;
- surface->mSurfaces = nullptr;
- delete[] surface->mImageLayouts;
- surface->mImageLayouts = nullptr;
+ delete[] surface->mImageInfos;
+ surface->mImageInfos = nullptr;
delete[] surface->mImages;
surface->mImages = nullptr;
}
@@ -286,8 +289,7 @@
GrPixelConfig config = wantSRGB ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
// set up initial image layouts and create surfaces
- surface->mImageLayouts = new VkImageLayout[surface->mImageCount];
- surface->mSurfaces = new sk_sp<SkSurface>[surface->mImageCount];
+ surface->mImageInfos = new VulkanSurface::ImageInfo[surface->mImageCount];
for (uint32_t i = 0; i < surface->mImageCount; ++i) {
GrBackendRenderTargetDesc desc;
GrVkImageInfo info;
@@ -306,9 +308,9 @@
desc.fStencilBits = 0;
desc.fRenderTargetHandle = (GrBackendObject) &info;
- surface->mSurfaces[i] = SkSurface::MakeFromBackendRenderTarget(mRenderThread.getGrContext(),
+ VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i];
+ imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(mRenderThread.getGrContext(),
desc, &props);
- surface->mImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
}
SkASSERT(mCommandPool != VK_NULL_HANDLE);
@@ -595,7 +597,7 @@
VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
surface->mCurrentBackbufferIndex;
GrVkImageInfo* imageInfo;
- SkSurface* skSurface = surface->mSurfaces[backbuffer->mImageIndex].get();
+ SkSurface* skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface.get();
skSurface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
SkSurface::kFlushRead_BackendHandleAccess);
// Check to make sure we never change the actually wrapped image
@@ -632,7 +634,7 @@
0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[1]);
- surface->mImageLayouts[backbuffer->mImageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ surface->mImageInfos[backbuffer->mImageIndex].mImageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
// insert the layout transfer into the queue and wait on the acquire
VkSubmitInfo submitInfo;
@@ -668,6 +670,20 @@
mQueuePresentKHR(mPresentQueue, &presentInfo);
surface->mBackbuffer.reset();
+ surface->mImageInfos[backbuffer->mImageIndex].mLastUsed = surface->mCurrentTime;
+ surface->mImageInfos[backbuffer->mImageIndex].mInvalid = false;
+ surface->mCurrentTime++;
+}
+
+int VulkanManager::getAge(VulkanSurface* surface) {
+ VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
+ surface->mCurrentBackbufferIndex;
+ if (mSwapBehavior == SwapBehavior::Discard
+ || surface->mImageInfos[backbuffer->mImageIndex].mInvalid) {
+ return 0;
+ }
+ uint16_t lastUsed = surface->mImageInfos[backbuffer->mImageIndex].mLastUsed;
+ return surface->mCurrentTime - lastUsed;
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index f0e3320..d225b3f 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -46,6 +46,13 @@
VkFence mUsageFences[2];
};
+ struct ImageInfo {
+ VkImageLayout mImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ sk_sp<SkSurface> mSurface;
+ uint16_t mLastUsed = 0;
+ bool mInvalid = true;
+ };
+
sk_sp<SkSurface> mBackbuffer;
VkSurfaceKHR mVkSurface = VK_NULL_HANDLE;
@@ -56,8 +63,8 @@
uint32_t mImageCount;
VkImage* mImages;
- VkImageLayout* mImageLayouts;
- sk_sp<SkSurface>* mSurfaces;
+ ImageInfo* mImageInfos;
+ uint16_t mCurrentTime = 0;
};
// This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
@@ -87,6 +94,8 @@
// VulkanSurface is passed into them so we just return true here.
bool isCurrent(VulkanSurface* surface) { return true; }
+ int getAge(VulkanSurface* surface);
+
// Returns an SkSurface which wraps the next image returned from vkAcquireNextImageKHR. It also
// will transition the VkImage from a present layout to color attachment so that it can be used
// by the client for drawing.
@@ -161,6 +170,12 @@
uint32_t mPresentQueueIndex;
VkQueue mPresentQueue = VK_NULL_HANDLE;
VkCommandPool mCommandPool = VK_NULL_HANDLE;
+
+ enum class SwapBehavior {
+ Discard,
+ BufferAge,
+ };
+ SwapBehavior mSwapBehavior = SwapBehavior::Discard;
};
} /* namespace renderthread */
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 0ce598d..363b94a 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -118,7 +118,8 @@
static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) {
std::unique_ptr<Snapshot> snapshot(new Snapshot());
- snapshot->clip(clip, SkRegion::kReplace_Op); // store clip first, so it isn't transformed
+ // store clip first, so it isn't transformed
+ snapshot->setClip(clip.left, clip.top, clip.right, clip.bottom);
*(snapshot->transform) = transform;
return snapshot;
}
diff --git a/libs/hwui/tests/common/scenes/ClippingAnimation.cpp b/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
index 8f2ba2d..45443b0 100644
--- a/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
@@ -34,11 +34,11 @@
[](RenderProperties& props, Canvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
{
- canvas.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, 200, 200, kIntersect_SkClipOp);
canvas.translate(100, 100);
canvas.rotate(45);
canvas.translate(-100, -100);
- canvas.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, 200, 200, kIntersect_SkClipOp);
canvas.drawColor(Color::Blue_500, SkBlendMode::kSrcOver);
}
canvas.restore();
@@ -47,7 +47,7 @@
{
SkPath clipCircle;
clipCircle.addCircle(100, 300, 100);
- canvas.clipPath(&clipCircle, SkRegion::kIntersect_Op);
+ canvas.clipPath(&clipCircle, kIntersect_SkClipOp);
canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
}
canvas.restore();
diff --git a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
index 3630935..8b2852b 100644
--- a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
@@ -36,7 +36,7 @@
// nested clipped saveLayers
canvas.saveLayerAlpha(0, 0, 400, 400, 200, SaveFlags::ClipToLayer);
canvas.drawColor(Color::Green_700, SkBlendMode::kSrcOver);
- canvas.clipRect(50, 50, 350, 350, SkRegion::kIntersect_Op);
+ canvas.clipRect(50, 50, 350, 350, kIntersect_SkClipOp);
canvas.saveLayerAlpha(100, 100, 300, 300, 128, SaveFlags::ClipToLayer);
canvas.drawColor(Color::Blue_500, SkBlendMode::kSrcOver);
canvas.restore();
diff --git a/libs/hwui/tests/common/scenes/ShapeAnimation.cpp b/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
index 5ef8773..d44c3d5 100644
--- a/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
@@ -82,7 +82,7 @@
int middleCount = canvas.save(SaveFlags::MatrixClip);
for (auto op : ops) {
int innerCount = canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(0, 0, cellSize, cellSize, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, cellSize, cellSize, kIntersect_SkClipOp);
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
op(canvas, cellSize, paint);
canvas.restoreToCount(innerCount);
diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index bbaf267..3ef0d1c 100644
--- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -177,7 +177,7 @@
// Clip to padding
// Can expect ~25% of views to have clip to padding with a non-null padding
int clipRestoreCount = canvas->save(SaveFlags::MatrixClip);
- canvas->clipRect(1, 1, 199, 199, SkRegion::kIntersect_Op);
+ canvas->clipRect(1, 1, 199, 199, kIntersect_SkClipOp);
canvas->insertReorderBarrier(true);
diff --git a/libs/hwui/tests/unit/CanvasStateTests.cpp b/libs/hwui/tests/unit/CanvasStateTests.cpp
index 0afabd8..7555fd4 100644
--- a/libs/hwui/tests/unit/CanvasStateTests.cpp
+++ b/libs/hwui/tests/unit/CanvasStateTests.cpp
@@ -23,7 +23,7 @@
#include <gtest/gtest.h>
#include <SkPath.h>
-#include <SkRegion.h>
+#include <SkClipOp.h>
namespace android {
namespace uirenderer {
@@ -68,13 +68,13 @@
state.initializeSaveStack(200, 200,
0, 0, 200, 200, Vector3());
- state.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
+ state.clipRect(0, 0, 100, 100, kIntersect_SkClipOp);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(100, 100));
- state.clipRect(10, 10, 200, 200, SkRegion::kIntersect_Op);
+ state.clipRect(10, 10, 200, 200, kIntersect_SkClipOp);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10, 100, 100));
- state.clipRect(50, 50, 150, 150, SkRegion::kReplace_Op);
+ state.clipRect(50, 50, 150, 150, kReplace_SkClipOp);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(50, 50, 150, 150));
}
@@ -88,7 +88,7 @@
// rotated clip causes complex clip
state.rotate(10);
EXPECT_TRUE(state.clipIsSimple());
- state.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
+ state.clipRect(0, 0, 200, 200, kIntersect_SkClipOp);
EXPECT_FALSE(state.clipIsSimple());
}
state.restore();
@@ -97,7 +97,7 @@
{
// subtracted clip causes complex clip
EXPECT_TRUE(state.clipIsSimple());
- state.clipRect(50, 50, 150, 150, SkRegion::kDifference_Op);
+ state.clipRect(50, 50, 150, 150, kDifference_SkClipOp);
EXPECT_FALSE(state.clipIsSimple());
}
state.restore();
@@ -108,7 +108,7 @@
SkPath path;
path.addOval(SkRect::MakeWH(200, 200));
EXPECT_TRUE(state.clipIsSimple());
- state.clipPath(&path, SkRegion::kDifference_Op);
+ state.clipPath(&path, kDifference_SkClipOp);
EXPECT_FALSE(state.clipIsSimple());
}
state.restore();
@@ -121,7 +121,7 @@
state.save(SaveFlags::Clip);
{
- state.clipRect(0, 0, 10, 10, SkRegion::kIntersect_Op);
+ state.clipRect(0, 0, 10, 10, kIntersect_SkClipOp);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
}
state.restore();
@@ -145,7 +145,7 @@
state.save(SaveFlags::Matrix); // NOTE: clip not saved
{
- state.clipRect(0, 0, 10, 10, SkRegion::kIntersect_Op);
+ state.clipRect(0, 0, 10, 10, kIntersect_SkClipOp);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
}
state.restore();
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index a1c225f..12622ff 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -174,7 +174,7 @@
auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); // intersection should be empty
+ canvas.clipRect(200, 200, 400, 400, kIntersect_SkClipOp); // intersection should be empty
canvas.drawRect(0, 0, 400, 400, SkPaint());
canvas.restore();
});
@@ -453,19 +453,19 @@
sk_sp<Bitmap> bitmap(TestUtils::createBitmap(20, 20));
// left side clipped (to inset left half)
- canvas.clipRect(10, 0, 50, 100, SkRegion::kReplace_Op);
+ canvas.clipRect(10, 0, 50, 100, kReplace_SkClipOp);
canvas.drawBitmap(*bitmap, 0, 40, nullptr);
// top side clipped (to inset top half)
- canvas.clipRect(0, 10, 100, 50, SkRegion::kReplace_Op);
+ canvas.clipRect(0, 10, 100, 50, kReplace_SkClipOp);
canvas.drawBitmap(*bitmap, 40, 0, nullptr);
// right side clipped (to inset right half)
- canvas.clipRect(50, 0, 90, 100, SkRegion::kReplace_Op);
+ canvas.clipRect(50, 0, 90, 100, kReplace_SkClipOp);
canvas.drawBitmap(*bitmap, 80, 40, nullptr);
// bottom not clipped, just abutting (inset bottom half)
- canvas.clipRect(0, 50, 100, 90, SkRegion::kReplace_Op);
+ canvas.clipRect(0, 50, 100, 90, kReplace_SkClipOp);
canvas.drawBitmap(*bitmap, 40, 70, nullptr);
});
@@ -488,7 +488,7 @@
SkPath path;
path.addCircle(200, 200, 200, SkPath::kCW_Direction);
canvas.save(SaveFlags::MatrixClip);
- canvas.clipPath(&path, SkRegion::kIntersect_Op);
+ canvas.clipPath(&path, kIntersect_SkClipOp);
SkPaint paint;
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setAntiAlias(true);
@@ -649,7 +649,7 @@
auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
[&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op);
+ canvas.clipRect(50, 50, 150, 150, kIntersect_SkClipOp);
canvas.drawLayer(layerUpdater.get());
canvas.restore();
});
@@ -973,7 +973,7 @@
auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op);
+ canvas.clipRect(200, 200, 400, 400, kIntersect_SkClipOp);
canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer);
// draw within save layer may still be recorded, but shouldn't be drawn
@@ -1781,7 +1781,7 @@
auto child = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
[&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
// Record time clip will be ignored by projectee
- canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op);
+ canvas.clipRect(100, 100, 300, 300, kIntersect_SkClipOp);
canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
canvas.drawRenderNode(projectingRipple.get());
@@ -1993,7 +1993,7 @@
[](RenderProperties& props, RecordingCanvas& canvas) {
// Apply a clip before the reorder barrier/shadow casting child is drawn.
// This clip must be applied to the shadow cast by the child.
- canvas.clipRect(25, 25, 75, 75, SkRegion::kIntersect_Op);
+ canvas.clipRect(25, 25, 75, 75, kIntersect_SkClipOp);
canvas.insertReorderBarrier(true);
canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
});
@@ -2252,7 +2252,7 @@
};
auto node = TestUtils::createNode<RecordingCanvas>(20, 20, 30, 30,
[](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.clipRect(0, -20, 10, 30, SkRegion::kReplace_Op);
+ canvas.clipRect(0, -20, 10, 30, kReplace_SkClipOp);
canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
});
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index dda432e..14fa5d6 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -57,7 +57,7 @@
TEST(RecordingCanvas, clipRect) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, 100, 100, kIntersect_SkClipOp);
canvas.drawRect(0, 0, 50, 50, SkPaint());
canvas.drawRect(50, 50, 100, 100, SkPaint());
canvas.restore();
@@ -73,8 +73,8 @@
TEST(RecordingCanvas, emptyClipRect) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
- canvas.clipRect(100, 100, 200, 200, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, 100, 100, kIntersect_SkClipOp);
+ canvas.clipRect(100, 100, 200, 200, kIntersect_SkClipOp);
canvas.drawRect(0, 0, 50, 50, SkPaint()); // rejected at record time
canvas.restore();
});
@@ -440,7 +440,7 @@
TEST(RecordingCanvas, saveLayer_addClipFlag) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(10, 20, 190, 180, SkRegion::kIntersect_Op);
+ canvas.clipRect(10, 20, 190, 180, kIntersect_SkClipOp);
canvas.saveLayerAlpha(10, 20, 190, 180, 128, (SaveFlags::Flags)0); // unclipped
canvas.drawRect(10, 20, 190, 180, SkPaint());
canvas.restore();
@@ -459,7 +459,7 @@
TEST(RecordingCanvas, saveLayer_viewportCrop) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
// shouldn't matter, since saveLayer will clip to its bounds
- canvas.clipRect(-1000, -1000, 1000, 1000, SkRegion::kReplace_Op);
+ canvas.clipRect(-1000, -1000, 1000, 1000, kReplace_SkClipOp);
canvas.saveLayerAlpha(100, 100, 300, 300, 128, SaveFlags::ClipToLayer);
canvas.drawRect(0, 0, 400, 400, SkPaint());
@@ -549,7 +549,7 @@
canvas.save(SaveFlags::MatrixClip);
canvas.translate(0, -20); // avoid identity case
// empty clip rect should force layer + contents to be rejected
- canvas.clipRect(0, -20, 200, -20, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, -20, 200, -20, kIntersect_SkClipOp);
canvas.saveLayerAlpha(0, 0, 200, 200, 128, SaveFlags::ClipToLayer);
canvas.drawRect(0, 0, 200, 200, SkPaint());
canvas.restore();
@@ -568,7 +568,7 @@
});
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [&child](RecordingCanvas& canvas) {
- canvas.clipRect(0, 0, 0, 0, SkRegion::kIntersect_Op); // empty clip, reject node
+ canvas.clipRect(0, 0, 0, 0, kIntersect_SkClipOp); // empty clip, reject node
canvas.drawRenderNode(child.get()); // shouldn't crash when rejecting node...
});
ASSERT_TRUE(dl->isEmpty());
@@ -621,7 +621,7 @@
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
// since no explicit clip set on canvas, this should be the one observed on op:
- canvas.clipRect(-100, -100, 300, 300, SkRegion::kIntersect_Op);
+ canvas.clipRect(-100, -100, 300, 300, kIntersect_SkClipOp);
SkPaint paint;
paint.setColor(SK_ColorWHITE);
@@ -637,7 +637,7 @@
TEST(RecordingCanvas, replaceClipIntersectWithRoot) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(-10, -10, 110, 110, SkRegion::kReplace_Op);
+ canvas.clipRect(-10, -10, 110, 110, kReplace_SkClipOp);
canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
canvas.restore();
});
@@ -675,7 +675,7 @@
canvas.drawRect(0, 0, 400, 400, SkPaint());
// second chunk: no recorded clip, since inorder region
- canvas.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, 200, 200, kIntersect_SkClipOp);
canvas.insertReorderBarrier(false);
canvas.drawRect(0, 0, 400, 400, SkPaint());
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index f4b686d..7c14952 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -469,7 +469,7 @@
auto child = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
// Record time clip will be ignored by projectee
- canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op);
+ canvas.clipRect(100, 100, 300, 300, kIntersect_SkClipOp);
canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
canvas.drawRenderNode(projectingRipple.get());
diff --git a/libs/hwui/utils/TestWindowContext.cpp b/libs/hwui/utils/TestWindowContext.cpp
index fa3e13d..598cd1e 100644
--- a/libs/hwui/utils/TestWindowContext.cpp
+++ b/libs/hwui/utils/TestWindowContext.cpp
@@ -93,8 +93,7 @@
SkCanvas* prepareToDraw() {
//mCanvas->reset(mSize.width(), mSize.height());
- mCanvas->clipRect(0, 0, mSize.width(), mSize.height(),
- SkRegion::Op::kReplace_Op);
+ mCanvas->clipRect(0, 0, mSize.width(), mSize.height(), kReplace_SkClipOp);
return mCanvas->asSkCanvas();
}
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 93e86af..4c39c30 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -131,14 +131,11 @@
public String text;
public int requestorIdEncoding;
public int textEncoding;
- public Bundle extras;
};
public static class GpsNiResponse {
/* User response, one of the values in GpsUserResponseType */
int userResponse;
- /* Optional extra data to pass with the user response */
- Bundle extras;
};
private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
diff --git a/media/java/android/media/AsyncPlayer.java b/media/java/android/media/AsyncPlayer.java
index dd5f6ba..c1a178a 100644
--- a/media/java/android/media/AsyncPlayer.java
+++ b/media/java/android/media/AsyncPlayer.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.media.PlayerBase;
import android.net.Uri;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -163,6 +164,7 @@
* @deprecated use {@link #play(Context, Uri, boolean, AudioAttributes)} instead
*/
public void play(Context context, Uri uri, boolean looping, int stream) {
+ PlayerBase.deprecateStreamTypeForPlayback(stream, "AsyncPlayer", "play()");
if (context == null || uri == null) {
return;
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 43fb4b9..16b3315 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -359,6 +359,9 @@
* for an AudioTrack instance in streaming mode.
* @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
* @throws java.lang.IllegalArgumentException
+ * @deprecated use {@link Builder} or
+ * {@link #AudioTrack(AudioAttributes, AudioFormat, int, int, int)} to specify the
+ * {@link AudioAttributes} instead of the stream type which is only for volume control.
*/
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes, int mode)
@@ -414,6 +417,9 @@
* @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
* @param sessionId Id of audio session the AudioTrack must be attached to
* @throws java.lang.IllegalArgumentException
+ * @deprecated use {@link Builder} or
+ * {@link #AudioTrack(AudioAttributes, AudioFormat, int, int, int)} to specify the
+ * {@link AudioAttributes} instead of the stream type which is only for volume control.
*/
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes, int mode, int sessionId)
@@ -429,6 +435,7 @@
.build(),
bufferSizeInBytes,
mode, sessionId);
+ deprecateStreamTypeForPlayback(streamType, "AudioTrack", "AudioTrack()");
}
/**
@@ -1044,11 +1051,12 @@
}
/**
- * Returns the type of audio stream this AudioTrack is configured for.
+ * Returns the volume stream type of this AudioTrack.
* Compare the result against {@link AudioManager#STREAM_VOICE_CALL},
* {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
* {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
- * {@link AudioManager#STREAM_NOTIFICATION}, or {@link AudioManager#STREAM_DTMF}.
+ * {@link AudioManager#STREAM_NOTIFICATION}, {@link AudioManager#STREAM_DTMF} or
+ * {@link AudioManager#STREAM_ACCESSIBILITY}.
*/
public int getStreamType() {
return mStreamType;
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index bbb7184..52d5b7ca 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -2765,23 +2765,28 @@
tag != null ? tag.name : null, dataFormat, numberOfComponents));
}
- if (tag == null || dataFormat <= 0 ||
- dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) {
- // Skip if the parsed tag number is not defined or invalid data format.
- if (DEBUG) {
- if (tag == null) {
- Log.w(TAG, "Skip tag entry since tag number is not defined: " + tagNumber);
- } else {
- Log.w(TAG, "Skip tag entry since data format is invalid: " + dataFormat);
- }
+ long byteCount = 0;
+ boolean valid = false;
+ if (tag == null) {
+ Log.w(TAG, "Skip the tag entry since tag number is not defined: " + tagNumber);
+ } else if (dataFormat <= 0 || dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) {
+ Log.w(TAG, "Skip the tag entry since data format is invalid: " + dataFormat);
+ } else {
+ byteCount = (long) numberOfComponents * IFD_FORMAT_BYTES_PER_FORMAT[dataFormat];
+ if (byteCount < 0 || byteCount > Integer.MAX_VALUE) {
+ Log.w(TAG, "Skip the tag entry since the number of components is invalid: "
+ + numberOfComponents);
+ } else {
+ valid = true;
}
+ }
+ if (!valid) {
dataInputStream.seek(nextEntryOffset);
continue;
}
// Read a value from data field or seek to the value offset which is stored in data
// field if the size of the entry value is bigger than 4.
- int byteCount = numberOfComponents * IFD_FORMAT_BYTES_PER_FORMAT[dataFormat];
if (byteCount > 4) {
int offset = dataInputStream.readInt();
if (DEBUG) {
@@ -2871,7 +2876,7 @@
continue;
}
- byte[] bytes = new byte[byteCount];
+ byte[] bytes = new byte[(int) byteCount];
dataInputStream.readFully(bytes);
ExifAttribute attribute = new ExifAttribute(dataFormat, numberOfComponents, bytes);
mAttributes[ifdType].put(tag.name, attribute);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index eff5aac..78da59c 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -124,7 +124,7 @@
* is called. It is a programming error to invoke methods such
* as {@link #getCurrentPosition()},
* {@link #getDuration()}, {@link #getVideoHeight()},
- * {@link #getVideoWidth()}, {@link #setAudioStreamType(int)},
+ * {@link #getVideoWidth()}, {@link #setAudioAttributes(AudioAttributes)},
* {@link #setLooping(boolean)},
* {@link #setVolume(float, float)}, {@link #pause()}, {@link #start()},
* {@link #stop()}, {@link #seekTo(int, int)}, {@link #prepare()} or
@@ -410,7 +410,7 @@
* Error} </p></td>
* <td>This method must be called in idle state as the audio session ID must be known before
* calling setDataSource. Calling it does not change the object state. </p></td></tr>
- * <tr><td>setAudioStreamType </p></td>
+ * <tr><td>setAudioStreamType (deprecated)</p></td>
* <td>{Idle, Initialized, Stopped, Prepared, Started, Paused,
* PlaybackCompleted}</p></td>
* <td>{Error}</p></td>
@@ -822,7 +822,7 @@
* to free the resources. If not released, too many MediaPlayer instances will
* result in an exception.</p>
* <p>Note that since {@link #prepare()} is called automatically in this method,
- * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+ * you cannot change the audio
* session ID (see {@link #setAudioSessionId(int)}) or audio attributes
* (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
*
@@ -841,7 +841,7 @@
* to free the resources. If not released, too many MediaPlayer instances will
* result in an exception.</p>
* <p>Note that since {@link #prepare()} is called automatically in this method,
- * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+ * you cannot change the audio
* session ID (see {@link #setAudioSessionId(int)}) or audio attributes
* (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
*
@@ -904,7 +904,7 @@
* to free the resources. If not released, too many MediaPlayer instances will
* result in an exception.</p>
* <p>Note that since {@link #prepare()} is called automatically in this method,
- * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+ * you cannot change the audio
* session ID (see {@link #setAudioSessionId(int)}) or audio attributes
* (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
*
@@ -1843,9 +1843,11 @@
* thereafter.
*
* @param streamtype the audio stream type
+ * @deprecated use {@link #setAudioAttributes(AudioAttributes)}
* @see android.media.AudioManager
*/
public void setAudioStreamType(int streamtype) {
+ deprecateStreamTypeForPlayback(streamtype, "MediaPlayer", "setAudioStreamType()");
baseUpdateAudioAttributes(
new AudioAttributes.Builder().setInternalLegacyStreamType(streamtype).build());
_setAudioStreamType(streamtype);
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 690a553..42f6b83 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -236,4 +236,28 @@
*/
abstract void playerSetVolume(boolean muting, float leftVolume, float rightVolume);
abstract int playerSetAuxEffectSendLevel(boolean muting, float level);
+
+ //=====================================================================
+ // Utilities
+
+ /**
+ * Use to generate warning or exception in legacy code paths that allowed passing stream types
+ * to qualify audio playback.
+ * @param streamType the stream type to check
+ * @throws IllegalArgumentException
+ */
+ public static void deprecateStreamTypeForPlayback(int streamType, String className,
+ String opName) throws IllegalArgumentException {
+ // STREAM_ACCESSIBILITY was introduced at the same time the use of stream types
+ // for audio playback was deprecated, so it is not allowed at all to qualify a playback
+ // use case
+ if (streamType == AudioManager.STREAM_ACCESSIBILITY) {
+ throw new IllegalArgumentException("Use of STREAM_ACCESSIBILITY is reserved for "
+ + "volume control");
+ }
+ Log.e(className, "Use of stream types is deprecated for operations other than " +
+ "volume control.");
+ Log.e(className, "See the documentation of " + opName + " for what to use instead with " +
+ "android.media.AudioAttributes to qualify your playback use case");
+ }
}
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 7767712..209ec42 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -103,6 +103,7 @@
*/
@Deprecated
public void setStreamType(int streamType) {
+ PlayerBase.deprecateStreamTypeForPlayback(streamType, "Ringtone", "setStreamType()");
setAudioAttributes(new AudioAttributes.Builder()
.setInternalLegacyStreamType(streamType)
.build());
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 3cb01de..de9f020 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -297,7 +297,7 @@
}
/**
- * Infers the playback stream type based on what type of ringtones this
+ * Infers the volume stream type based on what type of ringtones this
* manager is returning.
*
* @return The stream type.
@@ -616,6 +616,7 @@
return getRingtone(context, ringtoneUri, -1);
}
+ //FIXME bypass the notion of stream types within the class
/**
* Returns a {@link Ringtone} for a given sound URI on the given stream
* type. Normally, if you change the stream type on the returned
@@ -630,6 +631,7 @@
try {
final Ringtone r = new Ringtone(context, true);
if (streamType >= 0) {
+ //FIXME deprecated call
r.setStreamType(streamType);
}
r.setUri(ringtoneUri);
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index b429e22..838767c 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -24,6 +24,7 @@
import android.app.AppOpsManager;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
+import android.media.PlayerBase;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -146,6 +147,7 @@
public SoundPool(int maxStreams, int streamType, int srcQuality) {
this(maxStreams,
new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build());
+ PlayerBase.deprecateStreamTypeForPlayback(streamType, "SoundPool", "SoundPool()");
}
private SoundPool(int maxStreams, AudioAttributes attributes) {
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index bb8eb2c..03f0b4d 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -55,12 +55,14 @@
import java.util.Random;
public class CaptivePortalLoginActivity extends Activity {
- private static final String TAG = "CaptivePortalLogin";
+ private static final String TAG = CaptivePortalLoginActivity.class.getSimpleName();
+ private static final boolean DBG = true;
+
private static final int SOCKET_TIMEOUT_MS = 10000;
private enum Result { DISMISSED, UNWANTED, WANTED_AS_IS };
- private URL mURL;
+ private URL mUrl;
private Network mNetwork;
private CaptivePortal mCaptivePortal;
private NetworkCallback mNetworkCallback;
@@ -72,17 +74,18 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCm = ConnectivityManager.from(this);
- String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
- if (url == null) url = mCm.getCaptivePortalServerUrl();
- try {
- mURL = new URL(url);
- } catch (MalformedURLException e) {
- // System misconfigured, bail out in a way that at least provides network access.
- Log.e(TAG, "Invalid captive portal URL, url=" + url);
- done(Result.WANTED_AS_IS);
- }
mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
+ mUrl = getUrl();
+ if (mUrl == null) {
+ // getUrl() failed to parse the url provided in the intent: bail out in a way that
+ // at least provides network access.
+ done(Result.WANTED_AS_IS);
+ return;
+ }
+ if (DBG) {
+ Log.d(TAG, String.format("onCreate for %s", mUrl.toString()));
+ }
// Also initializes proxy system properties.
mCm.bindProcessToNetwork(mNetwork);
@@ -149,6 +152,9 @@
}
private void done(Result result) {
+ if (DBG) {
+ Log.d(TAG, String.format("Result %s for %s", result.name(), mUrl.toString()));
+ }
if (mNetworkCallback != null) {
mCm.unregisterNetworkCallback(mNetworkCallback);
mNetworkCallback = null;
@@ -185,22 +191,31 @@
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- int id = item.getItemId();
- if (id == R.id.action_use_network) {
- done(Result.WANTED_AS_IS);
- return true;
+ final Result result;
+ final String action;
+ final int id = item.getItemId();
+ switch (id) {
+ case R.id.action_use_network:
+ result = Result.WANTED_AS_IS;
+ action = "USE_NETWORK";
+ break;
+ case R.id.action_do_not_use_network:
+ result = Result.UNWANTED;
+ action = "DO_NOT_USE_NETWORK";
+ break;
+ default:
+ return super.onOptionsItemSelected(item);
}
- if (id == R.id.action_do_not_use_network) {
- done(Result.UNWANTED);
- return true;
+ if (DBG) {
+ Log.d(TAG, String.format("onOptionsItemSelect %s for %s", action, mUrl.toString()));
}
- return super.onOptionsItemSelected(item);
+ done(result);
+ return true;
}
@Override
public void onDestroy() {
super.onDestroy();
-
if (mNetworkCallback != null) {
mCm.unregisterNetworkCallback(mNetworkCallback);
mNetworkCallback = null;
@@ -215,10 +230,27 @@
} catch (InterruptedException e) {
}
}
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(mURL.toString())));
+ final String url = mUrl.toString();
+ if (DBG) {
+ Log.d(TAG, "starting activity with intent ACTION_VIEW for " + url);
+ }
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}
}
+ private URL getUrl() {
+ String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
+ if (url == null) {
+ url = mCm.getCaptivePortalServerUrl();
+ }
+ try {
+ return new URL(url);
+ } catch (MalformedURLException e) {
+ Log.e(TAG, "Invalid captive portal URL " + url);
+ }
+ return null;
+ }
+
private void testForCaptivePortal() {
new Thread(new Runnable() {
public void run() {
@@ -230,7 +262,7 @@
HttpURLConnection urlConnection = null;
int httpResponseCode = 500;
try {
- urlConnection = (HttpURLConnection) mURL.openConnection();
+ urlConnection = (HttpURLConnection) mUrl.openConnection();
urlConnection.setInstanceFollowRedirects(false);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
@@ -292,7 +324,7 @@
// settings. Now prompt the WebView read the Network-specific proxy settings.
setWebViewProxy();
// Load the real page.
- view.loadUrl(mURL.toString());
+ view.loadUrl(mUrl.toString());
return;
} else if (mPagesLoaded == 2) {
// Prevent going back to empty first page.
diff --git a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
index a7c9105..edcea0e 100644
--- a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
@@ -24,6 +24,7 @@
android:name=".SampleTrustAgent"
android:label="@string/app_name"
android:permission="android.permission.BIND_TRUST_AGENT"
+ android:directBootAware="true"
android:exported="true">
<intent-filter>
<action android:name="android.service.trust.TrustAgentService" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/layout-v26/sample_trust_agent_settings.xml b/packages/Keyguard/test/SampleTrustAgent/res/layout-v26/sample_trust_agent_settings.xml
new file mode 100644
index 0000000..4669971
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/res/layout-v26/sample_trust_agent_settings.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <Button android:id="@+id/enable_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Grant trust for 30 seconds" />
+ <Button android:id="@+id/revoke_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Revoke trust" />
+ <Button android:id="@+id/crash"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Crash" />
+ <CheckBox android:id="@+id/managing_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Managing trust" />
+ <CheckBox android:id="@+id/managing_trust_direct_boot"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Managing trust direct boot"/>
+
+ <CheckBox android:id="@+id/report_unlock_attempts"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Report unlock attempts" />
+ <CheckBox android:id="@+id/report_device_locked"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Report device locked or unlocked" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <Button android:id="@+id/check_device_locked"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Device locked?" />
+ <TextView android:id="@+id/check_device_locked_result"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/qs_tile_text.xml b/packages/Keyguard/test/SampleTrustAgent/res/xml-v26/sample_trust_agent.xml
similarity index 67%
rename from packages/SystemUI/res/color/qs_tile_text.xml
rename to packages/Keyguard/test/SampleTrustAgent/res/xml-v26/sample_trust_agent.xml
index 90e0bce..26d5aa0 100644
--- a/packages/SystemUI/res/color/qs_tile_text.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/res/xml-v26/sample_trust_agent.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-
<!--
- ~ Copyright (C) 2015 The Android Open Source Project
+ ~ Copyright (C) 2014 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.
@@ -15,8 +14,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="false" android:color="@color/qs_tile_disabled_color" />
- <item android:color="#B3FFFFFF" /> <!-- 70% white -->
-</selector>
\ No newline at end of file
+<trust-agent xmlns:android="http://schemas.android.com/apk/res/android"
+ android:settingsActivity=".SampleTrustAgentSettings"
+ android:unlockProfile="true" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml b/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
index b363ab4..6cd34bb 100644
--- a/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
@@ -15,4 +15,4 @@
~ limitations under the License
-->
<trust-agent xmlns:android="http://schemas.android.com/apk/res/android"
- android:settingsActivity=".SampleTrustAgentSettings" />
+ android:settingsActivity=".SampleTrustAgentSettings" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
index b8f16e7..4b50cf8 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -22,6 +22,7 @@
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.PersistableBundle;
+import android.os.UserManager;
import android.preference.PreferenceManager;
import android.service.trust.TrustAgentService;
import android.support.v4.content.LocalBroadcastManager;
@@ -57,26 +58,47 @@
= "preference.report_unlock_attempts";
private static final String PREFERENCE_MANAGING_TRUST
= "preference.managing_trust";
+ private static final String PREFERENCE_MANAGING_TRUST_DIRECT_BOOT
+ = "preference.managing_trust_direct_boot";
private static final String PREFERENCE_REPORT_DEVICE_LOCKED = "preference.report_device_locked";
private static final String TAG = "SampleTrustAgent";
+ private static final BroadcastReceiver mUnlockReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ }
+ };
+
+ private boolean mIsUserUnlocked;
+
@Override
public void onCreate() {
super.onCreate();
+ UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
+ mIsUserUnlocked = um.isUserUnlocked();
+ Log.i(TAG,, "onCreate, is user unlocked=" + mIsUserUnlocked);
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_GRANT_TRUST);
filter.addAction(ACTION_REVOKE_TRUST);
+ if (!mIsUserUnlocked) {
+ filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ }
mLocalBroadcastManager.registerReceiver(mReceiver, filter);
if (ALLOW_EXTERNAL_BROADCASTS) {
registerReceiver(mReceiver, filter);
}
- setManagingTrust(getIsManagingTrust(this));
- PreferenceManager.getDefaultSharedPreferences(this)
- .registerOnSharedPreferenceChangeListener(this);
+ if (!mIsUserUnlocked) {
+ boolean trustManaged = getIsManagingTrustDirectBoot(this);
+ Log.i(TAG, "in Direct boot." + (trustManaged ? "manage" : "cannot manage") + "trust");
+ setManagingTrust(getIsManagingTrustDirectBoot(this));
+ } else {
+ onBootCompleted();
+ }
}
@Override
@@ -137,6 +159,12 @@
.unregisterOnSharedPreferenceChangeListener(this);
}
+ private void onBootCompleted() {
+ PreferenceManager.getDefaultSharedPreferences(this)
+ .registerOnSharedPreferenceChangeListener(this);
+ setManagingTrust(getIsManagingTrust(this));
+ }
+
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -158,6 +186,9 @@
}
} else if (ACTION_REVOKE_TRUST.equals(action)) {
revokeTrust();
+ } else if (intent.ACTION_BOOT_COMPLETED.equals(action)) {
+ Log.d(TAG, "User unlocked and boot completed.");
+ onBootCompleted();
}
}
};
@@ -203,6 +234,7 @@
public static void setIsManagingTrust(Context context, boolean enabled) {
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);
+ Log.d("AAAA", "save manage trust preference. Enabled=" + enabled);
sharedPreferences.edit().putBoolean(PREFERENCE_MANAGING_TRUST, enabled).apply();
}
@@ -212,6 +244,21 @@
return sharedPreferences.getBoolean(PREFERENCE_MANAGING_TRUST, false);
}
+ public static void setIsManagingTrustDirectBoot(Context context, boolean enabled) {
+ Context directBootContext = context.createDeviceProtectedStorageContext();
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(directBootContext);
+ Log.d("AAAA", "save to direct boot preference. Enabled=" + enabled);
+ sharedPreferences.edit().putBoolean(PREFERENCE_MANAGING_TRUST_DIRECT_BOOT, enabled).apply();
+ }
+
+ public static boolean getIsManagingTrustDirectBoot(Context context) {
+ Context directBootContext = context.createDeviceProtectedStorageContext();
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(directBootContext);
+ return sharedPreferences.getBoolean(PREFERENCE_MANAGING_TRUST_DIRECT_BOOT, false);
+ }
+
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (PREFERENCE_MANAGING_TRUST.equals(key)) {
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
index 29b15cb..1b17169 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
@@ -33,6 +33,7 @@
private CheckBox mReportUnlockAttempts;
private CheckBox mReportDeviceLocked;
private CheckBox mManagingTrust;
+ private CheckBox mManagingTrustDirectBoot;
private TextView mCheckDeviceLockedResult;
private KeyguardManager mKeyguardManager;
@@ -59,6 +60,8 @@
mManagingTrust = (CheckBox) findViewById(R.id.managing_trust);
mManagingTrust.setOnCheckedChangeListener(this);
+ mManagingTrustDirectBoot = (CheckBox) findViewById(R.id.managing_trust_direct_boot);
+ mManagingTrustDirectBoot.setOnCheckedChangeListener(this);
mCheckDeviceLockedResult = (TextView) findViewById(R.id.check_device_locked_result);
}
@@ -68,6 +71,8 @@
super.onResume();
mReportUnlockAttempts.setChecked(SampleTrustAgent.getReportUnlockAttempts(this));
mManagingTrust.setChecked(SampleTrustAgent.getIsManagingTrust(this));
+ mManagingTrustDirectBoot.setChecked(
+ SampleTrustAgent.getIsManagingTrustDirectBoot(this));
updateTrustedState();
}
@@ -94,6 +99,8 @@
SampleTrustAgent.setIsManagingTrust(this, isChecked);
} else if (buttonView == mReportDeviceLocked) {
SampleTrustAgent.setReportDeviceLocked(this, isChecked);
+ } else if (buttonView == mManagingTrustDirectBoot) {
+ SampleTrustAgent.setIsManagingTrustDirectBoot(this, isChecked);
}
}
diff --git a/packages/MtpDocumentsProvider/res/values-in/strings.xml b/packages/MtpDocumentsProvider/res/values-in/strings.xml
index 905daec..6f65337 100644
--- a/packages/MtpDocumentsProvider/res/values-in/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-in/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="6271216747302322594">"Host MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Unduhan"</string>
+ <string name="downloads_app_label" msgid="7120690641874849726">"Download"</string>
<string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
<string name="accessing_notification_title" msgid="3030133609230917944">"Mengakses file dari <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
<string name="error_busy_device" msgid="3997316850357386589">"Perangkat lainnya sedang sibuk. Anda dapat mentransfer file jika telah tersedia."</string>
diff --git a/packages/MtpDocumentsProvider/res/values-uz-rUZ/strings.xml b/packages/MtpDocumentsProvider/res/values-uz-rUZ/strings.xml
index dea4cff..c511172 100644
--- a/packages/MtpDocumentsProvider/res/values-uz-rUZ/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-uz-rUZ/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Yuklanishlar"</string>
+ <string name="downloads_app_label" msgid="7120690641874849726">"Yuklanmalar"</string>
<string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g><xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
<string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> qurilmasidan fayllar o‘qilmoqda"</string>
<string name="error_busy_device" msgid="3997316850357386589">"Ulangan qurilma band. U bo‘shamaguncha fayllarni o‘tkazib bo‘lmaydi."</string>
diff --git a/packages/PrintRecommendationService/res/values/donottranslate.xml b/packages/PrintRecommendationService/res/values/donottranslate.xml
index e9b97a3..2cce56d8a 100644
--- a/packages/PrintRecommendationService/res/values/donottranslate.xml
+++ b/packages/PrintRecommendationService/res/values/donottranslate.xml
@@ -32,13 +32,6 @@
<item>Hewlett Packard</item>
</string-array>
- <!-- Samsung plugin -->
- <string-array name="known_print_vendor_info_for_samsung" translatable="false">
- <item>com.sec.app.samsungprintservice</item>
- <item>Samsung Electronics</item>
- <item>Samsung</item>
- </string-array>
-
<!-- Xerox plugin -->
<string-array name="known_print_vendor_info_for_xerox" translatable="false">
<item>com.xerox.printservice</item>
@@ -49,6 +42,8 @@
<array name="known_print_plugin_vendors" translatable="false">
<item>@array/known_print_vendor_info_for_mopria</item>
<item>@array/known_print_vendor_info_for_hp</item>
- <item>@array/known_print_vendor_info_for_samsung</item>
</array>
+
+ <!-- Samsung plugin -->
+ <string name="plugin_package_samsung">com.sec.app.samsungprintservice</string>
</resources>
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
index 3eedefd..d048396 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
@@ -78,7 +78,7 @@
try {
mPlugins.add(new RemotePrintServicePlugin(new SamsungRecommendationPlugin(this), this,
- false));
+ true));
} catch (Exception e) {
Log.e(LOG_TAG, "Could not initiate " + getString(R.string.plugin_vendor_samsung) +
" plugin", e);
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
index a2c0485..d60a25f 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
@@ -16,30 +16,52 @@
package com.android.printservice.recommendation.plugin.mdnsFilter;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StringRes;
import android.content.Context;
-import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
-import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
+import android.annotation.NonNull;
+import android.annotation.StringRes;
+
import com.android.printservice.recommendation.PrintServicePlugin;
-import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
-import com.android.printservice.recommendation.util.NsdResolveQueue;
+import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
+import com.android.printservice.recommendation.util.MDNSUtils;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* A plugin listening for mDNS results and only adding the ones that {@link
* MDNSUtils#isVendorPrinter match} configured list
*/
-public class MDNSFilterPlugin implements PrintServicePlugin, NsdManager.DiscoveryListener {
- private static final String LOG_TAG = "MDNSFilterPlugin";
+public class MDNSFilterPlugin implements PrintServicePlugin {
- private static final String PRINTER_SERVICE_TYPE = "_ipp._tcp";
+ /** The mDNS service types supported */
+ private static final Set<String> PRINTER_SERVICE_TYPES = new HashSet<String>() {{
+ add("_ipp._tcp");
+ }};
+
+ /**
+ * The printer filter for {@link MDNSFilteredDiscovery} passing only mDNS results
+ * that {@link MDNSUtils#isVendorPrinter match} configured list
+ */
+ private static class VendorNameFilter implements MDNSFilteredDiscovery.PrinterFilter {
+ /** mDNS names handled by the print service this plugin is for */
+ private final @NonNull Set<String> mMDNSNames;
+
+ /**
+ * Filter constructor
+ *
+ * @param vendorNames The vendor names to pass
+ */
+ VendorNameFilter(@NonNull Set<String> vendorNames) {
+ mMDNSNames = new HashSet<>(vendorNames);
+ }
+
+ @Override
+ public boolean matchesCriteria(NsdServiceInfo nsdServiceInfo) {
+ return MDNSUtils.isVendorPrinter(nsdServiceInfo, mMDNSNames);
+ }
+ }
/** Name of the print service this plugin is for */
private final @StringRes int mName;
@@ -47,26 +69,8 @@
/** Package name of the print service this plugin is for */
private final @NonNull CharSequence mPackageName;
- /** mDNS names handled by the print service this plugin is for */
- private final @NonNull HashSet<String> mMDNSNames;
-
- /** Printer identifiers of the mPrinters found. */
- @GuardedBy("mLock")
- private final @NonNull HashSet<String> mPrinters;
-
- /** Context of the user of this plugin */
- private final @NonNull Context mContext;
-
- /**
- * Call back to report the number of mPrinters found.
- *
- * We assume that {@link #start} and {@link #stop} are never called in parallel, hence it is
- * safe to not synchronize access to this field.
- */
- private @Nullable PrinterDiscoveryCallback mCallback;
-
- /** Queue used to resolve nsd infos */
- private final @NonNull NsdResolveQueue mResolveQueue;
+ /** The mDNS filtered discovery */
+ private final MDNSFilteredDiscovery mMDNSFilteredDiscovery;
/**
* Create new stub that assumes that a print service can be used to print on all mPrinters
@@ -79,16 +83,11 @@
*/
public MDNSFilterPlugin(@NonNull Context context, @NonNull String name,
@NonNull CharSequence packageName, @NonNull List<String> mDNSNames) {
- mContext = Preconditions.checkNotNull(context, "context");
- mName = mContext.getResources().getIdentifier(Preconditions.checkStringNotEmpty(name,
- "name"), null, "com.android.printservice.recommendation");
- mPackageName = Preconditions.checkStringNotEmpty(packageName);
- mMDNSNames = new HashSet<>(Preconditions
- .checkCollectionNotEmpty(Preconditions.checkCollectionElementsNotNull(mDNSNames,
- "mDNSNames"), "mDNSNames"));
-
- mResolveQueue = NsdResolveQueue.getInstance();
- mPrinters = new HashSet<>();
+ mName = context.getResources().getIdentifier(name, null,
+ "com.android.printservice.recommendation");
+ mPackageName = packageName;
+ mMDNSFilteredDiscovery = new MDNSFilteredDiscovery(context, PRINTER_SERVICE_TYPES,
+ new VendorNameFilter(new HashSet<>(mDNSNames)));
}
@Override
@@ -96,18 +95,9 @@
return mPackageName;
}
- /**
- * @return The NDS manager
- */
- private NsdManager getNDSManager() {
- return (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
- }
-
@Override
public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception {
- mCallback = callback;
-
- DiscoveryListenerMultiplexer.addListener(getNDSManager(), PRINTER_SERVICE_TYPE, this);
+ mMDNSFilteredDiscovery.start(callback);
}
@Override
@@ -117,82 +107,6 @@
@Override
public void stop() throws Exception {
- mCallback.onChanged(0);
- mCallback = null;
-
- DiscoveryListenerMultiplexer.removeListener(getNDSManager(), this);
- }
-
- @Override
- public void onStartDiscoveryFailed(String serviceType, int errorCode) {
- Log.w(LOG_TAG, "Failed to start network discovery for type " + serviceType + ": "
- + errorCode);
- }
-
- @Override
- public void onStopDiscoveryFailed(String serviceType, int errorCode) {
- Log.w(LOG_TAG, "Failed to stop network discovery for type " + serviceType + ": "
- + errorCode);
- }
-
- @Override
- public void onDiscoveryStarted(String serviceType) {
- // empty
- }
-
- @Override
- public void onDiscoveryStopped(String serviceType) {
- mPrinters.clear();
- }
-
- @Override
- public void onServiceFound(NsdServiceInfo serviceInfo) {
- mResolveQueue.resolve(getNDSManager(), serviceInfo,
- new NsdManager.ResolveListener() {
- @Override
- public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
- Log.w(LOG_TAG, "Service found: could not resolve " + serviceInfo + ": " +
- errorCode);
- }
-
- @Override
- public void onServiceResolved(NsdServiceInfo serviceInfo) {
- if (MDNSUtils.isVendorPrinter(serviceInfo, mMDNSNames)) {
- if (mCallback != null) {
- boolean added = mPrinters.add(serviceInfo.getHost().getHostAddress());
-
- if (added) {
- mCallback.onChanged(mPrinters.size());
- }
- }
- }
- }
- });
- }
-
- @Override
- public void onServiceLost(NsdServiceInfo serviceInfo) {
- mResolveQueue.resolve(getNDSManager(), serviceInfo,
- new NsdManager.ResolveListener() {
- @Override
- public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
- Log.w(LOG_TAG, "Service lost: Could not resolve " + serviceInfo + ": "
- + errorCode);
- }
-
- @Override
- public void onServiceResolved(NsdServiceInfo serviceInfo) {
- if (MDNSUtils.isVendorPrinter(serviceInfo, mMDNSNames)) {
- if (mCallback != null) {
- boolean removed = mPrinters
- .remove(serviceInfo.getHost().getHostAddress());
-
- if (removed) {
- mCallback.onChanged(mPrinters.size());
- }
- }
- }
- }
- });
+ mMDNSFilteredDiscovery.stop();
}
}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java
deleted file mode 100644
index 963e09b..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java
+++ /dev/null
@@ -1,74 +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 com.android.printservice.recommendation.plugin.samsung;
-
-import android.net.nsd.NsdServiceInfo;
-import android.text.TextUtils;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Locale;
-import java.util.Map;
-
-public class MDnsUtils {
- public static final String ATTRIBUTE__TY = "ty";
- public static final String ATTRIBUTE__PRODUCT = "product";
- public static final String ATTRIBUTE__USB_MFG = "usb_MFG";
- public static final String ATTRIBUTE__MFG = "mfg";
-
- public static String getString(byte[] value) {
- if (value != null) return new String(value,StandardCharsets.UTF_8);
- return null;
- }
-
- public static boolean isVendorPrinter(NsdServiceInfo networkDevice, String[] vendorValues) {
-
- Map<String,byte[]> attributes = networkDevice.getAttributes();
- String product = getString(attributes.get(ATTRIBUTE__PRODUCT));
- String ty = getString(attributes.get(ATTRIBUTE__TY));
- String usbMfg = getString(attributes.get(ATTRIBUTE__USB_MFG));
- String mfg = getString(attributes.get(ATTRIBUTE__MFG));
- return containsVendor(product, vendorValues) || containsVendor(ty, vendorValues) || containsVendor(usbMfg, vendorValues) || containsVendor(mfg, vendorValues);
-
- }
-
- public static String getVendor(NsdServiceInfo networkDevice) {
- String vendor;
-
- Map<String,byte[]> attributes = networkDevice.getAttributes();
- vendor = getString(attributes.get(ATTRIBUTE__MFG));
- if (!TextUtils.isEmpty(vendor)) return vendor;
- vendor = getString(attributes.get(ATTRIBUTE__USB_MFG));
- if (!TextUtils.isEmpty(vendor)) return vendor;
-
- return null;
- }
-
- private static boolean containsVendor(String container, String[] vendorValues) {
- if ((container == null) || (vendorValues == null)) return false;
- for (String value : vendorValues) {
- if (containsString(container, value)
- || containsString(container.toLowerCase(Locale.US), value.toLowerCase(Locale.US))
- || containsString(container.toUpperCase(Locale.US), value.toUpperCase(Locale.US)))
- return true;
- }
- return false;
- }
-
- private static boolean containsString(String container, String contained) {
- return (container != null) && (contained != null) && (container.equalsIgnoreCase(contained) || container.contains(contained + " "));
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterMopria.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterMopria.java
new file mode 100644
index 0000000..d03bb1d
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterMopria.java
@@ -0,0 +1,63 @@
+/*
+ * (c) Copyright 2016 Samsung Electronics
+ * (c) Copyright 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 com.android.printservice.recommendation.plugin.samsung;
+
+import android.net.nsd.NsdServiceInfo;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
+import com.android.printservice.recommendation.util.MDNSUtils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Printer filter for Mopria printer models supported by the print service plugin
+ */
+class PrinterFilterMopria implements MDNSFilteredDiscovery.PrinterFilter {
+ private static final String TAG = "PrinterFilterMopria";
+
+ static final Set<String> MOPRIA_MDNS_SERVICES = new HashSet<String>() {{
+ add("_ipp._tcp");
+ add("_ipps._tcp");
+ }};
+
+ private static final String PDL__PDF = "application/pdf";
+ private static final String PDL__PCLM = "application/PCLm";
+ private static final String PDL__PWG_RASTER = "image/pwg-raster";
+
+ private static final String PDL_ATTRIBUTE = "pdl";
+
+ @Override
+ public boolean matchesCriteria(NsdServiceInfo nsdServiceInfo) {
+ if (!MDNSUtils.isSupportedServiceType(nsdServiceInfo, MOPRIA_MDNS_SERVICES)) {
+ return false;
+ }
+
+ String pdls = MDNSUtils.getString(nsdServiceInfo.getAttributes().get(PDL_ATTRIBUTE));
+ boolean isMatch = !TextUtils.isEmpty(pdls)
+ && (pdls.contains(PDL__PDF)
+ || pdls.contains(PDL__PCLM)
+ || pdls.contains(PDL__PWG_RASTER));
+
+ if (isMatch) {
+ Log.d(TAG, "Mopria printer found: " + nsdServiceInfo.getServiceName());
+ }
+ return isMatch;
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterSamsung.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterSamsung.java
new file mode 100644
index 0000000..5b049ef
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterSamsung.java
@@ -0,0 +1,117 @@
+/*
+ * (c) Copyright 2016 Samsung Electronics
+ * (c) Copyright 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 com.android.printservice.recommendation.plugin.samsung;
+
+import android.net.nsd.NsdServiceInfo;
+import android.annotation.NonNull;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
+import com.android.printservice.recommendation.util.MDNSUtils;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Printer filter for Samsung printer models supported by the print service plugin
+ */
+class PrinterFilterSamsung implements MDNSFilteredDiscovery.PrinterFilter {
+ private static final String TAG = "PrinterFilterSamsung";
+
+ static final Set<String> SAMSUNG_MDNS_SERVICES = new HashSet<String>() {{
+ add("_pdl-datastream._tcp");
+ }};
+
+ private static final String[] NOT_SUPPORTED_MODELS = new String[]{
+ "SCX-5x15",
+ "SF-555P",
+ "CF-555P",
+ "SCX-4x16",
+ "SCX-4214F",
+ "CLP-500",
+ "CJX-",
+ "MJC-"
+ };
+ private static final String ATTR_USB_MFG = "usb_MFG";
+ private static final String ATTR_MFG = "mfg";
+ private static final String ATTR_USB_MDL = "usb_MDL";
+ private static final String ATTR_MDL = "mdl";
+ private static final String ATTR_PRODUCT = "product";
+ private static final String ATTR_TY = "ty";
+
+ private static Set<String> SAMUNG_VENDOR_SET = new HashSet<String>() {{
+ add("samsung");
+ }};
+
+ @Override
+ public boolean matchesCriteria(NsdServiceInfo nsdServiceInfo) {
+ if (!MDNSUtils.isSupportedServiceType(nsdServiceInfo, SAMSUNG_MDNS_SERVICES)) {
+ return false;
+ }
+
+ if (!MDNSUtils.isVendorPrinter(nsdServiceInfo, SAMUNG_VENDOR_SET)) {
+ return false;
+ }
+
+ String modelName = getSamsungModelName(nsdServiceInfo);
+ if (modelName != null && isSupportedSamsungModel(modelName)) {
+ Log.d(TAG, "Samsung printer found: " + nsdServiceInfo.getServiceName());
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isSupportedSamsungModel(String model) {
+ if (!TextUtils.isEmpty(model)) {
+ String modelToUpper = model.toUpperCase(Locale.US);
+ for (String unSupportedPrinter : NOT_SUPPORTED_MODELS) {
+ if (modelToUpper.contains(unSupportedPrinter)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private String getSamsungModelName(@NonNull NsdServiceInfo resolvedDevice) {
+ Map<String,byte[]> attributes = resolvedDevice.getAttributes();
+ String usb_mfg = MDNSUtils.getString(attributes.get(ATTR_USB_MFG));
+ if (TextUtils.isEmpty(usb_mfg)) {
+ usb_mfg = MDNSUtils.getString(attributes.get(ATTR_MFG));
+ }
+
+ String usb_mdl = MDNSUtils.getString(attributes.get(ATTR_USB_MDL));
+ if (TextUtils.isEmpty(usb_mdl)) {
+ usb_mdl = MDNSUtils.getString(attributes.get(ATTR_MDL));
+ }
+
+ String modelName;
+ if (!TextUtils.isEmpty(usb_mfg) && !TextUtils.isEmpty(usb_mdl)) {
+ modelName = usb_mfg.trim() + " " + usb_mdl.trim();
+ } else {
+ modelName = MDNSUtils.getString(attributes.get(ATTR_PRODUCT));
+ if (TextUtils.isEmpty(modelName)) {
+ modelName = MDNSUtils.getString(attributes.get(ATTR_TY));
+ }
+ }
+
+ return modelName;
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java
deleted file mode 100644
index 032fe22..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java
+++ /dev/null
@@ -1,33 +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 com.android.printservice.recommendation.plugin.samsung;
-
-import android.net.nsd.NsdServiceInfo;
-
-import java.util.HashMap;
-
-final class PrinterHashMap extends HashMap<String, NsdServiceInfo> {
- public static String getKey(NsdServiceInfo serviceInfo) {
- return serviceInfo.getServiceName();
- }
- public NsdServiceInfo addPrinter(NsdServiceInfo device) {
- return put(getKey(device), device);
- }
- public NsdServiceInfo removePrinter(NsdServiceInfo device) {
- return remove(getKey(device));
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
index e5b8a0f..eeb5122 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
@@ -1,102 +1,69 @@
-/*
-(c) Copyright 2016 Samsung Electronics..
-
-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.android.printservice.recommendation.plugin.samsung;
-
-import android.content.Context;
-import android.net.nsd.NsdServiceInfo;
-import android.text.TextUtils;
-
-import java.util.Locale;
-import java.util.Map;
-
-import com.android.printservice.recommendation.R;
-
-public class SamsungRecommendationPlugin extends ServiceRecommendationPlugin {
-
- private static final String TAG = "SamsungRecommendation";
-
- private static final String ATTR_USB_MFG = "usb_MFG";
- private static final String ATTR_MFG = "mfg";
- private static final String ATTR_USB_MDL = "usb_MDL";
- private static final String ATTR_MDL = "mdl";
- private static final String ATTR_PRODUCT = "product";
- private static final String ATTR_TY = "ty";
-
- private static String[] mNotSupportedDevices = new String[]{
- "SCX-5x15",
- "SF-555P",
- "CF-555P",
- "SCX-4x16",
- "SCX-4214F",
- "CLP-500",
- "CJX-",
- "MJC-"
- };
-
- private static boolean isSupportedModel(String model) {
- if (!TextUtils.isEmpty(model)) {
- String modelToUpper = model.toUpperCase(Locale.US);
- for (String unSupportedPrinter : mNotSupportedDevices) {
- if (modelToUpper.contains(unSupportedPrinter)) {
- return false;
- }
- }
- }
- return true;
- }
-
- public SamsungRecommendationPlugin(Context context) {
- super(context, R.string.plugin_vendor_samsung, new VendorInfo(context.getResources(), R.array.known_print_vendor_info_for_samsung), new String[]{"_pdl-datastream._tcp"});
- }
-
- @Override
- public boolean matchesCriteria(String vendor, NsdServiceInfo nsdServiceInfo) {
- if (!TextUtils.equals(vendor, mVendorInfo.mVendorID)) return false;
-
- String modelName = getModelName(nsdServiceInfo);
- if (modelName != null) {
- return (isSupportedModel(modelName));
- }
- return false;
- }
-
- private String getModelName(NsdServiceInfo resolvedDevice) {
- Map<String,byte[]> attributes = resolvedDevice.getAttributes();
- String usb_mfg = MDnsUtils.getString(attributes.get(ATTR_USB_MFG));
- if (TextUtils.isEmpty(usb_mfg)) {
- usb_mfg = MDnsUtils.getString(attributes.get(ATTR_MFG));
- }
-
- String usb_mdl = MDnsUtils.getString(attributes.get(ATTR_USB_MDL));
- if (TextUtils.isEmpty(usb_mdl)) {
- usb_mdl = MDnsUtils.getString(attributes.get(ATTR_MDL));
- }
-
- String modelName = null;
- if (!TextUtils.isEmpty(usb_mfg) && !TextUtils.isEmpty(usb_mdl)) {
- modelName = usb_mfg.trim() + " " + usb_mdl.trim();
- } else {
- modelName = MDnsUtils.getString(attributes.get(ATTR_PRODUCT));
- if (TextUtils.isEmpty(modelName)) {
- modelName = MDnsUtils.getString(attributes.get(ATTR_TY));
- }
- }
-
- return modelName;
- }
-}
+/*
+ * (c) Copyright 2016 Samsung Electronics
+ * (c) Copyright 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 com.android.printservice.recommendation.plugin.samsung;
+
+import android.content.Context;
+import android.net.nsd.NsdServiceInfo;
+import android.annotation.NonNull;
+
+import com.android.printservice.recommendation.PrintServicePlugin;
+import com.android.printservice.recommendation.R;
+import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class SamsungRecommendationPlugin implements PrintServicePlugin {
+ private static final Set<String> ALL_MDNS_SERVICES = new HashSet<String>() {{
+ addAll(PrinterFilterMopria.MOPRIA_MDNS_SERVICES);
+ addAll(PrinterFilterSamsung.SAMSUNG_MDNS_SERVICES);
+ }};
+
+ private final @NonNull Context mContext;
+ private final @NonNull MDNSFilteredDiscovery mMDNSFilteredDiscovery;
+
+ private final @NonNull PrinterFilterSamsung mPrinterFilterSamsung = new PrinterFilterSamsung();
+ private final @NonNull PrinterFilterMopria mPrinterFilterMopria = new PrinterFilterMopria();
+
+ public SamsungRecommendationPlugin(@NonNull Context context) {
+ mContext = context;
+ mMDNSFilteredDiscovery = new MDNSFilteredDiscovery(context, ALL_MDNS_SERVICES,
+ (NsdServiceInfo nsdServiceInfo) ->
+ mPrinterFilterSamsung.matchesCriteria(nsdServiceInfo) ||
+ mPrinterFilterMopria.matchesCriteria(nsdServiceInfo));
+ }
+
+ @Override
+ public int getName() {
+ return R.string.plugin_vendor_samsung;
+ }
+
+ @Override
+ public @NonNull CharSequence getPackageName() {
+ return mContext.getString(R.string.plugin_package_samsung);
+ }
+
+ @Override
+ public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception {
+ mMDNSFilteredDiscovery.start(callback);
+ }
+
+ @Override
+ public void stop() throws Exception {
+ mMDNSFilteredDiscovery.stop();
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java
deleted file mode 100644
index 7bb83c9..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java
+++ /dev/null
@@ -1,186 +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 com.android.printservice.recommendation.plugin.samsung;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.net.nsd.NsdManager;
-import android.net.nsd.NsdServiceInfo;
-import android.text.TextUtils;
-import android.util.Pair;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.android.printservice.recommendation.R;
-import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
-
-public class ServiceListener implements ServiceResolveQueue.ResolveCallback {
-
- private final NsdManager mNSDManager;
- private final Map<String, VendorInfo> mVendorInfoHashMap;
- private final String[] mServiceType;
- private final Observer mObserver;
- private final ServiceResolveQueue mResolveQueue;
- private List<NsdManager.DiscoveryListener> mListeners = new ArrayList<>();
- public HashMap<String, PrinterHashMap> mVendorHashMap = new HashMap<>();
-
- public interface Observer {
- boolean matchesCriteria(String vendor, NsdServiceInfo serviceInfo);
- void dataSetChanged();
- }
-
- public ServiceListener(Context context, Observer observer, String[] serviceTypes) {
- mObserver = observer;
- mServiceType = serviceTypes;
- mNSDManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE);
- mResolveQueue = ServiceResolveQueue.getInstance(mNSDManager);
-
- Map<String, VendorInfo> vendorInfoMap = new HashMap<>();
- TypedArray testArray = context.getResources().obtainTypedArray(R.array.known_print_plugin_vendors);
- for(int i = 0; i < testArray.length(); i++) {
- int arrayID = testArray.getResourceId(i, 0);
- if (arrayID != 0) {
- VendorInfo info = new VendorInfo(context.getResources(), arrayID);
- vendorInfoMap.put(info.mVendorID, info);
- vendorInfoMap.put(info.mPackageName, info);
- }
- }
- testArray.recycle();
- mVendorInfoHashMap = vendorInfoMap;
- }
-
- @Override
- public void serviceResolved(NsdServiceInfo nsdServiceInfo) {
- printerFound(nsdServiceInfo);
- }
-
- private synchronized void printerFound(NsdServiceInfo nsdServiceInfo) {
- if (nsdServiceInfo == null) return;
- if (TextUtils.isEmpty(PrinterHashMap.getKey(nsdServiceInfo))) return;
- String vendor = MDnsUtils.getVendor(nsdServiceInfo);
- if (vendor == null) vendor = "";
- for(Map.Entry<String,VendorInfo> entry : mVendorInfoHashMap.entrySet()) {
- for(String vendorValues : entry.getValue().mDNSValues) {
- if (vendor.equalsIgnoreCase(vendorValues)) {
- vendor = entry.getValue().mVendorID;
- break;
- }
- }
- // intentional pointer check
- //noinspection StringEquality
- if ((vendor != entry.getValue().mVendorID) &&
- MDnsUtils.isVendorPrinter(nsdServiceInfo, entry.getValue().mDNSValues)) {
- vendor = entry.getValue().mVendorID;
- }
- // intentional pointer check
- //noinspection StringEquality
- if (vendor == entry.getValue().mVendorID) break;
- }
-
- if (TextUtils.isEmpty(vendor)) {
- return;
- }
-
- if (!mObserver.matchesCriteria(vendor, nsdServiceInfo))
- return;
- boolean mapsChanged;
-
- PrinterHashMap vendorHash = mVendorHashMap.get(vendor);
- if (vendorHash == null) {
- vendorHash = new PrinterHashMap();
- }
- mapsChanged = (vendorHash.addPrinter(nsdServiceInfo) == null);
- mVendorHashMap.put(vendor, vendorHash);
-
- if (mapsChanged) {
- mObserver.dataSetChanged();
- }
- }
-
- private synchronized void printerRemoved(NsdServiceInfo nsdServiceInfo) {
- boolean wasRemoved = false;
- Set<String> vendors = mVendorHashMap.keySet();
- for(String vendor : vendors) {
- PrinterHashMap map = mVendorHashMap.get(vendor);
- wasRemoved |= (map.removePrinter(nsdServiceInfo) != null);
- if (map.isEmpty()) wasRemoved |= (mVendorHashMap.remove(vendor) != null);
- }
- if (wasRemoved) {
- mObserver.dataSetChanged();
- }
- }
-
- public void start() {
- stop();
- for(final String service :mServiceType) {
- NsdManager.DiscoveryListener listener = new NsdManager.DiscoveryListener() {
- @Override
- public void onStartDiscoveryFailed(String s, int i) {
-
- }
-
- @Override
- public void onStopDiscoveryFailed(String s, int i) {
-
- }
-
- @Override
- public void onDiscoveryStarted(String s) {
-
- }
-
- @Override
- public void onDiscoveryStopped(String s) {
-
- }
-
- @Override
- public void onServiceFound(NsdServiceInfo nsdServiceInfo) {
- mResolveQueue.queueRequest(nsdServiceInfo, ServiceListener.this);
- }
-
- @Override
- public void onServiceLost(NsdServiceInfo nsdServiceInfo) {
- mResolveQueue.removeRequest(nsdServiceInfo, ServiceListener.this);
- printerRemoved(nsdServiceInfo);
- }
- };
- DiscoveryListenerMultiplexer.addListener(mNSDManager, service, listener);
- mListeners.add(listener);
- }
- }
-
- public void stop() {
- for(NsdManager.DiscoveryListener listener : mListeners) {
- DiscoveryListenerMultiplexer.removeListener(mNSDManager, listener);
- }
- mVendorHashMap.clear();
- mListeners.clear();
- }
-
- public Pair<Integer, Integer> getCount() {
- int count = 0;
- for (PrinterHashMap map : mVendorHashMap.values()) {
- count += map.size();
- }
- return Pair.create(mVendorHashMap.size(), count);
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java
deleted file mode 100644
index 9d15f30..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java
+++ /dev/null
@@ -1,86 +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 com.android.printservice.recommendation.plugin.samsung;
-
-import android.content.Context;
-import android.net.nsd.NsdManager;
-import android.net.nsd.NsdServiceInfo;
-import android.annotation.NonNull;
-import android.text.TextUtils;
-import com.android.printservice.recommendation.PrintServicePlugin;
-
-public abstract class ServiceRecommendationPlugin implements PrintServicePlugin, ServiceListener.Observer {
-
- protected static final String PDL_ATTRIBUTE = "pdl";
-
- protected final Object mLock = new Object();
- protected PrinterDiscoveryCallback mCallback = null;
- protected final ServiceListener mListener;
- protected final NsdManager mNSDManager;
- protected final VendorInfo mVendorInfo;
- private final int mVendorStringID;
-
- protected ServiceRecommendationPlugin(Context context, int vendorStringID, VendorInfo vendorInfo, String[] services) {
- mNSDManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE);
- mVendorStringID = vendorStringID;
- mVendorInfo = vendorInfo;
- mListener = new ServiceListener(context, this, services);
- }
-
- @Override
- public int getName() {
- return mVendorStringID;
- }
-
- @NonNull
- @Override
- public CharSequence getPackageName() {
- return mVendorInfo.mPackageName;
- }
-
- @Override
- public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception {
- synchronized (mLock) {
- mCallback = callback;
- }
- mListener.start();
- }
-
- @Override
- public void stop() throws Exception {
- synchronized (mLock) {
- mCallback = null;
- }
- mListener.stop();
- }
-
- @Override
- public void dataSetChanged() {
- synchronized (mLock) {
- if (mCallback != null) mCallback.onChanged(getCount());
- }
- }
-
- @Override
- public boolean matchesCriteria(String vendor, NsdServiceInfo nsdServiceInfo) {
- return TextUtils.equals(vendor, mVendorInfo.mVendorID);
- }
-
- public int getCount() {
- return mListener.getCount().second;
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java
deleted file mode 100644
index e5691b7..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java
+++ /dev/null
@@ -1,109 +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 com.android.printservice.recommendation.plugin.samsung;
-
-import android.net.nsd.NsdManager;
-import android.net.nsd.NsdServiceInfo;
-import android.util.Pair;
-import com.android.printservice.recommendation.util.NsdResolveQueue;
-
-import java.util.LinkedList;
-
-final class ServiceResolveQueue {
-
- private final NsdManager mNsdManager;
- private final LinkedList<Pair<NsdServiceInfo, ResolveCallback>> mQueue = new LinkedList<>();
- private final Object mLock = new Object();
-
- private static Object sLock = new Object();
- private static ServiceResolveQueue sInstance = null;
- private final NsdResolveQueue mNsdResolveQueue;
- private Pair<NsdServiceInfo, ResolveCallback> mCurrentRequest = null;
-
- public static void createInstance(NsdManager nsdManager) {
- if (sInstance == null) sInstance = new ServiceResolveQueue(nsdManager);
- }
-
- public static ServiceResolveQueue getInstance(NsdManager nsdManager) {
- synchronized (sLock) {
- createInstance(nsdManager);
- return sInstance;
- }
- }
-
- public static void destroyInstance() {
- sInstance = null;
- }
-
- public interface ResolveCallback {
- void serviceResolved(NsdServiceInfo nsdServiceInfo);
- }
-
- public ServiceResolveQueue(NsdManager nsdManager) {
- mNsdManager = nsdManager;
- mNsdResolveQueue = NsdResolveQueue.getInstance();
- }
-
- public void queueRequest(NsdServiceInfo serviceInfo, ResolveCallback callback) {
- synchronized (mLock) {
- Pair<NsdServiceInfo, ResolveCallback> newRequest = Pair.create(serviceInfo, callback);
- if (mQueue.contains(newRequest)) return;
- mQueue.add(newRequest);
- makeNextRequest();
- }
- }
-
- public void removeRequest(NsdServiceInfo serviceInfo, ResolveCallback callback) {
- synchronized (mLock) {
- Pair<NsdServiceInfo, ResolveCallback> newRequest = Pair.create(serviceInfo, callback);
- mQueue.remove(newRequest);
- if ((mCurrentRequest != null) && newRequest.equals(mCurrentRequest)) mCurrentRequest = null;
- }
- }
-
- private void makeNextRequest() {
- synchronized (mLock) {
- if (mCurrentRequest != null) return;
- if (mQueue.isEmpty()) return;
- mCurrentRequest = mQueue.removeFirst();
- mNsdResolveQueue.resolve(mNsdManager, mCurrentRequest.first,
- new NsdManager.ResolveListener() {
- @Override
- public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int i) {
- synchronized (mLock) {
- if (mCurrentRequest != null) mQueue.add(mCurrentRequest);
- makeNextRequest();
- }
- }
-
- @Override
- public void onServiceResolved(NsdServiceInfo nsdServiceInfo) {
- synchronized (mLock) {
- if (mCurrentRequest != null) {
- mCurrentRequest.second.serviceResolved(nsdServiceInfo);
- mCurrentRequest = null;
- }
- makeNextRequest();
- }
- }
- });
-
- }
- }
-
-
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java
deleted file mode 100644
index 0ebb4e4..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java
+++ /dev/null
@@ -1,40 +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 com.android.printservice.recommendation.plugin.samsung;
-
-import android.content.res.Resources;
-
-import java.util.Arrays;
-
-public final class VendorInfo {
-
- public final String mPackageName;
- public final String mVendorID;
- public final String[] mDNSValues;
- public final int mID;
-
- public VendorInfo(Resources resources, int vendor_info_id) {
- mID = vendor_info_id;
- String[] data = resources.getStringArray(vendor_info_id);
- if ((data == null) || (data.length < 2)) {
- data = new String[] { null, null };
- }
- mPackageName = data[0];
- mVendorID = data[1];
- mDNSValues = (data.length > 2) ? Arrays.copyOfRange(data, 2, data.length) : new String[]{};
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java
new file mode 100644
index 0000000..c5dbc8c
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java
@@ -0,0 +1,212 @@
+/*
+ * 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 com.android.printservice.recommendation.util;
+
+import android.content.Context;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
+import com.android.printservice.recommendation.PrintServicePlugin;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A discovery listening for mDNS results and only adding the ones that {@link
+ * PrinterFilter#matchesCriteria match} configured list
+ */
+public class MDNSFilteredDiscovery implements NsdManager.DiscoveryListener {
+ private static final String LOG_TAG = "MDNSFilteredDiscovery";
+
+ /**
+ * mDNS service filter interface.
+ * Implement {@link PrinterFilter#matchesCriteria} to filter out supported services
+ */
+ public interface PrinterFilter {
+ /**
+ * Main filter method. Should return true if mDNS service is supported
+ * by the print service plugin
+ *
+ * @param nsdServiceInfo The service info to check
+ *
+ * @return True if service is supported by the print service plugin
+ */
+ boolean matchesCriteria(NsdServiceInfo nsdServiceInfo);
+ }
+
+ /** Printer identifiers of the mPrinters found. */
+ @GuardedBy("mLock")
+ private final @NonNull HashSet<String> mPrinters;
+
+ /** Service types discovered by this plugin */
+ private final @NonNull HashSet<String> mServiceTypes;
+
+ /** Context of the user of this plugin */
+ private final @NonNull Context mContext;
+
+ /** mDNS services filter */
+ private final @NonNull PrinterFilter mPrinterFilter;
+
+ /**
+ * Call back to report the number of mPrinters found.
+ *
+ * We assume that {@link #start} and {@link #stop} are never called in parallel, hence it is
+ * safe to not synchronize access to this field.
+ */
+ private @Nullable PrintServicePlugin.PrinterDiscoveryCallback mCallback;
+
+ /** Queue used to resolve nsd infos */
+ private final @NonNull NsdResolveQueue mResolveQueue;
+
+ /**
+ * Create new stub that assumes that a print service can be used to print on all mPrinters
+ * matching some mDNS names.
+ *
+ * @param context The context the plugin runs in
+ * @param serviceTypes The mDNS service types to listen to.
+ * @param printerFilter The filter for mDNS services
+ */
+ public MDNSFilteredDiscovery(@NonNull Context context,
+ @NonNull Set<String> serviceTypes,
+ @NonNull PrinterFilter printerFilter) {
+ mContext = Preconditions.checkNotNull(context, "context");
+ mServiceTypes = new HashSet<>(Preconditions
+ .checkCollectionNotEmpty(Preconditions.checkCollectionElementsNotNull(serviceTypes,
+ "serviceTypes"), "serviceTypes"));
+ mPrinterFilter = Preconditions.checkNotNull(printerFilter, "printerFilter");
+
+ mResolveQueue = NsdResolveQueue.getInstance();
+ mPrinters = new HashSet<>();
+ }
+
+ /**
+ * @return The NDS manager
+ */
+ private NsdManager getNDSManager() {
+ return (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
+ }
+
+ /**
+ * Start the discovery.
+ *
+ * @param callback Callbacks used by this plugin.
+ */
+ public void start(@NonNull PrintServicePlugin.PrinterDiscoveryCallback callback) {
+ mCallback = callback;
+ mCallback.onChanged(mPrinters.size());
+
+ for (String serviceType : mServiceTypes) {
+ DiscoveryListenerMultiplexer.addListener(getNDSManager(), serviceType, this);
+ }
+ }
+
+ /**
+ * Stop the discovery. This can only return once the plugin is completely finished and cleaned up.
+ */
+ public void stop() {
+ mCallback.onChanged(0);
+ mCallback = null;
+
+ for (int i = 0; i < mServiceTypes.size(); ++i) {
+ DiscoveryListenerMultiplexer.removeListener(getNDSManager(), this);
+ }
+ }
+
+ /**
+ *
+ * @return The number of discovered printers
+ */
+ public int getCount() {
+ return mPrinters.size();
+ }
+
+ @Override
+ public void onStartDiscoveryFailed(String serviceType, int errorCode) {
+ Log.w(LOG_TAG, "Failed to start network discovery for type " + serviceType + ": "
+ + errorCode);
+ }
+
+ @Override
+ public void onStopDiscoveryFailed(String serviceType, int errorCode) {
+ Log.w(LOG_TAG, "Failed to stop network discovery for type " + serviceType + ": "
+ + errorCode);
+ }
+
+ @Override
+ public void onDiscoveryStarted(String serviceType) {
+ // empty
+ }
+
+ @Override
+ public void onDiscoveryStopped(String serviceType) {
+ mPrinters.clear();
+ }
+
+ @Override
+ public void onServiceFound(NsdServiceInfo serviceInfo) {
+ mResolveQueue.resolve(getNDSManager(), serviceInfo,
+ new NsdManager.ResolveListener() {
+ @Override
+ public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
+ Log.w(LOG_TAG, "Service found: could not resolve " + serviceInfo + ": " +
+ errorCode);
+ }
+
+ @Override
+ public void onServiceResolved(NsdServiceInfo serviceInfo) {
+ if (mPrinterFilter.matchesCriteria(serviceInfo)) {
+ if (mCallback != null) {
+ boolean added = mPrinters.add(serviceInfo.getHost().getHostAddress());
+ if (added) {
+ mCallback.onChanged(mPrinters.size());
+ }
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onServiceLost(NsdServiceInfo serviceInfo) {
+ mResolveQueue.resolve(getNDSManager(), serviceInfo,
+ new NsdManager.ResolveListener() {
+ @Override
+ public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
+ Log.w(LOG_TAG, "Service lost: Could not resolve " + serviceInfo + ": "
+ + errorCode);
+ }
+
+ @Override
+ public void onServiceResolved(NsdServiceInfo serviceInfo) {
+ if (mPrinterFilter.matchesCriteria(serviceInfo)) {
+ if (mCallback != null) {
+ boolean removed = mPrinters
+ .remove(serviceInfo.getHost().getHostAddress());
+
+ if (removed) {
+ mCallback.onChanged(mPrinters.size());
+ }
+ }
+ }
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSUtils.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSUtils.java
similarity index 75%
rename from packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSUtils.java
rename to packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSUtils.java
index 4c27a47..a6df3c8 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSUtils.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSUtils.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.android.printservice.recommendation.plugin.mdnsFilter;
+package com.android.printservice.recommendation.util;
import android.annotation.NonNull;
import android.net.nsd.NsdServiceInfo;
@@ -27,12 +27,15 @@
/**
* Utils for dealing with mDNS attributes
*/
-class MDNSUtils {
+public class MDNSUtils {
public static final String ATTRIBUTE_TY = "ty";
public static final String ATTRIBUTE_PRODUCT = "product";
public static final String ATTRIBUTE_USB_MFG = "usb_mfg";
public static final String ATTRIBUTE_MFG = "mfg";
+ private MDNSUtils() {
+ }
+
/**
* Check if the service has any of a set of vendor names.
*
@@ -95,4 +98,35 @@
private static boolean containsString(@NonNull String container, @NonNull String contained) {
return container.equalsIgnoreCase(contained) || container.contains(contained + " ");
}
+
+ /**
+ * Return String from mDNS attribute byte array
+ *
+ * @param value the byte array with string data
+ *
+ * @return constructed string
+ */
+ public static String getString(byte[] value) {
+ if (value != null) return new String(value, StandardCharsets.UTF_8);
+ return null;
+ }
+
+ /**
+ * Check if service has a type of supported types set
+ *
+ * @param serviceInfo The service
+ * @param serviceTypes The supported service types set
+ *
+ * @return true if service has a type of supported types set
+ */
+ public static boolean isSupportedServiceType(@NonNull NsdServiceInfo serviceInfo,
+ @NonNull Set<String> serviceTypes) {
+ String curType = serviceInfo.getServiceType().toLowerCase();
+ for (String type : serviceTypes) {
+ if (curType.contains(type.toLowerCase())) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 5808b30..235ff3d 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -32,7 +32,7 @@
<string name="template_page_range" msgid="428638530038286328">"Mfululizo wa <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
<string name="pages_range_example" msgid="8558694453556945172">"k.m. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Chungulia kwanza kabla ya kuchapisha"</string>
- <string name="install_for_print_preview" msgid="6366303997385509332">"Sakinisha kitazamaji cha PDF kwa onyesho la kuchungulia"</string>
+ <string name="install_for_print_preview" msgid="6366303997385509332">"Sakinisha Kifungua PDF ili uweze kuchungulia"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Programu ya kuchapisha imeacha kufanya kazi"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Inaleta kazi ya kuchapisha"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Hifadhi kama PDF"</string>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 34d236b..fcda1d1 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Gepasmaak (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Hulp en terugvoer"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Kieslys"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"MGT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index c0b776e..a53e97a 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Fərdi (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Yardım və rəy"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 23adb5a..b32388e 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Персонализирано (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Помощ и отзиви"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"Средно време по Гринуич (GMT)"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 09988ed..3ee2642e 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"কাস্টম (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"সহায়তা ও মতামত"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"মেনু"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index 561af92..b207129 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagodi (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 5276b3a..159a939 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Vlastní (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Nápověda a zpětná vazba"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Nabídka"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 0c56b8d..49f1899 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tilpasset (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Hjælp og feedback"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 60f373b..95ac313 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Benutzerdefiniert (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Hilfe & Feedback"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index e0b5bb7..9127b2a 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Ayuda y comentarios"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index 7d70efe..f979db8 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Kohandatud (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Abi ja tagasiside"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menüü"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index e998b69..4a741f07 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"سفارشی (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"راهنما و بازخورد"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"منو"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index e2eb10d..afd343c 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisée (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 282ae4a..4d9d90c 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisé (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index f4bb7ad..1110fe2 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Axuda e suxestións"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index a2a6e04..eefdff1 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"कस्टम (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"सहायता और फ़ीडबैक"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"मेनू"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 76f04bd..9b38b61 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagođeno (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Izbornik"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index f5f6916..a373545 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Egyéni (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Súgó és visszajelzés"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 6dcb745..03bac7a 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Հատուկ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Օգնություն և հետադարձ կապ"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Ընտրացանկ"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 2ee38ef..aa3dc13 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"מותאם אישית (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"עזרה ומשוב"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"תפריט"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 8b2d784..f760d934 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -343,6 +343,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"カスタム(<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ヘルプとフィードバック"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"メニュー"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 92d7783..920b810 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Арнаулы (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Анықтама және пікір"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Mәзір"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 46cc6ce..d162bd1 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ផ្ទាល់ខ្លួន (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ជំនួយ និងមតិស្ថាបនា"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"ម៉ឺនុយ"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index 20d8ae9..ca0ba0a 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ಕಸ್ಟಮ್ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"ಮೆನು"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 03c0edf..2732853 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"맞춤(<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"고객센터"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"메뉴"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 41a8eef..7b16fd9 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ປັບແຕ່ງເອງ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ຊ່ວຍເຫຼືອ & ຄຳຕິຊົມ"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"ເມນູ"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 6930c7a..85e044f 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tinkintas (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Pagalba ir atsiliepimai"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Meniu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 7734881..36378f2 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Pielāgots (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Palīdzība un atsauksmes"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Izvēlne"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 8bcbf79..09c07ea 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ഇഷ്ടാനുസൃതം ( <xliff:g id="DENSITYDPI">%d</xliff:g> )"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"സഹായവും പ്രതികരണവും"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"മെനു"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 4fa3779..86a62a2 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Тогтмол утга (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Тусламж, санал хүсэлт"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Цэс"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"Гринвичийн цаг"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index cf77254..8935581 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tersuai (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Bantuan & maklum balas"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 9db8348..5f4dc50 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"စိတ်ကြိုက် (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"အကူအညီနှင့် အကြံပြုချက်"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"မီနူး"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"ဂရင်းနစ်စံတော်ချိန်"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index cc4e5678..76ff94f 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Egendefinert (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Hjelp og tilbakemelding"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Meny"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 834580b..8199cde 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -22,7 +22,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"सञ्जालका लागि स्क्यान गर्न सक्दैन"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"कुनै पनि होइन"</string>
- <string name="wifi_remembered" msgid="4955746899347821096">"बचत गरियो"</string>
+ <string name="wifi_remembered" msgid="4955746899347821096">"सुरक्षित गरियो"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"असक्षम पारियो"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP विन्यास असफल"</string>
<string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"वाईफाई जडान असफल"</string>
@@ -338,7 +338,7 @@
<string name="screen_zoom_summary_large" msgid="4835294730065424084">"ठूलो"</string>
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"अझ ठूलो"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"सबैभन्दा ठूलो"</string>
- <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"अनुकूलन (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"आफू अनुकूल (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"मद्दत र प्रतिक्रिया"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"मेनु"</string>
<string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index f19ba3e..cb46376 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ਮਦਦ ਅਤੇ ਪ੍ਰਤੀਕਰਮ"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"ਮੀਨੂ"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 5d0b965..da2f76f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizat (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Ajutor și feedback"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Meniu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index d301ce1..9600027 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Другой (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Справка/отзыв"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index f21793b..b775db6 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"අභිරුචි (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"උදව් සහ ප්රතිපෝෂණ"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"මෙනුව"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index b478ecf..8130866 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Vlastné (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Pomocník a spätná väzba"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Ponuka"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index b9da0eb..a3b666ca 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Po meri (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Pomoč in povratne informacije"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index c17376b..232ca0a 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"I personalizuar (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Ndihma dhe komentet"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menyja"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index f14cbdd..3c06d72 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Kiwango maalum (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Usaidizi na maoni"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 2640122..daf3ff2 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"தனிப்பயன் (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"உதவி & கருத்து"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"மெனு"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 60a4d72..31defb6 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"అనుకూలం (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"సహాయం & అభిప్రాయం"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"మెను"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index fbb67bc..5ec5871 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"กำหนดเอง (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ความช่วยเหลือและความคิดเห็น"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"เมนู"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 50c43bb..07e1c8bd 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Tulong at feedback"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index c5ae71c..78b4a61 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Özel (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Yardım ve geri bildirim"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 0b5e8a0..e1b545f 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"حسب ضرورت (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"مدد اور تاثرات"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"مینو"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 21e5b75..28dbe51 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tùy chỉnh (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Trợ giúp và phản hồi"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index ba657c6..7c8bb20 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自定义 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"帮助和反馈"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"菜单"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 60f56f1..62c7715 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"說明和意見反映"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"選單"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 6bb7308..17a62e1 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"說明與意見回饋"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"選單"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 6714b27..7e982ee 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Ngokwezifiso (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Usizo nempendulo"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Imenyu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"I-GMT"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index bb85de2..7206127 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -51,6 +51,7 @@
<bool name="def_wifi_on">false</bool>
<!-- 0 == never, 1 == only when plugged in, 2 == always -->
<integer name="def_wifi_sleep_policy">2</integer>
+ <bool name="def_wifi_wakeup_enabled">false</bool>
<bool name="def_networks_available_notification_on">true</bool>
<bool name="def_backup_enabled">false</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
index 222cc5c..3e6c3f2 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
@@ -119,7 +119,7 @@
// and twice max user count for system and secure.
final int size = 1 + 2 + 10 + 2 * UserManager.getMaxSupportedUsers();
try {
- mBackingStore = new MemoryIntArray(size, false);
+ mBackingStore = new MemoryIntArray(size);
if (DEBUG) {
Slog.e(LOG_TAG, "Created backing store " + mBackingStore);
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
index 461573f..cbeb878 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -243,8 +243,8 @@
return lines;
}
try {
- final Cursor cursor = provider.query(resolveCallingPackage(), uri, null, null, null,
- null, null);
+ final Cursor cursor = provider.query(resolveCallingPackage(), uri, null, null,
+ null);
try {
while (cursor != null && cursor.moveToNext()) {
lines.add(cursor.getString(1) + "=" + cursor.getString(2));
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
index 09879d8..d54e33f 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
@@ -26,7 +26,7 @@
public static final String ACTION = "com.android.systemui.action.PLUGIN_NAV_BUTTON";
- public static final int VERSION = 1;
+ public static final int VERSION = 2;
/**
* Returns a view in the nav bar. If the id is set "back", "home", "recent_apps", "menu",
@@ -38,14 +38,15 @@
* Interface for button actions.
*/
interface ButtonInterface {
- void setImageResource(@DrawableRes int resId);
void setImageDrawable(@Nullable Drawable drawable);
void abortCurrentGesture();
- void setLandscape(boolean landscape);
+ void setVertical(boolean vertical);
void setCarMode(boolean carMode);
+
+ void setDarkIntensity(float intensity);
}
}
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..0a6074b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..64bc40a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..fb44f22a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..a665e23
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..4f65660
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..c57face
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..bbaab44
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..dba0040
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..2b64b80
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..151a3c0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..3456a97
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..5383215
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..3a22912
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..c7e4731
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..d2949f3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..06e4c26
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..1c855c4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..371a84d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..360ed77
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..96cecc9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..9ff9825
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..e505f5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..472c55b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..c04d650
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..0f6d206
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..58bf920
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..f47533ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..f299d97
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..84d6dc8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..d813bc7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..30e8782
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..83fc662
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..71101a1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..4a477ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..bc24c00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
index 24ac018..604e918 100644
--- a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
+++ b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
@@ -22,6 +22,6 @@
android:pathData="m18.250000,12.000000a6.250000,6.250000 0.000000,1.000000 1.000000,-12.500000 0.000000,6.250000 6.250000,0.000000 1.000000,1.000000 12.500000,0.000000z"
android:fillColor="?android:attr/colorPrimary" />
<path
- android:fillColor="#FFFFFFFF"
+ android:fillColor="?android:attr/colorControlNormal"
android:pathData="M20.000000,8.700000L20.000000,4.000000L15.300000,4.000000L12.000000,0.700000 8.700000,4.000000L4.000000,4.000000L4.000000,8.700000L0.700000,12.000000 4.000000,15.300000L4.000000,20.000000L8.700000,20.000000L12.000000,23.299999 15.300000,20.000000L20.000000,20.000000L20.000000,15.300000L23.299999,12.000000 20.000000,8.700000zM12.000000,18.000000C8.700000,18.000000 6.000000,15.300000 6.000000,12.000000 6.000000,8.700000 8.700000,6.000000 12.000000,6.000000c3.300000,0.000000 6.000000,2.700000 6.000000,6.000000 0.000000,3.300000 -2.700000,6.000000 -6.000000,6.000000zM12.000000,8.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000 0.000000,2.200000 1.800000,4.000000 4.000000,4.000000 2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000 0.000000,-2.200000 -1.800000,-4.000000 -4.000000,-4.000000z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
index 4d9ca88..3345f61 100644
--- a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
+++ b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
@@ -21,5 +21,5 @@
android:viewportHeight="24.0">
<path
android:pathData="M20.000000,5.000000L4.000000,5.000000C2.900000,5.000000 2.000000,5.900000 2.000000,7.000000l0.000000,10.000000c0.000000,1.100000 0.900000,2.000000 2.000000,2.000000l16.000000,0.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L22.000000,7.000000C22.000000,5.900000 21.100000,5.000000 20.000000,5.000000zM11.000000,8.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,8.000000zM11.000000,11.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,11.000000zM8.000000,8.000000l2.000000,0.000000l0.000000,2.000000L8.000000,10.000000L8.000000,8.000000zM8.000000,11.000000l2.000000,0.000000l0.000000,2.000000L8.000000,13.000000L8.000000,11.000000zM7.000000,13.000000L5.000000,13.000000l0.000000,-2.000000l2.000000,0.000000L7.000000,13.000000zM7.000000,10.000000L5.000000,10.000000L5.000000,8.000000l2.000000,0.000000L7.000000,10.000000zM16.000000,17.000000L8.000000,17.000000l0.000000,-2.000000l8.000000,0.000000L16.000000,17.000000zM16.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L16.000000,13.000000zM16.000000,10.000000l-2.000000,0.000000L14.000000,8.000000l2.000000,0.000000L16.000000,10.000000zM19.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L19.000000,13.000000zM19.000000,10.000000l-2.000000,0.000000L17.000000,8.000000l2.000000,0.000000L19.000000,10.000000z"
- android:fillColor="@color/navigation_bar_icon_color"/>
+ android:fillColor="?attr/singleToneColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml b/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml
index f901e86..49ee48b 100644
--- a/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="icon"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
index 994cf8c..5aeceba 100644
--- a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="icon"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
index bc545ba..8b2585b 100644
--- a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
@@ -18,7 +18,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_screen_rotation_48px_outlines"
android:translateX="24"
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
index 0bd75d1..603d0bf 100644
--- a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
@@ -18,7 +18,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_screen_rotation_48px_outlines"
android:translateX="24"
diff --git a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
index 0ac6795..17185a7c 100644
--- a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
@@ -18,7 +18,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="icon"
android:translateX="24"
diff --git a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
index 0cca6e3..88bf486 100644
--- a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
@@ -18,7 +18,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="icon"
android:translateX="24"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
index 0c65389..8a3e975 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
index b9a315c..1dadc05 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml
index dd92126..435bb9b 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml
@@ -17,7 +17,8 @@
android:width="56dp"
android:height="56dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@color/qs_detail_empty"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
index 0cb1f32..36eb418 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
index 9a68dad..2e9e741 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_off.xml b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
index 8051795..0fdbe1f 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
index 794eb9e..d2e9eb2 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
index 28d2e26..164a557 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
@@ -18,7 +18,8 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:alpha=".3"
- android:width="64dp" >
+ android:width="64dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
index f4c20a9..7e2eca8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
index fb26c09..5f4fa11 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
similarity index 61%
rename from packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
rename to packages/SystemUI/res/drawable/ic_qs_network_logging.xml
index 71400db..1340ae1 100644
--- a/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -13,13 +13,17 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+<!-- Placeholder icon for network logging until the real icon is finalized-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="12.0dp"
+ android:height="12.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="#4DFFFFFF" >
<path
- android:fillColor="@color/qs_tile_text"
- android:pathData="M14.0,20.0l10.0,10.0 10.0,-10.0z"/>
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M7,18v-2h6v2H7z M7,14v-2h10v2H7z M8.5,9 12,5.5 15.5,9 13,9 13,13 11,13 11,9z"/>
+
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
index 778ccbc..b99dc03 100644
--- a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
@@ -18,10 +18,11 @@
android:height="64dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:alpha="0.3">
+ android:alpha="0.3"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="#FFF"
+ android:fillColor="#FFFFFF"
android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
index aaca663..d875592 100644
--- a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
@@ -17,10 +17,11 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="24"
- android:viewportHeight="24">
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="#FFF"
+ android:fillColor="#FFFFFF"
android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
index bd46012..2d831b2 100644
--- a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
@@ -17,7 +17,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
index b78d3bf..0673848 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
@@ -18,7 +18,8 @@
android:width="32.0dp"
android:height="32.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
android:fillAlpha="0.3"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
index e055de7..fbf9e71 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
@@ -18,7 +18,8 @@
android:width="32.0dp"
android:height="32.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
index 71c40df..3a55623 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
@@ -17,7 +17,8 @@
android:width="16.0dp"
android:height="32dp"
android:viewportWidth="12.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
index 8a48817..e9f5a0b 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
@@ -18,7 +18,8 @@
android:width="32.0dp"
android:height="32.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
index 39cc94c..769d648 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
@@ -18,7 +18,8 @@
android:width="32.0dp"
android:height="32.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
android:fillAlpha="0.3"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
index e9a57ea..ddd8065 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
@@ -17,7 +17,8 @@
android:width="17.333334dp"
android:height="32dp"
android:viewportWidth="13.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
index 012e95e..1bec1b8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
@@ -18,7 +18,8 @@
android:width="32.0dp"
android:height="32.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
index 42045d1..8e1f8eb 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
@@ -17,7 +17,8 @@
android:width="16.0dp"
android:height="32dp"
android:viewportWidth="12.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M4.600000,7.800000l0.700000,0.000000l0.000000,1.300000L4.600000,9.100000L4.600000,11.000000L3.000000,11.000000L3.000000,9.200000L0.100000,9.200000L0.000000,8.100000L3.000000,2.500000l1.700000,0.000000L4.700000,7.800000zM1.600000,7.800000L3.000000,7.800000l0.000000,-3.000000L2.900000,5.000000L1.600000,7.800000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
index 4d7f325..e0c6b68 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
index 96e2fd4..1c068e5 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
@@ -17,7 +17,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:name="dot1"
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
index 4f253e3..0a85392 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M21.799999,22.299999l-1.199999,-1.299999 0.000000,0.000000 -9.600000,-10.000000 0.000000,0.000000 -6.400000,-6.700000 -1.300000,1.300000 6.400000,6.700000 -8.700000,8.700000 16.900000,0.000000 2.600000,2.700001z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
index e49a409..4c90421 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
@@ -17,7 +17,8 @@
android:width="6.6666665dp"
android:height="32dp"
android:viewportWidth="5.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
index 326373d..db4df76 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
index 8baa4eb..6e5439d 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
index bf19a718..194edc3 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
index 01839e85..b57af5c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
index 48151ad..7d754a8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
index 9d42a44..64aadf9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
@@ -17,7 +17,8 @@
android:width="9.333333dp"
android:height="32dp"
android:viewportWidth="7.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
index f509d71..31918a9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
@@ -17,7 +17,8 @@
android:width="8.0dp"
android:height="32dp"
android:viewportWidth="6.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
index 236fdac..4122b76 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
@@ -17,7 +17,8 @@
android:width="6.0dp"
android:height="32dp"
android:viewportWidth="6.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6.000000,15.700000l-3.000000,5.599999 -3.000000,-5.599999z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
index b7242e6..8766075 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
@@ -17,7 +17,8 @@
android:width="17.333334dp"
android:height="32dp"
android:viewportWidth="13.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
index 3af0629..5ff7d85 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml b/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
index f7fd97c..4e65004 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M2.000000,22.000000l20.000000,0.000000L22.000000,2.000000L2.000000,22.000000zM20.000000,20.000000L6.800000,20.000000L20.000000,6.800000L20.000000,20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
index c510972..a3823ae 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
@@ -17,7 +17,8 @@
android:width="6.0dp"
android:height="32dp"
android:viewportWidth="6.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M0.000000,13.700000l3.000000,-5.700000 3.000000,5.700000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_r.xml b/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
index 66f64c9..2c10dc3f 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
@@ -17,7 +17,8 @@
android:width="8.0dp"
android:height="32dp"
android:viewportWidth="6.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.800000,7.900000l-1.000000,0.000000L1.800000,11.000000L0.200000,11.000000L0.200000,2.500000l2.700000,0.000000c0.900000,0.000000 1.500000,0.200000 2.000000,0.700000s0.700000,1.100000 0.700000,1.900000c0.000000,0.600000 -0.100000,1.100000 -0.300000,1.500000S4.800000,7.200000 4.400000,7.400000l1.500000,3.500000L5.900000,11.000000L4.100000,11.000000L2.800000,7.900000zM1.800000,6.500000l1.100000,0.000000c0.400000,0.000000 0.600000,-0.100000 0.800000,-0.400000S4.000000,5.600000 4.000000,5.200000c0.000000,-0.400000 -0.100000,-0.800000 -0.300000,-1.000000S3.300000,3.800000 2.900000,3.800000L1.800000,3.800000L1.800000,6.500000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
index e6f9292..fe963b1 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
android:fillAlpha="0.3"
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
index d423ccb..82d2be2 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
index 1982130..f30ba76 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
index b350111..8a17083 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
index 136a004..fcd57d0 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml
index ad6b247..a7889ab 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml
@@ -17,7 +17,8 @@
android:width="56dp"
android:height="56dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M24.0,4.0C15.0,4.0 6.7,7.0 0.0,12.0l24.0,32.0l24.0,-32.0C41.3,7.0 33.0,4.0 24.0,4.0z"
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
index c505783..bbff2e1 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M17.500000,16.500000L5.800000,3.400000c0.000000,0.000000 0.000000,0.000000 0.000000,0.000000l-2.700000,-3.000000L1.600000,1.800000l2.200000,2.500000c-2.000000,1.000000 -3.200000,2.000000 -3.400000,2.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l3.200000,-3.900000l2.400000,2.700000l1.500000,-1.400000L17.500000,16.500000L17.500000,16.500000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
index 2dcdb71..071892a 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
@@ -17,7 +17,8 @@
android:width="26.0dp"
android:height="24.0dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M21.0,8.5
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
index 1bc7438..c0e1037 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
index 5856115..f609295 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M13.100000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.500000,6.500000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
index 4a5e1f8..f44b303 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
index 965442d..850f5b9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
index b29d3f9..8ccc1fd9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml
index 3d58869..45cfc1c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M13.000000,2.000000C7.700000,2.000000 3.700000,3.900000 0.400000,6.400000L13.000000,22.000000L25.600000,6.500000C22.299999,4.000000 18.299999,2.000000 13.000000,2.000000zM13.000000,18.600000L3.300000,7.000000l0.000000,0.000000l0.000000,0.000000C6.000000,5.300000 8.700000,4.000000 13.000000,4.000000s7.000000,1.400000 9.700000,3.000000l0.000000,0.000000l0.000000,0.000000L13.000000,18.600000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
index 35844b7..542797a 100644
--- a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_signal_flashlight"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
index d53608f..a5ba05b 100644
--- a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_signal_flashlight"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
index 439851d..e36f270 100644
--- a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_signal_location"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
index 8614458..46a72bc 100644
--- a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_signal_location"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm.xml b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
index a8ca0d6..e64f445 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
@@ -17,10 +17,11 @@
android:height="24.0dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M44.0,11.44l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-28.24,-4.66l-2.57,-3.06 -9.19,7.71 2.57,3.06 9.19,-7.71zm9.24,9.22l-3.0,0.0l0.0,12.0l9.49,5.71 1.51,-2.47 -8.0,-4.74l0.0,-10.5zm-1.01,-8.0c-9.95,0.0 -17.99,8.06 -17.99,18.0s8.04,18.0 17.99,18.0 18.01,-8.06 18.01,-18.0 -8.06,-18.0 -18.01,-18.0zm0.01,32.0c-7.73,0.0 -14.0,-6.27 -14.0,-14.0s6.27,-14.0 14.0,-14.0 14.0,6.27 14.0,14.0 -6.26,14.0 -14.0,14.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
index 8e2f083..37d7690 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
@@ -17,10 +17,11 @@
android:height="24.0dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M24.0,12.0c7.73,0.0 14.0,6.27 14.0,14.0 0.0,1.69 -0.31,3.3 -0.86,4.8l3.04,3.04c1.16,-2.37 1.82,-5.03 1.82,-7.84 0.0,-9.94 -8.06,-18.0 -18.01,-18.0 -2.81,0.0 -5.46,0.66 -7.84,1.81l3.05,3.05c1.5,-0.55 3.11,-0.86 4.8,-0.86zm20.0,-0.56l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-38.16,-6.85l-2.55,2.54 2.66,2.66 -2.22,1.86 2.84,2.84 2.22,-1.86 1.6,1.6c-2.73,3.16 -4.39,7.27 -4.39,11.77 0.0,9.94 8.04,18.0 17.99,18.0 4.51,0.0 8.62,-1.67 11.77,-4.4l4.4,4.4 2.54,-2.55 -34.91,-34.91 -1.95,-1.95zm27.1,32.19c-2.43,2.01 -5.54,3.22 -8.94,3.22 -7.73,0.0 -14.0,-6.27 -14.0,-14.0 0.0,-3.4 1.21,-6.51 3.22,-8.94l19.72,19.72zm-16.91,-30.23l-2.84,-2.84 -1.7,1.43 2.84,2.84 1.7,-1.43z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
index 71df4d3..5c3c650 100644
--- a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
@@ -17,10 +17,11 @@
android:height="24.0dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M29.41,19.0L34.0,14.41L34.0,22.0l1.0,0.0l5.71,-5.71 -4.3,-4.29 4.29,-4.29L35.0,2.0l-1.0,0.0l0.0,7.59L29.41,5.0 28.0,6.41 33.59,12.0 28.0,17.59 29.41,19.0zM36.0,5.83l1.88,1.88L36.0,9.59L36.0,5.83zm0.0,8.58l1.88,1.88L36.0,18.17l0.0,-3.76zM40.0,31.0c-2.49,0.0 -4.89,-0.4 -7.14,-1.14 -0.69,-0.22 -1.48,-0.06 -2.0,0.49l-4.4,4.41c-5.67,-2.88 -10.29,-7.51 -13.18,-13.17l4.4,-4.41c0.55,-0.5 0.71,-1.3 0.49,-2.03C17.4,12.9 17.0,10.49 17.0,8.0c0.0,-1.11 -0.89,-2.0 -2.0,-2.0L8.0,6.0c-1.11,0.0 -2.0,0.89 -2.0,2.0 0.0,18.78 15.22,34.0 34.0,34.0 1.11,0.0 2.0,-0.89 2.0,-2.0l0.0,-7.0c0.0,-1.11 -0.89,-2.0 -2.0,-2.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_collapse.xml b/packages/SystemUI/res/drawable/ic_volume_collapse.xml
index dc6d301..0f488a4 100644
--- a/packages/SystemUI/res/drawable/ic_volume_collapse.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_collapse.xml
@@ -18,7 +18,8 @@
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="chevron_02"
diff --git a/packages/SystemUI/res/drawable/ic_volume_expand.xml b/packages/SystemUI/res/drawable/ic_volume_expand.xml
index a60623f..70ff1f3 100644
--- a/packages/SystemUI/res/drawable/ic_volume_expand.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_expand.xml
@@ -18,7 +18,8 @@
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="chevron_01"
diff --git a/packages/SystemUI/res/drawable/ic_volume_media.xml b/packages/SystemUI/res/drawable/ic_volume_media.xml
index 97089f1..d689207 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media.xml
@@ -17,10 +17,11 @@
android:height="24.0dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M12.0,3.0l0.0,9.28c-0.47,-0.17 -0.97,-0.28 -1.5,-0.28C8.01,12.0 6.0,14.01 6.0,16.5S8.01,21.0 10.5,21.0c2.31,0.0 4.2,-1.75 4.45,-4.0L15.0,17.0L15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
index 3364d9c..9b7b2da 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
@@ -17,13 +17,14 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M17.0,3.0l-7.0,0.0l0.0,9.3C9.5,12.1 9.0,12.0 8.5,12.0C6.0,12.0 4.0,14.0 4.0,16.5S6.0,21.0 8.5,21.0s4.5,-2.3 4.5,-4.5C13.0,14.7 13.0,6.0 13.0,6.0l4.0,0.0L17.0,3.0z"/>
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M23.4,9.9L20.5,7.0L20.0,7.0l0.0,3.8l-2.3,-2.3L17.0,9.2l2.8,2.8L17.0,14.8l0.7,0.7l2.3,-2.3L20.0,17.0l0.5,0.0l2.8,-2.8L21.2,12.0L23.4,9.9zM21.0,8.9l0.9,0.9l-0.9,1.0L21.0,8.9zM21.9,14.2L21.0,15.1l0.0,-1.9L21.9,14.2z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
index 39f54f1..17ac01d 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
@@ -17,16 +17,17 @@
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M13.0,6.0l4.0,0.0L17.0,3.0l-7.0,0.0l0.0,5.6l3.0,3.0C13.0,8.8 13.0,6.0 13.0,6.0z"/>
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M2.1,5.7L8.4,12.0C6.0,12.1 4.0,14.0 4.0,16.5S6.0,21.0 8.5,21.0c2.7,0.0 4.5,-2.3 4.5,-4.3l0.0,-0.1l3.9,3.9l1.3,-1.3L3.4,4.5L2.1,5.7z"/>
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M23.4,9.9L20.5,7.0L20.0,7.0l0.0,3.8l-2.3,-2.3L17.0,9.2l2.8,2.8L17.0,14.8l0.7,0.7l2.3,-2.3L20.0,17.0l0.5,0.0l2.8,-2.8L21.2,12.0L23.4,9.9zM21.0,8.9l0.9,0.9l-0.9,1.0L21.0,8.9zM21.9,14.2L21.0,15.1l0.0,-1.9L21.9,14.2z"/>
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
index beb806c..267d09d 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
@@ -17,13 +17,14 @@
android:height="24.0dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0l0.0,5.6l3.0,3.0C15.0,8.8 15.0,6.0 15.0,6.0z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M4.8,3.9L3.5,5.1l6.9,6.9C8.0,12.1 6.0,14.0 6.0,16.5C6.0,19.0 8.0,21.0 10.5,21.0c2.7,0.0 4.5,-2.3 4.5,-4.3c0.0,0.0 0.0,-0.1 0.0,-0.1l4.0,4.0l1.3,-1.3L4.8,3.9z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_remote.xml b/packages/SystemUI/res/drawable/ic_volume_remote.xml
index b363178..fe396d9 100644
--- a/packages/SystemUI/res/drawable/ic_volume_remote.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_remote.xml
@@ -17,10 +17,11 @@
android:height="24dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM38.0,14.0L10.0,14.0l0.0,3.3c7.9,2.6 14.2,8.8 16.7,16.7L38.0,34.0L38.0,14.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0zM42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml b/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml
index 5f39ad7..2e05122 100644
--- a/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml
@@ -17,22 +17,23 @@
android:height="24.0dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M23.7,21.3l-1.1,-1.0c0.0,0.0 0.0,0.0 0.0,0.0L21.0,18.8l0.0,0.0L5.8,5.0l0.0,0.0L3.6,3.0l0.0,0.0L1.7,1.3L0.3,2.7l1.1,1.0C1.2,4.1 1.0,4.5 1.0,5.0l0.0,3.0l2.0,0.0L3.0,5.2L18.2,19.0L14.0,19.0l0.0,2.0l6.4,0.0l1.9,1.7L23.7,21.3z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M21.0,5.0l0.0,11.1l2.0,1.8L23.0,5.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0L6.6,3.0l2.2,2.0L21.0,5.0z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M1.0,18.0l0.0,3.0l3.0,0.0C4.0,19.3 2.7,18.0 1.0,18.0z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M1.0,14.0l0.0,2.0c2.8,0.0 5.0,2.2 5.0,5.0l2.0,0.0C8.0,17.1 4.9,14.0 1.0,14.0z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M1.0,10.0l0.0,2.0c5.0,0.0 9.0,4.0 9.0,9.0l2.0,0.0C12.0,14.9 7.1,10.0 1.0,10.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer.xml b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
index c566d5a..18af711 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
@@ -17,10 +17,11 @@
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
index 0c20361..bc926c3 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
@@ -17,10 +17,11 @@
android:height="24dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M23.000000,44.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000l-8.000000,0.000000C19.000000,42.200001 20.799999,44.000000 23.000000,44.000000zM36.000000,21.000000c0.000000,-6.100000 -4.300000,-11.300000 -10.000000,-12.600000L26.000000,7.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,1.400000c-1.000000,0.200000 -2.000000,0.600000 -2.900000,1.100000L36.000000,28.400000L36.000000,21.000000zM35.500000,38.000000l4.000000,4.000000l2.500000,-2.500000L8.500000,6.000000L6.000000,8.500000l5.800000,5.800000C10.700000,16.299999 10.000000,18.600000 10.000000,21.000000l0.000000,11.000000l-4.000000,4.000000l0.000000,2.000000L35.500000,38.000000z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
index 38b3234..ffbffad 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
@@ -17,10 +17,11 @@
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M0.0,15.0l2.0,0.0L2.0,9.0L0.0,9.0L0.0,15.0zM3.0,17.0l2.0,0.0L5.0,7.0L3.0,7.0L3.0,17.0zM22.0,9.0l0.0,6.0l2.0,0.0L24.0,9.0L22.0,9.0zM19.0,17.0l2.0,0.0L21.0,7.0l-2.0,0.0L19.0,17.0zM16.5,3.0l-9.0,0.0C6.7,3.0 6.0,3.7 6.0,4.5l0.0,15.0C6.0,20.3 6.7,21.0 7.5,21.0l9.0,0.0c0.8,0.0 1.5,-0.7 1.5,-1.5l0.0,-15.0C18.0,3.7 17.3,3.0 16.5,3.0zM16.0,19.0L8.0,19.0L8.0,5.0l8.0,0.0L16.0,19.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_settings.xml b/packages/SystemUI/res/drawable/ic_volume_settings.xml
deleted file mode 100644
index 9f79b5a..0000000
--- a/packages/SystemUI/res/drawable/ic_volume_settings.xml
+++ /dev/null
@@ -1,26 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="20dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0"
- android:width="20dp" >
-
- <path
- android:fillColor="@color/volume_settings_icon_color"
- android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z" />
-
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_system.xml b/packages/SystemUI/res/drawable/ic_volume_system.xml
index ccd8e18..71eed34 100644
--- a/packages/SystemUI/res/drawable/ic_volume_system.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_system.xml
@@ -17,16 +17,17 @@
android:height="24.0dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M17.7,14.8l-4.5,-2.3c-0.2,-0.1 -0.4,-0.1 -0.5,-0.1l-0.8,0.0l0.0,-6.0c0.0,-0.8 -0.7,-1.5 -1.5,-1.5S8.9,5.6 8.9,6.4l0.0,10.7l-3.4,-0.7c-0.1,0.0 -0.2,0.0 -0.2,0.0c-0.3,0.0 -0.6,0.1 -0.8,0.3l-0.8,0.8l4.9,4.9c0.3,0.3 0.6,0.4 1.1,0.4l6.8,0.0c0.8,0.0 1.3,-0.6 1.4,-1.3l0.8,-5.3c0.0,-0.1 0.0,-0.1 0.0,-0.2C18.6,15.5 18.2,15.0 17.7,14.8z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M14.3,8.8l1.8,0.9c1.5,-2.0 1.4,-4.8 -0.4,-6.6l-1.4,1.4C15.5,5.7 15.5,7.6 14.3,8.8z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M17.9,10.6l1.8,0.9C22.0,8.0 21.6,3.3 18.5,0.3l-1.4,1.4C19.5,4.1 19.8,7.9 17.9,10.6z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_system_mute.xml b/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
index dfcb655..baad92a 100644
--- a/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
@@ -17,19 +17,20 @@
android:height="24.0dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M14.3,8.8l1.8,0.9c1.5,-2.0 1.4,-4.8 -0.4,-6.6l-1.4,1.4C15.5,5.7 15.5,7.6 14.3,8.8z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M17.9,10.6l1.8,0.9C22.0,8.0 21.6,3.3 18.5,0.3l-1.4,1.4C19.5,4.1 19.8,7.9 17.9,10.6z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M22.0,20.6l-3.5,-2.8l0.0,0.0l-9.6,-7.6l0.0,0.0L3.2,5.7L2.0,7.3l6.9,5.4L8.9,17.0l-3.4,-0.7c-0.1,0.0 -0.2,0.0 -0.2,0.0c-0.3,0.0 -0.6,0.1 -0.8,0.3l-0.8,0.8l4.9,4.9c0.3,0.3 0.6,0.4 1.1,0.4l6.8,0.0c0.8,0.0 1.3,-0.6 1.4,-1.3l0.2,-1.5l2.6,2.1L22.0,20.6z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M11.9,6.4c0.0,-0.8 -0.7,-1.5 -1.5,-1.5S8.9,5.6 8.9,6.4l0.0,1.5l3.0,2.4L11.9,6.4z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_voice.xml b/packages/SystemUI/res/drawable/ic_volume_voice.xml
index 133253e..7dc3dac 100644
--- a/packages/SystemUI/res/drawable/ic_volume_voice.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_voice.xml
@@ -17,10 +17,11 @@
android:height="24.0dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M13.25,21.59c2.88,5.66 7.51,10.29 13.18,13.17l4.4,-4.41c0.55,-0.55 1.34,-0.71 2.03,-0.49C35.1,30.6 37.51,31.0 40.0,31.0c1.11,0.0 2.0,0.89 2.0,2.0l0.0,7.0c0.0,1.11 -0.89,2.0 -2.0,2.0C21.22,42.0 6.0,26.78 6.0,8.0c0.0,-1.1 0.9,-2.0 2.0,-2.0l7.0,0.0c1.11,0.0 2.0,0.89 2.0,2.0 0.0,2.4 0.4,4.9 1.14,7.1 0.2,0.6 0.06,1.48 -0.49,2.03l-4.4,4.42z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/back.xml b/packages/SystemUI/res/layout/back.xml
index d256622..4e8726b 100644
--- a/packages/SystemUI/res/layout/back.xml
+++ b/packages/SystemUI/res/layout/back.xml
@@ -21,7 +21,6 @@
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:layout_weight="0"
- android:src="@drawable/ic_sysbar_back"
systemui:keyCode="4"
android:scaleType="center"
android:contentDescription="@string/accessibility_back"
diff --git a/packages/SystemUI/res/layout/home.xml b/packages/SystemUI/res/layout/home.xml
index f11592d..9586327 100644
--- a/packages/SystemUI/res/layout/home.xml
+++ b/packages/SystemUI/res/layout/home.xml
@@ -20,7 +20,6 @@
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:layout_weight="0"
- android:src="@drawable/ic_sysbar_home"
systemui:keyCode="3"
android:scaleType="center"
android:contentDescription="@string/accessibility_home"
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 90b74d0..5e85ba0 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -25,7 +25,6 @@
android:layout_width="@dimen/navigation_extra_key_width"
android:layout_height="match_parent"
android:layout_marginEnd="2dp"
- android:src="@drawable/ic_sysbar_menu"
android:scaleType="centerInside"
systemui:keyCode="82"
android:visibility="invisible"
@@ -36,7 +35,6 @@
android:layout_width="@dimen/navigation_extra_key_width"
android:layout_height="match_parent"
android:layout_marginEnd="2dp"
- android:src="@drawable/ic_ime_switcher_default"
android:visibility="invisible"
android:contentDescription="@string/accessibility_ime_switch_button"
android:scaleType="centerInside"
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index cce9c0f..5b0f0df 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -22,7 +22,7 @@
<TextView android:id="@+id/tile_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textColor="@color/qs_tile_text"
+ android:textColor="?android:attr/textColorSecondary"
android:gravity="center_horizontal"
android:minLines="2"
android:padding="0dp"
diff --git a/packages/SystemUI/res/layout/quick_settings_footer.xml b/packages/SystemUI/res/layout/quick_settings_footer.xml
index 53baf74..8667a5a 100644
--- a/packages/SystemUI/res/layout/quick_settings_footer.xml
+++ b/packages/SystemUI/res/layout/quick_settings_footer.xml
@@ -39,4 +39,16 @@
android:src="@drawable/ic_qs_vpn"
android:visibility="invisible" />
-</RelativeLayout>
\ No newline at end of file
+ <!-- Only shown if both images are visible -->
+ <ImageView
+ android:id="@+id/footer_icon2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_marginEnd="8dp"
+ android:layout_toStartOf="@id/footer_icon"
+ android:contentDescription="@null"
+ android:src="@drawable/ic_qs_network_logging"
+ android:visibility="invisible" />
+
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/recent_apps.xml b/packages/SystemUI/res/layout/recent_apps.xml
index eb8ee43c..870bcf7 100644
--- a/packages/SystemUI/res/layout/recent_apps.xml
+++ b/packages/SystemUI/res/layout/recent_apps.xml
@@ -21,7 +21,6 @@
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:layout_weight="0"
- android:src="@drawable/ic_sysbar_recent"
android:scaleType="center"
android:contentDescription="@string/accessibility_recent"
android:paddingStart="@dimen/navigation_key_padding"
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index 73f26e2..e4ea08e 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -42,7 +42,7 @@
android:singleLine="true"
android:ellipsize="start"
android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
- android:imeOptions="actionNone|flagNoExtractUi|flagNoFullscreen" />
+ android:imeOptions="actionSend|flagNoExtractUi|flagNoFullscreen" />
<FrameLayout
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 40308dc..a511c58 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Minder dringende kennisgewings hieronder"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tik weer om oop te maak"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Sleep op om te ontsluit"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Hierdie toestel word bestuur"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Hierdie toestel word deur <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> bestuur"</string>
<string name="phone_hint" msgid="4872890986869209950">"Swiep vanaf ikoon vir foon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Swiep vanaf ikoon vir stembystand"</string>
<string name="camera_hint" msgid="7939688436797157483">"Swiep vanaf ikoon vir kamera"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f807ba9..b40bd90 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"በጣም አስቸካይ ያልሆኑ ማሳወቂያዎች ከታች"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ለመክፈት ዳግም መታ ያድርጉ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ለማስከፈት ወደ ላይ ያንሸራትቱ"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ይህ መሣሪያ የሚተዳደር ነው"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ይህ መሣሪያ በ<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> የሚተዳደር ነው"</string>
<string name="phone_hint" msgid="4872890986869209950">"ለስልክ ከአዶ ላይ ጠረግ ያድርጉ"</string>
<string name="voice_hint" msgid="8939888732119726665">"ለድምጽ ረዳት ከአዶ ጠረግ ያድርጉ"</string>
<string name="camera_hint" msgid="7939688436797157483">"ለካሜራ ከአዶ ላይ ጠረግ ያድርጉ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 33110ce..9ec84f9 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -358,6 +358,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"الإشعارات الأقل إلحاحًا أدناه"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"انقر مرة أخرى للفتح"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"مرر سريعًا لأعلى لإلغاء القفل"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"تتم إدارة هذا الجهاز"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"تتم إدارة هذا الجهاز بواسطة <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"يمكنك التمرير سريعًا من الرمز لتشغيل الهاتف"</string>
<string name="voice_hint" msgid="8939888732119726665">"يمكنك التمرير سريعًا من الرمز لتشغيل المساعد الصوتي"</string>
<string name="camera_hint" msgid="7939688436797157483">"يمكنك التمرير سريعًا من الرمز لتشغيل الكاميرا"</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 49f27b2..14537a1 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Daha az təcili bildirişlər aşağıdadır"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Açmaq üçün yenidən tıklayın"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Kiliddən çıxarmaq üçün yuxarı çəkin"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Bu cihaz idarə olunur"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tərəfindən idarə olunur"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefon üçün ikonadan sürüşdürün"</string>
<string name="voice_hint" msgid="8939888732119726665">"Səs yardımçısı üçün ikonadan sürüşdürün"</string>
<string name="camera_hint" msgid="7939688436797157483">"Kamera üçün ikonadan sürüşdürün"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index dc21bde..c92490f 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Manje hitna obaveštenja su u nastavku"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite ponovo da biste otvorili"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Prevucite nagore da biste otključali"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Ovim uređajem se upravlja"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Prevucite od ikone za telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Prevucite od ikone za glasovnu pomoć"</string>
<string name="camera_hint" msgid="7939688436797157483">"Prevucite od ikone za kameru"</string>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index ac93da7..6ae9db5 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Менш тэрміновыя апавяшчэнні ніжэй"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Дакраніцеся яшчэ раз, каб адкрыць"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Правядзіце пальцам уверх, каб разблакіраваць"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Гэта прылада знаходзіцца пад кіраваннем"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Гэта прылада знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Тэлефон: правядзіце пальцам ад значка"</string>
<string name="voice_hint" msgid="8939888732119726665">"Галасавая дапамога: правядзіце пальцам ад значка"</string>
<string name="camera_hint" msgid="7939688436797157483">"Камера: правядзіце пальцам ад значка"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 7814efb..6079354 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Ппоказване на по-малко спешните известия по-долу"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Докоснете отново, за да отворите"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Плъзнете нагоре, за да отключите"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Това устройство се управлява"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Това устройство се управлява от <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Плъзнете с пръст от иконата, за да използвате телефона"</string>
<string name="voice_hint" msgid="8939888732119726665">"Прекарайте пръст от иконата, за да получите гласова помощ"</string>
<string name="camera_hint" msgid="7939688436797157483">"Плъзнете с пръст от иконата, за да включите камерата"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index c80efa4..32d00f6 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"নিচে অপেক্ষাকৃত কম জরুরী বিজ্ঞপ্তিগুলি"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"খোলার জন্য আবার আলতো চাপুন"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"আনলক করতে উপরের দিকে সোয়াইপ করুন"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"এই ডিভাইসটি পরিচালিত"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"এই ডিভাইসটি <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> এর দ্বারা পরিচালিত"</string>
<string name="phone_hint" msgid="4872890986869209950">"ফোনের জন্য আইকন থেকে সোয়াইপ করুন"</string>
<string name="voice_hint" msgid="8939888732119726665">"ভয়েস সহায়তার জন্য আইকন থেকে সোয়াইপ করুন"</string>
<string name="camera_hint" msgid="7939688436797157483">"ক্যামেরার জন্য আইকন থেকে সোয়াইপ করুন"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> হল ভলিউম ডায়লগ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"আসলটি পুনঃস্থাপন করতে আলতো চাপ দিন৷"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"আপনি আপনার কাজের প্রোফাইল ব্যবহার করছেন"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"কল করুন"</item>
+ <item msgid="5997713001067658559">"সিস্টেম"</item>
+ <item msgid="7858983209929864160">"রিং"</item>
+ <item msgid="1850038478268896762">"মিডিয়া"</item>
+ <item msgid="8265110906352372092">"অ্যালার্ম"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ব্লুটুথ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"অ্যাক্সেসযোগ্যতা"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। সশব্দ করতে আলতো চাপুন।"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। কম্পন এ সেট করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে নিঃশব্দ করা হতে পারে।"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। নিঃশব্দ করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে নিঃশব্দ করা হতে পারে।"</string>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 2d02a4f..0c35e18 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Prikaži manje važna obavještenja ispod"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite ponovo da otvorite"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Prevucite prema gore da otključate"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Ovim uređajem upravlja"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Prevucite preko ikone da otvorite telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Prevucite preko ikone za glasovnu pomoć"</string>
<string name="camera_hint" msgid="7939688436797157483">"Prevucite od ikone da otvorite kameru"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index b0e6fe5..fd660ac 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificacions menys urgents a continuació"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Torna a tocar per obrir-la."</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Llisca cap amunt per desbloquejar el teclat"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Aquest és un dispositiu gestionat"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> gestiona aquest dispositiu"</string>
<string name="phone_hint" msgid="4872890986869209950">"Llisca des de la icona per obrir el telèfon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Llisca des de la icona per obrir l\'assistent de veu"</string>
<string name="camera_hint" msgid="7939688436797157483">"Llisca des de la icona per obrir la càmera"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 639f8b5..a045ecd 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Méně urgentní oznámení níže"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Oznámení otevřete opětovným klepnutím"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Zařízení odemknete přejetím prstem nahoru"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Toto zařízení je spravováno"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Toto zařízení je spravováno organizací <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefon otevřete přejetím prstem od ikony"</string>
<string name="voice_hint" msgid="8939888732119726665">"Hlasovou asistenci otevřete přejetím prstem od ikony"</string>
<string name="camera_hint" msgid="7939688436797157483">"Fotoaparát otevřete přejetím prstem od ikony"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 8fa27ad..3eeabaa 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre presserende underretninger nedenfor"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tryk igen for at åbne"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Stryg opad for at låse op"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Dette er en administreret enhed"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Denne enhed administreres af <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Stryg fra telefonikonet"</string>
<string name="voice_hint" msgid="8939888732119726665">"Stryg fra mikrofonikonet"</string>
<string name="camera_hint" msgid="7939688436797157483">"Stryg fra kameraikonet"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er dialogboksen for lydstyrke"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Tryk for at gendanne det oprindelige."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du bruger din arbejdsprofil"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Opkald"</item>
+ <item msgid="5997713001067658559">"System"</item>
+ <item msgid="7858983209929864160">"Ring"</item>
+ <item msgid="1850038478268896762">"Medier"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Hjælpefunktioner"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tryk for at slå lyden til."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tryk for at konfigurere til at vibrere. Tilgængelighedstjenester kan blive deaktiveret."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tryk for at slå lyden fra. Lyden i tilgængelighedstjenester kan blive slået fra."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 564625f..603be91 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Weniger dringende Benachrichtigungen unten"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Erneut tippen, um Benachrichtigung zu öffnen"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Zum Entsperren nach oben wischen"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Dieses Gerät wird verwaltet"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Dieses Gerät wird von <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> verwaltet"</string>
<string name="phone_hint" msgid="4872890986869209950">"Zum Öffnen des Telefons vom Symbol wegwischen"</string>
<string name="voice_hint" msgid="8939888732119726665">"Zum Öffnen des Sprachassistenten vom Symbol wegwischen"</string>
<string name="camera_hint" msgid="7939688436797157483">"Zum Öffnen der Kamera vom Symbol wegwischen"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> regelt die Lautstärke."</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Tippe, um das Original wiederherzustellen."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du verwendest dein Arbeitsprofil."</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Anruf"</item>
+ <item msgid="5997713001067658559">"System"</item>
+ <item msgid="7858983209929864160">"Klingeln lassen"</item>
+ <item msgid="1850038478268896762">"Medien"</item>
+ <item msgid="8265110906352372092">"Wecker"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Bedienungshilfen"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Zum Aufheben der Stummschaltung tippen."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tippen, um Vibrieren festzulegen. Bedienungshilfen werden unter Umständen stummgeschaltet."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Zum Stummschalten tippen. Bedienungshilfen werden unter Umständen stummgeschaltet."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index a5c790c..2b160c7 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Λιγότερο επείγουσες ειδοποιήσεις παρακάτω"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Πατήστε ξανά για να ανοίξετε"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Σύρετε για να ξεκλειδώσετε"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Αυτή η συσκευή είναι διαχειριζόμενη"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Τη συσκευή διαχειρίζεται ο οργανισμός <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Σύρετε προς τα έξω για τηλέφωνο"</string>
<string name="voice_hint" msgid="8939888732119726665">"Σύρετε προς τα έξω για voice assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Σύρετε προς τα έξω για κάμερα"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 5dacfb2..d73e130 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"This device is managed"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Swipe from icon for camera"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 5dacfb2..d73e130 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"This device is managed"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Swipe from icon for camera"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 5dacfb2..d73e130 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"This device is managed"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Swipe from icon for camera"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 3ba4360..6f2c7d5 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificaciones menos urgentes abajo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Presionar de nuevo para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Desliza el dedo hacia arriba para desbloquear el teléfono"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este dispositivo está administrado"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> administra este dispositivo"</string>
<string name="phone_hint" msgid="4872890986869209950">"Desliza el dedo para desbloquear el teléfono."</string>
<string name="voice_hint" msgid="8939888732119726665">"Desliza el dedo desde el ícono para abrir asistente de voz."</string>
<string name="camera_hint" msgid="7939688436797157483">"Desliza el dedo para acceder a la cámara."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 969f812..ba9154d 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificaciones menos urgente abajo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toca de nuevo para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Desliza el dedo hacia arriba para desbloquear"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este es un dispositivo administrado"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Este dispositivo está administrado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Desliza desde el icono para abrir el teléfono"</string>
<string name="voice_hint" msgid="8939888732119726665">"Desliza desde el icono para abrir asistente de voz"</string>
<string name="camera_hint" msgid="7939688436797157483">"Desliza desde el icono para abrir la cámara"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index e1ebfd2..7566137 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Vähem kiireloomulised märguanded on allpool"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Avamiseks puudutage uuesti"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Lukustuse tühistamiseks pühkige üles"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Seda seadet hallatakse"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Seda seadet haldab <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefoni kasutamiseks pühkige ikoonilt eemale"</string>
<string name="voice_hint" msgid="8939888732119726665">"Häälabi kasutamiseks pühkige ikoonilt eemale"</string>
<string name="camera_hint" msgid="7939688436797157483">"Kaamera kasutamiseks pühkige ikoonilt eemale"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on helitugevuse dialoog"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Puudutage originaali taastamiseks."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Kasutate oma tööprofiili"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Helistamine"</item>
+ <item msgid="5997713001067658559">"Süsteem"</item>
+ <item msgid="7858983209929864160">"Helin"</item>
+ <item msgid="1850038478268896762">"Meedia"</item>
+ <item msgid="8265110906352372092">"Äratus"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Juurdepääsetavus"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Puudutage vaigistuse tühistamiseks."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Puudutage värinarežiimi määramiseks. Juurdepääsetavuse teenused võidakse vaigistada."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Puudutage vaigistamiseks. Juurdepääsetavuse teenused võidakse vaigistada."</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index fa0c711..b78ca62 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Horren premiazkoak ez diren jakinarazpenak daude behean"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Irekitzeko, ukitu berriro"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Desblokeatzeko, pasatu hatza gorantz"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Gailu kudeatu bat da hau"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> erakundeak kudeatzen du gailu hau"</string>
<string name="phone_hint" msgid="4872890986869209950">"Pasatu hatza ikonotik, telefonoa irekitzeko"</string>
<string name="voice_hint" msgid="8939888732119726665">"Pasatu hatza ikonotik, ahots-laguntza irekitzeko"</string>
<string name="camera_hint" msgid="7939688436797157483">"Pasatu hatza ikonotik, kamera irekitzeko"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index bd3c4fc..de596d2 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"اعلانهای کمتر فوری در زیر"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"دوباره ضربه بزنید تا باز شود"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"برای باز کردن قفل سریع به بالا بکشید"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"این دستگاه مدیریت میشود"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"این دستگاه توسط <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> مدیریت میشود"</string>
<string name="phone_hint" msgid="4872890986869209950">"انگشتتان را از نماد تلفن تند بکشید"</string>
<string name="voice_hint" msgid="8939888732119726665">"برای «دستیار صوتی»، تند بکشید"</string>
<string name="camera_hint" msgid="7939688436797157483">"انگشتتان را از نماد دوربین تند بکشید"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> کنترلکننده صدا است"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"برای بازیابی نسخه اصلی ضربه بزنید."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"درحال استفاده از نمایه کاریتان هستید"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"تماس"</item>
+ <item msgid="5997713001067658559">"سیستم"</item>
+ <item msgid="7858983209929864160">"تماس"</item>
+ <item msgid="1850038478268896762">"رسانه"</item>
+ <item msgid="8265110906352372092">"هشدار"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"بلوتوث"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"دسترسپذیری"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. برای باصدا کردن ضربه بزنید."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. برای تنظیم روی لرزش ضربه بزنید. ممکن است سرویسهای دسترسپذیری بیصدا شوند."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. برای بیصدا کردن ضربه بزنید. ممکن است سرویسهای دسترسپذیری بیصدا شوند."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 446c9f8..234a850 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Vähemmän kiireelliset ilmoitukset ovat alla"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Avaa napauttamalla uudelleen"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Avaa lukitus pyyhkäisemällä ylös"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Tämä on hallinnoitu laite."</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Tätä laitetta hallinnoi <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string>
<string name="phone_hint" msgid="4872890986869209950">"Avaa puhelu pyyhkäisemällä."</string>
<string name="voice_hint" msgid="8939888732119726665">"Avaa ääniapuri pyyhkäisemällä kuvakkeesta."</string>
<string name="camera_hint" msgid="7939688436797157483">"Avaa kamera pyyhkäisemällä."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a03e897..11edeb9 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifications moins urgentes affichées ci-dessous"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Touchez à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Glissez vers le haut pour déverrouiller"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Cet appareil est géré"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Cet appareil est géré par <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Balayez à partir de l\'icône pour accéder au téléphone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Balayez à partir de l\'icône pour accéder à l\'assist. vocale"</string>
<string name="camera_hint" msgid="7939688436797157483">"Balayez à partir de l\'icône pour accéder à l\'appareil photo"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Touchez pour restaurer l\'original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Vous utilisez votre profil professionnel."</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Appeler"</item>
+ <item msgid="5997713001067658559">"Système"</item>
+ <item msgid="7858983209929864160">"Sonnerie"</item>
+ <item msgid="1850038478268896762">"Multimédia"</item>
+ <item msgid="8265110906352372092">"Alarme"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Accessibilité"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Touchez pour réactiver le son."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Touchez pour activer les vibrations. Il est possible de couper le son des services d\'accessibilité."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Touchez pour couper le son. Il est possible de couper le son des services d\'accessibilité."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 1e72795..fa9494e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifications moins urgentes ci-dessous"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Appuyer à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Faire glisser pour déverrouiller"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Cet appareil est géré"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Cet appareil est géré par <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Balayer pour téléphoner"</string>
<string name="voice_hint" msgid="8939888732119726665">"Balayer l\'écran depuis l\'icône pour l\'assistance vocale"</string>
<string name="camera_hint" msgid="7939688436797157483">"Balayer pour prendre une photo"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Appuyez pour rétablir la version d\'origine."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Vous utilisez votre profil professionnel."</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Appeler"</item>
+ <item msgid="5997713001067658559">"Système"</item>
+ <item msgid="7858983209929864160">"Sonnerie"</item>
+ <item msgid="1850038478268896762">"Multimédia"</item>
+ <item msgid="8265110906352372092">"Alarme"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Accessibilité"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Appuyez pour ne plus ignorer."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Appuyez pour mettre en mode vibreur. Vous pouvez ignorer les services d\'accessibilité."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Appuyez pour ignorer. Vous pouvez ignorer les services d\'accessibilité."</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 515c729..2f9b2e6 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificacións menos urxentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toca de novo para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Pasa o dedo cara arriba para desbloquear"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este dispositivo está xestionado"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Este dispositivo está xestionado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Pasa o dedo desde a icona para acceder ao teléfono"</string>
<string name="voice_hint" msgid="8939888732119726665">"Pasa o dedo desde a icona para acceder ao asistente de voz"</string>
<string name="camera_hint" msgid="7939688436797157483">"Pasa o dedo desde a icona para acceder á cámara"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 9778b86..3649e85 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"નીચે ઓછી તાકીદની સૂચનાઓ"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ખોલવા માટે ફરીથી ટૅપ કરો"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"અનલૉક કરવા માટે ઉપર સ્વાઇપ કરો"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"આ ઉપકરણ સંચાલિત છે"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"આ ઉપકરણ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> દ્વારા સંચાલિત થાય છે"</string>
<string name="phone_hint" msgid="4872890986869209950">"ફોન માટે આયકનમાંથી સ્વાઇપ કરો"</string>
<string name="voice_hint" msgid="8939888732119726665">"વૉઇસ સહાય માટે આયકનમાંથી સ્વાઇપ કરો"</string>
<string name="camera_hint" msgid="7939688436797157483">"કૅમેરા માટે આયકનમાંથી સ્વાઇપ કરો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 1010126..7fd5eb6 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"कम अत्यावश्यक सूचनाएं नीचे दी गई हैं"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"खोलने के लिए पुन: टैप करें"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"अनलॉक करने के लिए ऊपर स्वाइप करें"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"यह डिवाइस प्रबंधित है"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"इस डिवाइस के प्रबंधक <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> हैं"</string>
<string name="phone_hint" msgid="4872890986869209950">"फ़ोन के लिए आइकन से स्वाइप करें"</string>
<string name="voice_hint" msgid="8939888732119726665">"वॉइस सहायक के लिए आइकन से स्वाइप करें"</string>
<string name="camera_hint" msgid="7939688436797157483">"कैमरे के लिए आइकन से स्वाइप करें"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद है"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"मूल को पुन: स्थापित करने के लिए टैप करें."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"आप अपनी कार्य प्रोफ़ाइल का उपयोग कर रहे हैं"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"कॉल करें"</item>
+ <item msgid="5997713001067658559">"सिस्टम"</item>
+ <item msgid="7858983209929864160">"रिंग करें"</item>
+ <item msgid="1850038478268896762">"मीडिया"</item>
+ <item msgid="8265110906352372092">"अलार्म"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ब्लूटूथ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"एक्सेस-योग्यता"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. अनम्यूट करने के लिए टैप करें."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. कंपन पर सेट करने के लिए टैप करें. एक्सेस-योग्यता सेवाएं म्यूट हो सकती हैं."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. म्यूट करने के लिए टैप करें. एक्सेस-योग्यता सेवाएं म्यूट हो सकती हैं."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 5d9162e..c105c23 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Manje hitne obavijesti pri dnu"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite opet za otvaranje"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Prijeđite prstom prema gore za otključavanje"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Ovim se uređajem upravlja"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Prijeđite prstom od ikone za telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Prijeđite prstom od ikone za glasovnu pomoć"</string>
<string name="camera_hint" msgid="7939688436797157483">"Prijeđite prstom od ikone za fotoaparat"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index bb78030..9944b21 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"A kevésbé sürgős értesítések lentebb vannak"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Koppintson rá ismét a megnyitáshoz"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Húzza felfelé az ujját a feloldáshoz"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Ez az eszköz felügyelt"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Az eszközt a(z) <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> felügyeli."</string>
<string name="phone_hint" msgid="4872890986869209950">"A telefonhoz csúsztasson az ikonról"</string>
<string name="voice_hint" msgid="8939888732119726665">"A hangsegéd eléréséhez csúsztassa ujját az ikonról"</string>
<string name="camera_hint" msgid="7939688436797157483">"A fényképezőhöz csúsztasson az ikonról"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index d9ec09e..1c3e9b3 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Պակաս հրատապ ծանուցումները ստորև"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Կրկին հպեք՝ բացելու համար"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Սահեցրեք վերև` ապակողպելու համար"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Այս սարքը կառավարվում է"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Այս սարքը կառավարվում է <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>-ի կողմից"</string>
<string name="phone_hint" msgid="4872890986869209950">"Սահահարվածեք հեռախոսի պատկերակից"</string>
<string name="voice_hint" msgid="8939888732119726665">"Սահահարվածեք ձայնային հուշման պատկերակից"</string>
<string name="camera_hint" msgid="7939688436797157483">"Սահահարվածեք խցիկի պատկերակից"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ձայնի ուժգնության երկխոսության հավելված է"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Հպեք՝ բնօրինակը վերականգնելու համար:"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Դուք օգտագործում եք ձեր աշխատանքային պրոֆիլը"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Զանգել"</item>
+ <item msgid="5997713001067658559">"Համակարգ"</item>
+ <item msgid="7858983209929864160">"Զանգ"</item>
+ <item msgid="1850038478268896762">"Մեդիա"</item>
+ <item msgid="8265110906352372092">"Զարթուցիչ"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Մատչելիություն"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s: Հպեք՝ ձայնը միացնելու համար:"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s: Հպեք՝ թրթռումը միացնելու համար: Մատչելիության ծառայությունների ձայնը կարող է անջատվել:"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s: Հպեք՝ ձայնն անջատելու համար: Մատչելիության ծառայությունների ձայնը կարող է անջատվել:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 49d5221..e1e522e 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifikasi kurang darurat di bawah"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ketuk lagi untuk membuka"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Gesek ke atas untuk membuka kunci"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Perangkat ini dikelola"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Perangkat ini dikelola oleh <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Gesek dari ikon untuk telepon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Gesek dari ikon untuk mengaktifkan bantuan suara"</string>
<string name="camera_hint" msgid="7939688436797157483">"Gesek dari ikon untuk kamera"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index f95d35f..d92092d 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Minna áríðandi tilkynningar fyrir neðan"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ýttu aftur til að opna"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Strjúktu upp til að opna"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Þessu tæki er stýrt"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Þessu tæki er stýrt af <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Strjúktu frá tákninu fyrir síma"</string>
<string name="voice_hint" msgid="8939888732119726665">"Strjúktu frá tákninu fyrir raddaðstoð"</string>
<string name="camera_hint" msgid="7939688436797157483">"Strjúktu frá tákninu fyrir myndavél"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index b30516d..43b5f34 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifiche meno urgenti in basso"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tocca ancora per aprire"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Scorri verso l\'alto per sbloccare"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Questo dispositivo è gestito"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Questo dispositivo è gestito da <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Scorri per accedere al telefono"</string>
<string name="voice_hint" msgid="8939888732119726665">"Scorri dall\'icona per accedere a Voice Assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Scorri dall\'icona per accedere alla fotocamera"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index c9f907a..b51020b 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -354,6 +354,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"הודעות בדחיפות נמוכה יותר בהמשך"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"הקש שוב כדי לפתוח"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"החלק מעלה כדי לבטל את הנעילה"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"המכשיר הזה מנוהל"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"המכשיר הזה מנוהל על ידי <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"החלק מהסמל כדי להפעיל את הטלפון"</string>
<string name="voice_hint" msgid="8939888732119726665">"החלק מהסמל כדי להפעיל את המסייע הקולי"</string>
<string name="camera_hint" msgid="7939688436797157483">"החלק מהסמל כדי להפעיל את המצלמה"</string>
@@ -444,7 +446,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> הוא תיבת הדו-שיח של עוצמת הקול"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"הקש כדי לשחזר את המקור."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"אתה משתמש בפרופיל העבודה שלך"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"שיחה"</item>
+ <item msgid="5997713001067658559">"מערכת"</item>
+ <item msgid="7858983209929864160">"השמע צלצול"</item>
+ <item msgid="1850038478268896762">"מדיה"</item>
+ <item msgid="8265110906352372092">"התראה"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"נגישות"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. הקש כדי לבטל את ההשתקה."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. הקש כדי להגדיר רטט. ייתכן ששירותי הנגישות מושתקים."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. הקש כדי להשתיק. ייתכן ששירותי הנגישות מושתקים."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b891b61..a949cbf 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"緊急度の低い通知を下に表示"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"開くにはもう一度タップしてください"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ロック解除するには上にスワイプしてください"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"この端末は組織が管理しています"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"この端末は <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> が管理しています"</string>
<string name="phone_hint" msgid="4872890986869209950">"右にスワイプして通話"</string>
<string name="voice_hint" msgid="8939888732119726665">"アイコンからスワイプして音声アシストを起動"</string>
<string name="camera_hint" msgid="7939688436797157483">"左にスワイプしてカメラを起動"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>を音量ダイアログとして使用"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"タップすると元に戻ります。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"仕事用プロファイルを使用しています"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"通話"</item>
+ <item msgid="5997713001067658559">"システム"</item>
+ <item msgid="7858983209929864160">"着信音"</item>
+ <item msgid="1850038478268896762">"メディア"</item>
+ <item msgid="8265110906352372092">"アラーム"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ユーザー補助機能"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。タップしてミュートを解除します。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。タップしてバイブレーションに設定します。ユーザー補助機能サービスがミュートされる場合があります。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。タップしてミュートします。ユーザー補助機能サービスがミュートされる場合があります。"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index e00d6b3..41de915 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ქვემოთ მითითებულია ნაკლებად სასწრაფო შეტყობინებები"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"შეეხეთ ისევ გასახსნელად"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"გაასრიალეთ ზევით განსაბლოკად"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ეს მოწყობილობა მართულია"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ამ მოწყობილობას მართავს <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"ტელეფონისთვის გადაფურცლეთ ხატულადან"</string>
<string name="voice_hint" msgid="8939888732119726665">"ხმოვანი დახმარებისთვის გადაფურცლეთ ხატულადან"</string>
<string name="camera_hint" msgid="7939688436797157483">"კამერისთვის გადაფურცლეთ ხატულადან"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 92b94bd..0f9699a 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Шұғылдығы азырақ хабарландырулар төменде"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ашу үшін қайта түртіңіз"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Құлыпты ашу үшін жоғары сырғытыңыз"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Бұл құрылғыны ұйым басқарады"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Бұл құрылғыны <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> басқарады"</string>
<string name="phone_hint" msgid="4872890986869209950">"Телефонды ашу үшін белгішеден әрі қарай сырғытыңыз"</string>
<string name="voice_hint" msgid="8939888732119726665">"Дауыс көмекшісін ашу үшін белгішеден әрі қарай сырғытыңыз"</string>
<string name="camera_hint" msgid="7939688436797157483">"Камераны ашу үшін белгішеден әрі қарай сырғытыңыз"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> — көлем диалогтық терезесі"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Бастапқы қалпына келтіру үшін түртіңіз."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Сіз жұмыс профиліңізді пайдаланып жатырсыз"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Қоңырау шалу"</item>
+ <item msgid="5997713001067658559">"Жүйе"</item>
+ <item msgid="7858983209929864160">"Шылдырлау"</item>
+ <item msgid="1850038478268896762">"Мультимeдиа"</item>
+ <item msgid="8265110906352372092">"Дабыл"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Арнайы мүмкіндіктер"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Дыбысын қосу үшін түртіңіз."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Діріл режимін орнату үшін түртіңіз. Арнайы мүмкіндік қызметтерінің дыбысы өшуі мүмкін."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Дыбысын өшіру үшін түртіңіз. Арнайы мүмкіндік қызметтерінің дыбысы өшуі мүмкін."</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 9a352fc..4ad9ac8 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ការជូនដំណឹងមិនសូវបន្ទាន់ខាងក្រោម"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ប៉ះម្ដងទៀត ដើម្បីបើក"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"អូសឡើងលើ ដើម្បីដោះសោ"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ឧបករណ៍នេះស្ថិតក្រោមការគ្រប់គ្រង"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ឧបករណ៍នេះត្រូវបានគ្រប់គ្រងដោយ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"អូសចេញពីរូបតំណាងដើម្បីប្រើទូរស័ព្ទ"</string>
<string name="voice_hint" msgid="8939888732119726665">"អូសចេញពីរូបតំណាងដើម្បីប្រើជំនួយសំឡេង"</string>
<string name="camera_hint" msgid="7939688436797157483">"អូសចេញពីរូបតំណាងដើម្បីប្រើកាមេរ៉ា"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> គឺជាប្រអប់សម្លេង"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ប៉ះដើម្បីស្តារច្បាប់ដើម"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"អ្នកកំពុងប្រើប្រវត្តិរូបការងាររបស់អ្នក"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ហៅ"</item>
+ <item msgid="5997713001067658559">"ប្រព័ន្ធ"</item>
+ <item msgid="7858983209929864160">"រោទ៍"</item>
+ <item msgid="1850038478268896762">"មេឌៀ"</item>
+ <item msgid="8265110906352372092">"ម៉ោងរោទ៍"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ប៊្លូធូស"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ភាពងាយស្រួល"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s។ ប៉ះដើម្បីបើកសំឡេង។"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s។ ប៉ះដើម្បីកំណត់ឲ្យញ័រ។ សេវាកម្មលទ្ធភាពប្រើប្រាស់អាចនឹងត្រូវបានបិទសំឡេង។"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s។ ប៉ះដើម្បីបិទសំឡេង។ សេវាកម្មលទ្ធភាពប្រើប្រាស់អាចនឹងត្រូវបានបិទសំឡេង។"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 990c721..3a29a6f 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ಕೆಳಗೆ ಕಡಿಮೆ ಅವಸರದ ಅಧಿಸೂಚನೆಗಳು"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ತೆರೆಯಲು ಮತ್ತೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ಅನ್ಲಾಕ್ ಮಾಡಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ಈ ಸಾಧನವನ್ನು ನಿರ್ವಹಿಸಲಾಗಿದೆ"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ಈ ಸಾಧನವನ್ನು <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ರಿಂದ ನಿರ್ವಹಿಸಲಾಗಿದೆ"</string>
<string name="phone_hint" msgid="4872890986869209950">"ಫೋನ್ಗಾಗಿ ಐಕಾನ್ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="voice_hint" msgid="8939888732119726665">"ಧ್ವನಿ ಸಹಾಯಕ್ಕಾಗಿ ಐಕಾನ್ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="camera_hint" msgid="7939688436797157483">"ಕ್ಯಾಮರಾಗಾಗಿ ಐಕಾನ್ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಿದೆ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ಮೂಲಕ್ಕೆ ಮರುಸ್ಥಾಪಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ನು ನೀವು ಬಳಸುತ್ತಿರುವಿರಿ"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ಕರೆಮಾಡಿ"</item>
+ <item msgid="5997713001067658559">"ಸಿಸ್ಟಂ"</item>
+ <item msgid="7858983209929864160">"ಉಂಗುರ"</item>
+ <item msgid="1850038478268896762">"ಮಾಧ್ಯಮ"</item>
+ <item msgid="8265110906352372092">"ಅಲಾರಮ್"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ಬ್ಲೂಟೂತ್"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ಪ್ರವೇಶಿಸುವಿಕೆ"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ಅನ್ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. ಕಂಪನಕ್ಕೆ ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್ ಮಾಡಬಹುದು."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್ ಮಾಡಬಹುದು."</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index b06f15e..cff469c 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"아래에 덜 급한 알림 표시"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"다시 탭하여 열기"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"위로 스와이프하여 잠금 해제"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"관리되는 기기입니다."</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>에서 관리하는 기기입니다."</string>
<string name="phone_hint" msgid="4872890986869209950">"전화 기능을 사용하려면 아이콘에서 스와이프하세요."</string>
<string name="voice_hint" msgid="8939888732119726665">"음성 지원을 사용하려면 아이콘에서 스와이프하세요."</string>
<string name="camera_hint" msgid="7939688436797157483">"카메라를 사용하려면 아이콘에서 스와이프하세요."</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>은(는) 볼륨 대화입니다."</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"원본을 복원하려면 탭하세요."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"직장 프로필을 사용하고 있습니다."</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"통화"</item>
+ <item msgid="5997713001067658559">"시스템"</item>
+ <item msgid="7858983209929864160">"벨 울리기"</item>
+ <item msgid="1850038478268896762">"미디어"</item>
+ <item msgid="8265110906352372092">"알람"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"블루투스"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"접근성"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. 탭하여 음소거를 해제하세요."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. 탭하여 진동으로 설정하세요. 접근성 서비스가 음소거될 수 있습니다."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. 탭하여 음소거로 설정하세요. 접근성 서비스가 음소거될 수 있습니다."</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index d5af0b3..a0675c0 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Анчейин шашылыш эмес эскертмелер төмөндө"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ачуу үчүн кайра таптап коюңуз"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Кулпуну ачуу үчүн серпип коюңуз"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Башкарылган түзмөк"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Бул түзмөк <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> тарабынан башкарылат"</string>
<string name="phone_hint" msgid="4872890986869209950">"Сүрөтчөнү серпип телефонго өтүңүз"</string>
<string name="voice_hint" msgid="8939888732119726665">"Сүрөтчөнү серпип үн жардамчысына өтүңүз"</string>
<string name="camera_hint" msgid="7939688436797157483">"Сүрөтчөнү серпип камерага өтүңүз"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 711a68d..2056194 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ການແຈ້ງເຕືອນທີ່ສຳຄັນໜ້ອຍກວ່າຢູ່ດ້ານລຸ່ມ"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ແຕະອີກຄັ້ງເພື່ອເປີດ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນຂຶ້ນເພື່ອປົດລັອກ"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ອຸປະກອນນີ້ຖືກຈັດການຢູ່"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ອຸປະກອນນີ້ຖືກຈັດການໂດຍ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"ປັດຈາກໄອຄອນສຳລັບໂທລະສັບ"</string>
<string name="voice_hint" msgid="8939888732119726665">"ປັດຈາກໄອຄອນສຳລັບການຊ່ວຍທາງສຽງ"</string>
<string name="camera_hint" msgid="7939688436797157483">"ປັດຈາກໄອຄອນສຳລັບກ້ອງຖ່າຍຮູບ"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ແມ່ນໜ້າຕ່າງລະດັບສຽງ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ແຕະເພື່ອກູ້ຕົ້ນສະບັບຄືນມາ."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ທ່ານກຳລັງໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານ"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ໂທ"</item>
+ <item msgid="5997713001067658559">"ລະບົບ"</item>
+ <item msgid="7858983209929864160">"ເຕືອນດ້ວຍສຽງ"</item>
+ <item msgid="1850038478268896762">"ມີເດຍ"</item>
+ <item msgid="8265110906352372092">"ໂມງປຸກ"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ການຊ່ວຍເຂົ້າເຖິງ"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ແຕະເພື່ອເຊົາປິດສຽງ."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. ແຕະເພື່ອຕັ້ງເປັນສັ່ນ. ບໍລິການຊ່ວຍເຂົ້າເຖິງອາດຖືກປິດສຽງໄວ້."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ແຕະເພື່ອປິດສຽງ. ບໍລິການຊ່ວຍເຂົ້າເຖິງອາດຖືກປິດສຽງໄວ້."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index aec484d..6dfdbe6 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -354,6 +354,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mažiau skubūs pranešimai toliau"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Palieskite dar kartą, kad atidarytumėte"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Perbraukite aukštyn, kad atrakintumėte"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Šis įrenginys tvarkomas"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Šį įrenginį tvarko <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Perbraukite iš telefono piktogramos"</string>
<string name="voice_hint" msgid="8939888732119726665">"Perbraukite iš „Voice Assist“ piktogramos"</string>
<string name="camera_hint" msgid="7939688436797157483">"Perbraukite iš fotoaparato piktogramos"</string>
@@ -444,7 +446,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ yra garsumo valdymo dialogo langas"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Palieskite, kad atkurtumėte originalą."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Naudojate darbo profilį"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Skambinti"</item>
+ <item msgid="5997713001067658559">"Sistema"</item>
+ <item msgid="7858983209929864160">"Skambinti"</item>
+ <item msgid="1850038478268896762">"Medija"</item>
+ <item msgid="8265110906352372092">"Signalas"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Pritaikymas neįgaliesiems"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Palieskite, kad įjungtumėte garsą."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Palieskite, kad nustatytumėte vibravimą. Gali būti nutildytos pritaikymo neįgaliesiems paslaugos."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Palieskite, kad nutildytumėte. Gali būti nutildytos pritaikymo neįgaliesiems paslaugos."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 900a955d..3862a8e 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mazāk steidzami paziņojumi tiek rādīti tālāk"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Pieskarieties vēlreiz, lai atvērtu"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Velciet uz augšu, lai atbloķētu"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Šī ierīce tiek pārvaldīta"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Šo ierīci pārvalda <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Lai lietotu tālruni, velciet no ikonas"</string>
<string name="voice_hint" msgid="8939888732119726665">"Lai lietotu balss palīgu, velciet no ikonas"</string>
<string name="camera_hint" msgid="7939688436797157483">"Lai lietotu kameru, velciet no ikonas"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ir skaļuma dialoglodziņš"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Pieskarieties, lai atjaunotu sākotnējo saturu."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Jūs izmantojat darba profilu."</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Zvans"</item>
+ <item msgid="5997713001067658559">"Sistēma"</item>
+ <item msgid="7858983209929864160">"Zvanīt"</item>
+ <item msgid="1850038478268896762">"Multivide"</item>
+ <item msgid="8265110906352372092">"Signāls"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Pieejamība"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Pieskarieties, lai ieslēgtu skaņu."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Pieskarieties, lai iestatītu uz vibrozvanu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Pieskarieties, lai izslēgtu skaņu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 716f76c..5d28e2b 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Долу се помалку итни известувања"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Допрете повторно за да се отвори"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Повлечете за да се отклучи"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Со уредов се управува"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Уредов го управува <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Повлечете од иконата за телефонот"</string>
<string name="voice_hint" msgid="8939888732119726665">"Повлечете од иконата за гласовна помош"</string>
<string name="camera_hint" msgid="7939688436797157483">"Повлечете од иконата за камерата"</string>
@@ -526,7 +528,7 @@
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Штедач на батерија"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Ја намалува изведбата и податоците во заднина"</string>
<string name="keyboard_key_button_template" msgid="6230056639734377300">"Копче <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="keyboard_key_home" msgid="2243500072071305073">"Почетна страница"</string>
+ <string name="keyboard_key_home" msgid="2243500072071305073">"Home-копче"</string>
<string name="keyboard_key_back" msgid="2337450286042721351">"Назад"</string>
<string name="keyboard_key_dpad_up" msgid="5584144111755734686">"Стрелка нагоре"</string>
<string name="keyboard_key_dpad_down" msgid="7331518671788337815">"Стрелка надолу"</string>
@@ -546,7 +548,7 @@
<string name="keyboard_key_page_up" msgid="5654098530106845603">"Страница нагоре"</string>
<string name="keyboard_key_page_down" msgid="8720502083731906136">"Страница надолу"</string>
<string name="keyboard_key_forward_del" msgid="1391451334716490176">"Избриши"</string>
- <string name="keyboard_key_move_home" msgid="2765693292069487486">"Почетна страница"</string>
+ <string name="keyboard_key_move_home" msgid="2765693292069487486">"Home-копче"</string>
<string name="keyboard_key_move_end" msgid="5901174332047975247">"Крај"</string>
<string name="keyboard_key_insert" msgid="8530501581636082614">"Вметни"</string>
<string name="keyboard_key_num_lock" msgid="5052537581246772117">"Num Lock"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 6c14826..f24b1e6 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ആവശ്യം കുറഞ്ഞ അറിയിപ്പുകൾ ചുവടെ നൽകിയിരിക്കുന്നു"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"തുറക്കുന്നതിന് വീണ്ടും ടാപ്പുചെയ്യുക"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"അൺലോക്കുചെയ്യുന്നതിന് മുകളിലേക്ക് സ്വൈപ്പുചെയ്യുക"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"മാനേജുചെയ്യപ്പെടുന്ന ഉപകരണമാണിത്"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> മാനേജുചെയ്യുന്ന ഉപകരണമാണിത്"</string>
<string name="phone_hint" msgid="4872890986869209950">"ഫോൺ ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string>
<string name="voice_hint" msgid="8939888732119726665">"വോയ്സ് അസിസ്റ്റിനായുള്ള ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string>
<string name="camera_hint" msgid="7939688436797157483">"ക്യാമറ ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗാണ്"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ഒറിജിനൽ പുനഃസ്ഥാപിക്കാൻ ടാപ്പുചെയ്യുക."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"നിങ്ങൾ ഉപയോഗിക്കുന്നത് ഔദ്യോഗിക പ്രൊഫൈലാണ്"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"വിളിക്കുക"</item>
+ <item msgid="5997713001067658559">"സിസ്റ്റം"</item>
+ <item msgid="7858983209929864160">"റിംഗുചെയ്യുക"</item>
+ <item msgid="1850038478268896762">"മീഡിയ"</item>
+ <item msgid="8265110906352372092">"അലാറം"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ബ്ലൂടൂത്ത്"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"പ്രവേശനക്ഷമത"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. അൺമ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. വൈബ്രേറ്റിലേക്ക് സജ്ജമാക്കുന്നതിന് ടാപ്പുചെയ്യുക. പ്രവേശനക്ഷമതാ സേവനങ്ങൾ മ്യൂട്ടുചെയ്യപ്പെട്ടേക്കാം."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. മ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക. പ്രവേശനക്ഷമതാ സേവനങ്ങൾ മ്യൂട്ടുചെയ്യപ്പെട്ടേക്കാം."</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 8171310..e285a42 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -348,6 +348,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Яаралтай биш мэдэгдлүүдийг доор"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Нээхийн тулд дахин товшино уу"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Түгжээг тайлах бол шудрана уу"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Энэ төхөөрөмжийг удирдаж байна"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Энэ төхөөрөмжийг <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> удирддаг"</string>
<string name="phone_hint" msgid="4872890986869209950">"Утсыг гаргахын тулд дүрс тэмдгээс шудрах"</string>
<string name="voice_hint" msgid="8939888732119726665">"Дуут туслахыг нээхийн тулд дүрс тэмдгээс шудрах"</string>
<string name="camera_hint" msgid="7939688436797157483">"Камер нээхийн тулд дүрс тэмдгийг шудрах"</string>
@@ -438,7 +440,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь дууны диалог юм."</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Эх хувилбарыг сэргээхийн тулд дарна уу."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Та өөрийн ажлын профайлыг ашиглаж байна"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Дуудлага"</item>
+ <item msgid="5997713001067658559">"Систем"</item>
+ <item msgid="7858983209929864160">"Хонх дуугаргах"</item>
+ <item msgid="1850038478268896762">"Медиа"</item>
+ <item msgid="8265110906352372092">"Сэрүүлэг"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Хүртээмж"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Дууг нь нээхийн тулд товшино уу."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Чичиргээнд тохируулахын тулд товшино уу. Хүртээмжийн үйлчилгээний дууг хаасан."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Дууг нь хаахын тулд товшино уу. Хүртээмжийн үйлчилгээний дууг хаасан."</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index ade3921..f94e859 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"खाली कमी तातडीच्या सूचना"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"उघडण्यासाठी पुन्हा टॅप करा"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"अनलॉक करण्यासाठी स्वाइप करा"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"हे डिव्हाइस व्यवस्थापित केले आहे"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ने व्यवस्थापित केले आहे"</string>
<string name="phone_hint" msgid="4872890986869209950">"फोनसाठी चिन्हावरून स्वाइप करा"</string>
<string name="voice_hint" msgid="8939888732119726665">"व्हॉइस सहाय्यासाठी चिन्हावरून स्वाइप करा"</string>
<string name="camera_hint" msgid="7939688436797157483">"कॅमेर्यासाठी चिन्हावरून स्वाइप करा"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index ebe2cf8..0c5924d 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Pemberitahuan kurang penting di bawah"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ketik lagi untuk membuka"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Leret ke atas untuk membuka kunci"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Peranti ini terurus"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Peranti ini diurus oleh <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Leret dari ikon untuk telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Leret dari ikon untuk bantuan suara"</string>
<string name="camera_hint" msgid="7939688436797157483">"Leret dari ikon untuk kamera"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ialah dialog kelantangan"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Ketik untuk memulihkan yang asal."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Anda sedang menggunakan profil kerja"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Panggil"</item>
+ <item msgid="5997713001067658559">"Sistem"</item>
+ <item msgid="7858983209929864160">"Dering"</item>
+ <item msgid="1850038478268896762">"Media"</item>
+ <item msgid="8265110906352372092">"Penggera"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Kebolehaksesan"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Ketik untuk menyahredam."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Ketik untuk menetapkan pada getar. Perkhidmatan kebolehaksesan mungkin diredamkan."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Ketik untuk meredam. Perkhidmatan kebolehaksesan mungkin diredamkan."</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index a1e6d37..af68511 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"အရေးပါမှု နည်းသည့် အကြောင်းကြားချက်များ အောက်မှာ"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ဖွင့်ရန် ထပ်ပြီး ပုတ်ပါ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"သော့ဖွင့်ရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ဤစက်ပစ္စည်းကို စီမံခန့်ခွဲထားပါသည်"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ဤစက်ပစ္စည်းကို <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> က စီမံခန့်ခွဲထားပါသည်"</string>
<string name="phone_hint" msgid="4872890986869209950">"ဖုန်းအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
<string name="voice_hint" msgid="8939888732119726665">"အသံအကူအညီအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
<string name="camera_hint" msgid="7939688436797157483">"ကင်မရာအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 4508276..1b9c35a 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre presserende varsler nedenfor"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Trykk på nytt for å åpne"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Sveip oppover for å låse opp"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Denne enheten blir administrert"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Denne enheten administreres av <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Sveip ikonet for å åpne telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Sveip fra ikonet for å åpne talehjelp"</string>
<string name="camera_hint" msgid="7939688436797157483">"Sveip ikonet for å åpne kamera"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 7afcac1..1d33a7d 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -331,7 +331,7 @@
<string name="recents_drag_hint_message" msgid="2649739267073203985">"विभाजित स्क्रिनको प्रयोग गर्नका लागि यहाँ तान्नुहोस्"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"तेर्सो रूपमा विभाजन गर्नुहोस्"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ठाडो रूपमा विभाजन गर्नुहोस्"</string>
- <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"अनुकूलन विभाजन गर्नुहोस्"</string>
+ <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"आफू अनुकूल विभाजन गर्नुहोस्"</string>
<string-array name="recents_blacklist_array">
</string-array>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज भयो"</string>
@@ -343,13 +343,15 @@
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>को लागि माथि धिसार्नुहोस्"</string>
<string name="description_direction_left" msgid="7207478719805562165">"स्लाइड <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>को लागि बायाँ।"</string>
<string name="zen_priority_introduction" msgid="3070506961866919502">"अलार्म, रिमाइन्डर, घटना, र तपाईँले निर्दिष्ट गर्नुहुने कलरहरू देखि बाहेक, आवाज र कम्पनले तपाईँ लाई वाधा गर्ने छैन।"</string>
- <string name="zen_priority_customize_button" msgid="7948043278226955063">"अनुकूलन गर्नुहोस्"</string>
+ <string name="zen_priority_customize_button" msgid="7948043278226955063">"आफू अनुकूल बनाउनुहोस्"</string>
<string name="zen_silence_introduction_voice" msgid="2284540992298200729">"यसले अलार्म, संगीत, भिडियो, र खेलहरू लगायतका सबै ध्वनि र कम्पन रोक्छ। तपाईँ अझै पनि फोन कल गर्न सक्षम हुनुहुन्छ।"</string>
<string name="zen_silence_introduction" msgid="3137882381093271568">"यसले अलार्म, संगीत, भिडियोहरू र खेलहरूसहित सबै ध्वनिहरू र कम्पनहरूलाई रोक्छ।"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"तल कम जरुरी सूचनाहरू"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"खोल्न पुनः ट्याप गर्नुहोस्"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"अनलक गर्न स्वाप गर्नुहोस्"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"यो यन्त्र व्यवस्थापन गरिएको छ"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"यो यन्त्र <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> द्वारा व्यवस्थापन गरिएको छ"</string>
<string name="phone_hint" msgid="4872890986869209950">"फोनको लागि आइकनबाट स्वाइप गर्नुहोस्"</string>
<string name="voice_hint" msgid="8939888732119726665">"आवाज सहायताका लागि आइकनबाट स्वाइप गर्नुहोस्"</string>
<string name="camera_hint" msgid="7939688436797157483">"क्यामेराको लागि आइकनबाट स्वाइप गर्नुहोस्"</string>
@@ -481,7 +483,7 @@
<string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Hotspot"</string>
<string name="accessibility_managed_profile" msgid="6613641363112584120">"कार्य प्रोफाइल"</string>
<string name="tuner_warning_title" msgid="7094689930793031682">"केहीका लागि रमाइलो हुन्छ तर सबैका लागि होइन"</string>
- <string name="tuner_warning" msgid="8730648121973575701">"प्रणाली UI ट्युनरले तपाईँलाई Android प्रयोगकर्ता इन्टरफेस अनुकूलन गर्न र ट्विक गर्न थप तरिकाहरू प्रदान गर्छ। यी प्रयोगात्मक सुविधाहरू भावी विमोचनमा परिवर्तन हुन, बिग्रिन वा हराउन सक्ने छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
+ <string name="tuner_warning" msgid="8730648121973575701">"प्रणाली UI ट्युनरले तपाईँलाई Android प्रयोगकर्ता इन्टरफेस आफू अनुकूल गर्न र ट्विक गर्न थप तरिकाहरू प्रदान गर्छ। यी प्रयोगात्मक सुविधाहरू भावी विमोचनमा परिवर्तन हुन, बिग्रिन वा हराउन सक्ने छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
<string name="tuner_persistent_warning" msgid="8597333795565621795">"यी प्रयोगात्मक सुविधाहरू भावी विमोचनहरूमा परिवर्तन हुन, बिग्रन वा हराउन सक्छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
<string name="got_it" msgid="2239653834387972602">"बुझेँ"</string>
<string name="tuner_toast" msgid="603429811084428439">"बधाईँ छ! सेटिङहरूमा प्रणाली UI ट्युनर थप गरिएको छ"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index a13030d..1d7ac5ec 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Minder urgente meldingen onderaan"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tik nogmaals om te openen"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Veeg omhoog om te ontgrendelen"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Dit apparaat wordt beheerd"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Dit apparaat wordt beheerd door <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Vegen voor telefoon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Vegen vanaf pictogram voor spraakassistent"</string>
<string name="camera_hint" msgid="7939688436797157483">"Vegen voor camera"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 6b5abe4..bdb1e43 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -70,7 +70,7 @@
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="screenshot_saving_text" msgid="2419718443411738818">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ।"</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਕੀਤਾ।"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਕੈਪਚਰ ਕੀਤਾ।"</string>
<string name="screenshot_saved_text" msgid="2685605830386712477">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਵੇਖਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕਰਨ ਦੌਰਾਨ ਸਮੱਸਿਆ ਆਈ।"</string>
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ਹੇਠਾਂ ਘੱਟ ਲਾਜ਼ਮੀ ਸੂਚਨਾਵਾਂ"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ਖੋਲ੍ਹਣ ਲਈ ਦੁਬਾਰਾ ਟੈਪ ਕਰੋ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਉੱਪਰ ਸਵਾਈਪ ਕਰੋ।"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ਇਹ ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਿਤ ਕੀਤੀ ਗਈ ਹੈ"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੀ ਗਈ ਹੈ"</string>
<string name="phone_hint" msgid="4872890986869209950">"ਫ਼ੋਨ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="voice_hint" msgid="8939888732119726665">"ਵੌਇਸ ਅਸਿਸਟ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="camera_hint" msgid="7939688436797157483">"ਕੈਮਰੇ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
@@ -395,7 +397,7 @@
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ਬੈਟਰੀ ਸੇਵਰ ਬੰਦ ਕਰੋ"</string>
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਉਹ ਸਭ ਕੁਝ ਕੈਪਚਰ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰ ਦੇਵੇਗਾ, ਜੋ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਤੇ ਡਿਸਪਲੇ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"ਦੁਬਾਰਾ ਨਾ ਦਿਖਾਓ"</string>
- <string name="clear_all_notifications_text" msgid="814192889771462828">"ਸਾਰੇ ਹਟਾਓ"</string>
+ <string name="clear_all_notifications_text" msgid="814192889771462828">"ਸਭ ਸਾਫ਼ ਕਰੋ"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ਹੁਣ ਚਾਲੂ ਕਰੋ"</string>
<string name="empty_shade_text" msgid="708135716272867002">"ਕੋਈ ਸੂਚਨਾਵਾਂ ਨਹੀਂ"</string>
<string name="device_owned_footer" msgid="3802752663326030053">"ਡੀਵਾਈਸ ਦਾ ਨਿਰੀਖਣ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੋਲਯੂਮ ਡਾਇਲੌਗ ਹੈ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ਅਸਲ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ਤੁਸੀਂ ਆਪਣੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਵਰਤ ਰਹੇ ਹੋ"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ਕਾਲ ਕਰੋ"</item>
+ <item msgid="5997713001067658559">"ਸਿਸਟਮ"</item>
+ <item msgid="7858983209929864160">"ਰਿੰਗ ਕਰੋ"</item>
+ <item msgid="1850038478268896762">"ਮੀਡੀਆ"</item>
+ <item msgid="8265110906352372092">"ਅਲਾਰਮ"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ਬਲੂਟੁੱਥ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ਪਹੁੰਚਯੋਗਤਾ"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। ਅਣਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। ਥਰਥਰਾਹਟ ਸੈੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 429fdfb..0bd9179 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -354,6 +354,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Poniżej widać mniej pilne powiadomienia"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Kliknij ponownie, by otworzyć"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Przesuń w górę, by odblokować"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"To urządzenie jest zarządzane"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Tym urządzeniem zarządza <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Aby włączyć telefon, przesuń palcem od ikony"</string>
<string name="voice_hint" msgid="8939888732119726665">"Aby uzyskać pomoc głosową, przesuń palcem od ikony"</string>
<string name="camera_hint" msgid="7939688436797157483">"Przesuń palcem od ikony, by włączyć aparat"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 828d4d9..ab107e8 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Deslize para cima para desbloquear"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este dispositivo é gerenciado"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Este dispositivo é gerenciado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Deslize a partir do ícone do telefone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Deslize a partir do ícone de assistência de voz"</string>
<string name="camera_hint" msgid="7939688436797157483">"Deslize a partir do ícone da câmera"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 60a1cda..ac34f24 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Deslizar rapidamente com o dedo para cima para desbloquear"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este dispositivo é gerido"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Este dispositivo é gerido por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Deslize rapid. a partir do ícone para aceder ao telemóvel"</string>
<string name="voice_hint" msgid="8939888732119726665">"Deslize rapid. a partir do ícone para aceder ao assist. voz"</string>
<string name="camera_hint" msgid="7939688436797157483">"Deslize rapidamente a partir do ícone para aceder à câmara"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 828d4d9..ab107e8 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Deslize para cima para desbloquear"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este dispositivo é gerenciado"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Este dispositivo é gerenciado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Deslize a partir do ícone do telefone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Deslize a partir do ícone de assistência de voz"</string>
<string name="camera_hint" msgid="7939688436797157483">"Deslize a partir do ícone da câmera"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index b418d4a..d18629f 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -354,6 +354,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificările mai puțin urgente mai jos"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Atingeți din nou pentru a deschide"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Glisați în sus pentru a debloca"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Acest dispozitiv este gestionat"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Acest dispozitiv este gestionat de <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Glisați dinspre telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Glisați dinspre pictogramă pentru asistentul vocal"</string>
<string name="camera_hint" msgid="7939688436797157483">"Glisați pentru a fotografia"</string>
@@ -444,7 +446,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> afișează caseta de dialog pentru volum"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Atingeți pentru a restabili versiunea originală."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Acum folosiți profilul de serviciu"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Apel"</item>
+ <item msgid="5997713001067658559">"Sistem"</item>
+ <item msgid="7858983209929864160">"Sonerie"</item>
+ <item msgid="1850038478268896762">"Conținut media"</item>
+ <item msgid="8265110906352372092">"Alarmă"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Accesibilitate"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Atingeți pentru a activa sunetul."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Atingeți pentru a seta vibrarea. Sunetul se poate dezactiva pentru serviciile de accesibilitate."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Atingeți pentru a dezactiva sunetul. Sunetul se poate dezactiva pentru serviciile de accesibilitate."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 05f0d38..bfd75e9 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Показать менее важные оповещения"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Нажмите ещё раз, чтобы открыть"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Проведите вверх, чтобы разблокировать"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Это управляемое устройство"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Этим устройством управляет компания \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string>
<string name="phone_hint" msgid="4872890986869209950">"Телефон: проведите от значка"</string>
<string name="voice_hint" msgid="8939888732119726665">"Аудиоподсказки: проведите от значка"</string>
<string name="camera_hint" msgid="7939688436797157483">"Камера: проведите от значка"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 2db54d0..d31d17b 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -342,14 +342,16 @@
<string name="description_target_search" msgid="3091587249776033139">"සෙවීම"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> සඳහා උඩට සර්පණය කරන්න."</string>
<string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> සඳහා වමට සර්පණය කරන්න."</string>
- <string name="zen_priority_introduction" msgid="3070506961866919502">"එලාම, සිහි කැඳවීම්, සිදුවීම් සහ ඔබ සඳහන් කරන අමතන්නන් වෙතින් හැර, වෙනත් ශබ්ද සහ කම්පනවලින් ඔබට බාධා නොවනු ඇත."</string>
+ <string name="zen_priority_introduction" msgid="3070506961866919502">"එලාම, සිහිකැඳවීම්, සිදුවීම් සහ ඔබ සඳහන් කරන අමතන්නන් වෙතින් හැර, ශබ්ද සහ කම්පනවලින් ඔබට බාධා නොවනු ඇත."</string>
<string name="zen_priority_customize_button" msgid="7948043278226955063">"අභිරුචිකරණය"</string>
- <string name="zen_silence_introduction_voice" msgid="2284540992298200729">"මෙය සීනු, සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු, සියලු ශබ්ද සහ කම්පන අවහිර කරයි. ඔබට තවමත් දුරකථන ඇමතුම් සිදු කිරීමේ හැකියාව ඇත."</string>
- <string name="zen_silence_introduction" msgid="3137882381093271568">"මෙය සීනු, සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු, සියලු ශබ්ද සහ කම්පන අවහිර කරයි."</string>
+ <string name="zen_silence_introduction_voice" msgid="2284540992298200729">"මෙය එලාම්, සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු, සියලු ශබ්ද සහ කම්පන අවහිර කරයි. ඔබට තවමත් දුරකථන ඇමතුම් ගැනීමට හැකියාව ඇත."</string>
+ <string name="zen_silence_introduction" msgid="3137882381093271568">"මෙය එලාම්, සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු, සියලු ශබ්ද සහ කම්පන අවහිර කරයි."</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"හදිසිය අඩු දැනුම් දීම් පහත"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"විවෘත කිරීමට නැවත තට්ටු කරන්න"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"අගුළු ඇරීමට ස්වයිප් කරන්න."</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"මෙම උපාංගය කළමනාකරණය නොකෙරේ"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> මගින් කළමනාකරණය කෙරේ"</string>
<string name="phone_hint" msgid="4872890986869209950">"දුරකථනය සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
<string name="voice_hint" msgid="8939888732119726665">"හඬ සහාය සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
<string name="camera_hint" msgid="7939688436797157483">"කැමරාව සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ධාරිතා සංවාදයයි"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"මුල් තත්ත්වය නැවත ප්රතිසාධනය කිරීමට තට්ටු කරන්න."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ඔබ ඔබේ කාර්යාල පැතිකඩ භාවිත කරමින් සිටී"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ඇමතුම"</item>
+ <item msgid="5997713001067658559">"පද්ධතිය"</item>
+ <item msgid="7858983209929864160">"නාද කරන්න"</item>
+ <item msgid="1850038478268896762">"මාධ්ය"</item>
+ <item msgid="8265110906352372092">"එලාමය"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"බ්ලූටූත්"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ප්රවේශ්යතාව"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. නිහඬ කිරීම ඉවත් කිරීමට තට්ටු කරන්න."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. කම්පනය කිරීමට තට්ටු කරන්න. ප්රවේශ්යතා සේවා නිහඬ කළ හැකිය."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. නිහඬ කිරීමට තට්ටු කරන්න. ප්රවේශ්යතා සේවා නිහඬ කළ හැකිය."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 803be7f..94eb561 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Menej naliehavé upozornenia sa nachádzajú nižšie"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Upozornenie otvoríte opätovným klepnutím"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Odomknete prejdením prstom nahor"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Toto zariadenie je spravované"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Toto zariadenie spravuje organizácia <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefón otvoríte prejdením prstom od ikony"</string>
<string name="voice_hint" msgid="8939888732119726665">"Hlasového asistenta otvoríte prejdením prstom od ikony"</string>
<string name="camera_hint" msgid="7939688436797157483">"Fotoaparát otvoríte prejdením prstom od ikony"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 0f03de9..ffbf4ff 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Manj nujna obvestila spodaj"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Znova se dotaknite, da odprete"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Povlecite, da odklenete"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Ta naprava je upravljana"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"To napravo upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Povlecite z ikone za telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Povlecite z ikone za glasovnega pomočnika"</string>
<string name="camera_hint" msgid="7939688436797157483">"Povlecite z ikone za fotoaparat"</string>
@@ -446,7 +448,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je pogovorno okno glede prostornine"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Dotaknite se, če želite obnoviti prvotno stanje."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Uporabljate delovni profil"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Klic"</item>
+ <item msgid="5997713001067658559">"Sistem"</item>
+ <item msgid="7858983209929864160">"Zvonjenje"</item>
+ <item msgid="1850038478268896762">"Predstavnost"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Funkcije za ljudi s posebnimi potrebami"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Dotaknite se, če želite vklopiti zvok."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Dotaknite se, če želite nastaviti vibriranje. V storitvah za ljudi s posebnimi potrebami bo morda izklopljen zvok."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Dotaknite se, če želite izklopiti zvok. V storitvah za ljudi s posebnimi potrebami bo morda izklopljen zvok."</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index c03c0fe..9b0b832 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Njoftimet më pak urgjente, më poshtë!"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Trokit përsëri për ta hapur"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Rrëshqit për të shkyçur"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Kjo është një pajisje e menaxhuar"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Kjo pajisje menaxhohet nga <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Rrëshqit për të hapur telefonin"</string>
<string name="voice_hint" msgid="8939888732119726665">"Rrëshqit për të hapur ndihmën zanore"</string>
<string name="camera_hint" msgid="7939688436797157483">"Rrëshqit për të hapur kamerën"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> është dialogu i volumit"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Trokit për të restauruar origjinalin."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Po përdor profilin tënd të punës"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Telefono"</item>
+ <item msgid="5997713001067658559">"Sistemi"</item>
+ <item msgid="7858983209929864160">"Bjeri ziles"</item>
+ <item msgid="1850038478268896762">"Media"</item>
+ <item msgid="8265110906352372092">"Alarmi"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Qasshmëria"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Trokit për të aktivizuar."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Trokit për ta caktuar te dridhja. Shërbimet e qasshmërisë mund të çaktivizohen."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Trokit për të çaktivizuar. Shërbimet e qasshmërisë mund të çaktivizohen."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fd560de..bf875e9 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Мање хитна обавештења су у наставку"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Додирните поново да бисте отворили"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Превуците нагоре да бисте откључали"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Овим уређајем се управља"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Овим уређајем управља <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Превуците од иконе за телефон"</string>
<string name="voice_hint" msgid="8939888732119726665">"Превуците од иконе за гласовну помоћ"</string>
<string name="camera_hint" msgid="7939688436797157483">"Превуците од иконе за камеру"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index e0c8472..6c4ee21 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre brådskande aviseringar nedan"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tryck igen för att öppna"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Svep uppåt för att låsa upp"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Den här enheten är hanterad"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Den här enheten hanteras av <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Svep från ikonen och öppna telefonen"</string>
<string name="voice_hint" msgid="8939888732119726665">"Svep från ikonen och öppna röstassistenten"</string>
<string name="camera_hint" msgid="7939688436797157483">"Svep från ikonen och öppna kameran"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 7c89410..e03615a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Arifa zisizo za dharura sana ziko hapo chini"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Gonga tena ili ufungue"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Telezesha kidole ili ufungue"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Kifaa hiki kinadhibitiwa"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Kifaa hiki kinadhibitiwa na <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telezesha kidole kutoka kwa aikoni ili ufikie simu"</string>
<string name="voice_hint" msgid="8939888732119726665">"Telezesha kidole kutoka aikoni ili upate mapendekezo ya sauti"</string>
<string name="camera_hint" msgid="7939688436797157483">"Telezesha kidole kutoka aikoni ili ufikie kamera"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index bd23b43..60f1d6a 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"அவசர நிலைக் குறைவான அறிவிப்புகள் கீழே உள்ளன"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"திறக்க, மீண்டும் தட்டவும்"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"திறக்க, மேலே ஸ்வைப் செய்யவும்"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"இந்தச் சாதனத்தை நிர்வகிப்பது:"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"இந்தச் சாதனத்தை நிர்வகிப்பது: <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"ஃபோனிற்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string>
<string name="voice_hint" msgid="8939888732119726665">"குரல் உதவிக்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string>
<string name="camera_hint" msgid="7939688436797157483">"கேமராவிற்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"ஒலியளவு செய்தி: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"அசலை மீட்டமைக்க, தட்டவும்."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"பணி சுயவிவரத்தைப் பயன்படுத்துகிறீர்கள்"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"அழைப்பு"</item>
+ <item msgid="5997713001067658559">"சாதனம்"</item>
+ <item msgid="7858983209929864160">"ரிங்"</item>
+ <item msgid="1850038478268896762">"மீடியா"</item>
+ <item msgid="8265110906352372092">"அலாரம்"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"புளூடூத்"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"அணுகல்தன்மை"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ஒலி இயக்க, தட்டவும்."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. அதிர்விற்கு அமைக்க, தட்டவும். அணுகல்தன்மை சேவைகள் ஒலியடக்கப்படக்கூடும்."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ஒலியடக்க, தட்டவும். அணுகல்தன்மை சேவைகள் ஒலியடக்கப்படக்கூடும்."</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 6ae1e67..f500fc2 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"తక్కువ అత్యవసర నోటిఫికేషన్లు దిగువన"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"తెరవడానికి మళ్లీ నొక్కండి"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"అన్లాక్ చేయడానికి ఎగువకు స్వైప్ చేయండి"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ఈ పరికరం నిర్వహణలో ఉంది"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> నిర్వహణలో ఉంది"</string>
<string name="phone_hint" msgid="4872890986869209950">"ఫోన్ కోసం చిహ్నాన్ని స్వైప్ చేయండి"</string>
<string name="voice_hint" msgid="8939888732119726665">"వాయిస్ సహాయకం చిహ్నం నుండి స్వైప్"</string>
<string name="camera_hint" msgid="7939688436797157483">"కెమెరా కోసం చిహ్నాన్ని స్వైప్ చేయండి"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"అసలు దాన్ని పునరుద్ధరించడానికి నొక్కండి."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"మీరు మీ కార్యాలయ ప్రొఫైల్ను ఉపయోగిస్తున్నారు"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"కాల్"</item>
+ <item msgid="5997713001067658559">"సిస్టమ్"</item>
+ <item msgid="7858983209929864160">"రింగ్"</item>
+ <item msgid="1850038478268896762">"మీడియా"</item>
+ <item msgid="8265110906352372092">"అలారం"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"బ్లూటూత్"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ప్రాప్యత"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. అన్మ్యూట్ చేయడానికి నొక్కండి."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. వైబ్రేషన్కు సెట్ చేయడానికి నొక్కండి. ప్రాప్యత సేవలు మ్యూట్ చేయబడవచ్చు."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. మ్యూట్ చేయడానికి నొక్కండి. ప్రాప్యత సేవలు మ్యూట్ చేయబడవచ్చు."</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 7e2c00f8..e4d39b7 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"การแจ้งเตือนที่เร่งด่วนน้อยด้านล่าง"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"แตะอีกครั้งเพื่อเปิด"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"เลื่อนเพื่อปลดล็อก"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"อุปกรณ์เครื่องนี้มีการจัดการ"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"อุปกรณ์เครื่องนี้จัดการโดย <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"เลื่อนไอคอนโทรศัพท์"</string>
<string name="voice_hint" msgid="8939888732119726665">"เลื่อนไอคอนตัวช่วยเสียง"</string>
<string name="camera_hint" msgid="7939688436797157483">"เลื่อนไอคอนกล้อง"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> เป็นช่องโต้ตอบระดับเสียง"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"แตะเพื่อคืนค่าเป็นค่าเดิม"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"คุณกำลังใช้โปรไฟล์งานของคุณ"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"โทร"</item>
+ <item msgid="5997713001067658559">"ระบบ"</item>
+ <item msgid="7858983209929864160">"ทำให้ส่งเสียง"</item>
+ <item msgid="1850038478268896762">"สื่อ"</item>
+ <item msgid="8265110906352372092">"การปลุก"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"บลูทูธ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"การเข้าถึง"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s แตะเพื่อเปิดเสียง"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s แตะเพื่อตั้งค่าให้สั่น อาจมีการปิดเสียงบริการการเข้าถึง"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s แตะเพื่อปิดเสียง อาจมีการปิดเสียงบริการการเข้าถึง"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e1e06df..de81f71 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Nasa ibaba ang mga notification na hindi masyadong mahalaga"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"I-tap ulit upang buksan"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"I-swipe pataas upang i-unlock"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Pinamamahalaan ang device na ito"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Pinamamahalaan ng <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ang device na ito"</string>
<string name="phone_hint" msgid="4872890986869209950">"Mag-swipe mula sa icon para sa telepono"</string>
<string name="voice_hint" msgid="8939888732119726665">"Mag-swipe mula sa icon para sa voice assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Mag-swipe mula sa icon para sa camera"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ang volume dialog"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"I-tap upang i-restore ang orihinal."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Ginagamit mo ang iyong profile sa trabaho"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Tawag"</item>
+ <item msgid="5997713001067658559">"System"</item>
+ <item msgid="7858983209929864160">"Ipa-ring"</item>
+ <item msgid="1850038478268896762">"Media"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Pagiging Naa-access"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. I-tap upang i-unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. I-tap upang itakda na mag-vibrate. Maaaring i-mute ang mga serbisyo sa Accessibility."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. I-tap upang i-mute. Maaaring i-mute ang mga serbisyo sa Accessibility."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index d416fdf..c6e4909 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Daha az acil bildirimler aşağıdadır"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Açmak için tekrar dokunun"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Kilidi açmak için hızlıca yukarı kaydırın"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Bu cihaz yönetilen bir cihazdır"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tarafından yönetilmektedir."</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefon için, simgeden hızlıca kaydırın"</string>
<string name="voice_hint" msgid="8939888732119726665">"Sesli yardım için, simgeden hızlıca kaydırın"</string>
<string name="camera_hint" msgid="7939688436797157483">"Kamera için, simgeden hızlıca kaydırın"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ses denetimi iletişim kutusu olarak ayarlandı"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Orijinali geri yüklemek için dokunun."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"İş profilinizi kullanıyorsunuz"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Çağrı"</item>
+ <item msgid="5997713001067658559">"Sistem"</item>
+ <item msgid="7858983209929864160">"Zili Çaldır"</item>
+ <item msgid="1850038478268896762">"Medya"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Erişilebilirlik"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Sesi açmak için hafifçe dokunun."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Titreşime ayarlamak için hafifçe dokunun. Erişilebilirlik hizmetlerinin sesi kapatılabilir."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Sesi kapatmak için hafifçe dokunun. Erişilebilirlik hizmetlerinin sesi kapatılabilir."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 5db65459..21f9e0e 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Менше термінових сповіщень нижче"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Торкніться знову, щоб відкрити"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Проведіть пальцем угору, щоб розблокувати"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Цим пристроєм керує адміністратор"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Цим пристроєм керує організація <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Телефон: проведіть пальцем від значка"</string>
<string name="voice_hint" msgid="8939888732119726665">"Голосові підказки: проведіть пальцем від значка"</string>
<string name="camera_hint" msgid="7939688436797157483">"Камера: проведіть пальцем від значка"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index bc89301..0bf112e 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"کم اہم اطلاعات ذیل میں ہیں"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"کھولنے کیلئے دوبارہ تھپتھپائیں"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"غیر مقفل کرنے کیلئے اوپر سوائپ کریں"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"یہ آلہ زیر انتظام ہے"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"یہ آلہ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> کے زیر انتظام ہے"</string>
<string name="phone_hint" msgid="4872890986869209950">"فون کیلئے آئیکن سے سوائپ کریں"</string>
<string name="voice_hint" msgid="8939888732119726665">"صوتی معاون کیلئے آئیکن سے سوائپ کریں"</string>
<string name="camera_hint" msgid="7939688436797157483">"کیمرہ کیلئے آئیکن سے سوائپ کریں"</string>
@@ -440,10 +442,22 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> والیوم ڈائلاگ ہے"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"اصل بحال کرنے کیلئے تھپتھپائیں۔"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"آپ اپنا دفتری پروفائل استعمال کر رہے ہیں۔"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"کال"</item>
+ <item msgid="5997713001067658559">"سسٹم"</item>
+ <item msgid="7858983209929864160">"رِنگ"</item>
+ <item msgid="1850038478268896762">"میڈیا"</item>
+ <item msgid="8265110906352372092">"الارم"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"بلوٹوتھ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ایکسیسبیلٹی"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s۔ آواز چالو کرنے کیلئے تھپتھپائیں۔"</string>
- <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s۔ ارتعاش پر سیٹ کرنے کیلئے تھپتھپائیں۔ Accessibility سروسز شاید خاموش ہوں۔"</string>
- <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s۔ خاموش کرنے کیلئے تھپتھپائیں۔ Accessibility سروسز شاید خاموش ہوں۔"</string>
+ <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s۔ ارتعاش پر سیٹ کرنے کیلئے تھپتھپائیں۔ ایکسیسبیلٹی سروسز شاید خاموش ہوں۔"</string>
+ <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s۔ خاموش کرنے کیلئے تھپتھپائیں۔ ایکسیسبیلٹی سروسز شاید خاموش ہوں۔"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s والیوم کے کنٹرولز دکھائے جا رہے ہیں۔ برخاست کرنے کیلئے سوائپ کریں۔"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"والیوم کے کنٹرولز مخفی ہیں"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"سسٹم UI ٹیونر"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index a71b539..591b98a 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Kam ahamiyatli bildirishnomalarni pastda ko‘rsatish"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ochish uchun yana bosing"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Qulfdan chiqarish uchun tepaga suring"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Bu – boshqariladigan qurilma"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Bu – <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tomonidan boshqariladigan qurilma"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefonni ochish uchun suring"</string>
<string name="voice_hint" msgid="8939888732119726665">"Ovozli yordam: belgidan boshlab suring"</string>
<string name="camera_hint" msgid="7939688436797157483">"Kamerani ochish uchun suring"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d0d8216..8b6ea67 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Thông báo ít khẩn cấp hơn bên dưới"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Nhấn lại để mở"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Vuốt lên để mở khóa"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Thiết bị này được quản lý"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Thiết bị này được <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> quản lý"</string>
<string name="phone_hint" msgid="4872890986869209950">"Vuốt từ biểu tượng để mở điện thoại"</string>
<string name="voice_hint" msgid="8939888732119726665">"Vuốt từ biểu tượng để mở trợ lý thoại"</string>
<string name="camera_hint" msgid="7939688436797157483">"Vuốt từ biểu tượng để mở máy ảnh"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> là hộp thoại khối lượng"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Nhấn để khôi phục ảnh chụp màn hình gốc."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Bạn đang sử dụng hồ sơ công việc của mình"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Gọi"</item>
+ <item msgid="5997713001067658559">"Hệ thống"</item>
+ <item msgid="7858983209929864160">"Chuông"</item>
+ <item msgid="1850038478268896762">"Phương tiện"</item>
+ <item msgid="8265110906352372092">"Báo thức"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Trợ năng"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Nhấn để bật tiếng."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Nhấn để đặt chế độ rung. Bạn có thể tắt tiếng dịch vụ trợ năng."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Nhấn để tắt tiếng. Bạn có thể tắt tiếng dịch vụ trợ năng."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7928bf9..172c107 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"不太紧急的通知会显示在下方"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次点按即可打开"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上滑动即可解锁"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"此设备已受到托管"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"此设备是由<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>托管"</string>
<string name="phone_hint" msgid="4872890986869209950">"滑动图标即可拨打电话"</string>
<string name="voice_hint" msgid="8939888732119726665">"滑动图标即可打开语音助理"</string>
<string name="camera_hint" msgid="7939688436797157483">"滑动图标即可打开相机"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”已用作音量控制对话框"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"点按即可恢复原始设置。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您当前正在使用工作资料"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"通话"</item>
+ <item msgid="5997713001067658559">"系统"</item>
+ <item msgid="7858983209929864160">"铃声"</item>
+ <item msgid="1850038478268896762">"媒体"</item>
+ <item msgid="8265110906352372092">"闹钟"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"蓝牙"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"无障碍"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。点按即可取消静音。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。点按即可设为振动,但可能会同时将无障碍服务设为静音。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。点按即可设为静音,但可能会同时将无障碍服务设为静音。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index b4ea6f8..afae1ee 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"不太緊急的通知會在下方顯示"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次輕按即可開啟"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上快速滑動即可解鎖"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"此裝置已受管理"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"此裝置由<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>管理"</string>
<string name="phone_hint" msgid="4872890986869209950">"從圖示快速滑動即可使用手機功能"</string>
<string name="voice_hint" msgid="8939888732119726665">"從圖示快速滑動即可使用語音助手"</string>
<string name="camera_hint" msgid="7939688436797157483">"從圖示快速滑動即可使用相機功能"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為音量對話框"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"輕按即可復原。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您正在使用工作設定檔"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"通話"</item>
+ <item msgid="5997713001067658559">"系統"</item>
+ <item msgid="7858983209929864160">"鈴聲"</item>
+ <item msgid="1850038478268896762">"媒體"</item>
+ <item msgid="8265110906352372092">"鬧鐘"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"藍牙"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"無障礙功能"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。輕按即可取消靜音。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。輕按即可設為震動。無障礙功能服務可能已經設為靜音。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。輕按即可設為靜音。無障礙功能服務可能已經設為靜音。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a6a87f6..17946f3 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"較不緊急的通知會顯示在下方"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次輕觸即可開啟"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上滑動即可解鎖"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"這個裝置受到管理"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"這個裝置是由 <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> 所管理"</string>
<string name="phone_hint" msgid="4872890986869209950">"滑動手機圖示即可啟用"</string>
<string name="voice_hint" msgid="8939888732119726665">"滑動語音小幫手圖示即可啟用"</string>
<string name="camera_hint" msgid="7939688436797157483">"滑動相機圖示即可啟用"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」現在是預設的音量控制對話方塊。"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"輕觸即可恢復原始設定。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您正在使用 Work 設定檔"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"通話"</item>
+ <item msgid="5997713001067658559">"系統"</item>
+ <item msgid="7858983209929864160">"鈴聲"</item>
+ <item msgid="1850038478268896762">"媒體"</item>
+ <item msgid="8265110906352372092">"鬧鐘"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"藍牙"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"協助工具"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。輕觸即可取消靜音。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。輕觸即可設為震動,但系統可能會將無障礙服務一併設為靜音。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。輕觸即可設為靜音,但系統可能會將無障礙服務一併設為靜音。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 324d306..9d76dc3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Izaziso ezingasheshi kakhulu ezingezansi"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Thepha futhi ukuze uvule"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swayiphela phezulu ukuze uvule"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Le divayisi iphethwe"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Le divayisi iphethwe yi-<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Swayiphela ifoni kusukela kusithonjana"</string>
<string name="voice_hint" msgid="8939888732119726665">"Swayiphela isilekeleli sezwi kusukela kusithonjana"</string>
<string name="camera_hint" msgid="7939688436797157483">"Swayiphela ikhamela kusukela kusithonjana"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 52565ba..e41991a 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -131,7 +131,6 @@
<color name="light_mode_icon_color_dual_tone_background">#4dffffff</color>
<color name="light_mode_icon_color_dual_tone_fill">#ffffff</color>
- <color name="volume_icon_color">#ffffffff</color>
<color name="volume_settings_icon_color">#7fffffff</color>
<color name="volume_slider_inactive">@*android:color/quaternary_device_default_settings</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a6604cb..a7d4aa0 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -81,6 +81,9 @@
<!-- Height of a heads up notification in the status bar -->
<dimen name="notification_max_heads_up_height">148dp</dimen>
+ <!-- a threshold in dp per second that is considered fast scrolling -->
+ <dimen name="scroll_fast_threshold">1500dp</dimen>
+
<!-- Height of a the shelf with the notification icons -->
<dimen name="notification_shelf_height">32dp</dimen>
@@ -94,6 +97,9 @@
<!-- The amount the content shifts upwards when transforming into the icon -->
<dimen name="notification_icon_transform_content_shift">32dp</dimen>
+ <!-- The padding on the bottom of the notifications on the keyguard -->
+ <dimen name="keyguard_indication_bottom_padding">12sp</dimen>
+
<!-- Minimum layouted height of a notification in the statusbar-->
<dimen name="min_notification_layout_height">48dp</dimen>
@@ -129,9 +135,6 @@
<dimen name="navigation_key_padding">0dp</dimen>
- <dimen name="navigation_key_width_sw600dp_land">162dp</dimen>
- <dimen name="navigation_key_padding_sw600dp_land">42dp</dimen>
-
<!-- The width of the view containing the menu/ime navigation bar icons -->
<dimen name="navigation_extra_key_width">36dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index bfc26e3..c8b3b69d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -840,10 +840,10 @@
<!-- Shows when people have pressed the unlock icon to explain how to unlock. [CHAR LIMIT=60] -->
<string name="keyguard_unlock">Swipe up to unlock</string>
- <!-- Text on keyguard screen indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=60] -->
+ <!-- Text on keyguard screen and in Quick Settings footer indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=60] -->
<string name="do_disclosure_generic">This device is managed</string>
- <!-- Text on keyguard screen indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=40] -->
+ <!-- Text on keyguard screen and in Quick Settings footer indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=40] -->
<string name="do_disclosure_with_name">This device is managed by <xliff:g id="organization_name" example="Foo, Inc.">%s</xliff:g></string>
<!-- Shows when people have clicked on the phone icon [CHAR LIMIT=60] -->
@@ -992,9 +992,6 @@
<!-- Text which is shown in the notification shade when there are no notifications. [CHAR LIMIT=30] -->
<string name="empty_shade_text">No notifications</string>
- <!-- Footer device owned text [CHAR LIMIT=50] -->
- <string name="device_owned_footer">Device may be monitored</string>
-
<!-- Footer profile owned text [CHAR LIMIT=50] -->
<string name="profile_owned_footer">Profile may be monitored</string>
@@ -1019,15 +1016,27 @@
<!-- Monitoring dialog disconnect vpn button [CHAR LIMIT=30] -->
<string name="disconnect_vpn">Disconnect VPN</string>
- <!-- Monitoring dialog device owner body text [CHAR LIMIT=400] -->
- <string name="monitoring_description_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information. For more information, contact your administrator.</string>
+ <!-- Monitoring dialog: Header indicating that the device is managed by a Device Owner app [CHAR LIMIT=80] -->
+ <string name="monitoring_description_do_header_generic">Your device is managed by <xliff:g id="device_owner_app" example="Google Mobile Management">%1$s</xliff:g>.</string>
+
+ <!-- Monitoring dialog: Header indicating that the device is managed by a Device Owner app [CHAR LIMIT=60] -->
+ <string name="monitoring_description_do_header_with_name"><xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> uses <xliff:g id="device_owner_app" example="Google Mobile Management">%2$s</xliff:g> to manage your device.</string>
+
+ <!-- Monitoring dialog: Part of text body explaining what a Device Owner app can do [CHAR LIMIT=130] -->
+ <string name="monitoring_description_do_body">Your administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.</string>
+
+ <!-- Monitoring dialog: Part of text body explaining that a VPN is connected and what it can do, for devices managed by a Device Owner app [CHAR LIMIT=130] -->
+ <string name="monitoring_description_do_body_vpn">You\'re connected to <xliff:g id="vpn_app">%1$s</xliff:g>, which can monitor your network activity, including emails, apps, and websites.</string>
+
+ <!-- Monitoring dialog: Space that separates the body text and the "learn more" link that follows it. [CHAR LIMIT=5] -->
+ <string name="monitoring_description_do_learn_more_separator">" "</string>
+
+ <!-- Monitoring dialog: Link to learn more about what a Device Owner app can do [CHAR LIMIT=55] -->
+ <string name="monitoring_description_do_learn_more">Learn more</string>
<!-- Monitoring dialog VPN text [CHAR LIMIT=400] -->
<string name="monitoring_description_vpn">You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps, and websites.</string>
- <!-- Monitoring dialog VPN with device owner text [CHAR LIMIT=400] -->
- <string name="monitoring_description_vpn_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nYou\'re connected to a VPN, which can monitor your network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string>
-
<!-- Monitoring dialog VPN with profile owner text [CHAR LIMIT=400] -->
<string name="monitoring_description_vpn_profile_owned">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator is capable of monitoring your network activity including emails, apps, and websites.\n\nFor more information, contact your administrator.\n\nYou\'re also connected to a VPN, which can monitor your network activity.</string>
@@ -1049,9 +1058,6 @@
<!-- Monitoring dialog text for multiple apps (in personal and work profiles) [CHAR LIMIT=400] -->
<string name="monitoring_description_app_personal_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application_work">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nYou\'re also connected to <xliff:g id="application_personal">%3$s</xliff:g>, which can monitor your personal network activity.</string>
- <!-- Monitoring dialog text for single app (with device owner) [CHAR LIMIT=400] -->
- <string name="monitoring_description_vpn_app_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nYou\'re connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string>
-
<!-- Indication on the keyguard that appears when the user disables trust agents until the next time they unlock manually. [CHAR LIMIT=NONE] -->
<string name="keyguard_indication_trust_disabled">Device will stay locked until you manually unlock</string>
@@ -1126,6 +1132,7 @@
<item></item> <!-- STREAM_SYSTEM_ENFORCED -->
<item></item> <!-- STREAM_DTMF -->
<item></item> <!-- STREAM_TTS -->
+ <item>Accessibility</item> <!-- STREAM_ACCESSIBILITY -->
</string-array>
<string name="volume_stream_muted" translatable="false">%s silent</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 78fc9f9..0f9e940 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -127,7 +127,7 @@
<style name="TextAppearance.StatusBar.Expanded.Clock">
<item name="android:textSize">@dimen/qs_time_expanded_size</item>
<item name="android:fontFamily">sans-serif-medium</item>
- <item name="android:textColor">#ffffff</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="TextAppearance.StatusBar.Expanded.Date">
@@ -159,7 +159,7 @@
<style name="TextAppearance.QS">
<item name="android:textStyle">normal</item>
- <item name="android:textColor">@color/qs_text</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:fontFamily">sans-serif</item>
</style>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index e036128..10328a4 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -30,6 +30,7 @@
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -96,9 +97,10 @@
dismissCallbackRegistry);
}
- public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
- View headsUpScrim, LockscreenWallpaper lockscreenWallpaper) {
- return new ScrimController(scrimBehind, scrimInFront, headsUpScrim);
+ public ScrimController createScrimController(LightBarController lightBarController,
+ ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
+ LockscreenWallpaper lockscreenWallpaper) {
+ return new ScrimController(lightBarController, scrimBehind, scrimInFront, headsUpScrim);
}
public VolumeDialogController createVolumeDialogController(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 951b27f..13e047c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -56,7 +56,41 @@
/** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */
DOZE_PULSE_DONE,
/** Doze is done. DozeService is finished. */
- FINISH,
+ FINISH;
+
+ boolean canPulse() {
+ switch (this) {
+ case DOZE:
+ case DOZE_AOD:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ boolean staysAwake() {
+ switch (this) {
+ case DOZE_REQUEST_PULSE:
+ case DOZE_PULSING:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ int screenState() {
+ switch (this) {
+ case UNINITIALIZED:
+ case INITIALIZED:
+ case DOZE:
+ return Display.STATE_OFF;
+ case DOZE_PULSING:
+ case DOZE_AOD:
+ return Display.STATE_DOZE; // TODO: use STATE_ON if appropriate.
+ default:
+ return Display.STATE_UNKNOWN;
+ }
+ }
}
private final Service mDozeService;
@@ -165,52 +199,32 @@
}
private void validateTransition(State newState) {
- switch (mState) {
- case FINISH:
- Preconditions.checkState(newState == State.FINISH);
- break;
- case UNINITIALIZED:
- Preconditions.checkState(newState == State.INITIALIZED);
- break;
- }
- switch (newState) {
- case UNINITIALIZED:
- throw new IllegalArgumentException("can't go to UNINITIALIZED");
- case INITIALIZED:
- Preconditions.checkState(mState == State.UNINITIALIZED);
- break;
- case DOZE_PULSING:
- Preconditions.checkState(mState == State.DOZE_REQUEST_PULSE);
- break;
- case DOZE_PULSE_DONE:
- Preconditions.checkState(mState == State.DOZE_PULSING);
- break;
- default:
- break;
- }
- }
-
- private int screenPolicy(State newState) {
- switch (newState) {
- case UNINITIALIZED:
- case INITIALIZED:
- case DOZE:
- return Display.STATE_OFF;
- case DOZE_PULSING:
- case DOZE_AOD:
- return Display.STATE_DOZE; // TODO: use STATE_ON if appropriate.
- default:
- return Display.STATE_UNKNOWN;
- }
- }
-
- private boolean wakeLockPolicy(State newState) {
- switch (newState) {
- case DOZE_REQUEST_PULSE:
- case DOZE_PULSING:
- return true;
- default:
- return false;
+ try {
+ switch (mState) {
+ case FINISH:
+ Preconditions.checkState(newState == State.FINISH);
+ break;
+ case UNINITIALIZED:
+ Preconditions.checkState(newState == State.INITIALIZED);
+ break;
+ }
+ switch (newState) {
+ case UNINITIALIZED:
+ throw new IllegalArgumentException("can't transition to UNINITIALIZED");
+ case INITIALIZED:
+ Preconditions.checkState(mState == State.UNINITIALIZED);
+ break;
+ case DOZE_PULSING:
+ Preconditions.checkState(mState == State.DOZE_REQUEST_PULSE);
+ break;
+ case DOZE_PULSE_DONE:
+ Preconditions.checkState(mState == State.DOZE_PULSING);
+ break;
+ default:
+ break;
+ }
+ } catch (RuntimeException e) {
+ throw new IllegalStateException("Illegal Transition: " + mState + " -> " + newState, e);
}
}
@@ -218,22 +232,26 @@
if (mState == State.FINISH) {
return State.FINISH;
}
+ if (requestedState == State.DOZE_REQUEST_PULSE && !mState.canPulse()) {
+ Log.i(TAG, "Dropping pulse request because current state can't pulse: " + mState);
+ return mState;
+ }
return requestedState;
}
private void updateWakeLockState(State newState) {
- boolean newPolicy = wakeLockPolicy(newState);
- if (mWakeLockHeldForCurrentState && !newPolicy) {
+ boolean staysAwake = newState.staysAwake();
+ if (mWakeLockHeldForCurrentState && !staysAwake) {
mWakeLock.release();
mWakeLockHeldForCurrentState = false;
- } else if (!mWakeLockHeldForCurrentState && newPolicy) {
+ } else if (!mWakeLockHeldForCurrentState && staysAwake) {
mWakeLock.acquire();
mWakeLockHeldForCurrentState = true;
}
}
private void updateScreenState(State newState) {
- int state = screenPolicy(newState);
+ int state = newState.screenState();
if (state != Display.STATE_UNKNOWN) {
mDozeService.setDozeScreenState(state);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 07e1193..c19e806 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1798,7 +1798,6 @@
// (like recents). Temporary enable/disable (e.g. the "back" button) are
// done in KeyguardHostView.
flags |= StatusBarManager.DISABLE_RECENT;
- flags |= StatusBarManager.DISABLE_SEARCH;
}
if (isShowingAndNotOccluded()) {
flags |= StatusBarManager.DISABLE_HOME;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index c6dde46..09671e7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -156,6 +156,10 @@
@Override
public void onListenerRegistered(IPinnedStackController controller) {
mPinnedStackController = controller;
+
+ // Update the controller with the current tuner state
+ setMinimizedState(mIsMinimized);
+ setSnapToEdge(mEnableSnapToEdge);
}
@Override
@@ -353,10 +357,13 @@
*/
private void setSnapToEdge(boolean snapToEdge) {
mSnapAlgorithm.setSnapToEdge(snapToEdge);
- try {
- mPinnedStackController.setSnapToEdge(snapToEdge);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not set snap mode to edge", e);
+
+ if (mPinnedStackController != null) {
+ try {
+ mPinnedStackController.setSnapToEdge(snapToEdge);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not set snap mode to edge", e);
+ }
}
}
@@ -365,10 +372,13 @@
*/
private void setMinimizedState(boolean isMinimized) {
mIsMinimized = isMinimized;
- try {
- mPinnedStackController.setIsMinimized(isMinimized);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not set minimized state", e);
+
+ if (mPinnedStackController != null) {
+ try {
+ mPinnedStackController.setIsMinimized(isMinimized);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not set minimized state", e);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index ccb28e9..f3da47b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -24,10 +24,15 @@
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.SpannableStringBuilder;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
@@ -46,19 +51,23 @@
private final View mRootView;
private final TextView mFooterText;
private final ImageView mFooterIcon;
+ private final ImageView mFooterIcon2;
private final Context mContext;
private final Callback mCallback = new Callback();
private SecurityController mSecurityController;
private AlertDialog mDialog;
private QSTileHost mHost;
- private Handler mHandler;
+ protected Handler mHandler;
private final Handler mMainHandler;
private boolean mIsVisible;
private boolean mIsIconVisible;
+ private boolean mIsIcon2Visible;
+ private CharSequence mFooterTextContent = null;
private int mFooterTextId;
private int mFooterIconId;
+ private int mFooterIcon2Id;
public QSFooter(QSPanel qsPanel, Context context) {
mRootView = LayoutInflater.from(context)
@@ -66,15 +75,18 @@
mRootView.setOnClickListener(this);
mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
+ mFooterIcon2 = (ImageView) mRootView.findViewById(R.id.footer_icon2);
mFooterIconId = R.drawable.ic_qs_vpn;
+ mFooterIcon2Id = R.drawable.ic_qs_network_logging;
mContext = context;
- mMainHandler = new Handler();
+ mMainHandler = new Handler(Looper.getMainLooper());
}
- public void setHost(QSTileHost host) {
+ public void setHostEnvironment(QSTileHost host, SecurityController securityController,
+ Looper looper) {
mHost = host;
- mSecurityController = host.getSecurityController();
- mHandler = new H(host.getLooper());
+ mSecurityController = securityController;
+ mHandler = new H(looper);
}
public void setListening(boolean listening) {
@@ -113,17 +125,36 @@
}
private void handleRefreshState() {
- mIsIconVisible = mSecurityController.isVpnEnabled();
- // If the device has device owner, show "Device may be monitored", but --
- // TODO See b/25779452 -- device owner doesn't actually have monitoring power.
+ boolean isVpnEnabled = mSecurityController.isVpnEnabled();
+ boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
+ mIsIconVisible = isVpnEnabled || isNetworkLoggingEnabled;
+ mIsIcon2Visible = isVpnEnabled && isNetworkLoggingEnabled;
if (mSecurityController.isDeviceManaged()) {
- mFooterTextId = R.string.device_owned_footer;
+ final CharSequence organizationName =
+ mSecurityController.getDeviceOwnerOrganizationName();
+ if (organizationName != null) {
+ mFooterTextContent = mContext.getResources().getString(
+ R.string.do_disclosure_with_name, organizationName);
+ } else {
+ mFooterTextContent =
+ mContext.getResources().getString(R.string.do_disclosure_generic);
+ }
mIsVisible = true;
+ int footerIconId = isVpnEnabled
+ ? R.drawable.ic_qs_vpn
+ : R.drawable.ic_qs_network_logging;
+ if (mFooterIconId != footerIconId) {
+ mFooterIconId = footerIconId;
+ mMainHandler.post(mUpdateIcon);
+ }
} else {
boolean isBranded = mSecurityController.isVpnBranded();
- mFooterTextId = isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer;
+ mFooterTextContent = mContext.getResources().getText(
+ isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer);
// Update the VPN footer icon, if needed.
- int footerIconId = isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn;
+ int footerIconId = isVpnEnabled
+ ? (isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn)
+ : R.drawable.ic_qs_network_logging;
if (mFooterIconId != footerIconId) {
mFooterIconId = footerIconId;
mMainHandler.post(mUpdateIcon);
@@ -142,23 +173,36 @@
}
private void createDialog() {
- String deviceOwner = mSecurityController.getDeviceOwnerName();
- String profileOwner = mSecurityController.getProfileOwnerName();
- String primaryVpn = mSecurityController.getPrimaryVpnName();
- String profileVpn = mSecurityController.getProfileVpnName();
- boolean managed = mSecurityController.hasProfileOwner();
- boolean isBranded = deviceOwner == null && mSecurityController.isVpnBranded();
+ final String deviceOwnerPackage = mSecurityController.getDeviceOwnerName();
+ final String profileOwnerPackage = mSecurityController.getProfileOwnerName();
+ final String primaryVpn = mSecurityController.getPrimaryVpnName();
+ final String profileVpn = mSecurityController.getProfileVpnName();
+ final CharSequence deviceOwnerOrganization =
+ mSecurityController.getDeviceOwnerOrganizationName();
+ boolean hasProfileOwner = mSecurityController.hasProfileOwner();
+ boolean isBranded = deviceOwnerPackage == null && mSecurityController.isVpnBranded();
mDialog = new SystemUIDialog(mContext);
if (!isBranded) {
- mDialog.setTitle(getTitle(deviceOwner));
+ mDialog.setTitle(getTitle(deviceOwnerPackage));
}
- mDialog.setMessage(getMessage(deviceOwner, profileOwner, primaryVpn, profileVpn, managed,
- isBranded));
+ mDialog.setMessage(getMessage(deviceOwnerPackage, profileOwnerPackage, primaryVpn,
+ profileVpn, deviceOwnerOrganization, hasProfileOwner, isBranded));
+
mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this);
if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) {
mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getSettingsButton(), this);
}
+
+ // Make the link "learn more" clickable.
+ // TODO: Reaching into SystemUIDialog's internal View hierarchy is ugly and error-prone.
+ // This is a temporary solution. b/33126622 will introduce a custom View hierarchy for this
+ // dialog, allowing us to set the movement method on the appropriate View without any
+ // knowledge of SystemUIDialog's internals.
+ mDialog.create();
+ ((TextView) mDialog.getWindow().findViewById(com.android.internal.R.id.message))
+ .setMovementMethod(new LinkMovementMethod());
+
mDialog.show();
}
@@ -170,22 +214,35 @@
return mContext.getString(isBranded ? android.R.string.ok : R.string.quick_settings_done);
}
- private String getMessage(String deviceOwner, String profileOwner, String primaryVpn,
- String profileVpn, boolean primaryUserIsManaged, boolean isBranded) {
- // Show a special warning when the device has device owner, but --
- // TODO See b/25779452 -- device owner doesn't actually have monitoring power.
- if (deviceOwner != null) {
- if (primaryVpn != null) {
- return mContext.getString(R.string.monitoring_description_vpn_app_device_owned,
- deviceOwner, primaryVpn);
+ protected CharSequence getMessage(String deviceOwnerPackage, String profileOwnerPackage,
+ String primaryVpn, String profileVpn, CharSequence deviceOwnerOrganization,
+ boolean hasProfileOwner, boolean isBranded) {
+ if (deviceOwnerPackage != null) {
+ final SpannableStringBuilder message = new SpannableStringBuilder();
+ if (deviceOwnerOrganization != null) {
+ message.append(mContext.getString(
+ R.string.monitoring_description_do_header_with_name,
+ deviceOwnerOrganization, deviceOwnerPackage));
} else {
- return mContext.getString(R.string.monitoring_description_device_owned,
- deviceOwner);
+ message.append(mContext.getString(R.string.monitoring_description_do_header_generic,
+ deviceOwnerPackage));
}
+ message.append("\n\n");
+ message.append(mContext.getString(R.string.monitoring_description_do_body));
+ if (primaryVpn != null) {
+ message.append("\n\n");
+ message.append(mContext.getString(R.string.monitoring_description_do_body_vpn,
+ primaryVpn));
+ }
+ message.append(mContext.getString(
+ R.string.monitoring_description_do_learn_more_separator));
+ message.append(mContext.getString(R.string.monitoring_description_do_learn_more),
+ new EnterprisePrivacySpan(), 0);
+ return message;
} else if (primaryVpn != null) {
if (profileVpn != null) {
return mContext.getString(R.string.monitoring_description_app_personal_work,
- profileOwner, profileVpn, primaryVpn);
+ profileOwnerPackage, profileVpn, primaryVpn);
} else {
if (isBranded) {
return mContext.getString(R.string.branded_monitoring_description_app_personal,
@@ -197,10 +254,10 @@
}
} else if (profileVpn != null) {
return mContext.getString(R.string.monitoring_description_app_work,
- profileOwner, profileVpn);
- } else if (profileOwner != null && primaryUserIsManaged) {
+ profileOwnerPackage, profileVpn);
+ } else if (profileOwnerPackage != null && hasProfileOwner) {
return mContext.getString(R.string.monitoring_description_device_owned,
- profileOwner);
+ profileOwnerPackage);
} else {
// No device owner, no personal VPN, no work VPN, no user owner. Why are we here?
return null;
@@ -219,17 +276,19 @@
@Override
public void run() {
mFooterIcon.setImageResource(mFooterIconId);
+ mFooterIcon2.setImageResource(mFooterIcon2Id);
}
};
private final Runnable mUpdateDisplayState = new Runnable() {
@Override
public void run() {
- if (mFooterTextId != 0) {
- mFooterText.setText(mFooterTextId);
+ if (mFooterTextContent != null) {
+ mFooterText.setText(mFooterTextContent);
}
mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE);
+ mFooterIcon2.setVisibility(mIsIcon2Visible ? View.VISIBLE : View.INVISIBLE);
}
};
@@ -267,4 +326,18 @@
}
}
+ protected class EnterprisePrivacySpan extends ClickableSpan {
+ @Override
+ public void onClick(View widget) {
+ final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mDialog.dismiss();
+ mContext.startActivity(intent);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ return object instanceof EnterprisePrivacySpan;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index e55ff70..d8855c8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -179,7 +179,7 @@
mHost = host;
mHost.addCallback(this);
setTiles(mHost.getTiles());
- mFooter.setHost(host);
+ mFooter.setHostEnvironment(host, host.getSecurityController(), host.getLooper());
mCustomizePanel = customizer;
if (mCustomizePanel != null) {
mCustomizePanel.setHost(mHost);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 7655e6c..790f3f6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -438,9 +438,9 @@
SystemServicesProxy ssp = Recents.getSystemServices();
ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
boolean screenPinningActive = ssp.isScreenPinningActive();
- boolean isRunningTaskInHomeStack = runningTask != null &&
- SystemServicesProxy.isHomeStack(runningTask.stackId);
- if (runningTask != null && !isRunningTaskInHomeStack && !screenPinningActive) {
+ boolean isRunningTaskInHomeOrRecentsStack = runningTask != null &&
+ ActivityManager.StackId.isHomeOrRecentsStack(runningTask.stackId);
+ if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) {
logDockAttempt(mContext, runningTask.topActivity, runningTask.resizeMode);
if (runningTask.isDockable) {
if (metricsDockAction != -1) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index af1823c..d5a6a58 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -399,7 +399,7 @@
RecentsActivityLaunchState launchState = config.getLaunchState();
if (!loadPlan.hasTasks()) {
loader.preloadTasks(loadPlan, launchState.launchedToTaskId,
- !launchState.launchedFromHome);
+ !launchState.launchedFromHome && !launchState.launchedViaDockGesture);
}
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
@@ -526,12 +526,14 @@
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
- // Workaround for b/22542869, if the RecentsActivity is started again, but without going
- // through SystemUI, we need to reset the config launch flags to ensure that we do not
- // wait on the system to send a signal that was never queued.
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- launchState.reset();
+ if (!isChangingConfigurations()) {
+ // Workaround for b/22542869, if the RecentsActivity is started again, but without going
+ // through SystemUI, we need to reset the config launch flags to ensure that we do not
+ // wait on the system to send a signal that was never queued.
+ RecentsConfiguration config = Recents.getConfiguration();
+ RecentsActivityLaunchState launchState = config.getLaunchState();
+ launchState.reset();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index abde44e..c9c4f2b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -18,6 +18,8 @@
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+import static android.app.ActivityManager.StackId.isHomeOrRecentsStack;
import static android.view.View.MeasureSpec;
import android.app.ActivityManager;
@@ -460,8 +462,8 @@
// Return early if there is no running task (can't determine affiliated tasks in this case)
ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
if (runningTask == null) return;
- // Return early if the running task is in the home stack (optimization)
- if (SystemServicesProxy.isHomeStack(runningTask.stackId)) return;
+ // Return early if the running task is in the home/recents stack (optimization)
+ if (isHomeOrRecentsStack(runningTask.stackId)) return;
// Find the task in the recents list
ArrayList<Task> tasks = focusedStack.getStackTasks();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 2272a72..ea50d89 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -321,7 +321,7 @@
// Remove home/recents/excluded tasks
int minNumTasksToQuery = 10;
int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
- int flags = ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
+ int flags = ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS |
ActivityManager.RECENT_INGORE_DOCKED_STACK_TOP_TASK |
ActivityManager.RECENT_INGORE_PINNED_STACK_TASKS |
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
@@ -399,21 +399,23 @@
if (mIam == null) return false;
try {
- ActivityManager.StackInfo stackInfo = mIam.getStackInfo(
+ ActivityManager.StackInfo homeStackInfo = mIam.getStackInfo(
ActivityManager.StackId.HOME_STACK_ID);
ActivityManager.StackInfo fullscreenStackInfo = mIam.getStackInfo(
ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID);
- ComponentName topActivity = stackInfo.topActivity;
- boolean homeStackVisibleNotOccluded = stackInfo.visible;
- if (fullscreenStackInfo != null) {
- boolean isFullscreenStackOccludingHome = fullscreenStackInfo.visible &&
- fullscreenStackInfo.position > stackInfo.position;
- homeStackVisibleNotOccluded &= !isFullscreenStackOccludingHome;
- }
+ ActivityManager.StackInfo recentsStackInfo = mIam.getStackInfo(
+ ActivityManager.StackId.RECENTS_STACK_ID);
+
+ boolean homeStackVisibleNotOccluded = isStackNotOccluded(homeStackInfo,
+ fullscreenStackInfo);
+ boolean recentsStackVisibleNotOccluded = isStackNotOccluded(recentsStackInfo,
+ fullscreenStackInfo);
if (isHomeStackVisible != null) {
isHomeStackVisible.value = homeStackVisibleNotOccluded;
}
- return (homeStackVisibleNotOccluded && topActivity != null
+ ComponentName topActivity = recentsStackInfo != null ?
+ recentsStackInfo.topActivity : null;
+ return (recentsStackVisibleNotOccluded && topActivity != null
&& topActivity.getPackageName().equals(RecentsImpl.RECENTS_PACKAGE)
&& Recents.RECENTS_ACTIVITIES.contains(topActivity.getClassName()));
} catch (RemoteException e) {
@@ -422,6 +424,17 @@
return false;
}
+ private boolean isStackNotOccluded(ActivityManager.StackInfo stackInfo,
+ ActivityManager.StackInfo fullscreenStackInfo) {
+ boolean stackVisibleNotOccluded = stackInfo == null || stackInfo.visible;
+ if (fullscreenStackInfo != null && stackInfo != null) {
+ boolean isFullscreenStackOccludingg = fullscreenStackInfo.visible &&
+ fullscreenStackInfo.position > stackInfo.position;
+ stackVisibleNotOccluded &= !isFullscreenStackOccludingg;
+ }
+ return stackVisibleNotOccluded;
+ }
+
/**
* Returns whether this device has freeform workspaces.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index d46d267..cf8d332 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -103,7 +103,7 @@
private boolean mDimmed;
private boolean mDark;
- private int mBgTint = 0;
+ private int mBgTint = NO_COLOR;
private float mBgAlpha = 1f;
/**
@@ -507,8 +507,10 @@
* Sets the tint color of the background
*/
public void setTintColor(int color, boolean animated) {
- mBgTint = color;
- updateBackgroundTint(animated);
+ if (color != mBgTint) {
+ mBgTint = color;
+ updateBackgroundTint(animated);
+ }
}
/**
@@ -567,13 +569,15 @@
}
private void setBackgroundTintColor(int color) {
- mCurrentBackgroundTint = color;
- if (color == mNormalColor) {
- // We don't need to tint a normal notification
- color = 0;
+ if (color != mCurrentBackgroundTint) {
+ mCurrentBackgroundTint = color;
+ if (color == mNormalColor) {
+ // We don't need to tint a normal notification
+ color = 0;
+ }
+ mBackgroundDimmed.setTint(color);
+ mBackgroundNormal.setTint(color);
}
- mBackgroundDimmed.setTint(color);
- mBackgroundNormal.setTint(color);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 661cc3c..e89fe55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -193,7 +193,7 @@
private View mChildAfterViewWhenDismissed;
private View mGroupParentWhenDismissed;
private boolean mRefocusOnDismiss;
- private float mIconTransformationAmount;
+ private float mContentTransformationAmount;
private boolean mIconsVisible = true;
private boolean mAboveShelf;
private boolean mIsLastChild;
@@ -837,23 +837,29 @@
/**
* Set how much this notification is transformed into an icon.
*
- * @param iconTransformationAmount A value from 0 to 1 indicating how much we are transformed
- * to an icon
+ * @param contentTransformationAmount A value from 0 to 1 indicating how much we are transformed
+ * to the content away
* @param isLastChild is this the last child in the list. If true, then the transformation is
* different since it's content fades out.
*/
- public void setIconTransformationAmount(float iconTransformationAmount, boolean isLastChild) {
+ public void setContentTransformationAmount(float contentTransformationAmount,
+ boolean isLastChild) {
boolean changeTransformation = isLastChild != mIsLastChild;
- changeTransformation |= mIconTransformationAmount != iconTransformationAmount;
+ changeTransformation |= mContentTransformationAmount != contentTransformationAmount;
mIsLastChild = isLastChild;
- mIconTransformationAmount = iconTransformationAmount;
+ mContentTransformationAmount = contentTransformationAmount;
if (changeTransformation) {
updateContentTransformation();
- boolean iconsVisible = mIconTransformationAmount == 0.0f;
- if (iconsVisible != mIconsVisible) {
- mIconsVisible = iconsVisible;
- updateIconVisibilities();
- }
+ }
+ }
+
+ /**
+ * Set the icons to be visible of this notification.
+ */
+ public void setIconsVisible(boolean iconsVisible) {
+ if (iconsVisible != mIconsVisible) {
+ mIconsVisible = iconsVisible;
+ updateIconVisibilities();
}
}
@@ -864,9 +870,9 @@
private void updateContentTransformation() {
float contentAlpha;
- float translationY = - mIconTransformationAmount * mIconTransformContentShift;
+ float translationY = -mContentTransformationAmount * mIconTransformContentShift;
if (mIsLastChild) {
- contentAlpha = 1.0f - mIconTransformationAmount;
+ contentAlpha = 1.0f - mContentTransformationAmount;
contentAlpha = Math.min(contentAlpha / 0.5f, 1.0f);
contentAlpha = Interpolators.ALPHA_OUT.getInterpolation(contentAlpha);
translationY *= 0.4f;
@@ -885,7 +891,9 @@
}
private void updateIconVisibilities() {
- boolean visible = isChildInGroup() || isBelowSpeedBump() || mIconsVisible;
+ boolean visible = isChildInGroup()
+ || (isBelowSpeedBump() && !NotificationShelf.SHOW_AMBIENT_ICONS)
+ || mIconsVisible;
mPublicLayout.setIconsVisible(visible);
mPrivateLayout.setIconsVisible(visible);
if (mChildrenContainer != null) {
@@ -1679,13 +1687,17 @@
@Override
public void setClipBottomAmount(int clipBottomAmount) {
- super.setClipBottomAmount(clipBottomAmount);
- mPrivateLayout.setClipBottomAmount(clipBottomAmount);
- mPublicLayout.setClipBottomAmount(clipBottomAmount);
- if (mGuts != null) {
- mGuts.setClipBottomAmount(clipBottomAmount);
+ if (clipBottomAmount != mClipBottomAmount) {
+ super.setClipBottomAmount(clipBottomAmount);
+ mPrivateLayout.setClipBottomAmount(clipBottomAmount);
+ mPublicLayout.setClipBottomAmount(clipBottomAmount);
+ if (mGuts != null) {
+ mGuts.setClipBottomAmount(clipBottomAmount);
+ }
}
if (mChildrenContainer != null) {
+ // We have to update this even if it hasn't changed, since the children locations can
+ // have changed
mChildrenContainer.setClipBottomAmount(clipBottomAmount);
}
}
@@ -1871,8 +1883,8 @@
}
@Override
- protected void onYTranslationAnimationFinished() {
- super.onYTranslationAnimationFinished();
+ protected void onYTranslationAnimationFinished(View view) {
+ super.onYTranslationAnimationFinished(view);
if (mHeadsupDisappearRunning) {
setHeadsUpAnimatingAway(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 3687f6d..a6e730d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -208,6 +208,13 @@
expandedIcon = null;
throw new IconException("Couldn't create icon: " + ic);
}
+ expandedIcon.setVisibility(View.INVISIBLE);
+ expandedIcon.setOnVisibilityChangedListener(
+ newVisibility -> {
+ if (row != null) {
+ row.setIconsVisible(newVisibility != View.VISIBLE);
+ }
+ });
}
public void setIconTag(int key, Object tag) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 680562a..e054bbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.res.Configuration;
+import android.os.SystemProperties;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
@@ -33,9 +34,7 @@
import com.android.systemui.statusbar.stack.ExpandableViewState;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackScrollState;
-
-import java.util.ArrayList;
-import java.util.WeakHashMap;
+import com.android.systemui.statusbar.stack.ViewState;
/**
* A notification shelf view that is placed inside the notification scroller. It manages the
@@ -43,10 +42,12 @@
*/
public class NotificationShelf extends ActivatableNotificationView {
+ public static final boolean SHOW_AMBIENT_ICONS = true;
+ private static final boolean USE_ANIMATIONS_WHEN_OPENING =
+ SystemProperties.getBoolean("debug.icon_opening_animations", true);
private ViewInvertHelper mViewInvertHelper;
private boolean mDark;
private NotificationIconContainer mShelfIcons;
- private ArrayList<StatusBarIconView> mIcons = new ArrayList<>();
private ShelfState mShelfState;
private int[] mTmp = new int[2];
private boolean mHideBackground;
@@ -60,6 +61,7 @@
private int mNotGoneIndex;
private boolean mHasItemsInStableShelf;
private NotificationIconContainer mCollapsedIcons;
+ private int mScrollFastThreshold;
public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -101,6 +103,8 @@
setLayoutParams(layoutParams);
int padding = getResources().getDimensionPixelOffset(R.dimen.shelf_icon_container_padding);
mShelfIcons.setPadding(padding, 0, padding, 0);
+ mScrollFastThreshold = getResources().getDimensionPixelOffset(
+ R.dimen.scroll_fast_threshold);
}
@Override
@@ -162,6 +166,7 @@
mShelfState.notGoneIndex = Math.min(mShelfState.notGoneIndex, mNotGoneIndex);
}
mShelfState.hasItemsInStableShelf = lastViewState.inShelf;
+ mShelfState.hidden = !mAmbientState.isShadeExpanded();
} else {
mShelfState.hidden = true;
mShelfState.location = ExpandableViewState.LOCATION_GONE;
@@ -174,15 +179,15 @@
* the icons from the notification area into the shelf.
*/
public void updateAppearance() {
- WeakHashMap<View, NotificationIconContainer.IconState> iconStates =
- mShelfIcons.resetViewStates();
+ mShelfIcons.resetViewStates();
+ float shelfStart = getTranslationY();
float numViewsInShelf = 0.0f;
View lastChild = mAmbientState.getLastVisibleBackgroundChild();
mNotGoneIndex = -1;
float interpolationStart = mMaxLayoutHeight - getIntrinsicHeight() * 2;
float expandAmount = 0.0f;
- if (getTranslationY() >= interpolationStart) {
- expandAmount = (getTranslationY() - interpolationStart) / getIntrinsicHeight();
+ if (shelfStart >= interpolationStart) {
+ expandAmount = (shelfStart - interpolationStart) / getIntrinsicHeight();
expandAmount = Math.min(1.0f, expandAmount);
}
// find the first view that doesn't overlap with the shelf
@@ -196,6 +201,12 @@
int colorTwoBefore = NO_COLOR;
int previousColor = NO_COLOR;
float transitionAmount = 0.0f;
+ boolean scrollingFast = mAmbientState.getCurrentScrollVelocity() > mScrollFastThreshold
+ || (mAmbientState.isExpansionChanging()
+ && Math.abs(mAmbientState.getExpandingVelocity()) > mScrollFastThreshold);
+ boolean expandingAnimated = mAmbientState.isExpansionChanging()
+ && !mAmbientState.isPanelTracking();
+ int baseZHeight = mAmbientState.getBaseZHeight();
while (notificationIndex < mHostLayout.getChildCount()) {
ExpandableView child = (ExpandableView) mHostLayout.getChildAt(notificationIndex);
notificationIndex++;
@@ -204,30 +215,28 @@
continue;
}
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- StatusBarIconView icon = row.getEntry().expandedIcon;
- NotificationIconContainer.IconState iconState = iconStates.get(icon);
float notificationClipEnd;
- float shelfStart = getTranslationY();
- boolean aboveShelf = row.getTranslationZ() > mAmbientState.getBaseZHeight();
+ boolean aboveShelf = row.getTranslationZ() > baseZHeight;
boolean isLastChild = child == lastChild;
+ float rowTranslationY = row.getTranslationY();
if (isLastChild || aboveShelf || backgroundForceHidden) {
notificationClipEnd = shelfStart + getIntrinsicHeight();
} else {
notificationClipEnd = shelfStart - mPaddingBetweenElements;
- float height = notificationClipEnd - row.getTranslationY();
+ float height = notificationClipEnd - rowTranslationY;
if (!row.isBelowSpeedBump() && height <= getNotificationMergeSize()) {
// We want the gap to close when we reached the minimum size and only shrink
// before
notificationClipEnd = Math.min(shelfStart,
- row.getTranslationY() + getNotificationMergeSize());
+ rowTranslationY + getNotificationMergeSize());
}
}
updateNotificationClipHeight(row, notificationClipEnd);
- float inShelfAmount = updateIconAppearance(row, iconState, icon, expandAmount,
- isLastChild);
+ float inShelfAmount = updateIconAppearance(row, expandAmount, scrollingFast,
+ expandingAnimated, isLastChild);
numViewsInShelf += inShelfAmount;
int ownColorUntinted = row.getBackgroundColorWithoutTint();
- if (row.getTranslationY() >= getTranslationY() && mNotGoneIndex == -1) {
+ if (rowTranslationY >= shelfStart && mNotGoneIndex == -1) {
mNotGoneIndex = notGoneIndex;
setTintColor(previousColor);
setOverrideTintColor(colorTwoBefore, transitionAmount);
@@ -248,11 +257,9 @@
notGoneIndex++;
previousColor = ownColorUntinted;
}
+ mShelfIcons.setSpeedBumpIndex(mAmbientState.getSpeedBumpIndex());
mShelfIcons.calculateIconTranslations();
mShelfIcons.applyIconStates();
- setVisibility(numViewsInShelf != 0.0f && mAmbientState.isShadeExpanded()
- ? VISIBLE
- : INVISIBLE);
boolean hideBackground = numViewsInShelf < 1.0f;
setHideBackground(hideBackground || backgroundForceHidden);
if (mNotGoneIndex == -1) {
@@ -275,41 +282,116 @@
/**
* @return the icon amount how much this notification is in the shelf;
*/
- private float updateIconAppearance(ExpandableNotificationRow row,
- NotificationIconContainer.IconState iconState, StatusBarIconView icon,
- float expandAmount, boolean isLastChild) {
+ private float updateIconAppearance(ExpandableNotificationRow row, float expandAmount,
+ boolean scrollingFast, boolean expandingAnimated, boolean isLastChild) {
// Let calculate how much the view is in the shelf
float viewStart = row.getTranslationY();
- int transformHeight = row.getActualHeight() + mPaddingBetweenElements;
+ int fullHeight = row.getActualHeight() + mPaddingBetweenElements;
+ float iconTransformDistance = getIntrinsicHeight() * 1.5f;
if (isLastChild) {
- transformHeight =
- Math.min(transformHeight, row.getMinHeight() - getIntrinsicHeight());
+ fullHeight = Math.min(fullHeight, row.getMinHeight() - getIntrinsicHeight());
+ iconTransformDistance = Math.min(iconTransformDistance, row.getMinHeight()
+ - getIntrinsicHeight());
}
- float viewEnd = viewStart + transformHeight;
- float iconAppearAmount;
- float yTranslation;
- float alpha = 1.0f;
- if (viewEnd >= getTranslationY() && (mAmbientState.isShadeExpanded()
+ float viewEnd = viewStart + fullHeight;
+ float fullTransitionAmount;
+ float iconTransitionAmount;
+ float shelfStart = getTranslationY();
+ if (viewEnd >= shelfStart && (mAmbientState.isShadeExpanded()
|| (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) {
- if (viewStart < getTranslationY()) {
- float linearAmount = (getTranslationY() - viewStart) / transformHeight;
+ if (viewStart < shelfStart) {
+
+ float fullAmount = (shelfStart - viewStart) / fullHeight;
float interpolatedAmount = Interpolators.ACCELERATE_DECELERATE.getInterpolation(
- linearAmount);
+ fullAmount);
interpolatedAmount = NotificationUtils.interpolate(
- interpolatedAmount, linearAmount, expandAmount);
- iconAppearAmount = 1.0f - interpolatedAmount;
+ interpolatedAmount, fullAmount, expandAmount);
+ fullTransitionAmount = 1.0f - interpolatedAmount;
+
+ iconTransitionAmount = (shelfStart - viewStart) / iconTransformDistance;
+ iconTransitionAmount = Math.min(1.0f, iconTransitionAmount);
+ iconTransitionAmount = 1.0f - iconTransitionAmount;
+
} else {
- iconAppearAmount = 1.0f;
+ fullTransitionAmount = 1.0f;
+ iconTransitionAmount = 1.0f;
}
} else {
- iconAppearAmount = 0.0f;
+ fullTransitionAmount = 0.0f;
+ iconTransitionAmount = 0.0f;
}
+ updateIconPositioning(row, iconTransitionAmount, fullTransitionAmount, scrollingFast,
+ expandingAnimated, isLastChild);
+ return fullTransitionAmount;
+ }
- // Lets now calculate how much of the transformation has already happened. This is different
- // from the above, since we only start transforming when the view is already quite a bit
- // pushed in.
+ private void updateIconPositioning(ExpandableNotificationRow row, float iconTransitionAmount,
+ float fullTransitionAmount, boolean scrollingFast, boolean expandingAnimated,
+ boolean isLastChild) {
+ StatusBarIconView icon = row.getEntry().expandedIcon;
+ NotificationIconContainer.IconState iconState = getIconState(icon);
+ if (iconState == null) {
+ return;
+ }
+ float clampedAmount = iconTransitionAmount > 0.5f ? 1.0f : 0.0f;
+ if (clampedAmount == iconTransitionAmount) {
+ iconState.keepClampedPosition = false;
+ }
+ if (clampedAmount == fullTransitionAmount) {
+ iconState.useFullTransitionAmount = fullTransitionAmount == 0.0f || scrollingFast
+ || expandingAnimated;
+ iconState.translateContent = mMaxLayoutHeight - getTranslationY()
+ - getIntrinsicHeight() > 0;
+ }
+ if (scrollingFast || (expandingAnimated && iconState.useFullTransitionAmount
+ && !ViewState.isAnimatingY(icon))) {
+ iconState.cancelAnimations(icon);
+ iconState.useFullTransitionAmount = true;
+ }
+ float transitionAmount;
+ boolean needCannedAnimation = iconState.clampedAppearAmount == 1.0f
+ && clampedAmount == 0.0f;
+ if (isLastChild || !USE_ANIMATIONS_WHEN_OPENING || iconState.useFullTransitionAmount) {
+ transitionAmount = iconTransitionAmount;
+ } else if (iconState.keepClampedPosition
+ && iconState.clampedAppearAmount != clampedAmount) {
+ // We animated to the clamped amount but then decided to go the other way. Let's
+ // animate it to the new position
+ transitionAmount = iconTransitionAmount;
+ iconState.needsCannedAnimation = true;
+ iconState.keepClampedPosition = false;
+ } else if (needCannedAnimation || iconState.keepClampedPosition
+ || iconState.iconAppearAmount == 1.0f) {
+ // We need to perform a canned animation since we crossed the treshhold
+ transitionAmount = clampedAmount;
+ iconState.keepClampedPosition = iconState.keepClampedPosition || needCannedAnimation;
+ iconState.needsCannedAnimation = needCannedAnimation;
+ } else {
+ transitionAmount = iconTransitionAmount;
+ }
+ iconState.iconAppearAmount = !USE_ANIMATIONS_WHEN_OPENING
+ || iconState.useFullTransitionAmount
+ ? fullTransitionAmount
+ : transitionAmount;
+ iconState.clampedAppearAmount = clampedAmount;
+ setIconTransformationAmount(row, transitionAmount);
+ float contentTransformationAmount = isLastChild || iconState.translateContent
+ ? iconTransitionAmount
+ : 0.0f;
+ row.setContentTransformationAmount(contentTransformationAmount, isLastChild);
+ }
+
+ private boolean isLastChild(ExpandableNotificationRow row) {
+ return row == mAmbientState.getLastVisibleBackgroundChild();
+ }
+
+ private void setIconTransformationAmount(ExpandableNotificationRow row,
+ float transitionAmount) {
+ StatusBarIconView icon = row.getEntry().expandedIcon;
+ NotificationIconContainer.IconState iconState = getIconState(icon);
+
View rowIcon = row.getNotificationIcon();
- float notificationIconPosition = viewStart;
+ float notificationIconPosition = row.getTranslationY();
float notificationIconSize = 0.0f;
int iconTopPadding;
if (rowIcon != null) {
@@ -322,28 +404,18 @@
float shelfIconPosition = getTranslationY() + icon.getTop();
shelfIconPosition += ((1.0f - icon.getIconScale()) * icon.getHeight()) / 2.0f;
float transitionDistance = getIntrinsicHeight() * 1.5f;
- if (isLastChild) {
+ if (row == mAmbientState.getLastVisibleBackgroundChild()) {
transitionDistance = Math.min(transitionDistance, row.getMinHeight()
- getIntrinsicHeight());
}
float transformationStartPosition = getTranslationY() - transitionDistance;
- float transitionAmount = 0.0f;
- if (viewStart < transformationStartPosition
- || (!mAmbientState.isShadeExpanded()
- && (row.isPinned() || row.isHeadsUpAnimatingAway()))) {
- // We simply place it on the icon of the notification
- yTranslation = notificationIconPosition - shelfIconPosition;
- } else {
- transitionAmount = (viewStart - transformationStartPosition)
- / transitionDistance;
- float startPosition = transformationStartPosition + iconTopPadding;
- yTranslation = NotificationUtils.interpolate(
- startPosition - shelfIconPosition, 0, transitionAmount);
- // If we are merging into the shelf, lets make sure the shelf is at least on our height,
- // otherwise the icons won't be visible.
- setTranslationZ(Math.max(getTranslationZ(), row.getTranslationZ()));
- }
+ float iconYTranslation = NotificationUtils.interpolate(
+ Math.min(notificationIconPosition, transformationStartPosition + iconTopPadding)
+ - shelfIconPosition,
+ 0,
+ transitionAmount);
float shelfIconSize = icon.getHeight() * icon.getIconScale();
+ float alpha = 1.0f;
if (!row.isShowingIcon()) {
// The view currently doesn't have an icon, lets transform it in!
alpha = transitionAmount;
@@ -352,15 +424,12 @@
// The notification size is different from the size in the shelf / statusbar
float newSize = NotificationUtils.interpolate(notificationIconSize, shelfIconSize,
transitionAmount);
- row.setIconTransformationAmount(transitionAmount, isLastChild);
if (iconState != null) {
iconState.scaleX = newSize / icon.getHeight() / icon.getIconScale();
iconState.scaleY = iconState.scaleX;
iconState.hidden = transitionAmount == 0.0f;
- iconState.iconAppearAmount = iconAppearAmount;
iconState.alpha = alpha;
- iconState.yTranslation = yTranslation;
- icon.setVisibility(transitionAmount == 0.0f ? INVISIBLE : VISIBLE);
+ iconState.yTranslation = iconYTranslation;
if (row.isInShelf() && !row.isTransformingIntoShelf()) {
iconState.iconAppearAmount = 1.0f;
iconState.alpha = 1.0f;
@@ -368,8 +437,14 @@
iconState.scaleY = 1.0f;
iconState.hidden = false;
}
+ if (row.isAboveShelf()) {
+ iconState.hidden = true;
+ }
}
- return iconAppearAmount;
+ }
+
+ private NotificationIconContainer.IconState getIconState(StatusBarIconView icon) {
+ return mShelfIcons.getIconState(icon);
}
private float getFullyClosedTranslation() {
@@ -386,9 +461,11 @@
}
private void setHideBackground(boolean hideBackground) {
- mHideBackground = hideBackground;
- updateBackground();
- updateOutline();
+ if (mHideBackground != hideBackground) {
+ mHideBackground = hideBackground;
+ updateBackground();
+ updateOutline();
+ }
}
public boolean hidesBackground() {
@@ -415,13 +492,23 @@
mShelfIcons.getWidth(),
openedAmount);
mShelfIcons.setActualLayoutWidth(width);
- float padding = NotificationUtils.interpolate(mCollapsedIcons.getPaddingEnd(),
+ boolean hasOverflow = mCollapsedIcons.hasOverflow();
+ int collapsedPadding = mCollapsedIcons.getPaddingEnd();
+ if (!hasOverflow) {
+ // we have to ensure that adding the low priority notification won't lead to an
+ // overflow
+ collapsedPadding -= (1.0f + NotificationIconContainer.OVERFLOW_EARLY_AMOUNT)
+ * mCollapsedIcons.getIconSize();
+ }
+ float padding = NotificationUtils.interpolate(collapsedPadding,
mShelfIcons.getPaddingEnd(),
openedAmount);
mShelfIcons.setActualPaddingEnd(padding);
float paddingStart = NotificationUtils.interpolate(start,
mShelfIcons.getPaddingStart(), openedAmount);
mShelfIcons.setActualPaddingStart(paddingStart);
+ mShelfIcons.setOpenedAmount(openedAmount);
+ mShelfIcons.setVisualOverflowAdaption(mCollapsedIcons.getVisualOverflowAdaption());
}
public void setMaxLayoutHeight(int maxLayoutHeight) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index bfa43fd..dba7130 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -42,7 +42,6 @@
private float mViewAlpha = 1.0f;
private ValueAnimator mAlphaAnimator;
private Rect mExcludedRect = new Rect();
- private int mLeftInset = 0;
private boolean mHasExcludedArea;
private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
= new ValueAnimator.AnimatorUpdateListener() {
@@ -88,12 +87,12 @@
if (mExcludedRect.top > 0) {
canvas.drawRect(0, 0, getWidth(), mExcludedRect.top, mPaint);
}
- if (mExcludedRect.left + mLeftInset > 0) {
- canvas.drawRect(0, mExcludedRect.top, mExcludedRect.left + mLeftInset,
- mExcludedRect.bottom, mPaint);
+ if (mExcludedRect.left > 0) {
+ canvas.drawRect(0, mExcludedRect.top, mExcludedRect.left, mExcludedRect.bottom,
+ mPaint);
}
- if (mExcludedRect.right + mLeftInset < getWidth()) {
- canvas.drawRect(mExcludedRect.right + mLeftInset,
+ if (mExcludedRect.right < getWidth()) {
+ canvas.drawRect(mExcludedRect.right,
mExcludedRect.top,
getWidth(),
mExcludedRect.bottom,
@@ -184,14 +183,4 @@
public void setChangeRunnable(Runnable changeRunnable) {
mChangeRunnable = changeRunnable;
}
-
- public void setLeftInset(int leftInset) {
- if (mLeftInset != leftInset) {
- mLeftInset = leftInset;
-
- if (mHasExcludedArea) {
- invalidate();
- }
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index d635bb0..a2c2fd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -37,6 +37,7 @@
import android.util.Log;
import android.util.Property;
import android.util.TypedValue;
+import android.view.View;
import android.view.ViewDebug;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Interpolator;
@@ -102,6 +103,7 @@
private ObjectAnimator mIconAppearAnimator;
private ObjectAnimator mDotAnimator;
private float mDotAppearAmount;
+ private OnVisibilityChangedListener mOnVisibilityChangedListener;
public StatusBarIconView(Context context, String slot, Notification notification) {
this(context, slot, notification, false);
@@ -453,6 +455,7 @@
}
public void setVisibleState(int visibleState, boolean animate, Runnable endRunnable) {
+ boolean runnableAdded = false;
if (visibleState != mVisibleState) {
mVisibleState = visibleState;
if (animate) {
@@ -465,20 +468,22 @@
targetAmount = 1.0f;
interpolator = Interpolators.LINEAR_OUT_SLOW_IN;
}
- mIconAppearAnimator = ObjectAnimator.ofFloat(this, ICON_APPEAR_AMOUNT,
- targetAmount);
- mIconAppearAnimator.setInterpolator(interpolator);
- mIconAppearAnimator.setDuration(100);
- mIconAppearAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mIconAppearAnimator = null;
- if (endRunnable != null) {
- endRunnable.run();
+ float currentAmount = getIconAppearAmount();
+ if (targetAmount != currentAmount) {
+ mIconAppearAnimator = ObjectAnimator.ofFloat(this, ICON_APPEAR_AMOUNT,
+ currentAmount, targetAmount);
+ mIconAppearAnimator.setInterpolator(interpolator);
+ mIconAppearAnimator.setDuration(100);
+ mIconAppearAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mIconAppearAnimator = null;
+ runRunnable(endRunnable);
}
- }
- });
- mIconAppearAnimator.start();
+ });
+ mIconAppearAnimator.start();
+ runnableAdded = true;
+ }
if (mDotAnimator != null) {
mDotAnimator.cancel();
@@ -489,22 +494,41 @@
targetAmount = 1.0f;
interpolator = Interpolators.LINEAR_OUT_SLOW_IN;
}
- mDotAnimator = ObjectAnimator.ofFloat(this, DOT_APPEAR_AMOUNT,
- targetAmount);
- mDotAnimator.setInterpolator(interpolator);
- mDotAnimator.setDuration(100);
- mDotAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mDotAnimator = null;
- }
- });
- mDotAnimator.start();
+ currentAmount = getDotAppearAmount();
+ if (targetAmount != currentAmount) {
+ mDotAnimator = ObjectAnimator.ofFloat(this, DOT_APPEAR_AMOUNT,
+ currentAmount, targetAmount);
+ mDotAnimator.setInterpolator(interpolator);
+ mDotAnimator.setDuration(100);
+ final boolean runRunnable = !runnableAdded;
+ mDotAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mDotAnimator = null;
+ if (runRunnable) {
+ runRunnable(endRunnable);
+ }
+ }
+ });
+ mDotAnimator.start();
+ runnableAdded = true;
+ }
} else {
setIconAppearAmount(visibleState == STATE_ICON ? 1.0f : 0.0f);
- setDotAppearAmount(visibleState == STATE_DOT ? 1.0f : 0.0f);
+ setDotAppearAmount(visibleState == STATE_DOT ? 1.0f
+ : visibleState == STATE_ICON ? 2.0f
+ : 0.0f);
}
}
+ if (!runnableAdded) {
+ runRunnable(endRunnable);
+ }
+ }
+
+ private void runRunnable(Runnable runnable) {
+ if (runnable != null) {
+ runnable.run();
+ }
}
public void setIconAppearAmount(float iconAppearAmount) {
@@ -525,7 +549,23 @@
invalidate();
}
+ @Override
+ public void setVisibility(int visibility) {
+ super.setVisibility(visibility);
+ if (mOnVisibilityChangedListener != null) {
+ mOnVisibilityChangedListener.onVisibilityChanged(visibility);
+ }
+ }
+
public float getDotAppearAmount() {
return mDotAppearAmount;
}
+
+ public void setOnVisibilityChangedListener(OnVisibilityChangedListener listener) {
+ mOnVisibilityChangedListener = listener;
+ }
+
+ public interface OnVisibilityChangedListener {
+ void onVisibilityChanged(int newVisibility);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index f6fe176..2bc2665 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -18,6 +18,7 @@
import android.view.View;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
+import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import java.util.ArrayList;
@@ -36,10 +37,11 @@
private View.OnLongClickListener mLongClickListener;
private Boolean mLongClickable;
private Integer mAlpha;
+ private Float mDarkIntensity;
private Integer mVisibility = -1;
- private int mImageResource = -1;
- private Drawable mImageDrawable;
+ private KeyButtonDrawable mImageDrawable;
private View mCurrentView;
+ private boolean mVertical;
public ButtonDispatcher(int id) {
mId = id;
@@ -49,13 +51,6 @@
mViews.clear();
}
- void addView(View view, boolean landscape) {
- addView(view);
- if (view instanceof ButtonInterface) {
- ((ButtonInterface) view).setLandscape(landscape);
- }
- }
-
void addView(View view) {
mViews.add(view);
view.setOnClickListener(mClickListener);
@@ -67,14 +62,19 @@
if (mAlpha != null) {
view.setAlpha(mAlpha);
}
+ if (mDarkIntensity != null) {
+ ((ButtonInterface) view).setDarkIntensity(mDarkIntensity);
+ }
if (mVisibility != null) {
view.setVisibility(mVisibility);
}
- if (mImageResource > 0) {
- ((ButtonInterface) view).setImageResource(mImageResource);
- } else if (mImageDrawable != null) {
+ if (mImageDrawable != null) {
((ButtonInterface) view).setImageDrawable(mImageDrawable);
}
+
+ if (view instanceof ButtonInterface) {
+ ((ButtonInterface) view).setVertical(mVertical);
+ }
}
public int getId() {
@@ -89,24 +89,14 @@
return mAlpha != null ? mAlpha : 1;
}
- public void setImageDrawable(Drawable drawable) {
+ public void setImageDrawable(KeyButtonDrawable drawable) {
mImageDrawable = drawable;
- mImageResource = -1;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable);
}
}
- public void setImageResource(int resource) {
- mImageResource = resource;
- mImageDrawable = null;
- final int N = mViews.size();
- for (int i = 0; i < N; i++) {
- ((ButtonInterface) mViews.get(i)).setImageResource(mImageResource);
- }
- }
-
public void setVisibility(int visibility) {
if (mVisibility == visibility) return;
mVisibility = visibility;
@@ -132,6 +122,14 @@
}
}
+ public void setDarkIntensity(float darkIntensity) {
+ mDarkIntensity = darkIntensity;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ ((ButtonInterface) mViews.get(i)).setDarkIntensity(darkIntensity);
+ }
+ }
+
public void setOnClickListener(View.OnClickListener clickListener) {
mClickListener = clickListener;
final int N = mViews.size();
@@ -186,4 +184,14 @@
}
}
+ public void setVertical(boolean vertical) {
+ mVertical = vertical;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ final View view = mViews.get(i);
+ if (view instanceof ButtonInterface) {
+ ((ButtonInterface) view).setVertical(vertical);
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index daa57c6..a2c106a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -32,6 +32,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
@@ -143,6 +144,7 @@
private boolean mLeftIsVoiceAssist;
private AssistManager mAssistManager;
+ private Drawable mLeftAssistIcon;
private IntentButton mRightButton = new DefaultRightButton();
private IntentButton mLeftButton = new DefaultLeftButton();
@@ -348,6 +350,14 @@
? View.VISIBLE : View.GONE);
}
+ /**
+ * Set an alternate icon for the left assist affordance (replace the mic icon)
+ */
+ public void setLeftAssistIcon(Drawable drawable) {
+ mLeftAssistIcon = drawable;
+ updateLeftAffordanceIcon();
+ }
+
private void updateLeftAffordanceIcon() {
IconState state = mLeftButton.getIcon();
mLeftAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE);
@@ -814,7 +824,11 @@
mLeftIsVoiceAssist = canLaunchVoiceAssist();
if (mLeftIsVoiceAssist) {
mIconState.isVisible = mUserSetupComplete;
- mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
+ if (mLeftAssistIcon == null) {
+ mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
+ } else {
+ mIconState.drawable = mLeftAssistIcon;
+ }
mIconState.contentDescription = mContext.getString(
R.string.accessibility_voice_assist_button);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
new file mode 100644
index 0000000..b5358a1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -0,0 +1,187 @@
+/*
+ * 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 com.android.systemui.statusbar.phone;
+
+import android.graphics.Rect;
+import android.view.View;
+
+import com.android.systemui.statusbar.policy.BatteryController;
+
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+
+/**
+ * Controls how light status bar flag applies to the icons.
+ */
+public class LightBarController implements BatteryController.BatteryStateChangeCallback {
+
+ private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
+
+ private final StatusBarIconController mStatusBarIconController;
+ private final BatteryController mBatteryController;
+ private FingerprintUnlockController mFingerprintUnlockController;
+ private final NavigationBarView mNavigationBarView;
+
+ private int mSystemUiVisibility;
+ private int mFullscreenStackVisibility;
+ private int mDockedStackVisibility;
+ private boolean mFullscreenLight;
+ private boolean mDockedLight;
+ private int mLastStatusBarMode;
+ private int mLastNavigationBarMode;
+ private boolean mNavigationLight;
+ private float mScrimAlpha;
+
+ private final Rect mLastFullscreenBounds = new Rect();
+ private final Rect mLastDockedBounds = new Rect();
+
+ public LightBarController(StatusBarIconController statusBarIconController,
+ NavigationBarView navigationBarView,
+ BatteryController batteryController) {
+ mStatusBarIconController = statusBarIconController;
+ mNavigationBarView = navigationBarView;
+ mBatteryController = batteryController;
+ batteryController.addCallback(this);
+ }
+
+ public void setFingerprintUnlockController(
+ FingerprintUnlockController fingerprintUnlockController) {
+ mFingerprintUnlockController = fingerprintUnlockController;
+ }
+
+ public void onSystemUiVisibilityChanged(int vis, int fullscreenStackVis, int dockedStackVis,
+ int mask, Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
+ int statusBarMode, boolean nbModeChanged, int navigationBarMode) {
+ int oldFullscreen = mFullscreenStackVisibility;
+ int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
+ int diffFullscreen = newFullscreen ^ oldFullscreen;
+ int oldDocked = mDockedStackVisibility;
+ int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
+ int diffDocked = newDocked ^ oldDocked;
+ if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
+ || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
+ || sbModeChanged
+ || !mLastFullscreenBounds.equals(fullscreenStackBounds)
+ || !mLastDockedBounds.equals(dockedStackBounds)) {
+
+ mFullscreenLight = isLight(newFullscreen, statusBarMode,
+ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ mDockedLight = isLight(newDocked, statusBarMode, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ updateStatus(fullscreenStackBounds, dockedStackBounds);
+ }
+
+ int oldVis = mSystemUiVisibility;
+ int newVis = (oldVis & ~mask) | (vis & mask);
+ int diffVis = newVis ^ oldVis;
+ if ((diffVis & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0
+ || nbModeChanged) {
+ boolean last = mNavigationLight;
+ mNavigationLight = isNavigationLight(newVis, navigationBarMode);
+ if (mNavigationLight != last) {
+ updateNavigation();
+ }
+ }
+ mFullscreenStackVisibility = newFullscreen;
+ mDockedStackVisibility = newDocked;
+ mSystemUiVisibility = newVis;
+ mLastStatusBarMode = statusBarMode;
+ mLastNavigationBarMode = navigationBarMode;
+ mLastFullscreenBounds.set(fullscreenStackBounds);
+ mLastDockedBounds.set(dockedStackBounds);
+ }
+
+ private void reevaluate() {
+ onSystemUiVisibilityChanged(mSystemUiVisibility, mFullscreenStackVisibility,
+ mDockedStackVisibility, 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds,
+ true /* sbModeChange*/, mLastStatusBarMode, true /* nbModeChange*/,
+ mLastNavigationBarMode);
+ }
+
+ public void setScrimAlpha(float alpha) {
+ mScrimAlpha = alpha;
+ reevaluate();
+ }
+
+ private boolean isNavigationLight(int vis, int barMode) {
+ return isLight(vis, barMode, View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
+ && mScrimAlpha < NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD;
+ }
+
+ private boolean isLight(int vis, int barMode, int flag) {
+ boolean isTransparentBar = (barMode == MODE_TRANSPARENT
+ || barMode == MODE_LIGHTS_OUT_TRANSPARENT);
+ boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
+ boolean light = (vis & flag) != 0;
+ return allowLight && light;
+ }
+
+ private boolean animateChange() {
+ if (mFingerprintUnlockController == null) {
+ return false;
+ }
+ int unlockMode = mFingerprintUnlockController.getMode();
+ return unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
+ && unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
+ }
+
+ private void updateStatus(Rect fullscreenStackBounds, Rect dockedStackBounds) {
+ boolean hasDockedStack = !dockedStackBounds.isEmpty();
+
+ // If both are light or fullscreen is light and there is no docked stack, all icons get
+ // dark.
+ if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
+ mStatusBarIconController.setIconsDarkArea(null);
+ mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
+
+ }
+
+ // If no one is light or the fullscreen is not light and there is no docked stack,
+ // all icons become white.
+ else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
+ mStatusBarIconController.getTransitionsController().setIconsDark(
+ false, animateChange());
+ }
+
+ // Not the same for every stack, magic!
+ else {
+ Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
+ if (bounds.isEmpty()) {
+ mStatusBarIconController.setIconsDarkArea(null);
+ } else {
+ mStatusBarIconController.setIconsDarkArea(bounds);
+ }
+ mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
+ }
+ }
+
+ private void updateNavigation() {
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().setIconsDark(
+ mNavigationLight, animateChange());
+ }
+ }
+
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+
+ }
+
+ @Override
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ reevaluate();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
new file mode 100644
index 0000000..1d4d2d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -0,0 +1,142 @@
+/*
+ * 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 com.android.systemui.statusbar.phone;
+
+import android.animation.ValueAnimator;
+import android.os.Handler;
+import android.os.SystemClock;
+
+import com.android.systemui.Interpolators;
+
+/**
+ * Class to control all aspects about light bar changes.
+ */
+public class LightBarTransitionsController {
+
+ public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
+
+ private final Handler mHandler;
+ private final DarkIntensityApplier mApplier;
+
+ private boolean mTransitionDeferring;
+ private long mTransitionDeferringStartTime;
+ private long mTransitionDeferringDuration;
+ private boolean mTransitionPending;
+ private boolean mTintChangePending;
+ private float mPendingDarkIntensity;
+ private ValueAnimator mTintAnimator;
+ private float mDarkIntensity;
+
+ private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mTransitionDeferring = false;
+ }
+ };
+
+ public LightBarTransitionsController(DarkIntensityApplier applier) {
+ mApplier = applier;
+ mHandler = new Handler();
+ }
+
+ public void appTransitionPending() {
+ mTransitionPending = true;
+ }
+
+ public void appTransitionCancelled() {
+ if (mTransitionPending && mTintChangePending) {
+ mTintChangePending = false;
+ animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+ }
+ mTransitionPending = false;
+ }
+
+ public void appTransitionStarting(long startTime, long duration) {
+ if (mTransitionPending && mTintChangePending) {
+ mTintChangePending = false;
+ animateIconTint(mPendingDarkIntensity,
+ Math.max(0, startTime - SystemClock.uptimeMillis()),
+ duration);
+
+ } else if (mTransitionPending) {
+
+ // If we don't have a pending tint change yet, the change might come in the future until
+ // startTime is reached.
+ mTransitionDeferring = true;
+ mTransitionDeferringStartTime = startTime;
+ mTransitionDeferringDuration = duration;
+ mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
+ mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
+ }
+ mTransitionPending = false;
+ }
+
+ public void setIconsDark(boolean dark, boolean animate) {
+ if (!animate) {
+ setIconTintInternal(dark ? 1.0f : 0.0f);
+ } else if (mTransitionPending) {
+ deferIconTintChange(dark ? 1.0f : 0.0f);
+ } else if (mTransitionDeferring) {
+ animateIconTint(dark ? 1.0f : 0.0f,
+ Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
+ mTransitionDeferringDuration);
+ } else {
+ animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+ }
+ }
+
+ public float getCurrentDarkIntensity() {
+ return mDarkIntensity;
+ }
+
+ private void deferIconTintChange(float darkIntensity) {
+ if (mTintChangePending && darkIntensity == mPendingDarkIntensity) {
+ return;
+ }
+ mTintChangePending = true;
+ mPendingDarkIntensity = darkIntensity;
+ }
+
+ private void animateIconTint(float targetDarkIntensity, long delay,
+ long duration) {
+ if (mTintAnimator != null) {
+ mTintAnimator.cancel();
+ }
+ if (mDarkIntensity == targetDarkIntensity) {
+ return;
+ }
+ mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
+ mTintAnimator.addUpdateListener(
+ animation -> setIconTintInternal((Float) animation.getAnimatedValue()));
+ mTintAnimator.setDuration(duration);
+ mTintAnimator.setStartDelay(delay);
+ mTintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mTintAnimator.start();
+ }
+
+ private void setIconTintInternal(float darkIntensity) {
+ mDarkIntensity = darkIntensity;
+ mApplier.applyDarkIntensity(darkIntensity);
+ }
+
+ /**
+ * Interface to apply a specific dark intensity.
+ */
+ public interface DarkIntensityApplier {
+ void applyDarkIntensity(float darkIntensity);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightStatusBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightStatusBarController.java
deleted file mode 100644
index dd7f3cc..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightStatusBarController.java
+++ /dev/null
@@ -1,141 +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 com.android.systemui.statusbar.phone;
-
-import android.graphics.Rect;
-import android.view.View;
-
-import com.android.systemui.statusbar.policy.BatteryController;
-
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
-
-/**
- * Controls how light status bar flag applies to the icons.
- */
-public class LightStatusBarController implements BatteryController.BatteryStateChangeCallback {
-
- private final StatusBarIconController mIconController;
- private final BatteryController mBatteryController;
- private FingerprintUnlockController mFingerprintUnlockController;
-
- private int mFullscreenStackVisibility;
- private int mDockedStackVisibility;
- private boolean mFullscreenLight;
- private boolean mDockedLight;
- private int mLastStatusBarMode;
-
- private final Rect mLastFullscreenBounds = new Rect();
- private final Rect mLastDockedBounds = new Rect();
-
- public LightStatusBarController(StatusBarIconController iconController,
- BatteryController batteryController) {
- mIconController = iconController;
- mBatteryController = batteryController;
- batteryController.addCallback(this);
- }
-
- public void setFingerprintUnlockController(
- FingerprintUnlockController fingerprintUnlockController) {
- mFingerprintUnlockController = fingerprintUnlockController;
- }
-
- public void onSystemUiVisibilityChanged(int fullscreenStackVis, int dockedStackVis, int mask,
- Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
- int statusBarMode) {
- int oldFullscreen = mFullscreenStackVisibility;
- int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
- int diffFullscreen = newFullscreen ^ oldFullscreen;
- int oldDocked = mDockedStackVisibility;
- int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
- int diffDocked = newDocked ^ oldDocked;
- if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
- || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
- || sbModeChanged
- || !mLastFullscreenBounds.equals(fullscreenStackBounds)
- || !mLastDockedBounds.equals(dockedStackBounds)) {
-
- mFullscreenLight = isLight(newFullscreen, statusBarMode);
- mDockedLight = isLight(newDocked, statusBarMode);
- update(fullscreenStackBounds, dockedStackBounds);
- }
- mFullscreenStackVisibility = newFullscreen;
- mDockedStackVisibility = newDocked;
- mLastStatusBarMode = statusBarMode;
- mLastFullscreenBounds.set(fullscreenStackBounds);
- mLastDockedBounds.set(dockedStackBounds);
- }
-
- private boolean isLight(int vis, int statusBarMode) {
- boolean isTransparentBar = (statusBarMode == MODE_TRANSPARENT
- || statusBarMode == MODE_LIGHTS_OUT_TRANSPARENT);
- boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
- boolean light = (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
- return allowLight && light;
- }
-
- private boolean animateChange() {
- if (mFingerprintUnlockController == null) {
- return false;
- }
- int unlockMode = mFingerprintUnlockController.getMode();
- return unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
- && unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
- }
-
- private void update(Rect fullscreenStackBounds, Rect dockedStackBounds) {
- boolean hasDockedStack = !dockedStackBounds.isEmpty();
-
- // If both are light or fullscreen is light and there is no docked stack, all icons get
- // dark.
- if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
- mIconController.setIconsDarkArea(null);
- mIconController.setIconsDark(true, animateChange());
-
- }
-
- // If no one is light or the fullscreen is not light and there is no docked stack,
- // all icons become white.
- else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
- mIconController.setIconsDark(false, animateChange());
-
- }
-
- // Not the same for every stack, magic!
- else {
- Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
- if (bounds.isEmpty()) {
- mIconController.setIconsDarkArea(null);
- } else {
- mIconController.setIconsDarkArea(bounds);
- }
- mIconController.setIconsDark(true, animateChange());
- }
- }
-
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-
- }
-
- @Override
- public void onPowerSaveChanged(boolean isPowerSave) {
- onSystemUiVisibilityChanged(mFullscreenStackVisibility, mDockedStackVisibility,
- 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds, true /* sbModeChange*/,
- mLastStatusBarMode);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
index 1a46815..4969a1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
@@ -14,134 +14,16 @@
package com.android.systemui.statusbar.phone;
-import android.app.ActivityManager;
-import android.app.StatusBarManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.UserInfo;
-import android.os.UserHandle;
-import android.os.UserManager;
-
import com.android.systemui.statusbar.phone.ManagedProfileController.Callback;
import com.android.systemui.statusbar.policy.CallbackController;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
+public interface ManagedProfileController extends CallbackController<Callback> {
-public class ManagedProfileController implements CallbackController<Callback> {
+ void setWorkModeEnabled(boolean enabled);
- private final List<Callback> mCallbacks = new ArrayList<>();
+ boolean hasActiveProfile();
- private final Context mContext;
- private final UserManager mUserManager;
- private final LinkedList<UserInfo> mProfiles;
- private boolean mListening;
- private int mCurrentUser;
-
- public ManagedProfileController(QSTileHost host) {
- mContext = host.getContext();
- mUserManager = UserManager.get(mContext);
- mProfiles = new LinkedList<UserInfo>();
- }
-
- public void addCallback(Callback callback) {
- mCallbacks.add(callback);
- if (mCallbacks.size() == 1) {
- setListening(true);
- }
- callback.onManagedProfileChanged();
- }
-
- public void removeCallback(Callback callback) {
- if (mCallbacks.remove(callback) && mCallbacks.size() == 0) {
- setListening(false);
- }
- }
-
- public void setWorkModeEnabled(boolean enableWorkMode) {
- synchronized (mProfiles) {
- for (UserInfo ui : mProfiles) {
- if (enableWorkMode) {
- if (!mUserManager.trySetQuietModeDisabled(ui.id, null)) {
- StatusBarManager statusBarManager = (StatusBarManager) mContext
- .getSystemService(android.app.Service.STATUS_BAR_SERVICE);
- statusBarManager.collapsePanels();
- }
- } else {
- mUserManager.setQuietModeEnabled(ui.id, true);
- }
- }
- }
- }
-
- private void reloadManagedProfiles() {
- synchronized (mProfiles) {
- boolean hadProfile = mProfiles.size() > 0;
- int user = ActivityManager.getCurrentUser();
- mProfiles.clear();
-
- for (UserInfo ui : mUserManager.getEnabledProfiles(user)) {
- if (ui.isManagedProfile()) {
- mProfiles.add(ui);
- }
- }
- if (mProfiles.size() == 0 && hadProfile && (user == mCurrentUser)) {
- for (Callback callback : mCallbacks) {
- callback.onManagedProfileRemoved();
- }
- }
- mCurrentUser = user;
- }
- }
-
- public boolean hasActiveProfile() {
- if (!mListening) reloadManagedProfiles();
- synchronized (mProfiles) {
- return mProfiles.size() > 0;
- }
- }
-
- public boolean isWorkModeEnabled() {
- if (!mListening) reloadManagedProfiles();
- synchronized (mProfiles) {
- for (UserInfo ui : mProfiles) {
- if (ui.isQuietModeEnabled()) {
- return false;
- }
- }
- return true;
- }
- }
-
- private void setListening(boolean listening) {
- mListening = listening;
- if (listening) {
- reloadManagedProfiles();
-
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
- mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
- } else {
- mContext.unregisterReceiver(mReceiver);
- }
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- reloadManagedProfiles();
- for (Callback callback : mCallbacks) {
- callback.onManagedProfileChanged();
- }
- }
- };
+ boolean isWorkModeEnabled();
public interface Callback {
void onManagedProfileChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
new file mode 100644
index 0000000..fc33ace
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
@@ -0,0 +1,142 @@
+/*
+ * 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 com.android.systemui.statusbar.phone;
+
+import android.app.ActivityManager;
+import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+public class ManagedProfileControllerImpl implements ManagedProfileController {
+
+ private final List<Callback> mCallbacks = new ArrayList<>();
+
+ private final Context mContext;
+ private final UserManager mUserManager;
+ private final LinkedList<UserInfo> mProfiles;
+ private boolean mListening;
+ private int mCurrentUser;
+
+ public ManagedProfileControllerImpl(QSTileHost host) {
+ mContext = host.getContext();
+ mUserManager = UserManager.get(mContext);
+ mProfiles = new LinkedList<UserInfo>();
+ }
+
+ public void addCallback(Callback callback) {
+ mCallbacks.add(callback);
+ if (mCallbacks.size() == 1) {
+ setListening(true);
+ }
+ callback.onManagedProfileChanged();
+ }
+
+ public void removeCallback(Callback callback) {
+ if (mCallbacks.remove(callback) && mCallbacks.size() == 0) {
+ setListening(false);
+ }
+ }
+
+ public void setWorkModeEnabled(boolean enableWorkMode) {
+ synchronized (mProfiles) {
+ for (UserInfo ui : mProfiles) {
+ if (enableWorkMode) {
+ if (!mUserManager.trySetQuietModeDisabled(ui.id, null)) {
+ StatusBarManager statusBarManager = (StatusBarManager) mContext
+ .getSystemService(android.app.Service.STATUS_BAR_SERVICE);
+ statusBarManager.collapsePanels();
+ }
+ } else {
+ mUserManager.setQuietModeEnabled(ui.id, true);
+ }
+ }
+ }
+ }
+
+ private void reloadManagedProfiles() {
+ synchronized (mProfiles) {
+ boolean hadProfile = mProfiles.size() > 0;
+ int user = ActivityManager.getCurrentUser();
+ mProfiles.clear();
+
+ for (UserInfo ui : mUserManager.getEnabledProfiles(user)) {
+ if (ui.isManagedProfile()) {
+ mProfiles.add(ui);
+ }
+ }
+ if (mProfiles.size() == 0 && hadProfile && (user == mCurrentUser)) {
+ for (Callback callback : mCallbacks) {
+ callback.onManagedProfileRemoved();
+ }
+ }
+ mCurrentUser = user;
+ }
+ }
+
+ public boolean hasActiveProfile() {
+ if (!mListening) reloadManagedProfiles();
+ synchronized (mProfiles) {
+ return mProfiles.size() > 0;
+ }
+ }
+
+ public boolean isWorkModeEnabled() {
+ if (!mListening) reloadManagedProfiles();
+ synchronized (mProfiles) {
+ for (UserInfo ui : mProfiles) {
+ if (ui.isQuietModeEnabled()) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ private void setListening(boolean listening) {
+ mListening = listening;
+ if (listening) {
+ reloadManagedProfiles();
+
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
+ } else {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ reloadManagedProfiles();
+ for (Callback callback : mCallbacks) {
+ callback.onManagedProfileChanged();
+ }
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index c420927..b2b093c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -17,12 +17,14 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.SparseArray;
+import android.view.Display;
+import android.view.Display.Mode;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Space;
@@ -72,12 +74,13 @@
protected FrameLayout mRot0;
protected FrameLayout mRot90;
+ private boolean isRot0Landscape;
private SparseArray<ButtonDispatcher> mButtonDispatchers;
private String mCurrentLayout;
- private View mLastRot0;
- private View mLastRot90;
+ private View mLastPortrait;
+ private View mLastLandscape;
private boolean mAlternativeOrder;
@@ -85,6 +88,10 @@
super(context, attrs);
mDensity = context.getResources().getConfiguration().densityDpi;
createInflaters();
+ Display display = ((WindowManager)
+ context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+ Mode displayMode = display.getMode();
+ isRot0Landscape = displayMode.getPhysicalWidth() > displayMode.getPhysicalHeight();
}
private void createInflaters() {
@@ -215,17 +222,17 @@
String[] center = sets[1].split(BUTTON_SEPARATOR);
String[] end = sets[2].split(BUTTON_SEPARATOR);
// Inflate these in start to end order or accessibility traversal will be messed up.
- inflateButtons(start, (ViewGroup) mRot0.findViewById(R.id.ends_group), false);
- inflateButtons(start, (ViewGroup) mRot90.findViewById(R.id.ends_group), true);
+ inflateButtons(start, (ViewGroup) mRot0.findViewById(R.id.ends_group), isRot0Landscape);
+ inflateButtons(start, (ViewGroup) mRot90.findViewById(R.id.ends_group), !isRot0Landscape);
- inflateButtons(center, (ViewGroup) mRot0.findViewById(R.id.center_group), false);
- inflateButtons(center, (ViewGroup) mRot90.findViewById(R.id.center_group), true);
+ inflateButtons(center, (ViewGroup) mRot0.findViewById(R.id.center_group), isRot0Landscape);
+ inflateButtons(center, (ViewGroup) mRot90.findViewById(R.id.center_group), !isRot0Landscape);
addGravitySpacer((LinearLayout) mRot0.findViewById(R.id.ends_group));
addGravitySpacer((LinearLayout) mRot90.findViewById(R.id.ends_group));
- inflateButtons(end, (ViewGroup) mRot0.findViewById(R.id.ends_group), false);
- inflateButtons(end, (ViewGroup) mRot90.findViewById(R.id.ends_group), true);
+ inflateButtons(end, (ViewGroup) mRot0.findViewById(R.id.ends_group), isRot0Landscape);
+ inflateButtons(end, (ViewGroup) mRot90.findViewById(R.id.ends_group), !isRot0Landscape);
}
private void addGravitySpacer(LinearLayout layout) {
@@ -234,7 +241,7 @@
private void inflateButtons(String[] buttons, ViewGroup parent, boolean landscape) {
for (int i = 0; i < buttons.length; i++) {
- inflateButton(buttons[i], parent, landscape, i);
+ inflateButton(buttons[i], parent, landscape);
}
}
@@ -247,8 +254,7 @@
}
@Nullable
- protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape,
- int indexInParent) {
+ protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape) {
LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
float size = extractSize(buttonSpec);
View v = createView(buttonSpec, parent, inflater, landscape);
@@ -259,15 +265,15 @@
params.width = (int) (params.width * size);
}
parent.addView(v);
- addToDispatchers(v, landscape);
- View lastView = landscape ? mLastRot90 : mLastRot0;
+ addToDispatchers(v);
+ View lastView = landscape ? mLastLandscape : mLastPortrait;
if (lastView != null) {
v.setAccessibilityTraversalAfter(lastView.getId());
}
if (landscape) {
- mLastRot90 = v;
+ mLastLandscape = v;
} else {
- mLastRot0 = v;
+ mLastPortrait = v;
}
return v;
}
@@ -283,19 +289,10 @@
}
if (HOME.equals(button)) {
v = inflater.inflate(R.layout.home, parent, false);
- if (landscape && isSw600Dp()) {
- setupLandButton(v);
- }
} else if (BACK.equals(button)) {
v = inflater.inflate(R.layout.back, parent, false);
- if (landscape && isSw600Dp()) {
- setupLandButton(v);
- }
} else if (RECENT.equals(button)) {
v = inflater.inflate(R.layout.recent_apps, parent, false);
- if (landscape && isSw600Dp()) {
- setupLandButton(v);
- }
} else if (MENU_IME.equals(button)) {
v = inflater.inflate(R.layout.menu_ime, parent, false);
} else if (NAVSPACE.equals(button)) {
@@ -348,37 +345,22 @@
return buttonSpec.substring(0, buttonSpec.indexOf(SIZE_MOD_START));
}
- private void addToDispatchers(View v, boolean landscape) {
+ private void addToDispatchers(View v) {
if (mButtonDispatchers != null) {
final int indexOfKey = mButtonDispatchers.indexOfKey(v.getId());
if (indexOfKey >= 0) {
- mButtonDispatchers.valueAt(indexOfKey).addView(v, landscape);
+ mButtonDispatchers.valueAt(indexOfKey).addView(v);
} else if (v instanceof ViewGroup) {
final ViewGroup viewGroup = (ViewGroup)v;
final int N = viewGroup.getChildCount();
for (int i = 0; i < N; i++) {
- addToDispatchers(viewGroup.getChildAt(i), landscape);
+ addToDispatchers(viewGroup.getChildAt(i));
}
}
}
}
- private boolean isSw600Dp() {
- Configuration configuration = mContext.getResources().getConfiguration();
- return (configuration.smallestScreenWidthDp >= 600);
- }
- /**
- * This manually sets the width of sw600dp landscape buttons because despite
- * overriding the configuration from the overridden resources aren't loaded currently.
- */
- private void setupLandButton(View v) {
- Resources res = mContext.getResources();
- v.getLayoutParams().width = res.getDimensionPixelOffset(
- R.dimen.navigation_key_width_sw600dp_land);
- int padding = res.getDimensionPixelOffset(R.dimen.navigation_key_padding_sw600dp_land);
- v.setPadding(padding, v.getPaddingTop(), padding, v.getPaddingBottom());
- }
private void clearViews() {
if (mButtonDispatchers != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 1fe0115..3be5e57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -16,13 +16,11 @@
package com.android.systemui.statusbar.phone;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.os.ServiceManager;
+import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.View;
-import android.view.animation.AccelerateInterpolator;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
@@ -31,6 +29,7 @@
private final NavigationBarView mView;
private final IStatusBarService mBarService;
+ private final LightBarTransitionsController mLightTransitionsController;
private boolean mLightsOut;
@@ -39,6 +38,7 @@
mView = view;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ mLightTransitionsController = new LightBarTransitionsController(this::applyDarkIntensity);
}
public void init() {
@@ -46,6 +46,10 @@
applyMode(getMode(), false /*animate*/, true /*force*/);
}
+ public LightBarTransitionsController getLightTransitionsController() {
+ return mLightTransitionsController;
+ }
+
@Override
protected void onTransition(int oldMode, int newMode, boolean animate) {
super.onTransition(oldMode, newMode, animate);
@@ -81,6 +85,18 @@
}
}
+
+ public void reapplyDarkIntensity() {
+ applyDarkIntensity(mLightTransitionsController.getCurrentDarkIntensity());
+ }
+
+ public void applyDarkIntensity(float darkIntensity) {
+ SparseArray<ButtonDispatcher> buttonDispatchers = mView.getButtonDispatchers();
+ for (int i = buttonDispatchers.size() - 1; i >= 0; i--) {
+ buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
+ }
+ }
+
private final View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent ev) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index a0ea9bf..d22f421 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -22,6 +22,7 @@
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
+import android.annotation.DrawableRes;
import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Configuration;
@@ -34,6 +35,7 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
+import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.IDockedStackListener.Stub;
import android.view.MotionEvent;
@@ -51,8 +53,10 @@
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.statusbar.phone.NavGesture;
import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
+import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.policy.DeadZone;
+import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -78,14 +82,14 @@
int mDisabledFlags = 0;
int mNavigationIconHints = 0;
- private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
- private Drawable mBackCarModeIcon, mBackLandCarModeIcon;
- private Drawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
- private Drawable mHomeDefaultIcon, mHomeCarModeIcon;
- private Drawable mRecentIcon;
- private Drawable mDockedIcon;
- private Drawable mImeIcon;
- private Drawable mMenuIcon;
+ private KeyButtonDrawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
+ private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
+ private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
+ private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
+ private KeyButtonDrawable mRecentIcon;
+ private KeyButtonDrawable mDockedIcon;
+ private KeyButtonDrawable mImeIcon;
+ private KeyButtonDrawable mMenuIcon;
private GestureHelper mGestureHelper;
private DeadZone mDeadZone;
@@ -217,6 +221,10 @@
return mBarTransitions;
}
+ public LightBarTransitionsController getLightTransitionsController() {
+ return mBarTransitions.getLightTransitionsController();
+ }
+
public void setComponents(RecentsComponent recentsComponent, Divider divider) {
mRecentsComponent = recentsComponent;
mDivider = divider;
@@ -281,29 +289,44 @@
return mButtonDispatchers.get(R.id.ime_switcher);
}
+ public SparseArray<ButtonDispatcher> getButtonDispatchers() {
+ return mButtonDispatchers;
+ }
+
private void updateCarModeIcons(Context ctx) {
- mBackCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_carmode);
+ mBackCarModeIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
mBackLandCarModeIcon = mBackCarModeIcon;
- mBackAltCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_ime_carmode);
+ mBackAltCarModeIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_back_ime_carmode, R.drawable.ic_sysbar_back_ime_carmode);
mBackAltLandCarModeIcon = mBackAltCarModeIcon;
- mHomeCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_home_carmode);
+ mHomeCarModeIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_home_carmode, R.drawable.ic_sysbar_home_carmode);
}
private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
if (oldConfig.orientation != newConfig.orientation
|| oldConfig.densityDpi != newConfig.densityDpi) {
- mDockedIcon = ctx.getDrawable(R.drawable.ic_sysbar_docked);
+ mDockedIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_docked, R.drawable.ic_sysbar_docked_dark);
}
if (oldConfig.densityDpi != newConfig.densityDpi) {
- mBackIcon = ctx.getDrawable(R.drawable.ic_sysbar_back);
+ mBackIcon = getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark);
mBackLandIcon = mBackIcon;
- mBackAltIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_ime);
+ mBackAltIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_back_ime, R.drawable.ic_sysbar_back_ime_dark);
mBackAltLandIcon = mBackAltIcon;
- mHomeDefaultIcon = ctx.getDrawable(R.drawable.ic_sysbar_home);
- mRecentIcon = ctx.getDrawable(R.drawable.ic_sysbar_recent);
- mMenuIcon = ctx.getDrawable(R.drawable.ic_sysbar_menu);
- mImeIcon = ctx.getDrawable(R.drawable.ic_ime_switcher_default);
+ mHomeDefaultIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
+ mRecentIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
+ mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
+
+ Context darkContext = new ContextThemeWrapper(ctx, R.style.DualToneDarkTheme);
+ Context lightContext = new ContextThemeWrapper(ctx, R.style.DualToneLightTheme);
+ mImeIcon = getDrawable(darkContext, lightContext,
+ R.drawable.ic_ime_switcher_default, R.drawable.ic_ime_switcher_default);
if (ALTERNATE_CAR_MODE_UI) {
updateCarModeIcons(ctx);
@@ -311,6 +334,17 @@
}
}
+ private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
+ @DrawableRes int darkIcon) {
+ return getDrawable(ctx, ctx, lightIcon, darkIcon);
+ }
+
+ private KeyButtonDrawable getDrawable(Context darkContext, Context lightContext,
+ @DrawableRes int lightIcon, @DrawableRes int darkIcon) {
+ return KeyButtonDrawable.create(lightContext.getDrawable(lightIcon),
+ darkContext.getDrawable(darkIcon));
+ }
+
@Override
public void setLayoutDirection(int layoutDirection) {
// Reload all the icons
@@ -328,13 +362,13 @@
setNavigationIconHints(hints, false);
}
- private Drawable getBackIconWithAlt(boolean carMode, boolean landscape) {
+ private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
return landscape
? carMode ? mBackAltLandCarModeIcon : mBackAltLandIcon
: carMode ? mBackAltCarModeIcon : mBackAltIcon;
}
- private Drawable getBackIcon(boolean carMode, boolean landscape) {
+ private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
return landscape
? carMode ? mBackLandCarModeIcon : mBackLandIcon
: carMode ? mBackCarModeIcon : mBackIcon;
@@ -357,7 +391,7 @@
// We have to replace or restore the back and home button icons when exiting or entering
// carmode, respectively. Recents are not available in CarMode in nav bar so change
// to recent icon is not required.
- Drawable backIcon = (backAlt)
+ KeyButtonDrawable backIcon = (backAlt)
? getBackIconWithAlt(mUseCarModeUi, mVertical)
: getBackIcon(mUseCarModeUi, mVertical);
@@ -380,6 +414,8 @@
getMenuButton().setImageDrawable(mMenuIcon);
setDisabledFlags(mDisabledFlags, true);
+
+ mBarTransitions.reapplyDarkIntensity();
}
public void setDisabledFlags(int disabledFlags) {
@@ -565,6 +601,7 @@
private void updateRecentsIcon() {
getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
+ mBarTransitions.reapplyDarkIntensity();
}
public boolean isVertical() {
@@ -590,6 +627,8 @@
updateTaskSwitchHelper();
setNavigationIconHints(mNavigationIconHints, true);
+
+ getHomeButton().setVertical(mVertical);
}
public void onKeyguardOccludedChanged(boolean keyguardOccluded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index d543f49..345dcbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -127,9 +127,9 @@
return mPhoneStatusBar.getStatusBarHeight();
}
- protected boolean shouldShowNotification(NotificationData.Entry entry,
- NotificationData notificationData) {
- if (notificationData.isAmbient(entry.key)
+ protected boolean shouldShowNotificationIcon(NotificationData.Entry entry,
+ NotificationData notificationData, boolean showAmbient) {
+ if (notificationData.isAmbient(entry.key) && !showAmbient
&& !NotificationData.showNotificationEvenIfUnprovisioned(entry.notification)) {
return false;
}
@@ -148,8 +148,10 @@
*/
public void updateNotificationIcons(NotificationData notificationData) {
- updateIconsForLayout(notificationData, entry -> entry.icon, mNotificationIcons);
- updateIconsForLayout(notificationData, entry -> entry.expandedIcon, mShelfIcons);
+ updateIconsForLayout(notificationData, entry -> entry.icon, mNotificationIcons,
+ false /* showAmbient */);
+ updateIconsForLayout(notificationData, entry -> entry.expandedIcon, mShelfIcons,
+ NotificationShelf.SHOW_AMBIENT_ICONS);
applyNotificationIconsTint();
ArrayList<NotificationData.Entry> activeNotifications
@@ -173,10 +175,11 @@
* @param notificationData the notification data to look up which notifications are relevant
* @param function A function to look up an icon view based on an entry
* @param hostLayout which layout should be updated
+ * @param showAmbient should ambient notification icons be shown
*/
private void updateIconsForLayout(NotificationData notificationData,
Function<NotificationData.Entry, StatusBarIconView> function,
- NotificationIconContainer hostLayout) {
+ NotificationIconContainer hostLayout, boolean showAmbient) {
ArrayList<StatusBarIconView> toShow = new ArrayList<>(
mNotificationScrollLayout.getChildCount());
@@ -185,7 +188,7 @@
View view = mNotificationScrollLayout.getChildAt(i);
if (view instanceof ExpandableNotificationRow) {
NotificationData.Entry ent = ((ExpandableNotificationRow) view).getEntry();
- if (shouldShowNotification(ent, notificationData)) {
+ if (shouldShowNotificationIcon(ent, notificationData, showAmbient)) {
toShow.add(function.apply(ent));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 03697b8..d323e4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -31,15 +31,23 @@
import com.android.systemui.statusbar.stack.AnimationProperties;
import com.android.systemui.statusbar.stack.ViewState;
-import java.util.WeakHashMap;
+import java.util.HashMap;
/**
* A container for notification icons. It handles overflowing icons properly and positions them
* correctly on the screen.
*/
public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
+ /**
+ * A float value indicating how much before the overflow start the icons should transform into
+ * a dot. A value of 0 means that they are exactly at the end and a value of 1 means it starts
+ * 1 icon width early.
+ */
+ public static final float OVERFLOW_EARLY_AMOUNT = 0.2f;
+ private static final int NO_VALUE = Integer.MIN_VALUE;
private static final String TAG = "NotificationIconContainer";
private static final boolean DEBUG = false;
+ private static final int CANNED_ANIMATION_DURATION = 100;
private static final AnimationProperties DOT_ANIMATION_PROPERTIES = new AnimationProperties() {
private AnimationFilter mAnimationFilter = new AnimationFilter().animateX();
@@ -49,6 +57,26 @@
}
}.setDuration(200);
+ private static final AnimationProperties ICON_ANIMATION_PROPERTIES = new AnimationProperties() {
+ private AnimationFilter mAnimationFilter = new AnimationFilter().animateY().animateAlpha();
+ // TODO: add scale
+
+ @Override
+ public AnimationFilter getAnimationFilter() {
+ return mAnimationFilter;
+ }
+ }.setDuration(CANNED_ANIMATION_DURATION);
+
+ private static final AnimationProperties mTempProperties = new AnimationProperties() {
+ private AnimationFilter mAnimationFilter = new AnimationFilter();
+ // TODO: add scale
+
+ @Override
+ public AnimationFilter getAnimationFilter() {
+ return mAnimationFilter;
+ }
+ }.setDuration(CANNED_ANIMATION_DURATION);
+
private static final AnimationProperties ADD_ICON_PROPERTIES = new AnimationProperties() {
private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
@@ -59,14 +87,19 @@
}.setDuration(200).setDelay(50);
private boolean mShowAllIcons = true;
- private WeakHashMap<View, IconState> mIconStates = new WeakHashMap<>();
+ private final HashMap<View, IconState> mIconStates = new HashMap<>();
private int mDotPadding;
private int mStaticDotRadius;
- private int mActualLayoutWidth = -1;
- private float mActualPaddingEnd = -1;
- private float mActualPaddingStart = -1;
+ private int mActualLayoutWidth = NO_VALUE;
+ private float mActualPaddingEnd = NO_VALUE;
+ private float mActualPaddingStart = NO_VALUE;
private boolean mChangingViewPositions;
- private int mAnimationStartIndex = -1;
+ private int mAddAnimationStartIndex = -1;
+ private int mCannedAnimationStartIndex = -1;
+ private int mSpeedBumpIndex = -1;
+ private int mIconSize;
+ private float mOpenedAmount = 0.0f;
+ private float mVisualOverflowAdaption;
public NotificationIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -97,6 +130,7 @@
protected void onLayout(boolean changed, int l, int t, int r, int b) {
float centerY = getHeight() / 2.0f;
// we layout all our children on the left at the top
+ mIconSize = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
// We need to layout all children even the GONE ones, such that the heights are
@@ -105,6 +139,9 @@
int height = child.getMeasuredHeight();
int top = (int) (centerY - height / 2.0f);
child.layout(0, top, width, top + height);
+ if (i == 0) {
+ mIconSize = child.getWidth();
+ }
}
if (mShowAllIcons) {
resetViewStates();
@@ -121,7 +158,8 @@
childState.applyToView(child);
}
}
- mAnimationStartIndex = -1;
+ mAddAnimationStartIndex = -1;
+ mCannedAnimationStartIndex = -1;
}
@Override
@@ -133,10 +171,10 @@
int childIndex = indexOfChild(child);
if (childIndex < getChildCount() - 1
&& mIconStates.get(getChildAt(childIndex + 1)).iconAppearAmount > 0.0f) {
- if (mAnimationStartIndex < 0) {
- mAnimationStartIndex = childIndex;
+ if (mAddAnimationStartIndex < 0) {
+ mAddAnimationStartIndex = childIndex;
} else {
- mAnimationStartIndex = Math.min(mAnimationStartIndex, childIndex);
+ mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, childIndex);
}
}
}
@@ -149,10 +187,10 @@
if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
&& child.getVisibility() == VISIBLE) {
int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX());
- if (mAnimationStartIndex < 0) {
- mAnimationStartIndex = animationStartIndex;
+ if (mAddAnimationStartIndex < 0) {
+ mAddAnimationStartIndex = animationStartIndex;
} else {
- mAnimationStartIndex = Math.min(mAnimationStartIndex, animationStartIndex);
+ mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, animationStartIndex);
}
}
if (!mChangingViewPositions) {
@@ -177,14 +215,13 @@
return getChildCount();
}
- public WeakHashMap<View, IconState> resetViewStates() {
+ public void resetViewStates() {
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
ViewState iconState = mIconStates.get(view);
iconState.initFrom(view);
iconState.alpha = 1.0f;
}
- return mIconStates;
}
/**
@@ -194,42 +231,74 @@
*/
public void calculateIconTranslations() {
float translationX = getActualPaddingStart();
- int overflowingIconIndex = -1;
- int lastTwoIconWidth = 0;
+ int firstOverflowIndex = -1;
int childCount = getChildCount();
+ float layoutEnd = getLayoutEnd();
+ float overflowStart = layoutEnd - mIconSize * (2 + OVERFLOW_EARLY_AMOUNT);
+ boolean hasAmbient = mSpeedBumpIndex != -1 && mSpeedBumpIndex < getChildCount();
+ float visualOverflowStart = 0;
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
IconState iconState = mIconStates.get(view);
iconState.xTranslation = translationX;
- iconState.visibleState = StatusBarIconView.STATE_ICON;
- translationX += iconState.iconAppearAmount * view.getWidth();
- if (translationX > getLayoutEnd()) {
- // we are overflowing it with this icon
- overflowingIconIndex = i - 1;
- lastTwoIconWidth = view.getWidth();
- break;
+ boolean isAmbient = mSpeedBumpIndex != -1 && i >= mSpeedBumpIndex
+ && iconState.iconAppearAmount > 0.0f;
+ boolean noOverflowAfter = i == childCount - 1;
+ if (mOpenedAmount != 0.0f) {
+ noOverflowAfter = noOverflowAfter && !hasAmbient;
}
+ iconState.visibleState = StatusBarIconView.STATE_ICON;
+ if (firstOverflowIndex == -1 && (isAmbient
+ || (translationX >= (noOverflowAfter ? layoutEnd - mIconSize : overflowStart)))) {
+ firstOverflowIndex = noOverflowAfter ? i - 1 : i;
+ int totalDotLength = mStaticDotRadius * 6 + 2 * mDotPadding;
+ visualOverflowStart = overflowStart + mIconSize * (1 + OVERFLOW_EARLY_AMOUNT)
+ - totalDotLength / 2
+ - mIconSize * 0.5f + mStaticDotRadius;
+ if (isAmbient) {
+ visualOverflowStart = Math.min(translationX, visualOverflowStart
+ + mStaticDotRadius * 2 + mDotPadding);
+ } else {
+ visualOverflowStart += (translationX - overflowStart) / mIconSize
+ * (mStaticDotRadius * 2 + mDotPadding);
+ }
+ if (mShowAllIcons) {
+ // We want to perfectly position the overflow in the static state, such that
+ // it's perfectly centered instead of measuring it from the end.
+ mVisualOverflowAdaption = 0;
+ if (firstOverflowIndex != -1) {
+ View firstOverflowView = getChildAt(i);
+ IconState overflowState = mIconStates.get(firstOverflowView);
+ float totalAmount = layoutEnd - overflowState.xTranslation;
+ float newPosition = overflowState.xTranslation + totalAmount / 2
+ - totalDotLength / 2
+ - mIconSize * 0.5f + mStaticDotRadius;
+ mVisualOverflowAdaption = newPosition - visualOverflowStart;
+ visualOverflowStart = newPosition;
+ }
+ } else {
+ visualOverflowStart += mVisualOverflowAdaption * (1f - mOpenedAmount);
+ }
+ }
+ translationX += iconState.iconAppearAmount * view.getWidth();
}
- if (overflowingIconIndex != -1) {
+ if (firstOverflowIndex != -1) {
int numDots = 1;
- View overflowIcon = getChildAt(overflowingIconIndex);
- IconState overflowState = mIconStates.get(overflowIcon);
- lastTwoIconWidth += overflowIcon.getWidth();
- int dotWidth = mStaticDotRadius * 2 + mDotPadding;
- int totalDotLength = mStaticDotRadius * 6 + 2 * mDotPadding;
- translationX = (getLayoutEnd() - lastTwoIconWidth / 2 - totalDotLength / 2)
- - overflowIcon.getWidth() * 0.3f + mStaticDotRadius;
- float overflowStart = getLayoutEnd() - lastTwoIconWidth;
- float overlapAmount = (overflowState.xTranslation - overflowStart)
- / overflowIcon.getWidth();
- translationX += overlapAmount * dotWidth;
- for (int i = overflowingIconIndex; i < childCount; i++) {
+ translationX = visualOverflowStart;
+ for (int i = firstOverflowIndex; i < childCount; i++) {
View view = getChildAt(i);
IconState iconState = mIconStates.get(view);
+ int dotWidth = mStaticDotRadius * 2 + mDotPadding;
iconState.xTranslation = translationX;
if (numDots <= 3) {
- iconState.visibleState = StatusBarIconView.STATE_DOT;
- translationX += numDots == 3 ? 3 * dotWidth : dotWidth;
+ if (numDots == 1 && iconState.iconAppearAmount < 0.8f) {
+ iconState.visibleState = StatusBarIconView.STATE_ICON;
+ numDots--;
+ } else {
+ iconState.visibleState = StatusBarIconView.STATE_DOT;
+ }
+ translationX += (numDots == 3 ? 3 * dotWidth : dotWidth)
+ * iconState.iconAppearAmount;
} else {
iconState.visibleState = StatusBarIconView.STATE_HIDDEN;
}
@@ -250,14 +319,14 @@
}
private float getActualPaddingEnd() {
- if (mActualPaddingEnd < 0) {
+ if (mActualPaddingEnd == NO_VALUE) {
return getPaddingEnd();
}
return mActualPaddingEnd;
}
private float getActualPaddingStart() {
- if (mActualPaddingStart < 0) {
+ if (mActualPaddingStart == NO_VALUE) {
return getPaddingStart();
}
return mActualPaddingStart;
@@ -295,7 +364,7 @@
}
public int getActualWidth() {
- if (mActualLayoutWidth < 0) {
+ if (mActualLayoutWidth == NO_VALUE) {
return getWidth();
}
return mActualLayoutWidth;
@@ -305,28 +374,90 @@
mChangingViewPositions = changingViewPositions;
}
+ public IconState getIconState(StatusBarIconView icon) {
+ return mIconStates.get(icon);
+ }
+
+ public void setSpeedBumpIndex(int speedBumpIndex) {
+ mSpeedBumpIndex = speedBumpIndex;
+ }
+
+ public void setOpenedAmount(float expandAmount) {
+ mOpenedAmount = expandAmount;
+ }
+
+ public float getVisualOverflowAdaption() {
+ return mVisualOverflowAdaption;
+ }
+
+ public void setVisualOverflowAdaption(float visualOverflowAdaption) {
+ mVisualOverflowAdaption = visualOverflowAdaption;
+ }
+
+ public boolean hasOverflow() {
+ float width = (getChildCount() + OVERFLOW_EARLY_AMOUNT) * mIconSize;
+ return width - (getWidth() - getActualPaddingStart() - getActualPaddingEnd()) > 0;
+ }
+
+ public int getIconSize() {
+ return mIconSize;
+ }
+
public class IconState extends ViewState {
public float iconAppearAmount = 1.0f;
+ public float clampedAppearAmount = 1.0f;
public int visibleState;
public boolean justAdded = true;
+ public boolean needsCannedAnimation;
+ public boolean keepClampedPosition;
+ public boolean useFullTransitionAmount;
+ public boolean translateContent;
@Override
public void applyToView(View view) {
if (view instanceof StatusBarIconView) {
StatusBarIconView icon = (StatusBarIconView) view;
- AnimationProperties animationProperties = DOT_ANIMATION_PROPERTIES;
+ boolean animate = false;
+ AnimationProperties animationProperties = null;
if (justAdded) {
super.applyToView(icon);
icon.setAlpha(0.0f);
icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, false /* animate */);
animationProperties = ADD_ICON_PROPERTIES;
+ animate = true;
+ } else if (visibleState != icon.getVisibleState()) {
+ animationProperties = DOT_ANIMATION_PROPERTIES;
+ animate = true;
}
- boolean animate = visibleState != icon.getVisibleState() || justAdded;
- if (!animate && mAnimationStartIndex >= 0
+ if (!animate && mAddAnimationStartIndex >= 0
+ && indexOfChild(view) >= mAddAnimationStartIndex
&& (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
|| visibleState != StatusBarIconView.STATE_HIDDEN)) {
- int viewIndex = indexOfChild(view);
- animate = viewIndex >= mAnimationStartIndex;
+ animationProperties = DOT_ANIMATION_PROPERTIES;
+ animate = true;
+ }
+ if (needsCannedAnimation) {
+ AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
+ animationFilter.reset();
+ animationFilter.combineFilter(ICON_ANIMATION_PROPERTIES.getAnimationFilter());
+ if (animationProperties != null) {
+ animationFilter.combineFilter(animationProperties.getAnimationFilter());
+ }
+ animationProperties = mTempProperties;
+ animationProperties.setDuration(CANNED_ANIMATION_DURATION);
+ animate = true;
+ mCannedAnimationStartIndex = indexOfChild(view);
+ }
+ if (!animate && mCannedAnimationStartIndex >= 0
+ && indexOfChild(view) > mCannedAnimationStartIndex
+ && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
+ || visibleState != StatusBarIconView.STATE_HIDDEN)) {
+ AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
+ animationFilter.reset();
+ animationFilter.animateX();
+ animationProperties = mTempProperties;
+ animationProperties.setDuration(CANNED_ANIMATION_DURATION);
+ animate = true;
}
icon.setVisibleState(visibleState);
if (animate) {
@@ -336,6 +467,13 @@
}
}
justAdded = false;
+ needsCannedAnimation = false;
+ }
+
+ protected void onYTranslationAnimationFinished(View view) {
+ if (hidden) {
+ view.setVisibility(INVISIBLE);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 99e98f2e..a239cb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -105,7 +105,7 @@
private boolean mAnimateNextTopPaddingChange;
private int mTrackingPointer;
- private VelocityTracker mVelocityTracker;
+ private VelocityTracker mQsVelocityTracker;
private boolean mQsTracking;
/**
@@ -208,6 +208,7 @@
};
private NotificationGroupManager mGroupManager;
private boolean mOpening;
+ private int mIndicationBottomPadding;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -273,6 +274,8 @@
R.dimen.notification_panel_min_side_margin);
mMaxFadeoutHeight = getResources().getDimensionPixelSize(
R.dimen.max_notification_fadeout_height);
+ mIndicationBottomPadding = getResources().getDimensionPixelSize(
+ R.dimen.keyguard_indication_bottom_padding);
}
public void updateResources() {
@@ -406,7 +409,8 @@
R.dimen.notification_divider_height));
float shelfSize = mNotificationStackScroller.getNotificationShelf().getIntrinsicHeight()
+ notificationPadding;
- float availableSpace = mNotificationStackScroller.getHeight() - minPadding - shelfSize;
+ float availableSpace = mNotificationStackScroller.getHeight() - minPadding - shelfSize
+ - mIndicationBottomPadding;
int count = 0;
for (int i = 0; i < mNotificationStackScroller.getChildCount(); i++) {
ExpandableView child = (ExpandableView) mNotificationStackScroller.getChildAt(i);
@@ -684,7 +688,7 @@
}
private void flingQsWithCurrentVelocity(float y, boolean isCancelMotionEvent) {
- float vel = getCurrentVelocity();
+ float vel = getCurrentQSVelocity();
final boolean expandsQs = flingExpandsQs(vel);
if (expandsQs) {
logQsSwipeDown(y);
@@ -693,7 +697,7 @@
}
private void logQsSwipeDown(float y) {
- float vel = getCurrentVelocity();
+ float vel = getCurrentQSVelocity();
final int gesture = mStatusBarState == StatusBarState.KEYGUARD
? EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS
: EventLogConstants.SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS;
@@ -922,9 +926,9 @@
flingQsWithCurrentVelocity(y,
event.getActionMasked() == MotionEvent.ACTION_CANCEL);
}
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
+ if (mQsVelocityTracker != null) {
+ mQsVelocityTracker.recycle();
+ mQsVelocityTracker = null;
}
break;
}
@@ -1286,24 +1290,24 @@
}
private void trackMovement(MotionEvent event) {
- if (mVelocityTracker != null) mVelocityTracker.addMovement(event);
+ if (mQsVelocityTracker != null) mQsVelocityTracker.addMovement(event);
mLastTouchX = event.getX();
mLastTouchY = event.getY();
}
private void initVelocityTracker() {
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
+ if (mQsVelocityTracker != null) {
+ mQsVelocityTracker.recycle();
}
- mVelocityTracker = VelocityTracker.obtain();
+ mQsVelocityTracker = VelocityTracker.obtain();
}
- private float getCurrentVelocity() {
- if (mVelocityTracker == null) {
+ private float getCurrentQSVelocity() {
+ if (mQsVelocityTracker == null) {
return 0;
}
- mVelocityTracker.computeCurrentVelocity(1000);
- return mVelocityTracker.getYVelocity();
+ mQsVelocityTracker.computeCurrentVelocity(1000);
+ return mQsVelocityTracker.getYVelocity();
}
private void cancelQsAnimation() {
@@ -2278,6 +2282,9 @@
}
protected void updateExpandedHeight(float expandedHeight) {
+ if (mTracking) {
+ mNotificationStackScroller.setExpandingVelocity(getCurrentExpandVelocity());
+ }
mNotificationStackScroller.setExpandedHeight(expandedHeight);
updateKeyguardBottomAreaAlpha();
setOpening(expandedHeight <= getOpeningHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index f16c834..55dd578 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -306,6 +306,7 @@
}
break;
case MotionEvent.ACTION_MOVE:
+ trackMovement(event);
float h = y - mInitialTouchY;
// If the panel was collapsed when touching, we only need to check for the
@@ -346,8 +347,6 @@
!isTrackingBlocked()) {
setExpandedHeightInternal(newHeight);
}
-
- trackMovement(event);
break;
case MotionEvent.ACTION_UP:
@@ -449,6 +448,14 @@
mPeekTouching = false;
}
+ protected float getCurrentExpandVelocity() {
+ if (mVelocityTracker == null) {
+ return 0;
+ }
+ mVelocityTracker.computeCurrentVelocity(1000);
+ return mVelocityTracker.getYVelocity();
+ }
+
private int getFalsingThreshold() {
float factor = mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
return (int) (mUnlockFalsingThreshold * factor);
@@ -685,7 +692,7 @@
mOverExpandedBeforeFling = getOverExpansionAmount() > 0f;
ValueAnimator animator = createHeightAnimator(target);
if (expand) {
- if (expandBecauseOfFalsing) {
+ if (expandBecauseOfFalsing && vel < 0) {
vel = 0;
}
mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 2b74c847..ae9d068 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -22,6 +22,7 @@
import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
+
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
@@ -83,8 +84,8 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.Trace;
import android.os.SystemProperties;
+import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
@@ -123,13 +124,13 @@
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.LatencyTracker;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.DemoMode;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
-import com.android.keyguard.LatencyTracker;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
@@ -145,10 +146,12 @@
import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
import com.android.systemui.recents.events.activity.UndockingTaskEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.stackdivider.WindowManagerProxy;
import com.android.systemui.statusbar.ActivatableNotificationView;
@@ -178,19 +181,20 @@
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.CastControllerImpl;
import com.android.systemui.statusbar.policy.EncryptionHelper;
-import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HotspotControllerImpl;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
import com.android.systemui.statusbar.policy.SecurityControllerImpl;
-import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -319,19 +323,19 @@
NetworkControllerImpl mNetworkController;
HotspotControllerImpl mHotspotController;
RotationLockControllerImpl mRotationLockController;
- UserInfoController mUserInfoController;
+ UserInfoControllerImpl mUserInfoController;
protected ZenModeController mZenModeController;
CastControllerImpl mCastController;
VolumeComponent mVolumeComponent;
KeyguardUserSwitcher mKeyguardUserSwitcher;
- FlashlightController mFlashlightController;
+ FlashlightControllerImpl mFlashlightController;
protected UserSwitcherController mUserSwitcherController;
- NextAlarmController mNextAlarmController;
- protected KeyguardMonitor mKeyguardMonitor;
+ NextAlarmControllerImpl mNextAlarmController;
+ protected KeyguardMonitorImpl mKeyguardMonitor;
BrightnessMirrorController mBrightnessMirrorController;
AccessibilityController mAccessibilityController;
protected FingerprintUnlockController mFingerprintUnlockController;
- LightStatusBarController mLightStatusBarController;
+ LightBarController mLightBarController;
protected LockscreenWallpaper mLockscreenWallpaper;
int mNaturalBarHeight = -1;
@@ -827,10 +831,45 @@
mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
}
+ mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
+ mKeyguardStatusView =
+ (KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view);
+ mKeyguardBottomArea =
+ (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
+ mKeyguardBottomArea.setActivityStarter(this);
+ mKeyguardBottomArea.setAssistManager(mAssistManager);
+ mKeyguardIndicationController = new KeyguardIndicationController(mContext,
+ (ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
+ mKeyguardBottomArea.getLockIcon());
+ mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
+
+ // set the initial view visibility
+ setAreThereNotifications();
+
+ createIconController();
+
+ mBatteryController = createBatteryController();
+ mBatteryController.addCallback(new BatteryStateChangeCallback() {
+ @Override
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ mHandler.post(mCheckBarModes);
+ if (mDozeServiceHost != null) {
+ mDozeServiceHost.firePowerSaveChanged(isPowerSave);
+ }
+ }
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ // noop
+ }
+ });
+
+ mLightBarController = new LightBarController(mIconController, mNavigationBarView,
+ mBatteryController);
+
ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
- mScrimController = SystemUIFactory.getInstance().createScrimController(
+ mScrimController = SystemUIFactory.getInstance().createScrimController(mLightBarController,
scrimBehind, scrimInFront, headsUpScrim, mLockscreenWallpaper);
if (mScrimSrcModeEnabled) {
Runnable runnable = new Runnable() {
@@ -849,23 +888,6 @@
mStatusBarView.setScrimController(mScrimController);
mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller);
- mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
- mKeyguardStatusView =
- (KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view);
- mKeyguardBottomArea =
- (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
- mKeyguardBottomArea.setActivityStarter(this);
- mKeyguardBottomArea.setAssistManager(mAssistManager);
- mKeyguardIndicationController = new KeyguardIndicationController(mContext,
- (ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
- mKeyguardBottomArea.getLockIcon());
- mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
-
- // set the initial view visibility
- setAreThereNotifications();
-
- createIconController();
-
// Background thread for any controllers that need it.
mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
@@ -873,20 +895,6 @@
// Other icons
mLocationController = new LocationControllerImpl(mContext,
mHandlerThread.getLooper()); // will post a notification
- mBatteryController = createBatteryController();
- mBatteryController.addCallback(new BatteryStateChangeCallback() {
- @Override
- public void onPowerSaveChanged(boolean isPowerSave) {
- mHandler.post(mCheckBarModes);
- if (mDozeServiceHost != null) {
- mDozeServiceHost.firePowerSaveChanged(isPowerSave);
- }
- }
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- // noop
- }
- });
mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
mNetworkController.setUserSetupComplete(mUserSetup);
mHotspotController = new HotspotControllerImpl(mContext);
@@ -895,7 +903,7 @@
if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {
mRotationLockController = new RotationLockControllerImpl(mContext);
}
- mUserInfoController = new UserInfoController(mContext);
+ mUserInfoController = new UserInfoControllerImpl(mContext);
mVolumeComponent = getComponent(VolumeComponent.class);
if (mVolumeComponent != null) {
mZenModeController = mVolumeComponent.getZenController();
@@ -906,16 +914,14 @@
initSignalCluster(mKeyguardStatusBar);
initEmergencyCryptkeeperText();
- mFlashlightController = new FlashlightController(mContext);
+ mFlashlightController = new FlashlightControllerImpl(mContext);
mKeyguardBottomArea.setFlashlightController(mFlashlightController);
mKeyguardBottomArea.setPhoneStatusBar(this);
mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
mAccessibilityController = new AccessibilityController(mContext);
mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
- mNextAlarmController = new NextAlarmController(mContext);
- mLightStatusBarController = new LightStatusBarController(mIconController,
- mBatteryController);
- mKeyguardMonitor = new KeyguardMonitor(mContext);
+ mNextAlarmController = new NextAlarmControllerImpl(mContext);
+ mKeyguardMonitor = new KeyguardMonitorImpl(mContext);
mUserSwitcherController = createUserSwitcherController();
if (UserManager.get(mContext).isUserSwitcherEnabled()) {
createUserSwitcher();
@@ -1303,7 +1309,7 @@
});
mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
- mLightStatusBarController.setFingerprintUnlockController(mFingerprintUnlockController);
+ mLightBarController.setFingerprintUnlockController(mFingerprintUnlockController);
Trace.endSection();
}
@@ -1358,6 +1364,14 @@
return false;
}
+ ActivityManager.RunningTaskInfo runningTask =
+ Recents.getSystemServices().getRunningTask();
+ boolean isRunningTaskInHomeOrRecentsStack = runningTask != null &&
+ ActivityManager.StackId.isHomeOrRecentsStack(runningTask.stackId);
+ if (isRunningTaskInHomeOrRecentsStack) {
+ return false;
+ }
+
toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS,
MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
return true;
@@ -3078,6 +3092,7 @@
Integer.toHexString(oldVal), Integer.toHexString(newVal),
Integer.toHexString(diff)));
boolean sbModeChanged = false;
+ boolean nbModeChanged = false;
if (diff != 0) {
mSystemUiVisibility = newVal;
@@ -3101,7 +3116,7 @@
View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
View.NAVIGATION_BAR_TRANSPARENT);
sbModeChanged = sbMode != -1;
- final boolean nbModeChanged = nbMode != -1;
+ nbModeChanged = nbMode != -1;
boolean checkBarModes = false;
if (sbModeChanged && sbMode != mStatusBarMode) {
mStatusBarMode = sbMode;
@@ -3131,8 +3146,9 @@
notifyUiVisibilityChanged(mSystemUiVisibility);
}
- mLightStatusBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis,
- mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode);
+ mLightBarController.onSystemUiVisibilityChanged(vis, fullscreenStackVis, dockedStackVis,
+ mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode,
+ nbModeChanged, mNavigationBarMode);
}
protected int computeStatusBarMode(int oldVal, int newVal) {
@@ -3572,10 +3588,18 @@
final boolean dismissShade,
final boolean afterKeyguardGone,
final boolean deferred) {
- dismissKeyguardThenExecute(() -> {
+ final Runnable dismissAction = () -> {
if (runnable != null) {
AsyncTask.execute(runnable);
}
+ };
+ dismissKeyguardThenExecute(() -> {
+ if (mStatusBarKeyguardViewManager.isShowing()
+ && mStatusBarKeyguardViewManager.isOccluded()) {
+ mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
+ } else {
+ dismissAction.run();
+ }
if (dismissShade) {
if (mExpandedVisible) {
animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */,
@@ -3664,8 +3688,6 @@
private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
boolean afterKeyguardGone) {
- afterKeyguardGone |= mStatusBarKeyguardViewManager.isShowing()
- && mStatusBarKeyguardViewManager.isOccluded();
if (mStatusBarKeyguardViewManager.isShowing()) {
mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
afterKeyguardGone);
@@ -4187,8 +4209,14 @@
onLaunchTransitionFadingEnded();
}
});
- mIconController.appTransitionStarting(SystemClock.uptimeMillis(),
- StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
+ mIconController.getTransitionsController().appTransitionStarting(
+ SystemClock.uptimeMillis(),
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionStarting(
+ SystemClock.uptimeMillis(),
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+ }
}
};
if (mNotificationPanel.isLaunchTransitionRunning()) {
@@ -4319,7 +4347,10 @@
// Treat Keyguard exit animation as an app transition to achieve nice transition for status
// bar.
mKeyguardGoingAway = true;
- mIconController.appTransitionPending();
+ mIconController.getTransitionsController().appTransitionPending();
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionPending();
+ }
}
/**
@@ -4334,11 +4365,16 @@
mKeyguardFadingAwayDelay = delay;
mKeyguardFadingAwayDuration = fadeoutDuration;
mWaitingForKeyguardExit = false;
- mIconController.appTransitionStarting(
+ mIconController.getTransitionsController().appTransitionStarting(
startTime + fadeoutDuration
- - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION,
- StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
+ - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
recomputeDisableFlags(fadeoutDuration > 0 /* animate */);
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionStarting(
+ startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+ }
}
public boolean isKeyguardFadingAway() {
@@ -4559,6 +4595,7 @@
mGroupManager.setStatusBarState(state);
mFalsingManager.setStatusBarState(state);
mStatusBarWindowManager.setStatusBarState(state);
+ mStackScroller.setStatusBarState(state);
updateReportRejectedTouchVisibility();
updateDozing();
}
@@ -4968,13 +5005,19 @@
// Use own timings when Keyguard is going away, see keyguardGoingAway and
// setKeyguardFadingAway
if (!mKeyguardFadingAway) {
- mIconController.appTransitionPending();
+ mIconController.getTransitionsController().appTransitionPending();
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionPending();
+ }
}
}
@Override
public void appTransitionCancelled() {
- mIconController.appTransitionCancelled();
+ mIconController.getTransitionsController().appTransitionCancelled();
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionCancelled();
+ }
EventBus.getDefault().send(new AppTransitionFinishedEvent());
}
@@ -4984,7 +5027,11 @@
// Use own timings when Keyguard is going away, see keyguardGoingAway and
// setKeyguardFadingAway.
if (!mKeyguardGoingAway) {
- mIconController.appTransitionStarting(startTime, duration);
+ mIconController.getTransitionsController().appTransitionStarting(startTime, duration);
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionStarting(
+ startTime, duration);
+ }
}
if (mIconPolicy != null) {
mIconPolicy.appTransitionStarting(startTime, duration);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index fc15477..567ab3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -143,7 +143,7 @@
mBattery = battery;
mIconController = iconController;
mNextAlarmController = nextAlarmController;
- mProfileController = new ManagedProfileController(this);
+ mProfileController = new ManagedProfileControllerImpl(this);
mHandlerThread = new HandlerThread(QSTileHost.class.getSimpleName(),
Process.THREAD_PRIORITY_BACKGROUND);
@@ -335,12 +335,16 @@
QSTile<?> tile = mTiles.get(tileSpec);
if (tile != null && (!(tile instanceof CustomTile)
|| ((CustomTile) tile).getUser() == currentUser)) {
- if (DEBUG) Log.d(TAG, "Adding " + tile);
- tile.removeCallbacks();
- if (!(tile instanceof CustomTile) && mCurrentUser != currentUser) {
- tile.userSwitch(currentUser);
+ if (tile.isAvailable()) {
+ if (DEBUG) Log.d(TAG, "Adding " + tile);
+ tile.removeCallbacks();
+ if (!(tile instanceof CustomTile) && mCurrentUser != currentUser) {
+ tile.userSwitch(currentUser);
+ }
+ newTiles.put(tileSpec, tile);
+ } else {
+ tile.destroy();
}
- newTiles.put(tileSpec, tile);
} else {
if (DEBUG) Log.d(TAG, "Creating tile: " + tileSpec);
try {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 28aed87..08a91bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -32,6 +32,7 @@
import android.widget.TextView;
import android.widget.Toast;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.keyguard.KeyguardStatusView;
@@ -236,10 +237,12 @@
}
@Override
- protected void onDetachedFromWindow() {
+ @VisibleForTesting
+ public void onDetachedFromWindow() {
setListening(false);
mHost.getUserInfoController().removeCallback(this);
mHost.getNetworkController().removeEmergencyListener(this);
+ mHost.getUserInfoController().removeCallback(this);
super.onDetachedFromWindow();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 0e74e57..944495e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -59,6 +59,7 @@
private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
private static final int TAG_END_ALPHA = R.id.scrim_alpha_end;
+ private final LightBarController mLightBarController;
protected final ScrimView mScrimBehind;
private final ScrimView mScrimInFront;
private final UnlockMethodCache mUnlockMethodCache;
@@ -99,13 +100,15 @@
private boolean mKeyguardFadingOutInProgress;
private ValueAnimator mKeyguardFadeoutAnimation;
- public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim) {
+ public ScrimController(LightBarController lightBarController, ScrimView scrimBehind,
+ ScrimView scrimInFront, View headsUpScrim) {
mScrimBehind = scrimBehind;
mScrimInFront = scrimInFront;
mHeadsUpScrim = headsUpScrim;
final Context context = scrimBehind.getContext();
mUnlockMethodCache = UnlockMethodCache.getInstance(context);
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
+ mLightBarController = lightBarController;
updateHeadsUpScrim(false);
}
@@ -341,6 +344,7 @@
alpha = Math.max(0.0f, Math.min(1.0f, alpha));
mCurrentHeadsUpAlpha = alpha;
}
+ mLightBarController.setScrimAlpha(mCurrentBehindAlpha);
}
protected void updateScrimColor(View scrim) {
@@ -556,10 +560,6 @@
mScrimBehind.setExcludedArea(area);
}
- public void setLeftInset(int inset) {
- mScrimBehind.setLeftInset(inset);
- }
-
public int getScrimBehindColor() {
return mScrimBehind.getScrimColorWithAlpha();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index a948a08..a0425e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -60,7 +60,6 @@
*/
public class StatusBarIconController extends StatusBarIconList implements Tunable {
- public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
public static final String ICON_BLACKLIST = "icon_blacklist";
public static final int DEFAULT_ICON_TINT = Color.WHITE;
@@ -90,31 +89,16 @@
private static final Rect sTmpRect = new Rect();
private static final int[] sTmpInt2 = new int[2];
- private boolean mTransitionPending;
- private boolean mTintChangePending;
- private float mPendingDarkIntensity;
- private ValueAnimator mTintAnimator;
-
private int mDarkModeIconColorSingleTone;
private int mLightModeIconColorSingleTone;
- private final Handler mHandler;
- private boolean mTransitionDeferring;
- private long mTransitionDeferringStartTime;
- private long mTransitionDeferringDuration;
+ private final LightBarTransitionsController mTransitionsController;
private boolean mClockVisibleByPolicy = true;
private boolean mClockVisibleByUser = true;
private final ArraySet<String> mIconBlacklist = new ArraySet<>();
- private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
- @Override
- public void run() {
- mTransitionDeferring = false;
- }
- };
-
public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
PhoneStatusBar phoneStatusBar) {
super(context.getResources().getStringArray(
@@ -144,16 +128,21 @@
mClock = (TextView) statusBar.findViewById(R.id.clock);
mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
- mHandler = new Handler();
loadDimens();
TunerService.get(mContext).addTunable(this, ICON_BLACKLIST);
+
+ mTransitionsController = new LightBarTransitionsController(this::setIconTintInternal);
}
public void setSignalCluster(SignalClusterView signalCluster) {
mSignalCluster = signalCluster;
}
+ public LightBarTransitionsController getTransitionsController() {
+ return mTransitionsController;
+ }
+
/**
* Looks up the scale factor for status bar icons and scales the battery view by that amount.
*/
@@ -444,41 +433,6 @@
mNotificationIconAreaController.setTintArea(darkArea);
}
- public void setIconsDark(boolean dark, boolean animate) {
- if (!animate) {
- setIconTintInternal(dark ? 1.0f : 0.0f);
- } else if (mTransitionPending) {
- deferIconTintChange(dark ? 1.0f : 0.0f);
- } else if (mTransitionDeferring) {
- animateIconTint(dark ? 1.0f : 0.0f,
- Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
- mTransitionDeferringDuration);
- } else {
- animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
- }
- }
-
- private void animateIconTint(float targetDarkIntensity, long delay,
- long duration) {
- if (mTintAnimator != null) {
- mTintAnimator.cancel();
- }
- if (mDarkIntensity == targetDarkIntensity) {
- return;
- }
- mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
- mTintAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- setIconTintInternal((Float) animation.getAnimatedValue());
- }
- });
- mTintAnimator.setDuration(duration);
- mTintAnimator.setStartDelay(delay);
- mTintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- mTintAnimator.start();
- }
-
private void setIconTintInternal(float darkIntensity) {
mDarkIntensity = darkIntensity;
mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
@@ -487,14 +441,6 @@
applyIconTint();
}
- private void deferIconTintChange(float darkIntensity) {
- if (mTintChangePending && darkIntensity == mPendingDarkIntensity) {
- return;
- }
- mTintChangePending = true;
- mPendingDarkIntensity = darkIntensity;
- }
-
/**
* @return the tint to apply to {@param view} depending on the desired tint {@param color} and
* the screen {@param tintArea} in which to apply that tint
@@ -551,38 +497,6 @@
mClock.setTextColor(getTint(mTintArea, mClock, mIconTint));
}
- public void appTransitionPending() {
- mTransitionPending = true;
- }
-
- public void appTransitionCancelled() {
- if (mTransitionPending && mTintChangePending) {
- mTintChangePending = false;
- animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
- }
- mTransitionPending = false;
- }
-
- public void appTransitionStarting(long startTime, long duration) {
- if (mTransitionPending && mTintChangePending) {
- mTintChangePending = false;
- animateIconTint(mPendingDarkIntensity,
- Math.max(0, startTime - SystemClock.uptimeMillis()),
- duration);
-
- } else if (mTransitionPending) {
-
- // If we don't have a pending tint change yet, the change might come in the future until
- // startTime is reached.
- mTransitionDeferring = true;
- mTransitionDeferringStartTime = startTime;
- mTransitionDeferringDuration = duration;
- mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
- mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
- }
- mTransitionPending = false;
- }
-
public static ArraySet<String> getIconBlacklist(String blackListStr) {
ArraySet<String> ret = new ArraySet<String>();
if (blackListStr == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 4263670..2e279b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -40,6 +40,8 @@
import static com.android.keyguard.KeyguardHostView.OnDismissAction;
import static com.android.systemui.statusbar.phone.FingerprintUnlockController.*;
+import java.util.ArrayList;
+
/**
* Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
* via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
@@ -90,6 +92,7 @@
protected boolean mLastRemoteInputActive;
private OnDismissAction mAfterKeyguardGoneAction;
+ private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
private boolean mDeviceWillWakeUp;
private boolean mDeferScrimFadeOut;
@@ -165,6 +168,13 @@
}
/**
+ * Adds a {@param runnable} to be executed after Keyguard is gone.
+ */
+ public void addAfterKeyguardGoneRunnable(Runnable runnable) {
+ mAfterKeyguardGoneRunnables.add(runnable);
+ }
+
+ /**
* Reset the state of the view.
*/
public void reset(boolean hideBouncerWhenShowing) {
@@ -418,6 +428,10 @@
mAfterKeyguardGoneAction.onDismiss();
mAfterKeyguardGoneAction = null;
}
+ for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
+ mAfterKeyguardGoneRunnables.get(i).run();
+ }
+ mAfterKeyguardGoneRunnables.clear();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index f6dd88d9..487f0e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -130,7 +130,6 @@
}
private void applyMargins() {
- mService.mScrimController.setLeftInset(mLeftInset);
final int N = getChildCount();
for (int i = 0; i < N; i++) {
View child = getChildAt(i);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
index e5f1e68..0df7859 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
@@ -14,92 +14,14 @@
package com.android.systemui.statusbar.policy;
-import android.content.Context;
-import android.net.INetworkPolicyListener;
-import android.net.NetworkPolicyManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
-
import com.android.systemui.statusbar.policy.DataSaverController.Listener;
-import java.util.ArrayList;
+public interface DataSaverController extends CallbackController<Listener> {
-public class DataSaverController implements CallbackController<Listener> {
-
- private final Handler mHandler = new Handler(Looper.getMainLooper());
- private final ArrayList<Listener> mListeners = new ArrayList<>();
- private final NetworkPolicyManager mPolicyManager;
-
- public DataSaverController(Context context) {
- mPolicyManager = NetworkPolicyManager.from(context);
- }
-
- private void handleRestrictBackgroundChanged(boolean isDataSaving) {
- synchronized (mListeners) {
- for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onDataSaverChanged(isDataSaving);
- }
- }
- }
-
- public void addCallback(Listener listener) {
- synchronized (mListeners) {
- mListeners.add(listener);
- if (mListeners.size() == 1) {
- mPolicyManager.registerListener(mPolicyListener);
- }
- }
- listener.onDataSaverChanged(isDataSaverEnabled());
- }
-
- public void removeCallback(Listener listener) {
- synchronized (mListeners) {
- mListeners.remove(listener);
- if (mListeners.size() == 0) {
- mPolicyManager.unregisterListener(mPolicyListener);
- }
- }
- }
-
- public boolean isDataSaverEnabled() {
- return mPolicyManager.getRestrictBackground();
- }
-
- public void setDataSaverEnabled(boolean enabled) {
- mPolicyManager.setRestrictBackground(enabled);
- try {
- mPolicyListener.onRestrictBackgroundChanged(enabled);
- } catch (RemoteException e) {
- }
- }
-
- private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
- @Override
- public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
- }
-
- @Override
- public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
- }
-
- @Override
- public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- handleRestrictBackgroundChanged(isDataSaving);
- }
- });
- }
-
- @Override
- public void onUidPoliciesChanged(int uid, int uidPolicies) throws RemoteException {
- }
- };
+ boolean isDataSaverEnabled();
+ void setDataSaverEnabled(boolean enabled);
public interface Listener {
void onDataSaverChanged(boolean isDataSaving);
}
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
new file mode 100644
index 0000000..2951943
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
@@ -0,0 +1,101 @@
+/*
+ * 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 com.android.systemui.statusbar.policy;
+
+import android.content.Context;
+import android.net.INetworkPolicyListener;
+import android.net.NetworkPolicyManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+
+import com.android.systemui.statusbar.policy.DataSaverController.Listener;
+
+import java.util.ArrayList;
+
+public class DataSaverControllerImpl implements DataSaverController {
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+ private final ArrayList<Listener> mListeners = new ArrayList<>();
+ private final NetworkPolicyManager mPolicyManager;
+
+ public DataSaverControllerImpl(Context context) {
+ mPolicyManager = NetworkPolicyManager.from(context);
+ }
+
+ private void handleRestrictBackgroundChanged(boolean isDataSaving) {
+ synchronized (mListeners) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onDataSaverChanged(isDataSaving);
+ }
+ }
+ }
+
+ public void addCallback(Listener listener) {
+ synchronized (mListeners) {
+ mListeners.add(listener);
+ if (mListeners.size() == 1) {
+ mPolicyManager.registerListener(mPolicyListener);
+ }
+ }
+ listener.onDataSaverChanged(isDataSaverEnabled());
+ }
+
+ public void removeCallback(Listener listener) {
+ synchronized (mListeners) {
+ mListeners.remove(listener);
+ if (mListeners.size() == 0) {
+ mPolicyManager.unregisterListener(mPolicyListener);
+ }
+ }
+ }
+
+ public boolean isDataSaverEnabled() {
+ return mPolicyManager.getRestrictBackground();
+ }
+
+ public void setDataSaverEnabled(boolean enabled) {
+ mPolicyManager.setRestrictBackground(enabled);
+ try {
+ mPolicyListener.onRestrictBackgroundChanged(enabled);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+ @Override
+ public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
+ }
+
+ @Override
+ public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
+ }
+
+ @Override
+ public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ handleRestrictBackgroundChanged(isDataSaving);
+ }
+ });
+ }
+
+ @Override
+ public void onUidPoliciesChanged(int uid, int uidPolicies) throws RemoteException {
+ }
+ };
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
index 8abfb89..a2d1baf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.policy;
import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -41,12 +42,20 @@
public class EmergencyCryptkeeperText extends TextView {
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
+ private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onPhoneStateChanged(int phoneState) {
update();
}
};
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
+ update();
+ }
+ }
+ };
public EmergencyCryptkeeperText(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -58,6 +67,8 @@
super.onAttachedToWindow();
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
mKeyguardUpdateMonitor.registerCallback(mCallback);
+ getContext().registerReceiver(mReceiver,
+ new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
update();
}
@@ -67,6 +78,7 @@
if (mKeyguardUpdateMonitor != null) {
mKeyguardUpdateMonitor.removeCallback(mCallback);
}
+ getContext().unregisterReceiver(mReceiver);
}
public void update() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 0f77b03..6023f3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -1,255 +1,27 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * 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
+ * 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.android.systemui.statusbar.policy;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.text.TextUtils;
-import android.util.Log;
-
import com.android.systemui.statusbar.policy.FlashlightController.FlashlightListener;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
+public interface FlashlightController extends CallbackController<FlashlightListener> {
-/**
- * Manages the flashlight.
- */
-public class FlashlightController implements CallbackController<FlashlightListener> {
-
- private static final String TAG = "FlashlightController";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- private static final int DISPATCH_ERROR = 0;
- private static final int DISPATCH_CHANGED = 1;
- private static final int DISPATCH_AVAILABILITY_CHANGED = 2;
-
- private final CameraManager mCameraManager;
- private final Context mContext;
- /** Call {@link #ensureHandler()} before using */
- private Handler mHandler;
-
- /** Lock on mListeners when accessing */
- private final ArrayList<WeakReference<FlashlightListener>> mListeners = new ArrayList<>(1);
-
- /** Lock on {@code this} when accessing */
- private boolean mFlashlightEnabled;
-
- private String mCameraId;
- private boolean mTorchAvailable;
-
- public FlashlightController(Context context) {
- mContext = context;
- mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
-
- tryInitCamera();
- }
-
- private void tryInitCamera() {
- try {
- mCameraId = getCameraId();
- } catch (Throwable e) {
- Log.e(TAG, "Couldn't initialize.", e);
- return;
- }
-
- if (mCameraId != null) {
- ensureHandler();
- mCameraManager.registerTorchCallback(mTorchCallback, mHandler);
- }
- }
-
- public void setFlashlight(boolean enabled) {
- boolean pendingError = false;
- synchronized (this) {
- if (mCameraId == null) return;
- if (mFlashlightEnabled != enabled) {
- mFlashlightEnabled = enabled;
- try {
- mCameraManager.setTorchMode(mCameraId, enabled);
- } catch (CameraAccessException e) {
- Log.e(TAG, "Couldn't set torch mode", e);
- mFlashlightEnabled = false;
- pendingError = true;
- }
- }
- }
- dispatchModeChanged(mFlashlightEnabled);
- if (pendingError) {
- dispatchError();
- }
- }
-
- public boolean hasFlashlight() {
- return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
- }
-
- public synchronized boolean isEnabled() {
- return mFlashlightEnabled;
- }
-
- public synchronized boolean isAvailable() {
- return mTorchAvailable;
- }
-
- public void addCallback(FlashlightListener l) {
- synchronized (mListeners) {
- if (mCameraId == null) {
- tryInitCamera();
- }
- cleanUpListenersLocked(l);
- mListeners.add(new WeakReference<>(l));
- }
- }
-
- public void removeCallback(FlashlightListener l) {
- synchronized (mListeners) {
- cleanUpListenersLocked(l);
- }
- }
-
- private synchronized void ensureHandler() {
- if (mHandler == null) {
- HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
- thread.start();
- mHandler = new Handler(thread.getLooper());
- }
- }
-
- private String getCameraId() throws CameraAccessException {
- String[] ids = mCameraManager.getCameraIdList();
- for (String id : ids) {
- CameraCharacteristics c = mCameraManager.getCameraCharacteristics(id);
- Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
- Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
- if (flashAvailable != null && flashAvailable
- && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
- return id;
- }
- }
- return null;
- }
-
- private void dispatchModeChanged(boolean enabled) {
- dispatchListeners(DISPATCH_CHANGED, enabled);
- }
-
- private void dispatchError() {
- dispatchListeners(DISPATCH_CHANGED, false /* argument (ignored) */);
- }
-
- private void dispatchAvailabilityChanged(boolean available) {
- dispatchListeners(DISPATCH_AVAILABILITY_CHANGED, available);
- }
-
- private void dispatchListeners(int message, boolean argument) {
- synchronized (mListeners) {
- final int N = mListeners.size();
- boolean cleanup = false;
- for (int i = 0; i < N; i++) {
- FlashlightListener l = mListeners.get(i).get();
- if (l != null) {
- if (message == DISPATCH_ERROR) {
- l.onFlashlightError();
- } else if (message == DISPATCH_CHANGED) {
- l.onFlashlightChanged(argument);
- } else if (message == DISPATCH_AVAILABILITY_CHANGED) {
- l.onFlashlightAvailabilityChanged(argument);
- }
- } else {
- cleanup = true;
- }
- }
- if (cleanup) {
- cleanUpListenersLocked(null);
- }
- }
- }
-
- private void cleanUpListenersLocked(FlashlightListener listener) {
- for (int i = mListeners.size() - 1; i >= 0; i--) {
- FlashlightListener found = mListeners.get(i).get();
- if (found == null || found == listener) {
- mListeners.remove(i);
- }
- }
- }
-
- private final CameraManager.TorchCallback mTorchCallback =
- new CameraManager.TorchCallback() {
-
- @Override
- public void onTorchModeUnavailable(String cameraId) {
- if (TextUtils.equals(cameraId, mCameraId)) {
- setCameraAvailable(false);
- }
- }
-
- @Override
- public void onTorchModeChanged(String cameraId, boolean enabled) {
- if (TextUtils.equals(cameraId, mCameraId)) {
- setCameraAvailable(true);
- setTorchMode(enabled);
- }
- }
-
- private void setCameraAvailable(boolean available) {
- boolean changed;
- synchronized (FlashlightController.this) {
- changed = mTorchAvailable != available;
- mTorchAvailable = available;
- }
- if (changed) {
- if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")");
- dispatchAvailabilityChanged(available);
- }
- }
-
- private void setTorchMode(boolean enabled) {
- boolean changed;
- synchronized (FlashlightController.this) {
- changed = mFlashlightEnabled != enabled;
- mFlashlightEnabled = enabled;
- }
- if (changed) {
- if (DEBUG) Log.d(TAG, "dispatchModeChanged(" + enabled + ")");
- dispatchModeChanged(enabled);
- }
- }
- };
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("FlashlightController state:");
-
- pw.print(" mCameraId=");
- pw.println(mCameraId);
- pw.print(" mFlashlightEnabled=");
- pw.println(mFlashlightEnabled);
- pw.print(" mTorchAvailable=");
- pw.println(mTorchAvailable);
- }
+ boolean hasFlashlight();
+ void setFlashlight(boolean newState);
+ boolean isAvailable();
+ boolean isEnabled();
public interface FlashlightListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
new file mode 100644
index 0000000..008d837
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2014 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.android.systemui.statusbar.policy;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Process;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.systemui.statusbar.policy.FlashlightController.FlashlightListener;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+/**
+ * Manages the flashlight.
+ */
+public class FlashlightControllerImpl implements FlashlightController {
+
+ private static final String TAG = "FlashlightController";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final int DISPATCH_ERROR = 0;
+ private static final int DISPATCH_CHANGED = 1;
+ private static final int DISPATCH_AVAILABILITY_CHANGED = 2;
+
+ private final CameraManager mCameraManager;
+ private final Context mContext;
+ /** Call {@link #ensureHandler()} before using */
+ private Handler mHandler;
+
+ /** Lock on mListeners when accessing */
+ private final ArrayList<WeakReference<FlashlightListener>> mListeners = new ArrayList<>(1);
+
+ /** Lock on {@code this} when accessing */
+ private boolean mFlashlightEnabled;
+
+ private String mCameraId;
+ private boolean mTorchAvailable;
+
+ public FlashlightControllerImpl(Context context) {
+ mContext = context;
+ mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
+
+ tryInitCamera();
+ }
+
+ private void tryInitCamera() {
+ try {
+ mCameraId = getCameraId();
+ } catch (Throwable e) {
+ Log.e(TAG, "Couldn't initialize.", e);
+ return;
+ }
+
+ if (mCameraId != null) {
+ ensureHandler();
+ mCameraManager.registerTorchCallback(mTorchCallback, mHandler);
+ }
+ }
+
+ public void setFlashlight(boolean enabled) {
+ boolean pendingError = false;
+ synchronized (this) {
+ if (mCameraId == null) return;
+ if (mFlashlightEnabled != enabled) {
+ mFlashlightEnabled = enabled;
+ try {
+ mCameraManager.setTorchMode(mCameraId, enabled);
+ } catch (CameraAccessException e) {
+ Log.e(TAG, "Couldn't set torch mode", e);
+ mFlashlightEnabled = false;
+ pendingError = true;
+ }
+ }
+ }
+ dispatchModeChanged(mFlashlightEnabled);
+ if (pendingError) {
+ dispatchError();
+ }
+ }
+
+ public boolean hasFlashlight() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
+ }
+
+ public synchronized boolean isEnabled() {
+ return mFlashlightEnabled;
+ }
+
+ public synchronized boolean isAvailable() {
+ return mTorchAvailable;
+ }
+
+ public void addCallback(FlashlightListener l) {
+ synchronized (mListeners) {
+ if (mCameraId == null) {
+ tryInitCamera();
+ }
+ cleanUpListenersLocked(l);
+ mListeners.add(new WeakReference<>(l));
+ }
+ }
+
+ public void removeCallback(FlashlightListener l) {
+ synchronized (mListeners) {
+ cleanUpListenersLocked(l);
+ }
+ }
+
+ private synchronized void ensureHandler() {
+ if (mHandler == null) {
+ HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
+ thread.start();
+ mHandler = new Handler(thread.getLooper());
+ }
+ }
+
+ private String getCameraId() throws CameraAccessException {
+ String[] ids = mCameraManager.getCameraIdList();
+ for (String id : ids) {
+ CameraCharacteristics c = mCameraManager.getCameraCharacteristics(id);
+ Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
+ Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
+ if (flashAvailable != null && flashAvailable
+ && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
+ return id;
+ }
+ }
+ return null;
+ }
+
+ private void dispatchModeChanged(boolean enabled) {
+ dispatchListeners(DISPATCH_CHANGED, enabled);
+ }
+
+ private void dispatchError() {
+ dispatchListeners(DISPATCH_CHANGED, false /* argument (ignored) */);
+ }
+
+ private void dispatchAvailabilityChanged(boolean available) {
+ dispatchListeners(DISPATCH_AVAILABILITY_CHANGED, available);
+ }
+
+ private void dispatchListeners(int message, boolean argument) {
+ synchronized (mListeners) {
+ final int N = mListeners.size();
+ boolean cleanup = false;
+ for (int i = 0; i < N; i++) {
+ FlashlightListener l = mListeners.get(i).get();
+ if (l != null) {
+ if (message == DISPATCH_ERROR) {
+ l.onFlashlightError();
+ } else if (message == DISPATCH_CHANGED) {
+ l.onFlashlightChanged(argument);
+ } else if (message == DISPATCH_AVAILABILITY_CHANGED) {
+ l.onFlashlightAvailabilityChanged(argument);
+ }
+ } else {
+ cleanup = true;
+ }
+ }
+ if (cleanup) {
+ cleanUpListenersLocked(null);
+ }
+ }
+ }
+
+ private void cleanUpListenersLocked(FlashlightListener listener) {
+ for (int i = mListeners.size() - 1; i >= 0; i--) {
+ FlashlightListener found = mListeners.get(i).get();
+ if (found == null || found == listener) {
+ mListeners.remove(i);
+ }
+ }
+ }
+
+ private final CameraManager.TorchCallback mTorchCallback =
+ new CameraManager.TorchCallback() {
+
+ @Override
+ public void onTorchModeUnavailable(String cameraId) {
+ if (TextUtils.equals(cameraId, mCameraId)) {
+ setCameraAvailable(false);
+ }
+ }
+
+ @Override
+ public void onTorchModeChanged(String cameraId, boolean enabled) {
+ if (TextUtils.equals(cameraId, mCameraId)) {
+ setCameraAvailable(true);
+ setTorchMode(enabled);
+ }
+ }
+
+ private void setCameraAvailable(boolean available) {
+ boolean changed;
+ synchronized (FlashlightControllerImpl.this) {
+ changed = mTorchAvailable != available;
+ mTorchAvailable = available;
+ }
+ if (changed) {
+ if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")");
+ dispatchAvailabilityChanged(available);
+ }
+ }
+
+ private void setTorchMode(boolean enabled) {
+ boolean changed;
+ synchronized (FlashlightControllerImpl.this) {
+ changed = mFlashlightEnabled != enabled;
+ mFlashlightEnabled = enabled;
+ }
+ if (changed) {
+ if (DEBUG) Log.d(TAG, "dispatchModeChanged(" + enabled + ")");
+ dispatchModeChanged(enabled);
+ }
+ }
+ };
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("FlashlightController state:");
+
+ pw.print(" mCameraId=");
+ pw.println(mCameraId);
+ pw.print(" mFlashlightEnabled=");
+ pw.println(mFlashlightEnabled);
+ pw.print(" mTorchAvailable=");
+ pw.println(mTorchAvailable);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
new file mode 100644
index 0000000..3ee01de
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.android.systemui.statusbar.policy;
+
+import android.annotation.Nullable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+
+/**
+ * Drawable for {@link KeyButtonView}s which contains an asset for both normal mode and light
+ * navigation bar mode.
+ */
+public class KeyButtonDrawable extends LayerDrawable {
+
+ private final boolean mHasDarkDrawable;
+
+ public static KeyButtonDrawable create(Drawable lightDrawable,
+ @Nullable Drawable darkDrawable) {
+ if (darkDrawable != null) {
+ return new KeyButtonDrawable(
+ new Drawable[] { lightDrawable.mutate(), darkDrawable.mutate() });
+ } else {
+ return new KeyButtonDrawable(new Drawable[] { lightDrawable.mutate() });
+ }
+ }
+
+ private KeyButtonDrawable(Drawable[] drawables) {
+ super(drawables);
+ mutate();
+ mHasDarkDrawable = drawables.length > 1;
+ setDarkIntensity(0f);
+ }
+
+ public void setDarkIntensity(float intensity) {
+ if (!mHasDarkDrawable) {
+ return;
+ }
+ getDrawable(0).setAlpha((int) ((1 - intensity) * 255f));
+ getDrawable(1).setAlpha((int) (intensity * 255f));
+ invalidateSelf();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index 57e092a..8e51ddb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -41,6 +41,7 @@
private static final float GLOW_MAX_SCALE_FACTOR = 1.35f;
private static final float GLOW_MAX_ALPHA = 0.2f;
+ private static final float GLOW_MAX_ALPHA_DARK = 0.1f;
private static final int ANIMATION_DURATION_SCALE = 350;
private static final int ANIMATION_DURATION_FADE = 450;
@@ -57,6 +58,8 @@
private boolean mPressed;
private boolean mDrawingHardwareGlow;
private int mMaxWidth;
+ private boolean mLastDark;
+ private boolean mDark;
private final Interpolator mInterpolator = new LogInterpolator();
private boolean mSupportHardware;
@@ -70,11 +73,15 @@
mTargetView = targetView;
}
+ public void setDarkIntensity(float darkIntensity) {
+ mDark = darkIntensity >= 0.5f;
+ }
+
private Paint getRipplePaint() {
if (mRipplePaint == null) {
mRipplePaint = new Paint();
mRipplePaint.setAntiAlias(true);
- mRipplePaint.setColor(0xffffffff);
+ mRipplePaint.setColor(mLastDark ? 0xff000000 : 0xffffffff);
}
return mRipplePaint;
}
@@ -155,6 +162,10 @@
invalidateSelf();
}
+ private float getMaxGlowAlpha() {
+ return mLastDark ? GLOW_MAX_ALPHA_DARK : GLOW_MAX_ALPHA;
+ }
+
@Override
protected boolean onStateChange(int[] state) {
boolean pressed = false;
@@ -184,6 +195,10 @@
}
public void setPressed(boolean pressed) {
+ if (mDark != mLastDark && pressed) {
+ mRipplePaint = null;
+ mLastDark = mDark;
+ }
if (mSupportHardware) {
setPressedHardware(pressed);
} else {
@@ -212,7 +227,7 @@
private void enterSoftware() {
cancelAnimations();
- mGlowAlpha = GLOW_MAX_ALPHA;
+ mGlowAlpha = getMaxGlowAlpha();
ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(this, "glowScale",
0f, GLOW_MAX_SCALE_FACTOR);
scaleAnimator.setInterpolator(mInterpolator);
@@ -312,7 +327,7 @@
}
mGlowScale = GLOW_MAX_SCALE_FACTOR;
- mGlowAlpha = GLOW_MAX_ALPHA;
+ mGlowAlpha = getMaxGlowAlpha();
mRipplePaint = getRipplePaint();
mRipplePaint.setAlpha((int) (mGlowAlpha * 255));
mPaintProp = CanvasProperty.createPaint(mRipplePaint);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index bcc5a3f..45cfbdc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.policy;
-import android.annotation.DrawableRes;
-import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Configuration;
@@ -60,6 +58,7 @@
private boolean mGestureAborted;
private boolean mLongClicked;
private OnClickListener mOnClickListener;
+ private final KeyButtonRipple mRipple;
private final Runnable mCheckLongPress = new Runnable() {
public void run() {
@@ -99,11 +98,12 @@
a.recycle();
-
setClickable(true);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- setBackground(new KeyButtonRipple(context, this));
+
+ mRipple = new KeyButtonRipple(context, this);
+ setBackground(mRipple);
}
public void setCode(int code) {
@@ -265,17 +265,20 @@
}
@Override
- public void setImageResource(@DrawableRes int resId) {
- super.setImageResource(resId);
+ public void setDarkIntensity(float darkIntensity) {
+ Drawable drawable = getDrawable();
+ if (drawable != null) {
+ ((KeyButtonDrawable) getDrawable()).setDarkIntensity(darkIntensity);
+
+ // Since we reuse the same drawable for multiple views, we need to invalidate the view
+ // manually.
+ invalidate();
+ }
+ mRipple.setDarkIntensity(darkIntensity);
}
@Override
- public void setImageDrawable(@Nullable Drawable drawable) {
- super.setImageDrawable(drawable);
- }
-
- @Override
- public void setLandscape(boolean landscape) {
+ public void setVertical(boolean vertical) {
//no op
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index 0396613..de47267 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -1,126 +1,28 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * 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.
+ * 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.android.systemui.statusbar.policy;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.os.RemoteException;
-import android.view.WindowManagerGlobal;
-
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
-import java.util.ArrayList;
+public interface KeyguardMonitor extends CallbackController<Callback> {
-public class KeyguardMonitor extends KeyguardUpdateMonitorCallback
- implements CallbackController<Callback> {
-
- private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
-
- private final Context mContext;
- private final CurrentUserTracker mUserTracker;
- private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-
- private int mCurrentUser;
- private boolean mShowing;
- private boolean mSecure;
- private boolean mOccluded;
- private boolean mCanSkipBouncer;
-
- private boolean mListening;
-
- public KeyguardMonitor(Context context) {
- mContext = context;
- mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
- mUserTracker = new CurrentUserTracker(mContext) {
- @Override
- public void onUserSwitched(int newUserId) {
- mCurrentUser = newUserId;
- updateCanSkipBouncerState();
- }
- };
- }
-
- public void addCallback(Callback callback) {
- mCallbacks.add(callback);
- if (mCallbacks.size() != 0 && !mListening) {
- mListening = true;
- mCurrentUser = ActivityManager.getCurrentUser();
- updateCanSkipBouncerState();
- mKeyguardUpdateMonitor.registerCallback(this);
- mUserTracker.startTracking();
- }
- }
-
- public void removeCallback(Callback callback) {
- if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) {
- mListening = false;
- mKeyguardUpdateMonitor.removeCallback(this);
- mUserTracker.stopTracking();
- }
- }
-
- public boolean isShowing() {
- return mShowing;
- }
-
- public boolean isSecure() {
- return mSecure;
- }
-
- public boolean isOccluded() {
- return mOccluded;
- }
-
- public boolean canSkipBouncer() {
- return mCanSkipBouncer;
- }
-
- public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
- if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
- mShowing = showing;
- mSecure = secure;
- mOccluded = occluded;
- notifyKeyguardChanged();
- }
-
- @Override
- public void onTrustChanged(int userId) {
- updateCanSkipBouncerState();
- notifyKeyguardChanged();
- }
-
- public boolean isDeviceInteractive() {
- return mKeyguardUpdateMonitor.isDeviceInteractive();
- }
-
- private void updateCanSkipBouncerState() {
- mCanSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(mCurrentUser);
- }
-
- private void notifyKeyguardChanged() {
- for (Callback callback : mCallbacks) {
- callback.onKeyguardChanged();
- }
- }
+ boolean isSecure();
+ boolean canSkipBouncer();
+ boolean isShowing();
public interface Callback {
void onKeyguardChanged();
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
new file mode 100644
index 0000000..769f93f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2014 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.android.systemui.statusbar.policy;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.view.WindowManagerGlobal;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
+
+import java.util.ArrayList;
+
+public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
+ implements KeyguardMonitor {
+
+ private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+
+ private final Context mContext;
+ private final CurrentUserTracker mUserTracker;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+ private int mCurrentUser;
+ private boolean mShowing;
+ private boolean mSecure;
+ private boolean mOccluded;
+ private boolean mCanSkipBouncer;
+
+ private boolean mListening;
+
+ public KeyguardMonitorImpl(Context context) {
+ mContext = context;
+ mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+ mUserTracker = new CurrentUserTracker(mContext) {
+ @Override
+ public void onUserSwitched(int newUserId) {
+ mCurrentUser = newUserId;
+ updateCanSkipBouncerState();
+ }
+ };
+ }
+
+ public void addCallback(Callback callback) {
+ mCallbacks.add(callback);
+ if (mCallbacks.size() != 0 && !mListening) {
+ mListening = true;
+ mCurrentUser = ActivityManager.getCurrentUser();
+ updateCanSkipBouncerState();
+ mKeyguardUpdateMonitor.registerCallback(this);
+ mUserTracker.startTracking();
+ }
+ }
+
+ public void removeCallback(Callback callback) {
+ if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) {
+ mListening = false;
+ mKeyguardUpdateMonitor.removeCallback(this);
+ mUserTracker.stopTracking();
+ }
+ }
+
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ public boolean isSecure() {
+ return mSecure;
+ }
+
+ public boolean isOccluded() {
+ return mOccluded;
+ }
+
+ public boolean canSkipBouncer() {
+ return mCanSkipBouncer;
+ }
+
+ public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
+ if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
+ mShowing = showing;
+ mSecure = secure;
+ mOccluded = occluded;
+ notifyKeyguardChanged();
+ }
+
+ @Override
+ public void onTrustChanged(int userId) {
+ updateCanSkipBouncerState();
+ notifyKeyguardChanged();
+ }
+
+ public boolean isDeviceInteractive() {
+ return mKeyguardUpdateMonitor.isDeviceInteractive();
+ }
+
+ private void updateCanSkipBouncerState() {
+ mCanSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(mCurrentUser);
+ }
+
+ private void notifyKeyguardChanged() {
+ for (Callback callback : mCallbacks) {
+ callback.onKeyguardChanged();
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 1a9756f..a7fab41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -159,7 +159,7 @@
mConfig = config;
mReceiverHandler = new Handler(bgLooper);
mCallbackHandler = callbackHandler;
- mDataSaverController = new DataSaverController(context);
+ mDataSaverController = new DataSaverControllerImpl(context);
mSubscriptionManager = subManager;
mSubDefaults = defaultsHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java
index 28935bf..e5b0c03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java
@@ -1,84 +1,24 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * 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
+ * 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.android.systemui.statusbar.policy;
import android.app.AlarmManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.UserHandle;
import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-public class NextAlarmController extends BroadcastReceiver
- implements CallbackController<NextAlarmChangeCallback> {
-
- private final ArrayList<NextAlarmChangeCallback> mChangeCallbacks = new ArrayList<>();
-
- private AlarmManager mAlarmManager;
- private AlarmManager.AlarmClockInfo mNextAlarm;
-
- public NextAlarmController(Context context) {
- mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
- context.registerReceiverAsUser(this, UserHandle.ALL, filter, null, null);
- updateNextAlarm();
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("NextAlarmController state:");
- pw.print(" mNextAlarm="); pw.println(mNextAlarm);
- }
-
- public void addCallback(NextAlarmChangeCallback cb) {
- mChangeCallbacks.add(cb);
- cb.onNextAlarmChanged(mNextAlarm);
- }
-
- public void removeCallback(NextAlarmChangeCallback cb) {
- mChangeCallbacks.remove(cb);
- }
-
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (action.equals(Intent.ACTION_USER_SWITCHED)
- || action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) {
- updateNextAlarm();
- }
- }
-
- private void updateNextAlarm() {
- mNextAlarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
- fireNextAlarmChanged();
- }
-
- private void fireNextAlarmChanged() {
- int n = mChangeCallbacks.size();
- for (int i = 0; i < n; i++) {
- mChangeCallbacks.get(i).onNextAlarmChanged(mNextAlarm);
- }
- }
+public interface NextAlarmController extends CallbackController<NextAlarmChangeCallback> {
public interface NextAlarmChangeCallback {
void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
new file mode 100644
index 0000000..dfdeae1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 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.android.systemui.statusbar.policy;
+
+import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.UserHandle;
+
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+public class NextAlarmControllerImpl extends BroadcastReceiver
+ implements NextAlarmController {
+
+ private final ArrayList<NextAlarmChangeCallback> mChangeCallbacks = new ArrayList<>();
+
+ private AlarmManager mAlarmManager;
+ private AlarmManager.AlarmClockInfo mNextAlarm;
+
+ public NextAlarmControllerImpl(Context context) {
+ mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
+ context.registerReceiverAsUser(this, UserHandle.ALL, filter, null, null);
+ updateNextAlarm();
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("NextAlarmController state:");
+ pw.print(" mNextAlarm="); pw.println(mNextAlarm);
+ }
+
+ public void addCallback(NextAlarmChangeCallback cb) {
+ mChangeCallbacks.add(cb);
+ cb.onNextAlarmChanged(mNextAlarm);
+ }
+
+ public void removeCallback(NextAlarmChangeCallback cb) {
+ mChangeCallbacks.remove(cb);
+ }
+
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(Intent.ACTION_USER_SWITCHED)
+ || action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) {
+ updateNextAlarm();
+ }
+ }
+
+ private void updateNextAlarm() {
+ mNextAlarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
+ fireNextAlarmChanged();
+ }
+
+ private void fireNextAlarmChanged() {
+ int n = mChangeCallbacks.size();
+ for (int i = 0; i < n; i++) {
+ mChangeCallbacks.get(i).onNextAlarmChanged(mNextAlarm);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
index 43ced48..3142228 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
@@ -23,6 +23,8 @@
boolean hasProfileOwner();
String getDeviceOwnerName();
String getProfileOwnerName();
+ CharSequence getDeviceOwnerOrganizationName();
+ boolean isNetworkLoggingEnabled();
boolean isVpnEnabled();
boolean isVpnRestricted();
/** Whether the VPN app should use branded VPN iconography. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 07d3b59..df959bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -130,6 +130,11 @@
}
@Override
+ public CharSequence getDeviceOwnerOrganizationName() {
+ return mDevicePolicyManager.getDeviceOwnerOrganizationName();
+ }
+
+ @Override
public String getPrimaryVpnName() {
VpnConfig cfg = mCurrentVpns.get(mVpnUserId);
if (cfg != null) {
@@ -154,6 +159,11 @@
}
@Override
+ public boolean isNetworkLoggingEnabled() {
+ return mDevicePolicyManager.isNetworkLoggingEnabled(null);
+ }
+
+ @Override
public boolean isVpnEnabled() {
for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) {
if (mCurrentVpns.get(profileId) != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
index c09747b..1e23a20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
@@ -1,233 +1,28 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * 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
+ * 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.android.systemui.statusbar.policy;
-import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.ContactsContract;
-import android.util.Log;
-import com.android.internal.util.UserIcons;
-import com.android.settingslib.drawable.UserIconDrawable;
-import com.android.systemui.R;
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
-import java.util.ArrayList;
+public interface UserInfoController extends CallbackController<OnUserInfoChangedListener> {
-public class UserInfoController implements CallbackController<OnUserInfoChangedListener> {
-
- private static final String TAG = "UserInfoController";
-
- private final Context mContext;
- private final ArrayList<OnUserInfoChangedListener> mCallbacks =
- new ArrayList<OnUserInfoChangedListener>();
- private AsyncTask<Void, Void, UserInfoQueryResult> mUserInfoTask;
-
- private String mUserName;
- private Drawable mUserDrawable;
- private String mUserAccount;
-
- public UserInfoController(Context context) {
- mContext = context;
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- mContext.registerReceiver(mReceiver, filter);
-
- IntentFilter profileFilter = new IntentFilter();
- profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
- profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
- mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
- null, null);
- }
-
- public void addCallback(OnUserInfoChangedListener callback) {
- mCallbacks.add(callback);
- callback.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
- }
-
- public void removeCallback(OnUserInfoChangedListener callback) {
- mCallbacks.remove(callback);
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- reloadUserInfo();
- }
- }
- };
-
- private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
- Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
- try {
- final int currentUser = ActivityManager.getService().getCurrentUser().id;
- final int changedUser =
- intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
- if (changedUser == currentUser) {
- reloadUserInfo();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Couldn't get current user id for profile change", e);
- }
- }
- }
- };
-
- public void reloadUserInfo() {
- if (mUserInfoTask != null) {
- mUserInfoTask.cancel(false);
- mUserInfoTask = null;
- }
- queryForUserInformation();
- }
-
- private void queryForUserInformation() {
- Context currentUserContext;
- UserInfo userInfo;
- try {
- userInfo = ActivityManager.getService().getCurrentUser();
- currentUserContext = mContext.createPackageContextAsUser("android", 0,
- new UserHandle(userInfo.id));
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "Couldn't create user context", e);
- throw new RuntimeException(e);
- } catch (RemoteException e) {
- Log.e(TAG, "Couldn't get user info", e);
- throw new RuntimeException(e);
- }
- final int userId = userInfo.id;
- final boolean isGuest = userInfo.isGuest();
- final String userName = userInfo.name;
-
- final Resources res = mContext.getResources();
- final int avatarSize = Math.max(
- res.getDimensionPixelSize(R.dimen.multi_user_avatar_expanded_size),
- res.getDimensionPixelSize(R.dimen.multi_user_avatar_keyguard_size));
-
- final Context context = currentUserContext;
- mUserInfoTask = new AsyncTask<Void, Void, UserInfoQueryResult>() {
-
- @Override
- protected UserInfoQueryResult doInBackground(Void... params) {
- final UserManager um = UserManager.get(mContext);
-
- // Fall back to the UserManager nickname if we can't read the name from the local
- // profile below.
- String name = userName;
- Drawable avatar = null;
- Bitmap rawAvatar = um.getUserIcon(userId);
- if (rawAvatar != null) {
- avatar = new UserIconDrawable(avatarSize)
- .setIcon(rawAvatar).setBadgeIfManagedUser(mContext, userId).bake();
- } else {
- avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
- /* light= */ true);
- }
-
- // If it's a single-user device, get the profile name, since the nickname is not
- // usually valid
- if (um.getUsers().size() <= 1) {
- // Try and read the display name from the local profile
- final Cursor cursor = context.getContentResolver().query(
- ContactsContract.Profile.CONTENT_URI, new String[] {
- ContactsContract.CommonDataKinds.Phone._ID,
- ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
- }, null, null, null);
- if (cursor != null) {
- try {
- if (cursor.moveToFirst()) {
- name = cursor.getString(cursor.getColumnIndex(
- ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
- }
- } finally {
- cursor.close();
- }
- }
- }
- String userAccount = um.getUserAccount(userId);
- return new UserInfoQueryResult(name, avatar, userAccount);
- }
-
- @Override
- protected void onPostExecute(UserInfoQueryResult result) {
- mUserName = result.getName();
- mUserDrawable = result.getAvatar();
- mUserAccount = result.getUserAccount();
- mUserInfoTask = null;
- notifyChanged();
- }
- };
- mUserInfoTask.execute();
- }
-
- private void notifyChanged() {
- for (OnUserInfoChangedListener listener : mCallbacks) {
- listener.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
- }
- }
-
- public void onDensityOrFontScaleChanged() {
- reloadUserInfo();
- }
+ void reloadUserInfo();
public interface OnUserInfoChangedListener {
public void onUserInfoChanged(String name, Drawable picture, String userAccount);
}
-
- private static class UserInfoQueryResult {
- private String mName;
- private Drawable mAvatar;
- private String mUserAccount;
-
- public UserInfoQueryResult(String name, Drawable avatar, String userAccount) {
- mName = name;
- mAvatar = avatar;
- mUserAccount = userAccount;
- }
-
- public String getName() {
- return mName;
- }
-
- public Drawable getAvatar() {
- return mAvatar;
- }
-
- public String getUserAccount() {
- return mUserAccount;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
new file mode 100644
index 0000000..b1e4b03
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2014 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.android.systemui.statusbar.policy;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.ContactsContract;
+import android.util.Log;
+
+import com.android.internal.util.UserIcons;
+import com.android.settingslib.drawable.UserIconDrawable;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
+
+import java.util.ArrayList;
+
+public class UserInfoControllerImpl implements UserInfoController {
+
+ private static final String TAG = "UserInfoController";
+
+ private final Context mContext;
+ private final ArrayList<OnUserInfoChangedListener> mCallbacks =
+ new ArrayList<OnUserInfoChangedListener>();
+ private AsyncTask<Void, Void, UserInfoQueryResult> mUserInfoTask;
+
+ private String mUserName;
+ private Drawable mUserDrawable;
+ private String mUserAccount;
+
+ public UserInfoControllerImpl(Context context) {
+ mContext = context;
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ mContext.registerReceiver(mReceiver, filter);
+
+ IntentFilter profileFilter = new IntentFilter();
+ profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
+ profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
+ mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
+ null, null);
+ }
+
+ public void addCallback(OnUserInfoChangedListener callback) {
+ mCallbacks.add(callback);
+ callback.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
+ }
+
+ public void removeCallback(OnUserInfoChangedListener callback) {
+ mCallbacks.remove(callback);
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ reloadUserInfo();
+ }
+ }
+ };
+
+ private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
+ Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
+ try {
+ final int currentUser = ActivityManager.getService().getCurrentUser().id;
+ final int changedUser =
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
+ if (changedUser == currentUser) {
+ reloadUserInfo();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't get current user id for profile change", e);
+ }
+ }
+ }
+ };
+
+ public void reloadUserInfo() {
+ if (mUserInfoTask != null) {
+ mUserInfoTask.cancel(false);
+ mUserInfoTask = null;
+ }
+ queryForUserInformation();
+ }
+
+ private void queryForUserInformation() {
+ Context currentUserContext;
+ UserInfo userInfo;
+ try {
+ userInfo = ActivityManager.getService().getCurrentUser();
+ currentUserContext = mContext.createPackageContextAsUser("android", 0,
+ new UserHandle(userInfo.id));
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Couldn't create user context", e);
+ throw new RuntimeException(e);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't get user info", e);
+ throw new RuntimeException(e);
+ }
+ final int userId = userInfo.id;
+ final boolean isGuest = userInfo.isGuest();
+ final String userName = userInfo.name;
+
+ final Resources res = mContext.getResources();
+ final int avatarSize = Math.max(
+ res.getDimensionPixelSize(R.dimen.multi_user_avatar_expanded_size),
+ res.getDimensionPixelSize(R.dimen.multi_user_avatar_keyguard_size));
+
+ final Context context = currentUserContext;
+ mUserInfoTask = new AsyncTask<Void, Void, UserInfoQueryResult>() {
+
+ @Override
+ protected UserInfoQueryResult doInBackground(Void... params) {
+ final UserManager um = UserManager.get(mContext);
+
+ // Fall back to the UserManager nickname if we can't read the name from the local
+ // profile below.
+ String name = userName;
+ Drawable avatar = null;
+ Bitmap rawAvatar = um.getUserIcon(userId);
+ if (rawAvatar != null) {
+ avatar = new UserIconDrawable(avatarSize)
+ .setIcon(rawAvatar).setBadgeIfManagedUser(mContext, userId).bake();
+ } else {
+ avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
+ /* light= */ true);
+ }
+
+ // If it's a single-user device, get the profile name, since the nickname is not
+ // usually valid
+ if (um.getUsers().size() <= 1) {
+ // Try and read the display name from the local profile
+ final Cursor cursor = context.getContentResolver().query(
+ ContactsContract.Profile.CONTENT_URI, new String[] {
+ ContactsContract.CommonDataKinds.Phone._ID,
+ ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
+ }, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ name = cursor.getString(cursor.getColumnIndex(
+ ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+ String userAccount = um.getUserAccount(userId);
+ return new UserInfoQueryResult(name, avatar, userAccount);
+ }
+
+ @Override
+ protected void onPostExecute(UserInfoQueryResult result) {
+ mUserName = result.getName();
+ mUserDrawable = result.getAvatar();
+ mUserAccount = result.getUserAccount();
+ mUserInfoTask = null;
+ notifyChanged();
+ }
+ };
+ mUserInfoTask.execute();
+ }
+
+ private void notifyChanged() {
+ for (OnUserInfoChangedListener listener : mCallbacks) {
+ listener.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
+ }
+ }
+
+ public void onDensityOrFontScaleChanged() {
+ reloadUserInfo();
+ }
+
+ private static class UserInfoQueryResult {
+ private String mName;
+ private Drawable mAvatar;
+ private String mUserAccount;
+
+ public UserInfoQueryResult(String name, Drawable avatar, String userAccount) {
+ mName = name;
+ mAvatar = avatar;
+ mUserAccount = userAccount;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public Drawable getAvatar() {
+ return mAvatar;
+ }
+
+ public String getUserAccount() {
+ return mUserAccount;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index 26f74ea..e1ff297 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -22,6 +22,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.ActivatableNotificationView;
import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import java.util.ArrayList;
@@ -52,6 +53,11 @@
private int mBaseZHeight;
private int mMaxLayoutHeight;
private ActivatableNotificationView mLastVisibleBackgroundChild;
+ private float mCurrentScrollVelocity;
+ private int mStatusBarState;
+ private float mExpandingVelocity;
+ private boolean mPanelTracking;
+ private boolean mExpansionChanging;
public AmbientState(Context context) {
reload(context);
@@ -241,4 +247,44 @@
public ActivatableNotificationView getLastVisibleBackgroundChild() {
return mLastVisibleBackgroundChild;
}
+
+ public void setCurrentScrollVelocity(float currentScrollVelocity) {
+ mCurrentScrollVelocity = currentScrollVelocity;
+ }
+
+ public float getCurrentScrollVelocity() {
+ return mCurrentScrollVelocity;
+ }
+
+ public boolean isOnKeyguard() {
+ return mStatusBarState == StatusBarState.KEYGUARD;
+ }
+
+ public void setStatusBarState(int statusBarState) {
+ mStatusBarState = statusBarState;
+ }
+
+ public void setExpandingVelocity(float expandingVelocity) {
+ mExpandingVelocity = expandingVelocity;
+ }
+
+ public void setExpansionChanging(boolean expansionChanging) {
+ mExpansionChanging = expansionChanging;
+ }
+
+ public boolean isExpansionChanging() {
+ return mExpansionChanging;
+ }
+
+ public float getExpandingVelocity() {
+ return mExpandingVelocity;
+ }
+
+ public void setPanelTracking(boolean panelTracking) {
+ mPanelTracking = panelTracking;
+ }
+
+ public boolean isPanelTracking() {
+ return mPanelTracking;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
index d3d58f9..38bb40e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
@@ -120,7 +120,7 @@
}
}
- private void combineFilter(AnimationFilter filter) {
+ public void combineFilter(AnimationFilter filter) {
animateAlpha |= filter.animateAlpha;
animateX |= filter.animateX;
animateY |= filter.animateY;
@@ -134,7 +134,7 @@
hasDelays |= filter.hasDelays;
}
- private void reset() {
+ public void reset() {
animateAlpha = false;
animateX = false;
animateY = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index b8f8cb2..22709f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -213,7 +213,7 @@
mDividers.add(newIndex, divider);
updateGroupOverflow();
- row.setIconTransformationAmount(0, false /* isLastChild */);
+ row.setContentTransformationAmount(0, false /* isLastChild */);
}
public void removeNotification(ExpandableNotificationRow row) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 10d995c..7d4927b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -357,6 +357,7 @@
private Rect mRequestedClipBounds;
private boolean mInHeadsUpPinnedMode;
private boolean mHeadsUpAnimatingAway;
+ private int mStatusBarState;
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -575,6 +576,9 @@
*/
private void updateChildren() {
updateScrollStateForAddedChildren();
+ mAmbientState.setCurrentScrollVelocity(mScroller.isFinished()
+ ? 0
+ : mScroller.getCurrVelocity());
mAmbientState.setScrollY(mOwnScrollY);
mStackScrollAlgorithm.getStackScrollState(mAmbientState, mCurrentStackScrollState);
if (!isCurrentlyAnimating() && !mNeedsAnimation) {
@@ -715,7 +719,6 @@
requestChildrenUpdate();
}
setStackTranslation(translationY);
- requestChildrenUpdate();
}
private void setRequestedClipBounds(Rect clipRect) {
@@ -1185,7 +1188,7 @@
}
private boolean onKeyguard() {
- return mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD;
+ return mStatusBarState == StatusBarState.KEYGUARD;
}
private void setSwipingInProgress(boolean isSwiped) {
@@ -2122,7 +2125,7 @@
top = mTopPadding;
bottom = top;
}
- if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+ if (mStatusBarState != StatusBarState.KEYGUARD) {
top = (int) Math.max(mTopPadding + mStackTranslation, top);
} else {
// otherwise the animation from the shade to the keyguard will jump as it's maxed
@@ -2356,7 +2359,7 @@
}
break;
case MotionEvent.ACTION_UP:
- if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD && mTouchIsClick &&
+ if (mStatusBarState != StatusBarState.KEYGUARD && mTouchIsClick &&
isBelowLastNotification(mInitialTouchX, mInitialTouchY)) {
mOnEmptySpaceClickListener.onEmptySpaceClicked(mInitialTouchX, mInitialTouchY);
}
@@ -3121,10 +3124,12 @@
public void onExpansionStarted() {
mIsExpansionChanging = true;
+ mAmbientState.setExpansionChanging(true);
}
public void onExpansionStopped() {
mIsExpansionChanging = false;
+ mAmbientState.setExpansionChanging(false);
if (!mIsExpanded) {
setOwnScrollY(0);
mPhoneStatusBar.resetUserExpandedStates();
@@ -3152,9 +3157,11 @@
public void onPanelTrackingStarted() {
mPanelTracking = true;
+ mAmbientState.setPanelTracking(true);
}
public void onPanelTrackingStopped() {
mPanelTracking = false;
+ mAmbientState.setPanelTracking(false);
}
public void resetScrollPosition() {
@@ -3979,6 +3986,15 @@
updateClipping();
}
+ public void setStatusBarState(int statusBarState) {
+ mStatusBarState = statusBarState;
+ mAmbientState.setStatusBarState(statusBarState);
+ }
+
+ public void setExpandingVelocity(float expandingVelocity) {
+ mAmbientState.setExpandingVelocity(expandingVelocity);
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 7afc7ba..50b6d70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -124,7 +124,8 @@
private void updateClipping(StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
- float drawStart = ambientState.getTopPadding() + ambientState.getStackTranslation();
+ float drawStart = !ambientState.isOnKeyguard() ? ambientState.getTopPadding()
+ + ambientState.getStackTranslation() : 0;
float previousNotificationEnd = 0;
float previousNotificationStart = 0;
int childCount = algorithmState.visibleChildren.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
index 8a5ddd4..b747592 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
@@ -99,36 +99,6 @@
// don't do anything with it
return;
}
- boolean becomesInvisible = this.alpha == 0.0f || this.hidden;
- boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
- if (animatingAlpha) {
- updateAlphaAnimation(view);
- } else if (view.getAlpha() != this.alpha) {
- // apply layer type
- boolean becomesFullyVisible = this.alpha == 1.0f;
- boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible
- && view.hasOverlappingRendering();
- int layerType = view.getLayerType();
- int newLayerType = newLayerTypeIsHardware
- ? View.LAYER_TYPE_HARDWARE
- : View.LAYER_TYPE_NONE;
- if (layerType != newLayerType) {
- view.setLayerType(newLayerType, null);
- }
-
- // apply alpha
- view.setAlpha(this.alpha);
- }
-
- // apply visibility
- int oldVisibility = view.getVisibility();
- int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
- if (newVisibility != oldVisibility) {
- if (!(view instanceof ExpandableView) || !((ExpandableView) view).willBeGone()) {
- // We don't want views to change visibility when they are animating to GONE
- view.setVisibility(newVisibility);
- }
- }
// apply xTranslation
boolean animatingX = isAnimating(view, TAG_ANIMATOR_TRANSLATION_X);
@@ -163,6 +133,53 @@
if (view.getScaleY() != this.scaleY) {
view.setScaleY(this.scaleY);
}
+
+ boolean becomesInvisible = this.alpha == 0.0f || (this.hidden && !isAnimating(view));
+ boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
+ if (animatingAlpha) {
+ updateAlphaAnimation(view);
+ } else if (view.getAlpha() != this.alpha) {
+ // apply layer type
+ boolean becomesFullyVisible = this.alpha == 1.0f;
+ boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible
+ && view.hasOverlappingRendering();
+ int layerType = view.getLayerType();
+ int newLayerType = newLayerTypeIsHardware
+ ? View.LAYER_TYPE_HARDWARE
+ : View.LAYER_TYPE_NONE;
+ if (layerType != newLayerType) {
+ view.setLayerType(newLayerType, null);
+ }
+
+ // apply alpha
+ view.setAlpha(this.alpha);
+ }
+
+ // apply visibility
+ int oldVisibility = view.getVisibility();
+ int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
+ if (newVisibility != oldVisibility) {
+ if (!(view instanceof ExpandableView) || !((ExpandableView) view).willBeGone()) {
+ // We don't want views to change visibility when they are animating to GONE
+ view.setVisibility(newVisibility);
+ }
+ }
+ }
+
+ protected boolean isAnimating(View view) {
+ if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_X)) {
+ return true;
+ }
+ if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y)) {
+ return true;
+ }
+ if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_Z)) {
+ return true;
+ }
+ if (isAnimating(view, TAG_ANIMATOR_ALPHA)) {
+ return true;
+ }
+ return false;
}
private boolean isAnimating(View view, int tag) {
@@ -482,7 +499,7 @@
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
child.setTag(TAG_START_TRANSLATION_Y, null);
child.setTag(TAG_END_TRANSLATION_Y, null);
- onYTranslationAnimationFinished();
+ onYTranslationAnimationFinished(child);
}
});
startAnimator(animator, listener);
@@ -491,7 +508,10 @@
child.setTag(TAG_END_TRANSLATION_Y, newEndValue);
}
- protected void onYTranslationAnimationFinished() {
+ protected void onYTranslationAnimationFinished(View view) {
+ if (hidden) {
+ view.setVisibility(View.INVISIBLE);
+ }
}
protected void startAnimator(Animator animator, AnimatorListenerAdapter listener) {
@@ -548,7 +568,26 @@
}
}
- public static boolean isAnimatingY(ExpandableView child) {
+ public static boolean isAnimatingY(View child) {
return getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y) != null;
}
+
+ public void cancelAnimations(View view) {
+ Animator animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_X);
+ if (animator != null) {
+ animator.cancel();
+ }
+ animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Y);
+ if (animator != null) {
+ animator.cancel();
+ }
+ animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Z);
+ if (animator != null) {
+ animator.cancel();
+ }
+ animator = getChildTag(view, TAG_ANIMATOR_ALPHA);
+ if (animator != null) {
+ animator.cancel();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index ebc962d..565ac08 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -92,6 +92,10 @@
mUserTracker.startTracking();
}
+ public void destroy() {
+ mUserTracker.stopTracking();
+ }
+
private void upgradeTuner(int oldVersion, int newVersion) {
if (oldVersion < 1) {
String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST);
diff --git a/packages/SystemUI/src/com/android/systemui/util/LayoutInflaterBuilder.java b/packages/SystemUI/src/com/android/systemui/util/LayoutInflaterBuilder.java
new file mode 100644
index 0000000..f420921
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/LayoutInflaterBuilder.java
@@ -0,0 +1,162 @@
+/*
+ * 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 com.android.systemui.util;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Builder class to create a {@link LayoutInflater} with various properties.
+ *
+ * Call any desired configuration methods on the Builder and then use
+ * {@link Builder#build} to create the LayoutInflater. This is an alternative to directly using
+ * {@link LayoutInflater#setFilter} and {@link LayoutInflater#setFactory}.
+ * @hide for use by framework
+ */
+public class LayoutInflaterBuilder {
+ private static final String TAG = "LayoutInflaterBuilder";
+
+ private Context mFromContext;
+ private Context mTargetContext;
+ private Map<String, String> mReplaceMap;
+ private Set<Class> mDisallowedClasses;
+ private LayoutInflater mBuiltInflater;
+
+ /**
+ * Creates a new Builder which will construct a LayoutInflater.
+ *
+ * @param fromContext This context's LayoutInflater will be cloned by the Builder using
+ * {@link LayoutInflater#cloneInContext}. By default, the new LayoutInflater will point at
+ * this same Context.
+ */
+ public LayoutInflaterBuilder(@NonNull Context fromContext) {
+ mFromContext = fromContext;
+ mTargetContext = fromContext;
+ mReplaceMap = null;
+ mDisallowedClasses = null;
+ mBuiltInflater = null;
+ }
+
+ /**
+ * Instructs the Builder to point the LayoutInflater at a different Context.
+ *
+ * @param targetContext Context to be provided to
+ * {@link LayoutInflater#cloneInContext(Context)}.
+ * @return Builder object post-modification.
+ */
+ public LayoutInflaterBuilder target(@NonNull Context targetContext) {
+ assertIfAlreadyBuilt();
+ mTargetContext = targetContext;
+ return this;
+ }
+
+ /**
+ * Instructs the Builder to configure the LayoutInflater such that all instances
+ * of one {@link View} will be replaced with instances of another during inflation.
+ *
+ * @param from Instances of this class will be replaced during inflation.
+ * @param to Instances of this class will be inflated as replacements.
+ * @return Builder object post-modification.
+ */
+ public LayoutInflaterBuilder replace(@NonNull Class from, @NonNull Class to) {
+ assertIfAlreadyBuilt();
+ if (mReplaceMap == null) {
+ mReplaceMap = new ArrayMap<String, String>();
+ }
+ mReplaceMap.put(from.getName(), to.getName());
+ return this;
+ }
+
+ /**
+ * Instructs the Builder to configure the LayoutInflater such that any attempt to inflate
+ * a {@link View} of a given type will throw a {@link InflateException}.
+ *
+ * @param disallowedClass The Class type that will be disallowed.
+ * @return Builder object post-modification.
+ */
+ public LayoutInflaterBuilder disallow(@NonNull Class disallowedClass) {
+ assertIfAlreadyBuilt();
+ if (mDisallowedClasses == null) {
+ mDisallowedClasses = new ArraySet<Class>();
+ }
+ mDisallowedClasses.add(disallowedClass);
+ return this;
+ }
+
+ /**
+ * Builds and returns the LayoutInflater. Afterwards, this Builder can no longer can be
+ * used, all future calls on the Builder will throw {@link AssertionError}.
+ */
+ public LayoutInflater build() {
+ assertIfAlreadyBuilt();
+ mBuiltInflater =
+ LayoutInflater.from(mFromContext).cloneInContext(mTargetContext);
+ setFactoryIfNeeded(mBuiltInflater);
+ setFilterIfNeeded(mBuiltInflater);
+ return mBuiltInflater;
+ }
+
+ private void assertIfAlreadyBuilt() {
+ if (mBuiltInflater != null) {
+ throw new AssertionError("Cannot use this Builder after build() has been called.");
+ }
+ }
+
+ private void setFactoryIfNeeded(LayoutInflater inflater) {
+ if (mReplaceMap == null) {
+ return;
+ }
+ inflater.setFactory(
+ new LayoutInflater.Factory() {
+ @Override
+ public View onCreateView(String name, Context context, AttributeSet attrs) {
+ String replacingClassName = mReplaceMap.get(name);
+ if (replacingClassName != null) {
+ try {
+ return inflater.createView(replacingClassName, null, attrs);
+ } catch (ClassNotFoundException e) {
+ Log.e(TAG, "Could not replace " + name
+ + " with " + replacingClassName
+ + ", Exception: ", e);
+ }
+ }
+ return null;
+ }
+ });
+ }
+
+ private void setFilterIfNeeded(LayoutInflater inflater) {
+ if (mDisallowedClasses == null) {
+ return;
+ }
+ inflater.setFilter(
+ new LayoutInflater.Filter() {
+ @Override
+ public boolean onLoadClass(Class clazz) {
+ return !mDisallowedClasses.contains(clazz);
+ }
+ });
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
index ec0e4cd..bb5632b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
@@ -78,6 +78,7 @@
AudioSystem.STREAM_SYSTEM_ENFORCED,
AudioSystem.STREAM_TTS,
AudioSystem.STREAM_VOICE_CALL,
+ AudioSystem.STREAM_ACCESSIBILITY,
};
private final HandlerThread mWorkerThread;
@@ -119,7 +120,26 @@
mObserver = new SettingObserver(mWorker);
mObserver.init();
mReceiver.init();
- mStreamTitles = mContext.getResources().getStringArray(R.array.volume_stream_titles);
+ final String[] titles =
+ mContext.getResources().getStringArray(R.array.volume_stream_titles);
+ if (STREAMS.length == titles.length) {
+ mStreamTitles = titles;
+ } else if (STREAMS.length > titles.length) {
+ Log.e(TAG, String.format("Missing stream titles (found %d, expected %d): "
+ + " invalid resources for volume_stream_titles",
+ titles.length, STREAMS.length));
+ mStreamTitles = new String[STREAMS.length];
+ System.arraycopy(titles, 0, mStreamTitles, 0, titles.length);
+ for (int i = titles.length ; i < STREAMS.length ; i++) {
+ mStreamTitles[i] = "";
+ }
+ } else { // STREAMS.length < titles.length
+ Log.e(TAG, String.format("Too many stream titles (found %d, expected %d): "
+ + " invalid resources for volume_stream_titles",
+ titles.length, STREAMS.length));
+ mStreamTitles = new String[STREAMS.length];
+ System.arraycopy(titles, 0, mStreamTitles, 0, STREAMS.length);
+ }
mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
mHasVibrator = mVibrator != null && mVibrator.hasVibrator();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/FragmentTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/FragmentTestCase.java
index f87336c..447edac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/FragmentTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/FragmentTestCase.java
@@ -26,6 +26,8 @@
import android.view.View;
import android.widget.FrameLayout;
+import com.android.systemui.utils.leaks.LeakCheckedTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -139,7 +141,7 @@
private class HostCallbacks extends FragmentHostCallback<FragmentTestCase> {
public HostCallbacks() {
- super(getTrackedContext(), FragmentTestCase.this.mHandler, 0);
+ super(mContext, FragmentTestCase.this.mHandler, 0);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/LeakCheckedTest.java b/packages/SystemUI/tests/src/com/android/systemui/LeakCheckedTest.java
deleted file mode 100644
index d64669d..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/LeakCheckedTest.java
+++ /dev/null
@@ -1,287 +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 com.android.systemui;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentCallbacks;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.systemui.statusbar.phone.ManagedProfileController;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.DataSaverController;
-import com.android.systemui.statusbar.policy.FlashlightController;
-import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.statusbar.policy.CallbackController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.ZenModeController;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Base class for tests to check if receivers are left registered, services bound, or other
- * listeners listening.
- */
-public class LeakCheckedTest extends SysuiTestCase {
- private static final String TAG = "LeakCheckedTest";
-
- private final Map<String, Tracker> mTrackers = new HashMap<>();
- private final Map<Class, Object> mLeakCheckers = new ArrayMap<>();
- private TrackingContext mTrackedContext;
-
- @Rule
- public TestWatcher successWatcher = new TestWatcher() {
- @Override
- protected void succeeded(Description description) {
- verify();
- }
- };
-
- @Before
- public void setup() {
- mTrackedContext = new TrackingContext(mContext);
- addSupportedLeakCheckers();
- }
-
- public <T> T getLeakChecker(Class<T> cls) {
- T obj = (T) mLeakCheckers.get(cls);
- if (obj == null) {
- Assert.fail(cls.getName() + " is not supported by LeakCheckedTest yet");
- }
- return obj;
- }
-
- public Context getTrackedContext() {
- return mTrackedContext;
- }
-
- private Tracker getTracker(String tag) {
- Tracker t = mTrackers.get(tag);
- if (t == null) {
- t = new Tracker();
- mTrackers.put(tag, t);
- }
- return t;
- }
-
- public void verify() {
- mTrackers.values().forEach(Tracker::verify);
- }
-
- public static class Tracker {
- private Map<Object, LeakInfo> mObjects = new ArrayMap<>();
-
- LeakInfo getLeakInfo(Object object) {
- LeakInfo leakInfo = mObjects.get(object);
- if (leakInfo == null) {
- leakInfo = new LeakInfo();
- mObjects.put(object, leakInfo);
- }
- return leakInfo;
- }
-
- private void verify() {
- mObjects.values().forEach(LeakInfo::verify);
- }
- }
-
- public static class LeakInfo {
- private List<Throwable> mThrowables = new ArrayList<>();
-
- private LeakInfo() {
- }
-
- private void addAllocation(Throwable t) {
- // TODO: Drop off the first element in the stack trace here to have a cleaner stack.
- mThrowables.add(t);
- }
-
- private void clearAllocations() {
- mThrowables.clear();
- }
-
- public void verify() {
- if (mThrowables.size() == 0) return;
- Log.e(TAG, "Listener or binding not properly released");
- for (Throwable t : mThrowables) {
- Log.e(TAG, "Allocation found", t);
- }
- StringWriter writer = new StringWriter();
- mThrowables.get(0).printStackTrace(new PrintWriter(writer));
- Assert.fail("Listener or binding not properly released\n"
- + writer.toString());
- }
- }
-
- private void addSupportedLeakCheckers() {
- addListening("bluetooth", BluetoothController.class);
- addListening("location", LocationController.class);
- addListening("rotation", RotationLockController.class);
- addListening("zen", ZenModeController.class);
- addListening("cast", CastController.class);
- addListening("hotspot", HotspotController.class);
- addListening("flashlight", FlashlightController.class);
- addListening("user", UserInfoController.class);
- addListening("keyguard", KeyguardMonitor.class);
- addListening("battery", BatteryController.class);
- addListening("security", SecurityController.class);
- addListening("profile", ManagedProfileController.class);
- addListening("alarm", NextAlarmController.class);
- NetworkController network = addListening("network", NetworkController.class);
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- getTracker("emergency").getLeakInfo(invocation.getArguments()[0])
- .addAllocation(new Throwable());
- return null;
- }
- }).when(network).addEmergencyListener(any());
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- getTracker("emergency").getLeakInfo(invocation.getArguments()[0]).clearAllocations();
- return null;
- }
- }).when(network).removeEmergencyListener(any());
- DataSaverController datasaver = addListening("datasaver", DataSaverController.class);
- when(network.getDataSaverController()).thenReturn(datasaver);
- }
-
- private <T extends CallbackController> T addListening(final String tag, Class<T> cls) {
- T mock = mock(cls);
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- getTracker(tag).getLeakInfo(invocation.getArguments()[0])
- .addAllocation(new Throwable());
- return null;
- }
- }).when(mock).addCallback(any());
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- getTracker(tag).getLeakInfo(invocation.getArguments()[0]).clearAllocations();
- return null;
- }
- }).when(mock).removeCallback(any());
- mLeakCheckers.put(cls, mock);
- return mock;
- }
-
- class TrackingContext extends ContextWrapper {
- public TrackingContext(Context base) {
- super(base);
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
- getTracker("receiver").getLeakInfo(receiver).addAllocation(new Throwable());
- return super.registerReceiver(receiver, filter);
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
- String broadcastPermission, Handler scheduler) {
- getTracker("receiver").getLeakInfo(receiver).addAllocation(new Throwable());
- return super.registerReceiver(receiver, filter, broadcastPermission, scheduler);
- }
-
- @Override
- public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
- IntentFilter filter, String broadcastPermission, Handler scheduler) {
- getTracker("receiver").getLeakInfo(receiver).addAllocation(new Throwable());
- return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
- scheduler);
- }
-
- @Override
- public void unregisterReceiver(BroadcastReceiver receiver) {
- getTracker("receiver").getLeakInfo(receiver).clearAllocations();
- super.unregisterReceiver(receiver);
- }
-
- @Override
- public boolean bindService(Intent service, ServiceConnection conn, int flags) {
- getTracker("service").getLeakInfo(conn).addAllocation(new Throwable());
- return super.bindService(service, conn, flags);
- }
-
- @Override
- public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
- Handler handler, UserHandle user) {
- getTracker("service").getLeakInfo(conn).addAllocation(new Throwable());
- return super.bindServiceAsUser(service, conn, flags, handler, user);
- }
-
- @Override
- public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
- UserHandle user) {
- getTracker("service").getLeakInfo(conn).addAllocation(new Throwable());
- return super.bindServiceAsUser(service, conn, flags, user);
- }
-
- @Override
- public void unbindService(ServiceConnection conn) {
- getTracker("service").getLeakInfo(conn).clearAllocations();
- super.unbindService(conn);
- }
-
- @Override
- public void registerComponentCallbacks(ComponentCallbacks callback) {
- getTracker("component").getLeakInfo(callback).addAllocation(new Throwable());
- super.registerComponentCallbacks(callback);
- }
-
- @Override
- public void unregisterComponentCallbacks(ComponentCallbacks callback) {
- getTracker("component").getLeakInfo(callback).clearAllocations();
- super.unregisterComponentCallbacks(callback);
- }
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 5dac8e5..008580a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -22,6 +22,7 @@
import android.os.MessageQueue;
import com.android.systemui.utils.TestableContext;
+import com.android.systemui.utils.leaks.Tracker;
import org.junit.After;
import org.junit.Before;
@@ -29,14 +30,14 @@
/**
* Base class that does System UI specific setup.
*/
-public class SysuiTestCase {
+public abstract class SysuiTestCase {
private Handler mHandler;
protected TestableContext mContext;
@Before
public void SysuiSetup() throws Exception {
- mContext = new TestableContext(InstrumentationRegistry.getTargetContext());
+ mContext = new TestableContext(InstrumentationRegistry.getTargetContext(), this);
}
@After
@@ -71,6 +72,11 @@
}
}
+ // Used for leak tracking, returns null to indicate no leak tracking by default.
+ public Tracker getTracker(String tag) {
+ return null;
+ }
+
public static final class EmptyRunnable implements Runnable {
public void run() {
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 863f0e5..8b99d72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -202,6 +202,18 @@
@Test
@UiThreadTest
+ public void testPulseDuringPulse_doesntCrash() {
+ mMachine.requestState(INITIALIZED);
+
+ mMachine.requestState(DOZE);
+ mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestState(DOZE_PULSING);
+ mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestState(DOZE_PULSE_DONE);
+ }
+
+ @Test
+ @UiThreadTest
public void testScreen_offInDoze() {
mMachine.requestState(INITIALIZED);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
new file mode 100644
index 0000000..4c25c62e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
@@ -0,0 +1,231 @@
+/*
+ * 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 com.android.systemui.qs;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Looper;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.SpannableStringBuilder;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.SecurityController;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class QSFooterTest extends SysuiTestCase {
+
+ private final String MANAGING_ORGANIZATION = "organization";
+ private final String DEVICE_OWNER_PACKAGE = "TestDPC";
+ private final String VPN_PACKAGE = "TestVPN";
+
+ private ViewGroup mRootView = mock(ViewGroup.class);
+ private TextView mFooterText = mock(TextView.class);
+ private ImageView mFooterIcon = mock(ImageView.class);
+ private ImageView mFooterIcon2 = mock(ImageView.class);
+ private QSFooter mFooter;
+ private Resources mResources;
+ private SecurityController mSecurityController = mock(SecurityController.class);
+
+ @Before
+ public void setUp() {
+ when(mRootView.findViewById(R.id.footer_text)).thenReturn(mFooterText);
+ when(mRootView.findViewById(R.id.footer_icon)).thenReturn(mFooterIcon);
+ when(mRootView.findViewById(R.id.footer_icon2)).thenReturn(mFooterIcon2);
+ final LayoutInflater layoutInflater = mock(LayoutInflater.class);
+ when(layoutInflater.inflate(eq(R.layout.quick_settings_footer), anyObject(), anyBoolean()))
+ .thenReturn(mRootView);
+ final Context context = mock(Context.class);
+ when(context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).thenReturn(layoutInflater);
+ mResources = mContext.getResources();
+ when(context.getResources()).thenReturn(mResources);
+ mFooter = new QSFooter(null, context);
+ reset(mRootView);
+ mFooter.setHostEnvironment(null, mSecurityController, Looper.getMainLooper());
+ }
+
+ @Test
+ public void testUnmanaged() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(false);
+ when(mSecurityController.isVpnEnabled()).thenReturn(false);
+ when(mSecurityController.isVpnBranded()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mRootView).setVisibility(View.GONE);
+ verifyNoMoreInteractions(mRootView);
+ }
+
+ @Test
+ public void testManagedNoOwnerName() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.getDeviceOwnerOrganizationName()).thenReturn(null);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterText).setText(mResources.getString(R.string.do_disclosure_generic));
+ verifyNoMoreInteractions(mFooterText);
+ verify(mRootView).setVisibility(View.VISIBLE);
+ verifyNoMoreInteractions(mRootView);
+ }
+
+ @Test
+ public void testManagedOwnerName() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.getDeviceOwnerOrganizationName())
+ .thenReturn(MANAGING_ORGANIZATION);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterText).setText(mResources.getString(R.string.do_disclosure_with_name,
+ MANAGING_ORGANIZATION));
+ verifyNoMoreInteractions(mFooterText);
+ verify(mRootView).setVisibility(View.VISIBLE);
+ verifyNoMoreInteractions(mRootView);
+ }
+
+ @Test
+ public void testNetworkLoggingEnabled() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnEnabled()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterIcon).setVisibility(View.VISIBLE);
+ verify(mFooterIcon).setImageResource(R.drawable.ic_qs_network_logging);
+ verify(mFooterIcon2).setVisibility(View.INVISIBLE);
+ }
+
+ @Test
+ public void testVpnEnabled() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(false);
+ when(mSecurityController.isVpnEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnBranded()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterIcon).setVisibility(View.VISIBLE);
+ verify(mFooterIcon, never()).setImageResource(anyInt());
+ verify(mFooterIcon2).setVisibility(View.INVISIBLE);
+ }
+
+ @Test
+ public void testNetworkLoggingAndVpnEnabled() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnBranded()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterIcon).setVisibility(View.VISIBLE);
+ verify(mFooterIcon, never()).setImageResource(anyInt());
+ verify(mFooterIcon2).setVisibility(View.VISIBLE);
+ verify(mFooterIcon2, never()).setImageResource(anyInt());
+ }
+
+ @Test
+ public void testGetMessageWithNoOrganizationAndNoVPN() {
+ assertEquals(getExpectedMessage(false /* hasDeviceOwnerOrganization */, false /* hasVPN */),
+ mFooter.getMessage(DEVICE_OWNER_PACKAGE,
+ null /* profileOwnerPackage */,
+ null /* primaryVpn */,
+ null /* profileVpn */,
+ null /* deviceOwnerOrganization */,
+ false /* hasProfileOwner */,
+ false /* isBranded */));
+ }
+
+ @Test
+ public void testGetMessageWithNoOrganizationAndVPN() {
+ assertEquals(getExpectedMessage(false /* hasDeviceOwnerOrganization */, true /* hasVPN */),
+ mFooter.getMessage(DEVICE_OWNER_PACKAGE,
+ null /* profileOwnerPackage */,
+ VPN_PACKAGE,
+ null /* profileVpn */,
+ null /* deviceOwnerOrganization */,
+ false /* hasProfileOwner */,
+ false /* isBranded */));
+ }
+
+ @Test
+ public void testGetMessageWithOrganizationAndNoVPN() {
+ assertEquals(getExpectedMessage(true /* hasDeviceOwnerOrganization */, false /* hasVPN */),
+ mFooter.getMessage(DEVICE_OWNER_PACKAGE,
+ null /* profileOwnerPackage */,
+ null /* primaryVpn */,
+ null /* profileVpn */,
+ MANAGING_ORGANIZATION,
+ false /* hasProfileOwner */,
+ false /* isBranded */));
+ }
+
+ @Test
+ public void testGetMessageWithOrganizationAndVPN() {
+ assertEquals(getExpectedMessage(true /* hasDeviceOwnerOrganization */, true /* hasVPN */),
+ mFooter.getMessage(DEVICE_OWNER_PACKAGE,
+ null /* profileOwnerPackage */,
+ VPN_PACKAGE,
+ null /* profileVpn */,
+ MANAGING_ORGANIZATION,
+ false /* hasProfileOwner */,
+ false /* isBranded */));
+ }
+
+ private CharSequence getExpectedMessage(boolean hasDeviceOwnerOrganization, boolean hasVPN) {
+ final SpannableStringBuilder message = new SpannableStringBuilder();
+ message.append(hasDeviceOwnerOrganization ?
+ mResources.getString(R.string.monitoring_description_do_header_with_name,
+ MANAGING_ORGANIZATION, DEVICE_OWNER_PACKAGE) :
+ mResources.getString(R.string.monitoring_description_do_header_generic,
+ DEVICE_OWNER_PACKAGE));
+ message.append("\n\n");
+ message.append(mResources.getString(R.string.monitoring_description_do_body));
+ if (hasVPN) {
+ message.append("\n\n");
+ message.append(mResources.getString(R.string.monitoring_description_do_body_vpn,
+ VPN_PACKAGE));
+ }
+ message.append(mResources.getString(
+ R.string.monitoring_description_do_learn_more_separator));
+ message.append(mResources.getString(R.string.monitoring_description_do_learn_more),
+ mFooter.new EnterprisePrivacySpan(), 0);
+ return message;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 6ceaead..350a95f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -21,8 +21,10 @@
import android.support.test.runner.AndroidJUnit4;
import com.android.systemui.FragmentTestCase;
+import com.android.systemui.R;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
@@ -38,6 +40,7 @@
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.tuner.TunerService;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -59,7 +62,7 @@
KeyguardMonitor keyguardMonitor = getLeakChecker(KeyguardMonitor.class);
when(userSwitcher.getKeyguardMonitor()).thenReturn(keyguardMonitor);
when(userSwitcher.getUsers()).thenReturn(new ArrayList<>());
- QSTileHost host = new QSTileHost(getTrackedContext(),
+ QSTileHost host = new QSTileHost(mContext,
mock(PhoneStatusBar.class),
getLeakChecker(BluetoothController.class),
getLeakChecker(LocationController.class),
@@ -85,6 +88,12 @@
qs.setListening(false);
waitForIdleSync(h);
+ // Manually push header through detach so it can handle standard cleanup it does on
+ // removed from window.
+ ((QuickStatusBarHeader) qs.getView().findViewById(R.id.header)).onDetachedFromWindow();
+
host.destroy();
+ // Ensure the tuner cleans up its persistent listeners.
+ TunerService.get(mContext).destroy();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
new file mode 100644
index 0000000..9a697ee
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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 com.android.systemui.statusbar.policy;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.net.ConnectivityManager;
+import android.os.UserManager;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SecurityControllerTest extends SysuiTestCase {
+ private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class);
+ private SecurityControllerImpl mSecurityController;
+
+ @Before
+ public void setUp() throws Exception {
+ final Context context = mock(Context.class);
+ when(context.getSystemService(Context.DEVICE_POLICY_SERVICE))
+ .thenReturn(mDevicePolicyManager);
+ when(context.getSystemService(Context.CONNECTIVITY_SERVICE))
+ .thenReturn(mock(ConnectivityManager.class));
+ final UserManager userManager = mock(UserManager.class);
+ when(userManager.getUserInfo(anyInt())).thenReturn(mock(UserInfo.class));
+ when(context.getSystemService(Context.USER_SERVICE))
+ .thenReturn(userManager);
+ mSecurityController = new SecurityControllerImpl(context);
+ }
+
+ @Test
+ public void testIsDeviceManaged() {
+ when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
+ assertTrue(mSecurityController.isDeviceManaged());
+
+ when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false);
+ assertFalse(mSecurityController.isDeviceManaged());
+ }
+
+ @Test
+ public void testGetDeviceOwnerOrganizationName() {
+ when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn("organization");
+ assertEquals("organization", mSecurityController.getDeviceOwnerOrganizationName());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
index 5179823..bf73416 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
@@ -14,18 +14,31 @@
package com.android.systemui.utils;
+import android.content.BroadcastReceiver;
+import android.content.ComponentCallbacks;
import android.content.ContentProviderClient;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.UserHandle;
import android.provider.Settings;
+import com.android.systemui.utils.leaks.Tracker;
+import com.android.systemui.SysuiTestCase;
+
public class TestableContext extends ContextWrapper {
private final FakeContentResolver mFakeContentResolver;
private final FakeSettingsProvider mSettingsProvider;
- public TestableContext(Context base) {
+ private Tracker mReceiver;
+ private Tracker mService;
+ private Tracker mComponent;
+
+ public TestableContext(Context base, SysuiTestCase test) {
super(base);
mFakeContentResolver = new FakeContentResolver(base);
ContentProviderClient settings = base.getContentResolver()
@@ -33,6 +46,9 @@
mSettingsProvider = FakeSettingsProvider.getFakeSettingsProvider(settings,
mFakeContentResolver);
mFakeContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider);
+ mReceiver = test.getTracker("receiver");
+ mService = test.getTracker("service");
+ mComponent = test.getTracker("component");
}
public FakeSettingsProvider getSettingsProvider() {
@@ -49,4 +65,69 @@
// Return this so its always a TestableContext.
return this;
}
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+ if (mReceiver != null) mReceiver.getLeakInfo(receiver).addAllocation(new Throwable());
+ return super.registerReceiver(receiver, filter);
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+ String broadcastPermission, Handler scheduler) {
+ if (mReceiver != null) mReceiver.getLeakInfo(receiver).addAllocation(new Throwable());
+ return super.registerReceiver(receiver, filter, broadcastPermission, scheduler);
+ }
+
+ @Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ if (mReceiver != null) mReceiver.getLeakInfo(receiver).addAllocation(new Throwable());
+ return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
+ scheduler);
+ }
+
+ @Override
+ public void unregisterReceiver(BroadcastReceiver receiver) {
+ if (mReceiver != null) mReceiver.getLeakInfo(receiver).clearAllocations();
+ super.unregisterReceiver(receiver);
+ }
+
+ @Override
+ public boolean bindService(Intent service, ServiceConnection conn, int flags) {
+ if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
+ return super.bindService(service, conn, flags);
+ }
+
+ @Override
+ public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
+ Handler handler, UserHandle user) {
+ if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
+ return super.bindServiceAsUser(service, conn, flags, handler, user);
+ }
+
+ @Override
+ public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
+ UserHandle user) {
+ if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
+ return super.bindServiceAsUser(service, conn, flags, user);
+ }
+
+ @Override
+ public void unbindService(ServiceConnection conn) {
+ if (mService != null) mService.getLeakInfo(conn).clearAllocations();
+ super.unbindService(conn);
+ }
+
+ @Override
+ public void registerComponentCallbacks(ComponentCallbacks callback) {
+ if (mComponent != null) mComponent.getLeakInfo(callback).addAllocation(new Throwable());
+ super.registerComponentCallbacks(callback);
+ }
+
+ @Override
+ public void unregisterComponentCallbacks(ComponentCallbacks callback) {
+ if (mComponent != null) mComponent.getLeakInfo(callback).clearAllocations();
+ super.unregisterComponentCallbacks(callback);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/BaseLeakChecker.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/BaseLeakChecker.java
new file mode 100644
index 0000000..0238bf7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/BaseLeakChecker.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.CallbackController;
+
+public class BaseLeakChecker<T> implements CallbackController<T> {
+
+ private final Tracker mTracker;
+
+ public BaseLeakChecker(LeakCheckedTest test, String tag) {
+ mTracker = test.getTracker(tag);
+ }
+
+ protected final Tracker getTracker() {
+ return mTracker;
+ }
+
+ @Override
+ public void addCallback(T listener) {
+ mTracker.getLeakInfo(listener).addAllocation(new Throwable());
+ }
+
+ @Override
+ public void removeCallback(T listener) {
+ mTracker.getLeakInfo(listener).clearAllocations();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
new file mode 100644
index 0000000..fa07d33
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
@@ -0,0 +1,50 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import android.os.Bundle;
+
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+public class FakeBatteryController extends BaseLeakChecker<BatteryStateChangeCallback>
+ implements BatteryController {
+ public FakeBatteryController(LeakCheckedTest test) {
+ super(test, "battery");
+ }
+
+ @Override
+ public void dispatchDemoCommand(String command, Bundle args) {
+
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+
+ }
+
+ @Override
+ public void setPowerSaveMode(boolean powerSave) {
+
+ }
+
+ @Override
+ public boolean isPowerSave() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java
new file mode 100644
index 0000000..6074a01
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java
@@ -0,0 +1,84 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.BluetoothController.Callback;
+
+import java.util.Collection;
+
+public class FakeBluetoothController extends BaseLeakChecker<Callback> implements
+ BluetoothController {
+
+ public FakeBluetoothController(LeakCheckedTest test) {
+ super(test, "bluetooth");
+ }
+
+ @Override
+ public boolean isBluetoothSupported() {
+ return false;
+ }
+
+ @Override
+ public boolean isBluetoothEnabled() {
+ return false;
+ }
+
+ @Override
+ public int getBluetoothState() {
+ return 0;
+ }
+
+ @Override
+ public boolean isBluetoothConnected() {
+ return false;
+ }
+
+ @Override
+ public boolean isBluetoothConnecting() {
+ return false;
+ }
+
+ @Override
+ public String getLastDeviceName() {
+ return null;
+ }
+
+ @Override
+ public void setBluetoothEnabled(boolean enabled) {
+
+ }
+
+ @Override
+ public Collection<CachedBluetoothDevice> getDevices() {
+ return null;
+ }
+
+ @Override
+ public void connect(CachedBluetoothDevice device) {
+
+ }
+
+ @Override
+ public void disconnect(CachedBluetoothDevice device) {
+
+ }
+
+ @Override
+ public boolean canConfigBluetooth() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeCastController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeCastController.java
new file mode 100644
index 0000000..08211f8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeCastController.java
@@ -0,0 +1,51 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.CastController.Callback;
+
+import java.util.Set;
+
+public class FakeCastController extends BaseLeakChecker<Callback> implements CastController {
+ public FakeCastController(LeakCheckedTest test) {
+ super(test, "cast");
+ }
+
+ @Override
+ public void setDiscovering(boolean request) {
+
+ }
+
+ @Override
+ public void setCurrentUserId(int currentUserId) {
+
+ }
+
+ @Override
+ public Set<CastDevice> getCastDevices() {
+ return null;
+ }
+
+ @Override
+ public void startCasting(CastDevice device) {
+
+ }
+
+ @Override
+ public void stopCasting(CastDevice device) {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeDataSaverController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeDataSaverController.java
new file mode 100644
index 0000000..857a785
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeDataSaverController.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.DataSaverController.Listener;
+
+public class FakeDataSaverController extends BaseLeakChecker<Listener> implements DataSaverController {
+
+ public FakeDataSaverController(LeakCheckedTest test) {
+ super(test, "datasaver");
+ }
+
+ @Override
+ public boolean isDataSaverEnabled() {
+ return false;
+ }
+
+ @Override
+ public void setDataSaverEnabled(boolean enabled) {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeFlashlightController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeFlashlightController.java
new file mode 100644
index 0000000..630abd7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeFlashlightController.java
@@ -0,0 +1,45 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.FlashlightController.FlashlightListener;
+
+public class FakeFlashlightController extends BaseLeakChecker<FlashlightListener>
+ implements FlashlightController {
+ public FakeFlashlightController(LeakCheckedTest test) {
+ super(test, "flashlight");
+ }
+
+ @Override
+ public boolean hasFlashlight() {
+ return false;
+ }
+
+ @Override
+ public void setFlashlight(boolean newState) {
+
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return false;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java
new file mode 100644
index 0000000..781960d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.HotspotController.Callback;
+
+public class FakeHotspotController extends BaseLeakChecker<Callback> implements HotspotController {
+
+ public FakeHotspotController(LeakCheckedTest test) {
+ super(test, "hotspot");
+ }
+
+ @Override
+ public boolean isHotspotEnabled() {
+ return false;
+ }
+
+ @Override
+ public void setHotspotEnabled(boolean enabled) {
+
+ }
+
+ @Override
+ public boolean isHotspotSupported() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
new file mode 100644
index 0000000..39bbf2d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
@@ -0,0 +1,51 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+
+public class FakeKeyguardMonitor implements KeyguardMonitor {
+
+ private final BaseLeakChecker<Callback> mCallbackController;
+
+ public FakeKeyguardMonitor(LeakCheckedTest test) {
+ mCallbackController = new BaseLeakChecker<Callback>(test, "keyguard");
+ }
+
+ @Override
+ public void addCallback(Callback callback) {
+ mCallbackController.addCallback(callback);
+ }
+
+ @Override
+ public void removeCallback(Callback callback) {
+ mCallbackController.removeCallback(callback);
+ }
+
+ @Override
+ public boolean isSecure() {
+ return false;
+ }
+
+ @Override
+ public boolean isShowing() {
+ return false;
+ }
+
+ @Override
+ public boolean canSkipBouncer() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java
new file mode 100644
index 0000000..eab436c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
+
+public class FakeLocationController extends BaseLeakChecker<LocationSettingsChangeCallback>
+ implements LocationController {
+ public FakeLocationController(LeakCheckedTest test) {
+ super(test, "location");
+ }
+
+ @Override
+ public boolean isLocationEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean setLocationEnabled(boolean enabled) {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeManagedProfileController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeManagedProfileController.java
new file mode 100644
index 0000000..0ec0d77
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeManagedProfileController.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.phone.ManagedProfileController;
+import com.android.systemui.statusbar.phone.ManagedProfileController.Callback;
+
+public class FakeManagedProfileController extends BaseLeakChecker<Callback> implements
+ ManagedProfileController {
+ public FakeManagedProfileController(LeakCheckedTest test) {
+ super(test, "profile");
+ }
+
+ @Override
+ public void setWorkModeEnabled(boolean enabled) {
+
+ }
+
+ @Override
+ public boolean hasActiveProfile() {
+ return false;
+ }
+
+ @Override
+ public boolean isWorkModeEnabled() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
new file mode 100644
index 0000000..fcfe9aa
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
@@ -0,0 +1,78 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.settingslib.net.DataUsageController;
+import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+
+public class FakeNetworkController extends BaseLeakChecker<SignalCallback>
+ implements NetworkController {
+
+ private final FakeDataSaverController mDataSaverController;
+ private final BaseLeakChecker<EmergencyListener> mEmergencyChecker;
+
+ public FakeNetworkController(LeakCheckedTest test) {
+ super(test, "network");
+ mDataSaverController = new FakeDataSaverController(test);
+ mEmergencyChecker = new BaseLeakChecker<EmergencyListener>(test, "emergency");
+ }
+
+ @Override
+ public void addEmergencyListener(EmergencyListener listener) {
+ mEmergencyChecker.addCallback(listener);
+ }
+
+ @Override
+ public void removeEmergencyListener(EmergencyListener listener) {
+ mEmergencyChecker.removeCallback(listener);
+ }
+
+ @Override
+ public DataSaverController getDataSaverController() {
+ return mDataSaverController;
+ }
+
+ @Override
+ public boolean hasMobileDataFeature() {
+ return false;
+ }
+
+ @Override
+ public void setWifiEnabled(boolean enabled) {
+
+ }
+
+ @Override
+ public void onUserSwitched(int newUserId) {
+
+ }
+
+ @Override
+ public AccessPointController getAccessPointController() {
+ return null;
+ }
+
+ @Override
+ public DataUsageController getMobileDataController() {
+ return null;
+ }
+
+ @Override
+ public boolean hasVoiceCallingFeature() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNextAlarmController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNextAlarmController.java
new file mode 100644
index 0000000..707fc4b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNextAlarmController.java
@@ -0,0 +1,26 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+
+public class FakeNextAlarmController extends BaseLeakChecker<NextAlarmChangeCallback>
+ implements NextAlarmController {
+
+ public FakeNextAlarmController(LeakCheckedTest test) {
+ super(test, "alarm");
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeRotationLockController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeRotationLockController.java
new file mode 100644
index 0000000..00e2404
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeRotationLockController.java
@@ -0,0 +1,50 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
+
+public class FakeRotationLockController extends BaseLeakChecker<RotationLockControllerCallback>
+ implements RotationLockController {
+ public FakeRotationLockController(LeakCheckedTest test) {
+ super(test, "rotation");
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+
+ }
+
+ @Override
+ public int getRotationLockOrientation() {
+ return 0;
+ }
+
+ @Override
+ public boolean isRotationLockAffordanceVisible() {
+ return false;
+ }
+
+ @Override
+ public boolean isRotationLocked() {
+ return false;
+ }
+
+ @Override
+ public void setRotationLocked(boolean locked) {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
new file mode 100644
index 0000000..2d53c77
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
@@ -0,0 +1,85 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.statusbar.policy.SecurityController.SecurityControllerCallback;
+
+public class FakeSecurityController extends BaseLeakChecker<SecurityControllerCallback>
+ implements SecurityController {
+ public FakeSecurityController(LeakCheckedTest test) {
+ super(test, "security");
+ }
+
+ @Override
+ public boolean isDeviceManaged() {
+ return false;
+ }
+
+ @Override
+ public boolean hasProfileOwner() {
+ return false;
+ }
+
+ @Override
+ public String getDeviceOwnerName() {
+ return null;
+ }
+
+ @Override
+ public String getProfileOwnerName() {
+ return null;
+ }
+
+ @Override
+ public CharSequence getDeviceOwnerOrganizationName() {
+ return null;
+ }
+
+ @Override
+ public boolean isNetworkLoggingEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean isVpnEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean isVpnRestricted() {
+ return false;
+ }
+
+ @Override
+ public boolean isVpnBranded() {
+ return false;
+ }
+
+ @Override
+ public String getPrimaryVpnName() {
+ return null;
+ }
+
+ @Override
+ public String getProfileVpnName() {
+ return null;
+ }
+
+ @Override
+ public void onUserSwitched(int newUserId) {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeUserInfoController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeUserInfoController.java
new file mode 100644
index 0000000..578b310
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeUserInfoController.java
@@ -0,0 +1,30 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
+
+public class FakeUserInfoController extends BaseLeakChecker<OnUserInfoChangedListener>
+ implements UserInfoController {
+ public FakeUserInfoController(LeakCheckedTest test) {
+ super(test, "user_info");
+ }
+
+ @Override
+ public void reloadUserInfo() {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java
new file mode 100644
index 0000000..13ea385
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java
@@ -0,0 +1,84 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.ZenRule;
+
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.policy.ZenModeController.Callback;
+
+public class FakeZenModeController extends BaseLeakChecker<Callback> implements ZenModeController {
+ public FakeZenModeController(LeakCheckedTest test) {
+ super(test, "zen");
+ }
+
+ @Override
+ public void setZen(int zen, Uri conditionId, String reason) {
+
+ }
+
+ @Override
+ public int getZen() {
+ return 0;
+ }
+
+ @Override
+ public ZenRule getManualRule() {
+ return null;
+ }
+
+ @Override
+ public ZenModeConfig getConfig() {
+ return null;
+ }
+
+ @Override
+ public long getNextAlarm() {
+ return 0;
+ }
+
+ @Override
+ public void setUserId(int userId) {
+
+ }
+
+ @Override
+ public boolean isZenAvailable() {
+ return false;
+ }
+
+ @Override
+ public ComponentName getEffectsSuppressor() {
+ return null;
+ }
+
+ @Override
+ public boolean isCountdownConditionSupported() {
+ return false;
+ }
+
+ @Override
+ public int getCurrentUser() {
+ return 0;
+ }
+
+ @Override
+ public boolean isVolumeRestricted() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
new file mode 100644
index 0000000..728ed60
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+
+import android.util.ArrayMap;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.phone.ManagedProfileController;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.CallbackController;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Base class for tests to check if receivers are left registered, services bound, or other
+ * listeners listening.
+ */
+public abstract class LeakCheckedTest extends SysuiTestCase {
+ private static final String TAG = "LeakCheckedTest";
+
+ private final Map<String, Tracker> mTrackers = new HashMap<>();
+ private final Map<Class, Object> mLeakCheckers = new ArrayMap<>();
+
+ @Rule
+ public TestWatcher successWatcher = new TestWatcher() {
+ @Override
+ protected void succeeded(Description description) {
+ verify();
+ }
+ };
+
+ public <T> T getLeakChecker(Class<T> cls) {
+ Object obj = mLeakCheckers.get(cls);
+ if (obj == null) {
+ // Lazy create checkers so we only have the ones we need.
+ if (cls == BluetoothController.class) {
+ obj = new FakeBluetoothController(this);
+ } else if (cls == LocationController.class) {
+ obj = new FakeLocationController(this);
+ } else if (cls == RotationLockController.class) {
+ obj = new FakeRotationLockController(this);
+ } else if (cls == ZenModeController.class) {
+ obj = new FakeZenModeController(this);
+ } else if (cls == CastController.class) {
+ obj = new FakeCastController(this);
+ } else if (cls == HotspotController.class) {
+ obj = new FakeHotspotController(this);
+ } else if (cls == FlashlightController.class) {
+ obj = new FakeFlashlightController(this);
+ } else if (cls == UserInfoController.class) {
+ obj = new FakeUserInfoController(this);
+ } else if (cls == KeyguardMonitor.class) {
+ obj = new FakeKeyguardMonitor(this);
+ } else if (cls == BatteryController.class) {
+ obj = new FakeBatteryController(this);
+ } else if (cls == SecurityController.class) {
+ obj = new FakeSecurityController(this);
+ } else if (cls == ManagedProfileController.class) {
+ obj = new FakeManagedProfileController(this);
+ } else if (cls == NextAlarmController.class) {
+ obj = new FakeNextAlarmController(this);
+ } else if (cls == NetworkController.class) {
+ obj = new FakeNetworkController(this);
+ } else {
+ Assert.fail(cls.getName() + " is not supported by LeakCheckedTest yet");
+ }
+ mLeakCheckers.put(cls, obj);
+ }
+ return (T) obj;
+ }
+
+ @Override
+ public Tracker getTracker(String tag) {
+ Tracker t = mTrackers.get(tag);
+ if (t == null) {
+ t = new Tracker();
+ mTrackers.put(tag, t);
+ }
+ return t;
+ }
+
+ public void verify() {
+ mTrackers.values().forEach(Tracker::verify);
+ }
+
+ public <T extends CallbackController> T addListening(T mock, Class<T> cls, String tag) {
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ getTracker(tag).getLeakInfo(invocation.getArguments()[0])
+ .addAllocation(new Throwable());
+ return null;
+ }
+ }).when(mock).addCallback(any());
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ getTracker(tag).getLeakInfo(invocation.getArguments()[0]).clearAllocations();
+ return null;
+ }
+ }).when(mock).removeCallback(any());
+ mLeakCheckers.put(cls, mock);
+ return mock;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakInfo.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakInfo.java
new file mode 100644
index 0000000..1d016fb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakInfo.java
@@ -0,0 +1,53 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import android.util.Log;
+
+import org.junit.Assert;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class LeakInfo {
+ private static final String TAG = "LeakInfo";
+ private List<Throwable> mThrowables = new ArrayList<>();
+
+ LeakInfo() {
+ }
+
+ public void addAllocation(Throwable t) {
+ // TODO: Drop off the first element in the stack trace here to have a cleaner stack.
+ mThrowables.add(t);
+ }
+
+ public void clearAllocations() {
+ mThrowables.clear();
+ }
+
+ void verify() {
+ if (mThrowables.size() == 0) return;
+ Log.e(TAG, "Listener or binding not properly released");
+ for (Throwable t : mThrowables) {
+ Log.e(TAG, "Allocation found", t);
+ }
+ StringWriter writer = new StringWriter();
+ mThrowables.get(0).printStackTrace(new PrintWriter(writer));
+ Assert.fail("Listener or binding not properly released\n"
+ + writer.toString());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/Tracker.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/Tracker.java
new file mode 100644
index 0000000..26ffd10
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/Tracker.java
@@ -0,0 +1,38 @@
+/*
+ * 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 com.android.systemui.utils.leaks;
+
+import android.util.ArrayMap;
+
+import com.android.systemui.utils.leaks.LeakInfo;
+
+import java.util.Map;
+
+public class Tracker {
+ private Map<Object, LeakInfo> mObjects = new ArrayMap<>();
+
+ public LeakInfo getLeakInfo(Object object) {
+ LeakInfo leakInfo = mObjects.get(object);
+ if (leakInfo == null) {
+ leakInfo = new LeakInfo();
+ mObjects.put(object, leakInfo);
+ }
+ return leakInfo;
+ }
+
+ void verify() {
+ mObjects.values().forEach(LeakInfo::verify);
+ }
+}
diff --git a/preloaded-classes b/preloaded-classes
index a79ae50..da3861a 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -365,6 +365,8 @@
android.app.BackStackRecord
android.app.BackStackRecord$Op
android.app.BackStackRecord$TransitionState
+android.app.ContentProviderHolder
+android.app.ContentProviderHolder$1
android.app.ContextImpl
android.app.ContextImpl$ApplicationContentResolver
android.app.Dialog
@@ -383,8 +385,8 @@
android.app.FragmentManagerImpl$1
android.app.FragmentTransaction
android.app.IActivityManager
-android.app.IActivityManager$ContentProviderHolder
-android.app.IActivityManager$ContentProviderHolder$1
+android.app.IActivityManager$Stub
+android.app.IActivityManager$Stub$Proxy
android.app.IAlarmManager
android.app.IAlarmManager$Stub
android.app.IAlarmManager$Stub$Proxy
diff --git a/proto/src/ipconnectivity.proto b/proto/src/ipconnectivity.proto
index 29b318f..cf372bc 100644
--- a/proto/src/ipconnectivity.proto
+++ b/proto/src/ipconnectivity.proto
@@ -17,6 +17,22 @@
optional int32 network_id = 1;
};
+// Transport describes a physical technology used by a network. It is a subset
+// of the TRANSPORT_* constants defined in android.net.NetworkCapabilities.
+enum Transport {
+ UNKNOWN = 0;
+ BLUETOOTH = 1;
+ CELLULAR = 2;
+ ETHERNET = 3;
+ WIFI = 4;
+};
+
+// A pair of (key, value) integers for describing histogram-like statistics.
+message Pair {
+ optional int32 key = 1;
+ optional int32 value = 2;
+};
+
// Logs changes in the system default network. Changes can be 1) acquiring a
// default network with no previous default, 2) a switch of the system default
// network to a new default network, 3) a loss of the system default network.
@@ -49,7 +65,8 @@
// This message is associated to android.net.metrics.IpReachabilityEvent.
message IpReachabilityEvent {
// The interface name (wlan, rmnet, lo, ...) on which the probe was sent.
- optional string if_name = 1;
+ // Deprecated since version 2, replaced by transport field.
+ optional string if_name = 1 [deprecated = true];
// The event type code of the probe, represented by constants defined in
// android.net.metrics.IpReachabilityEvent.
@@ -93,6 +110,7 @@
// Logs DNS lookup latencies. Repeated fields must have the same length.
// This message is associated to android.net.metrics.DnsEvent.
+// Deprecated since version 2.
message DNSLookupBatch {
// The id of the network on which the DNS lookups took place.
optional NetworkId network_id = 1;
@@ -107,13 +125,62 @@
repeated int32 latencies_ms = 4;
};
+// Represents a collections of DNS lookup latencies and counters for a
+// particular combination of DNS query type and return code.
+// Since version 2.
+message DNSLatencies {
+ // The type of the DNS lookups, as defined in android.net.metrics.DnsEvent.
+ // Acts as a key for a set of DNS query results.
+ // Possible values are: 0 for getaddrinfo, 1 for gethostbyname.
+ optional int32 type = 1;
+
+ // The return value of the DNS resolver for the DNS lookups.
+ // Acts as a key for a set of DNS query results.
+ // Possible values are: 0 for success, or errno code for failures.
+ optional int32 return_code = 2;
+
+ // The number of query operations recorded.
+ optional int32 query_count = 3;
+
+ // The number of query operations returning A IPv4 records.
+ optional int32 a_count = 4;
+
+ // The number of query operations returning AAAA IPv6 records.
+ optional int32 aaaa_count = 5;
+
+ // The time it took for each DNS lookup to complete. The number of repeated
+ // values can be less than query_count in case of event rate-limiting.
+ repeated int32 latencies_ms = 6;
+};
+
+// Represents latency and errno statistics of the connect() system call.
+// Since version 2.
+message ConnectStatistics {
+ // The number of connect() operations recorded.
+ optional int32 connect_count = 1;
+
+ // The number of connect() operations with IPv6 socket address.
+ optional int32 ipv6_addr_count = 2;
+
+ // The time it took for each successful connect() operation to complete.
+ // The number of repeated values can be less than connect_count in case of
+ // event rate-limiting.
+ repeated int32 latencies_ms = 3;
+
+ // Counts of all error values returned by failed connect() operations.
+ // The Pair key field is the errno code. The Pair value field is the count
+ // for that errno code.
+ repeated Pair errnos_counters = 4;
+};
+
// Represents a DHCP event on a single interface, which can be a DHCPClient
// state transition or a response packet parsing error.
// This message is associated to android.net.metrics.DhcpClientEvent and
// android.net.metrics.DhcpErrorEvent.
message DHCPEvent {
// The interface name (wlan, rmnet, lo, ...) on which the event happened.
- optional string if_name = 1;
+ // Deprecated since version 2, replaced by transport field.
+ optional string if_name = 1 [deprecated = true];
oneof value {
// The name of a state in the DhcpClient state machine, represented by
@@ -217,7 +284,8 @@
// This message is associated to android.net.metrics.IpManagerEvent.
message IpProvisioningEvent {
// The interface name (wlan, rmnet, lo, ...) on which the probe was sent.
- optional string if_name = 1;
+ // Deprecated since version 2, replaced by transport field.
+ optional string if_name = 1 [deprecated = true];
// The code of the IP provisioning event, represented by constants defined in
// android.net.metrics.IpManagerEvent.
@@ -228,11 +296,15 @@
}
// Represents one of the IP connectivity event defined in this file.
-// Next tag: 12
+// Next tag: 15
message IpConnectivityEvent {
// Time in ms when the event was recorded.
optional int64 time_ms = 1;
+ // Physical transport of the network on which the event happened.
+ // Since version 2.
+ optional Transport transport = 12;
+
// Event type.
oneof event {
@@ -246,7 +318,14 @@
NetworkEvent network_event = 4;
// A batch of DNS lookups.
- DNSLookupBatch dns_lookup_batch = 5;
+ // Deprecated in the nyc-mr2 release since version 2, and replaced by dns_latencies.
+ DNSLookupBatch dns_lookup_batch = 5 [deprecated = true];
+
+ // DNS lookup latency statistics.
+ DNSLatencies dns_latencies = 13;
+
+ // Connect latency and errno statistics.
+ ConnectStatistics connect_statistics = 14;
// A DHCP client event or DHCP receive error.
DHCPEvent dhcp_event = 6;
@@ -277,9 +356,9 @@
optional int32 dropped_events = 2;
// The version number of the metrics events being collected.
- // nyc-dev: not populated, implicitly 0
- // nyc-dr1: not populated, implicitly 1 (sailfish and marlin only)
- // nyc-mr1: not populated, implicitly 1
- // nyc-mr2: 2
+ // nyc-dev: not populated, implicitly 0.
+ // nyc-dr1: not populated, implicitly 1 (sailfish and marlin only).
+ // nyc-mr1: not populated, implicitly 1.
+ // nyc-mr2: 2.
optional int32 version = 3;
};
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index f08408b..ef9d8f2 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3083,6 +3083,28 @@
// PACKAGE: The package name of the app the permission was revoked for
ACTION_PERMISSION_REVOKE_WRITE_EXTERNAL_STORAGE = 733;
+ // ACTION: Logged when a provisioning session has started
+ PROVISIONING_SESSION_STARTED = 734;
+
+ // ACTION: Logged when a provisioning session has completed
+ PROVISIONING_SESSION_COMPLETED = 735;
+
+ // ACTION: An app requested the permission READ_PHONE_NUMBER
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_PERMISSION_REQUEST_READ_PHONE_NUMBER = 736;
+
+ // ACTION: An app was granted the permission READ_PHONE_NUMBER
+ // PACKAGE: The package name of the app that was granted the permission
+ ACTION_PERMISSION_GRANT_READ_PHONE_NUMBER = 737;
+
+ // ACTION: An app requested the permission READ_PHONE_NUMBER and the request was denied
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_PERMISSION_DENIED_READ_PHONE_NUMBER = 738;
+
+ // ACTION: The permission READ_PHONE_NUMBER was revoked for an app
+ // PACKAGE: The package name of the app the permission was revoked for
+ ACTION_PERMISSION_REVOKE_READ_PHONE_NUMBER = 739;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ab111a0..df71ced 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2843,15 +2843,8 @@
}
if (mMotionEventInjector != null) {
List<GestureDescription.GestureStep> steps = gestureSteps.getList();
- List<MotionEvent> events = GestureDescription.MotionEventGenerator
- .getMotionEventsFromGestureSteps(steps);
- // Confirm that the motion events end with an UP event.
- if (events.get(events.size() - 1).getAction() == MotionEvent.ACTION_UP) {
- mMotionEventInjector.injectEvents(events, mServiceInterface, sequence);
- return;
- } else {
- Slog.e(LOG_TAG, "Gesture is not well-formed");
- }
+ mMotionEventInjector.injectEvents(steps, mServiceInterface, sequence);
+ return;
} else {
Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
}
diff --git a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
index 8042ddb..48041ad 100644
--- a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
+++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
@@ -16,49 +16,67 @@
package com.android.server.accessibility;
+import android.accessibilityservice.GestureDescription;
+import android.accessibilityservice.GestureDescription.GestureStep;
+import android.accessibilityservice.GestureDescription.TouchPoint;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.os.SomeArgs;
-import com.android.server.accessibility.AccessibilityManagerService.Service;
+import java.util.ArrayList;
import java.util.List;
/**
* Injects MotionEvents to permit {@code AccessibilityService}s to touch the screen on behalf of
* users.
- *
+ * <p>
* All methods except {@code injectEvents} must be called only from the main thread.
*/
public class MotionEventInjector implements EventStreamTransformation, Handler.Callback {
private static final String LOG_TAG = "MotionEventInjector";
private static final int MESSAGE_SEND_MOTION_EVENT = 1;
private static final int MESSAGE_INJECT_EVENTS = 2;
- private static final int MAX_POINTERS = 11; // Non-binding maximum
+
+ /**
+ * Constants used to initialize all MotionEvents
+ */
+ private static final int EVENT_META_STATE = 0;
+ private static final int EVENT_BUTTON_STATE = 0;
+ private static final int EVENT_DEVICE_ID = 0;
+ private static final int EVENT_EDGE_FLAGS = 0;
+ private static final int EVENT_SOURCE = InputDevice.SOURCE_TOUCHSCREEN;
+ private static final int EVENT_FLAGS = 0;
+ private static final float EVENT_X_PRECISION = 1;
+ private static final float EVENT_Y_PRECISION = 1;
+
+ private static MotionEvent.PointerCoords[] sPointerCoords;
+ private static MotionEvent.PointerProperties[] sPointerProps;
private final Handler mHandler;
private final SparseArray<Boolean> mOpenGesturesInProgress = new SparseArray<>();
- // These two arrays must be the same length
- private MotionEvent.PointerProperties[] mPointerProperties =
- new MotionEvent.PointerProperties[MAX_POINTERS];
- private MotionEvent.PointerCoords[] mPointerCoords =
- new MotionEvent.PointerCoords[MAX_POINTERS];
private EventStreamTransformation mNext;
private IAccessibilityServiceClient mServiceInterfaceForCurrentGesture;
- private int mSequenceForCurrentGesture;
- private int mSourceOfInjectedGesture = InputDevice.SOURCE_UNKNOWN;
+ private IntArray mSequencesInProgress = new IntArray(5);
private boolean mIsDestroyed = false;
+ private TouchPoint[] mLastTouchPoints;
+ private int mNumLastTouchPoints;
+ private long mDownTime;
+ private long mLastScheduledEventTime;
+ private SparseIntArray mStrokeIdToPointerId = new SparseIntArray(5);
/**
* @param looper A looper on the main thread to use for dispatching new events
@@ -75,18 +93,18 @@
}
/**
- * Schedule a series of events for injection. These events must comprise a complete, valid
- * sequence. All gestures currently in progress will be cancelled, and all {@code downTime}
- * and {@code eventTime} fields will be offset by the current time.
+ * Schedule a gesture for injection. The gesture is defined by a set of {@code GestureStep}s,
+ * from which {@code MotionEvent}s will be derived. All gestures currently in progress will be
+ * cancelled.
*
- * @param events The events to inject. Must all be from the same source.
+ * @param gestureSteps The gesture steps to inject.
* @param serviceInterface The interface to call back with a result when the gesture is
* either complete or cancelled.
*/
- public void injectEvents(List<MotionEvent> events,
+ public void injectEvents(List<GestureStep> gestureSteps,
IAccessibilityServiceClient serviceInterface, int sequence) {
SomeArgs args = SomeArgs.obtain();
- args.arg1 = events;
+ args.arg1 = gestureSteps;
args.arg2 = serviceInterface;
args.argi1 = sequence;
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_INJECT_EVENTS, args));
@@ -138,7 +156,7 @@
public boolean handleMessage(Message message) {
if (message.what == MESSAGE_INJECT_EVENTS) {
SomeArgs args = (SomeArgs) message.obj;
- injectEventsMainThread((List<MotionEvent>) args.arg1,
+ injectEventsMainThread((List<GestureStep>) args.arg1,
(IAccessibilityServiceClient) args.arg2, args.argi1);
args.recycle();
return true;
@@ -148,16 +166,16 @@
return false;
}
MotionEvent motionEvent = (MotionEvent) message.obj;
- sendMotionEventToNext(motionEvent, motionEvent,
- WindowManagerPolicy.FLAG_PASS_TO_USER);
- // If the message queue is now empty, then this gesture is complete
- if (!mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) {
- notifyService(true);
+ sendMotionEventToNext(motionEvent, motionEvent, WindowManagerPolicy.FLAG_PASS_TO_USER);
+ boolean isEndOfSequence = message.arg1 != 0;
+ if (isEndOfSequence) {
+ notifyService(mServiceInterfaceForCurrentGesture, mSequencesInProgress.get(0), true);
+ mSequencesInProgress.remove(0);
}
return true;
}
- private void injectEventsMainThread(List<MotionEvent> events,
+ private void injectEventsMainThread(List<GestureStep> gestureSteps,
IAccessibilityServiceClient serviceInterface, int sequence) {
if (mIsDestroyed) {
try {
@@ -168,48 +186,110 @@
}
return;
}
- cancelAnyPendingInjectedEvents();
- mSourceOfInjectedGesture = events.get(0).getSource();
- cancelAnyGestureInProgress(mSourceOfInjectedGesture);
- mServiceInterfaceForCurrentGesture = serviceInterface;
- mSequenceForCurrentGesture = sequence;
+
if (mNext == null) {
- notifyService(false);
+ notifyService(serviceInterface, sequence, false);
return;
}
- long startTime = SystemClock.uptimeMillis();
+ boolean continuingGesture = newGestureTriesToContinueOldOne(gestureSteps);
+
+ if (continuingGesture) {
+ if ((serviceInterface != mServiceInterfaceForCurrentGesture)
+ || !prepareToContinueOldGesture(gestureSteps)) {
+ cancelAnyPendingInjectedEvents();
+ notifyService(serviceInterface, sequence, false);
+ return;
+ }
+ }
+ if (!continuingGesture) {
+ cancelAnyPendingInjectedEvents();
+ // Injected gestures have been canceled, but real gestures still need cancelling
+ cancelAnyGestureInProgress(EVENT_SOURCE);
+ }
+ mServiceInterfaceForCurrentGesture = serviceInterface;
+
+ long currentTime = SystemClock.uptimeMillis();
+ List<MotionEvent> events = getMotionEventsFromGestureSteps(gestureSteps,
+ (mSequencesInProgress.size() == 0) ? currentTime : mLastScheduledEventTime);
+ if (events.isEmpty()) {
+ notifyService(serviceInterface, sequence, false);
+ return;
+ }
+ mSequencesInProgress.add(sequence);
+
for (int i = 0; i < events.size(); i++) {
MotionEvent event = events.get(i);
- int numPointers = event.getPointerCount();
- if (numPointers > mPointerCoords.length) {
- mPointerCoords = new MotionEvent.PointerCoords[numPointers];
- mPointerProperties = new MotionEvent.PointerProperties[numPointers];
- }
- for (int j = 0; j < numPointers; j++) {
- if (mPointerCoords[j] == null) {
- mPointerCoords[j] = new MotionEvent.PointerCoords();
- mPointerProperties[j] = new MotionEvent.PointerProperties();
- }
- event.getPointerCoords(j, mPointerCoords[j]);
- event.getPointerProperties(j, mPointerProperties[j]);
- }
-
- /*
- * MotionEvent doesn't have a setEventTime() method (it carries around history data,
- * which could become inconsistent), so we need to obtain a new one.
- */
- MotionEvent offsetEvent = MotionEvent.obtain(startTime + event.getDownTime(),
- startTime + event.getEventTime(), event.getAction(), numPointers,
- mPointerProperties, mPointerCoords, event.getMetaState(),
- event.getButtonState(), event.getXPrecision(), event.getYPrecision(),
- event.getDeviceId(), event.getEdgeFlags(), event.getSource(),
- event.getFlags());
- Message message = mHandler.obtainMessage(MESSAGE_SEND_MOTION_EVENT, offsetEvent);
- mHandler.sendMessageDelayed(message, event.getEventTime());
+ int isEndOfSequence = (i == events.size() - 1) ? 1 : 0;
+ Message message = mHandler.obtainMessage(
+ MESSAGE_SEND_MOTION_EVENT, isEndOfSequence, 0, event);
+ mLastScheduledEventTime = event.getEventTime();
+ mHandler.sendMessageDelayed(message, Math.max(0, event.getEventTime() - currentTime));
}
}
+ private boolean newGestureTriesToContinueOldOne(List<GestureStep> gestureSteps) {
+ if (gestureSteps.isEmpty()) {
+ return false;
+ }
+ GestureStep firstStep = gestureSteps.get(0);
+ for (int i = 0; i < firstStep.numTouchPoints; i++) {
+ if (!firstStep.touchPoints[i].mIsStartOfPath) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A gesture can only continue a gesture if it contains intermediate points that continue
+ * each continued stroke of the last gesture, and no extra points.
+ *
+ * @param gestureSteps The steps of the new gesture
+ * @return {@code true} if the new gesture could continue the last one dispatched. {@code false}
+ * otherwise.
+ */
+ private boolean prepareToContinueOldGesture(List<GestureStep> gestureSteps) {
+ if (gestureSteps.isEmpty() || (mLastTouchPoints == null) || (mNumLastTouchPoints == 0)) {
+ return false;
+ }
+ GestureStep firstStep = gestureSteps.get(0);
+ // Make sure all of the continuing paths match up
+ int numContinuedStrokes = 0;
+ for (int i = 0; i < firstStep.numTouchPoints; i++) {
+ TouchPoint touchPoint = firstStep.touchPoints[i];
+ if (!touchPoint.mIsStartOfPath) {
+ int continuedPointerId = mStrokeIdToPointerId
+ .get(touchPoint.mContinuedStrokeId, -1);
+ if (continuedPointerId == -1) {
+ return false;
+ }
+ mStrokeIdToPointerId.put(touchPoint.mStrokeId, continuedPointerId);
+ int lastPointIndex = findPointByStrokeId(
+ mLastTouchPoints, mNumLastTouchPoints, touchPoint.mContinuedStrokeId);
+ if (lastPointIndex < 0) {
+ return false;
+ }
+ if (mLastTouchPoints[lastPointIndex].mIsEndOfPath
+ || (mLastTouchPoints[lastPointIndex].mX != touchPoint.mX)
+ || (mLastTouchPoints[lastPointIndex].mY != touchPoint.mY)) {
+ return false;
+ }
+ // Update the last touch point to match the continuation, so the gestures will
+ // line up
+ mLastTouchPoints[lastPointIndex].mStrokeId = touchPoint.mStrokeId;
+ }
+ numContinuedStrokes++;
+ }
+ // Make sure we didn't miss any paths
+ for (int i = 0; i < mNumLastTouchPoints; i++) {
+ if (!mLastTouchPoints[i].mIsEndOfPath) {
+ numContinuedStrokes--;
+ }
+ }
+ return numContinuedStrokes == 0;
+ }
+
private void sendMotionEventToNext(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
if (mNext != null) {
@@ -228,7 +308,7 @@
if ((mNext != null) && mOpenGesturesInProgress.get(source, false)) {
long now = SystemClock.uptimeMillis();
MotionEvent cancelEvent =
- MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+ obtainMotionEvent(now, now, MotionEvent.ACTION_CANCEL, getLastTouchPoints(), 1);
sendMotionEventToNext(cancelEvent, cancelEvent,
WindowManagerPolicy.FLAG_PASS_TO_USER);
mOpenGesturesInProgress.put(source, false);
@@ -237,19 +317,187 @@
private void cancelAnyPendingInjectedEvents() {
if (mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) {
- cancelAnyGestureInProgress(mSourceOfInjectedGesture);
mHandler.removeMessages(MESSAGE_SEND_MOTION_EVENT);
- notifyService(false);
+ cancelAnyGestureInProgress(EVENT_SOURCE);
+ for (int i = mSequencesInProgress.size() - 1; i >= 0; i--) {
+ notifyService(mServiceInterfaceForCurrentGesture,
+ mSequencesInProgress.get(i), false);
+ mSequencesInProgress.remove(i);
+ }
+ } else if (mNumLastTouchPoints != 0) {
+ // An injected gesture is in progress and waiting for a continuation. Cancel it.
+ cancelAnyGestureInProgress(EVENT_SOURCE);
}
+ mNumLastTouchPoints = 0;
+ mStrokeIdToPointerId.clear();
}
- private void notifyService(boolean success) {
+ private void notifyService(IAccessibilityServiceClient service, int sequence, boolean success) {
try {
- mServiceInterfaceForCurrentGesture.onPerformGestureResult(
- mSequenceForCurrentGesture, success);
+ service.onPerformGestureResult(sequence, success);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error sending motion event injection status to "
+ mServiceInterfaceForCurrentGesture, re);
}
}
+
+ private List<MotionEvent> getMotionEventsFromGestureSteps(
+ List<GestureStep> steps, long startTime) {
+ final List<MotionEvent> motionEvents = new ArrayList<>();
+
+ TouchPoint[] lastTouchPoints = getLastTouchPoints();
+
+ for (int i = 0; i < steps.size(); i++) {
+ GestureDescription.GestureStep step = steps.get(i);
+ int currentTouchPointSize = step.numTouchPoints;
+ if (currentTouchPointSize > lastTouchPoints.length) {
+ mNumLastTouchPoints = 0;
+ motionEvents.clear();
+ return motionEvents;
+ }
+
+ appendMoveEventIfNeeded(motionEvents, step.touchPoints, currentTouchPointSize,
+ startTime + step.timeSinceGestureStart);
+ appendUpEvents(motionEvents, step.touchPoints, currentTouchPointSize,
+ startTime + step.timeSinceGestureStart);
+ appendDownEvents(motionEvents, step.touchPoints, currentTouchPointSize,
+ startTime + step.timeSinceGestureStart);
+ }
+ return motionEvents;
+ }
+
+ private TouchPoint[] getLastTouchPoints() {
+ if (mLastTouchPoints == null) {
+ int capacity = GestureDescription.getMaxStrokeCount();
+ mLastTouchPoints = new TouchPoint[capacity];
+ for (int i = 0; i < capacity; i++) {
+ mLastTouchPoints[i] = new GestureDescription.TouchPoint();
+ }
+ }
+ return mLastTouchPoints;
+ }
+
+ private void appendMoveEventIfNeeded(List<MotionEvent> motionEvents,
+ TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
+ /* Look for pointers that have moved */
+ boolean moveFound = false;
+ TouchPoint[] lastTouchPoints = getLastTouchPoints();
+ for (int i = 0; i < currentTouchPointsSize; i++) {
+ int lastPointsIndex = findPointByStrokeId(lastTouchPoints, mNumLastTouchPoints,
+ currentTouchPoints[i].mStrokeId);
+ if (lastPointsIndex >= 0) {
+ moveFound |= (lastTouchPoints[lastPointsIndex].mX != currentTouchPoints[i].mX)
+ || (lastTouchPoints[lastPointsIndex].mY != currentTouchPoints[i].mY);
+ lastTouchPoints[lastPointsIndex].copyFrom(currentTouchPoints[i]);
+ }
+ }
+
+ if (moveFound) {
+ motionEvents.add(obtainMotionEvent(mDownTime, currentTime, MotionEvent.ACTION_MOVE,
+ lastTouchPoints, mNumLastTouchPoints));
+ }
+ }
+
+ private void appendUpEvents(List<MotionEvent> motionEvents,
+ TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
+ /* Look for a pointer at the end of its path */
+ TouchPoint[] lastTouchPoints = getLastTouchPoints();
+ for (int i = 0; i < currentTouchPointsSize; i++) {
+ if (currentTouchPoints[i].mIsEndOfPath) {
+ int indexOfUpEvent = findPointByStrokeId(lastTouchPoints, mNumLastTouchPoints,
+ currentTouchPoints[i].mStrokeId);
+ if (indexOfUpEvent < 0) {
+ continue; // Should not happen
+ }
+ int action = (mNumLastTouchPoints == 1) ? MotionEvent.ACTION_UP
+ : MotionEvent.ACTION_POINTER_UP;
+ action |= indexOfUpEvent << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ motionEvents.add(obtainMotionEvent(mDownTime, currentTime, action,
+ lastTouchPoints, mNumLastTouchPoints));
+ /* Remove this point from lastTouchPoints */
+ for (int j = indexOfUpEvent; j < mNumLastTouchPoints - 1; j++) {
+ lastTouchPoints[j].copyFrom(mLastTouchPoints[j + 1]);
+ }
+ mNumLastTouchPoints--;
+ if (mNumLastTouchPoints == 0) {
+ mStrokeIdToPointerId.clear();
+ }
+ }
+ }
+ }
+
+ private void appendDownEvents(List<MotionEvent> motionEvents,
+ TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
+ /* Look for a pointer that is just starting */
+ TouchPoint[] lastTouchPoints = getLastTouchPoints();
+ for (int i = 0; i < currentTouchPointsSize; i++) {
+ if (currentTouchPoints[i].mIsStartOfPath) {
+ /* Add the point to last coords and use the new array to generate the event */
+ lastTouchPoints[mNumLastTouchPoints++].copyFrom(currentTouchPoints[i]);
+ int action = (mNumLastTouchPoints == 1) ? MotionEvent.ACTION_DOWN
+ : MotionEvent.ACTION_POINTER_DOWN;
+ if (action == MotionEvent.ACTION_DOWN) {
+ mDownTime = currentTime;
+ }
+ action |= i << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ motionEvents.add(obtainMotionEvent(mDownTime, currentTime, action,
+ lastTouchPoints, mNumLastTouchPoints));
+ }
+ }
+ }
+
+ private MotionEvent obtainMotionEvent(long downTime, long eventTime, int action,
+ TouchPoint[] touchPoints, int touchPointsSize) {
+ if ((sPointerCoords == null) || (sPointerCoords.length < touchPointsSize)) {
+ sPointerCoords = new MotionEvent.PointerCoords[touchPointsSize];
+ for (int i = 0; i < touchPointsSize; i++) {
+ sPointerCoords[i] = new MotionEvent.PointerCoords();
+ }
+ }
+ if ((sPointerProps == null) || (sPointerProps.length < touchPointsSize)) {
+ sPointerProps = new MotionEvent.PointerProperties[touchPointsSize];
+ for (int i = 0; i < touchPointsSize; i++) {
+ sPointerProps[i] = new MotionEvent.PointerProperties();
+ }
+ }
+ for (int i = 0; i < touchPointsSize; i++) {
+ int pointerId = mStrokeIdToPointerId.get(touchPoints[i].mStrokeId, -1);
+ if (pointerId == -1) {
+ pointerId = getUnusedPointerId();
+ mStrokeIdToPointerId.put(touchPoints[i].mStrokeId, pointerId);
+ }
+ sPointerProps[i].id = pointerId;
+ sPointerProps[i].toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
+ sPointerCoords[i].clear();
+ sPointerCoords[i].pressure = 1.0f;
+ sPointerCoords[i].size = 1.0f;
+ sPointerCoords[i].x = touchPoints[i].mX;
+ sPointerCoords[i].y = touchPoints[i].mY;
+ }
+ return MotionEvent.obtain(downTime, eventTime, action, touchPointsSize,
+ sPointerProps, sPointerCoords, EVENT_META_STATE, EVENT_BUTTON_STATE,
+ EVENT_X_PRECISION, EVENT_Y_PRECISION, EVENT_DEVICE_ID, EVENT_EDGE_FLAGS,
+ EVENT_SOURCE, EVENT_FLAGS);
+ }
+
+ private static int findPointByStrokeId(TouchPoint[] touchPoints, int touchPointsSize,
+ int strokeId) {
+ for (int i = 0; i < touchPointsSize; i++) {
+ if (touchPoints[i].mStrokeId == strokeId) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ private int getUnusedPointerId() {
+ int MAX_POINTER_ID = 10;
+ int pointerId = 0;
+ while (mStrokeIdToPointerId.indexOfValue(pointerId) >= 0) {
+ pointerId++;
+ if (pointerId >= MAX_POINTER_ID) {
+ return MAX_POINTER_ID;
+ }
+ }
+ return pointerId;
+ }
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 8151c8a..31ecb75 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2399,16 +2399,15 @@
} catch (InterruptedException e) {
// just bail
Slog.w(TAG, "Interrupted: " + e);
- mActivityManager.clearPendingBackup();
- return null;
+ mConnecting = false;
+ mConnectedAgent = null;
}
}
// if we timed out with no connect, abort and move on
if (mConnecting == true) {
Slog.w(TAG, "Timeout waiting for agent " + app);
- mActivityManager.clearPendingBackup();
- return null;
+ mConnectedAgent = null;
}
if (DEBUG) Slog.i(TAG, "got agent " + mConnectedAgent);
agent = mConnectedAgent;
@@ -2417,6 +2416,13 @@
// can't happen - ActivityManager is local
}
}
+ if (agent == null) {
+ try {
+ mActivityManager.clearPendingBackup();
+ } catch (RemoteException e) {
+ // can't happen - ActivityManager is local
+ }
+ }
return agent;
}
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 88a8385..efadbef 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -12,6 +12,7 @@
java/com/android/server/am/EventLogTags.logtags \
../../../../system/netd/server/binder/android/net/INetd.aidl \
../../../../system/netd/server/binder/android/net/metrics/INetdEventListener.aidl \
+ ../../../native/cmds/installd/binder/android/os/IInstalld.aidl \
LOCAL_AIDL_INCLUDES += \
system/netd/server/binder
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index f7068cf..b0c5603 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -42,6 +42,7 @@
import android.database.ContentObserver;
import android.os.Binder;
import android.os.Build;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -52,6 +53,8 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.UserManagerInternal;
+import android.os.UserManagerInternal.UserRestrictionsListener;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
@@ -177,6 +180,24 @@
}
};
+ private final UserRestrictionsListener mUserRestrictionsListener =
+ new UserRestrictionsListener() {
+ @Override
+ public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
+ Bundle prevRestrictions) {
+ final boolean bluetoothDisallowed =
+ newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH);
+ if ((mEnable || mEnableExternal) && bluetoothDisallowed) {
+ try {
+ disable(null, true);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Exception when disabling Bluetooth from UserRestrictionsListener",
+ e);
+ }
+ }
+ }
+ };
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -634,6 +655,13 @@
public boolean enableNoAutoConnect()
{
+ if (isBluetoothDisallowed()) {
+ if (DBG) {
+ Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
+ }
+ return false;
+ }
+
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
@@ -659,6 +687,13 @@
final int callingUid = Binder.getCallingUid();
final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
+ if (isBluetoothDisallowed()) {
+ if (DBG) {
+ Slog.d(TAG,"enable(): not enabling - bluetooth disallowed");
+ }
+ return false;
+ }
+
if (!callerSystem) {
if (!checkIfCallerIsForegroundUser()) {
Slog.w(TAG, "enable(): not allowed for non-active and non system user");
@@ -872,6 +907,12 @@
*/
public void handleOnBootPhase() {
if (DBG) Slog.d(TAG, "Bluetooth boot completed");
+ UserManagerInternal userManagerInternal =
+ LocalServices.getService(UserManagerInternal.class);
+ userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
+ if (isBluetoothDisallowed()) {
+ return;
+ }
if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth.");
sendEnableMsg(mQuietEnableExternal);
@@ -1916,6 +1957,16 @@
}
}
+ private boolean isBluetoothDisallowed() {
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ return mContext.getSystemService(UserManager.class)
+ .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5eceb9f1..c9fd568 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4606,28 +4606,9 @@
} catch (Exception e) {
loge("Exception in setDnsConfigurationForNetwork: " + e);
}
- final NetworkAgentInfo defaultNai = getDefaultNetwork();
- if (defaultNai != null && defaultNai.network.netId == netId) {
- setDefaultDnsSystemProperties(dnses);
- }
flushVmDnsCache();
}
- private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
- int last = 0;
- for (InetAddress dns : dnses) {
- ++last;
- String key = "net.dns" + last;
- String value = dns.getHostAddress();
- SystemProperties.set(key, value);
- }
- for (int i = last + 1; i <= mNumDnsEntries; ++i) {
- String key = "net.dns" + i;
- SystemProperties.set(key, "");
- }
- mNumDnsEntries = last;
- }
-
private String getNetworkPermission(NetworkCapabilities nc) {
// TODO: make these permission strings AIDL constants instead.
if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
@@ -4844,7 +4825,6 @@
notifyLockdownVpn(newNetwork);
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
- setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 8092b4a..9f63e30 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -211,7 +211,10 @@
private long mMaintenanceStartTime;
private int mActiveIdleOpCount;
- private PowerManager.WakeLock mActiveIdleWakeLock;
+ private PowerManager.WakeLock mActiveIdleWakeLock; // held when there are operations in progress
+ private PowerManager.WakeLock mGoingIdleWakeLock; // held when we are going idle so hardware
+ // (especially NetworkPolicyManager) can shut
+ // down.
private boolean mJobsActive;
private boolean mAlarmsActive;
private boolean mReportedMaintenanceActivity;
@@ -998,14 +1001,14 @@
}
}
- static final int MSG_WRITE_CONFIG = 1;
- static final int MSG_REPORT_IDLE_ON = 2;
- static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
- static final int MSG_REPORT_IDLE_OFF = 4;
- static final int MSG_REPORT_ACTIVE = 5;
- static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
- static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7;
- static final int MSG_FINISH_IDLE_OP = 8;
+ private static final int MSG_WRITE_CONFIG = 1;
+ private static final int MSG_REPORT_IDLE_ON = 2;
+ private static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
+ private static final int MSG_REPORT_IDLE_OFF = 4;
+ private static final int MSG_REPORT_ACTIVE = 5;
+ private static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
+ private static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7;
+ private static final int MSG_FINISH_IDLE_OP = 8;
final class MyHandler extends Handler {
MyHandler(Looper looper) {
@@ -1016,10 +1019,12 @@
if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
switch (msg.what) {
case MSG_WRITE_CONFIG: {
+ // Does not hold a wakelock. Just let this happen whenever.
handleWriteConfigFile();
} break;
case MSG_REPORT_IDLE_ON:
case MSG_REPORT_IDLE_ON_LIGHT: {
+ // mGoingIdleWakeLock is held at this point
EventLogTags.writeDeviceIdleOnStart();
final boolean deepChanged;
final boolean lightChanged;
@@ -1044,8 +1049,10 @@
getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
}
EventLogTags.writeDeviceIdleOnComplete();
+ mGoingIdleWakeLock.release();
} break;
case MSG_REPORT_IDLE_OFF: {
+ // mActiveIdleWakeLock is held at this point
EventLogTags.writeDeviceIdleOffStart("unknown");
final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
@@ -1071,6 +1078,7 @@
EventLogTags.writeDeviceIdleOffComplete();
} break;
case MSG_REPORT_ACTIVE: {
+ // The device is awake at this point, so no wakelock necessary.
String activeReason = (String)msg.obj;
int activeUid = msg.arg1;
EventLogTags.writeDeviceIdleOffStart(
@@ -1092,10 +1100,12 @@
EventLogTags.writeDeviceIdleOffComplete();
} break;
case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
+ // TODO: What is keeping the device awake at this point? Does it need to be?
int uid = msg.arg1;
checkTempAppWhitelistTimeout(uid);
} break;
case MSG_REPORT_MAINTENANCE_ACTIVITY: {
+ // TODO: What is keeping the device awake at this point? Does it need to be?
boolean active = (msg.arg1 == 1);
final int size = mMaintenanceActivityListeners.beginBroadcast();
try {
@@ -1111,6 +1121,7 @@
}
} break;
case MSG_FINISH_IDLE_OP: {
+ // mActiveIdleWakeLock is held at this point
decActiveIdleOps();
} break;
}
@@ -1356,6 +1367,9 @@
mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"deviceidle_maint");
mActiveIdleWakeLock.setReferenceCounted(false);
+ mGoingIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ "deviceidle_going_idle");
+ mGoingIdleWakeLock.setReferenceCounted(true);
mConnectivityService = (ConnectivityService)ServiceManager.getService(
Context.CONNECTIVITY_SERVICE);
mLocalAlarmManager = getLocalService(AlarmManagerService.LocalService.class);
@@ -1898,6 +1912,7 @@
mLightState = LIGHT_STATE_IDLE;
EventLogTags.writeDeviceIdleLight(mLightState, reason);
addEvent(EVENT_LIGHT_IDLE);
+ mGoingIdleWakeLock.acquire();
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
break;
case LIGHT_STATE_IDLE:
@@ -2023,6 +2038,7 @@
}
EventLogTags.writeDeviceIdle(mState, reason);
addEvent(EVENT_DEEP_IDLE);
+ mGoingIdleWakeLock.acquire();
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
break;
case STATE_IDLE:
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 3dfbdc3..372e9a6 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1105,7 +1105,6 @@
mWindowManagerInternal.setOnHardKeyboardStatusChangeListener(
mHardKeyboardListener);
}
- buildInputMethodListLocked(!mImeSelectedOnBoot /* resetDefaultEnabledIme */);
if (!mImeSelectedOnBoot) {
Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here.");
resetStateIfCurrentLocaleChangedLocked();
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 72fa1e3..27e4aa4 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -30,13 +30,18 @@
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppManager;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.RecommendationRequest;
+import android.net.RecommendationResult;
import android.net.ScoredNetwork;
+import android.net.wifi.WifiConfiguration;
import android.os.Binder;
import android.os.IBinder;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.R;
@@ -49,11 +54,11 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Set;
+import java.util.function.Consumer;
/**
* Backing service for {@link android.net.NetworkScoreManager}.
@@ -65,7 +70,8 @@
private final Context mContext;
private final NetworkScorerAppManager mNetworkScorerAppManager;
- private final Map<Integer, INetworkScoreCache> mScoreCaches;
+ @GuardedBy("mScoreCaches")
+ private final Map<Integer, RemoteCallbackList<INetworkScoreCache>> mScoreCaches;
/** Lock used to update mPackageMonitor when scorer package changes occur. */
private final Object mPackageMonitorLock = new Object[0];
@@ -163,7 +169,7 @@
NetworkScoreService(Context context, NetworkScorerAppManager networkScoreAppManager) {
mContext = context;
mNetworkScorerAppManager = networkScoreAppManager;
- mScoreCaches = new HashMap<>();
+ mScoreCaches = new ArrayMap<>();
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
// TODO: Need to update when we support per-user scorers. http://b/23422763
mContext.registerReceiverAsUser(
@@ -273,7 +279,7 @@
}
// Separate networks by type.
- Map<Integer, List<ScoredNetwork>> networksByType = new HashMap<>();
+ Map<Integer, List<ScoredNetwork>> networksByType = new ArrayMap<>();
for (ScoredNetwork network : networks) {
List<ScoredNetwork> networkList = networksByType.get(network.networkKey.type);
if (networkList == null) {
@@ -284,19 +290,32 @@
}
// Pass the scores of each type down to the appropriate network scorer.
- for (Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) {
- INetworkScoreCache scoreCache = mScoreCaches.get(entry.getKey());
- if (scoreCache != null) {
- try {
- scoreCache.updateScores(entry.getValue());
- } catch (RemoteException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e);
+ for (final Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) {
+ final RemoteCallbackList<INetworkScoreCache> callbackList;
+ final boolean isEmpty;
+ synchronized (mScoreCaches) {
+ callbackList = mScoreCaches.get(entry.getKey());
+ isEmpty = callbackList == null || callbackList.getRegisteredCallbackCount() == 0;
+ }
+ if (isEmpty) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding");
+ }
+ continue;
+ }
+
+ sendCallback(new Consumer<INetworkScoreCache>() {
+ @Override
+ public void accept(INetworkScoreCache networkScoreCache) {
+ try {
+ networkScoreCache.updateScores(entry.getValue());
+ } catch (RemoteException e) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e);
+ }
}
}
- } else if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding");
- }
+ }, Collections.singleton(callbackList));
}
return true;
@@ -391,33 +410,69 @@
/** Clear scores. Callers are responsible for checking permissions as appropriate. */
private void clearInternal() {
- Set<INetworkScoreCache> cachesToClear = getScoreCaches();
+ sendCallback(new Consumer<INetworkScoreCache>() {
+ @Override
+ public void accept(INetworkScoreCache networkScoreCache) {
+ try {
+ networkScoreCache.clearScores();
+ } catch (RemoteException e) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Unable to clear scores", e);
+ }
+ }
+ }
+ }, getScoreCacheLists());
+ }
- for (INetworkScoreCache scoreCache : cachesToClear) {
- try {
- scoreCache.clearScores();
- } catch (RemoteException e) {
+ @Override
+ public void registerNetworkScoreCache(int networkType,
+ INetworkScoreCache scoreCache,
+ int filterType) {
+ mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ synchronized (mScoreCaches) {
+ RemoteCallbackList<INetworkScoreCache> callbackList = mScoreCaches.get(networkType);
+ if (callbackList == null) {
+ callbackList = new RemoteCallbackList<>();
+ mScoreCaches.put(networkType, callbackList);
+ }
+ if (!callbackList.register(scoreCache, filterType)) {
+ if (callbackList.getRegisteredCallbackCount() == 0) {
+ mScoreCaches.remove(networkType);
+ }
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Unable to clear scores", e);
+ Log.v(TAG, "Unable to register NetworkScoreCache for type " + networkType);
}
}
}
}
@Override
- public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+ public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
synchronized (mScoreCaches) {
- if (mScoreCaches.containsKey(networkType)) {
- throw new IllegalArgumentException(
- "Score cache already registered for type " + networkType);
+ RemoteCallbackList<INetworkScoreCache> callbackList = mScoreCaches.get(networkType);
+ if (callbackList == null || !callbackList.unregister(scoreCache)) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Unable to unregister NetworkScoreCache for type " + networkType);
+ }
+ } else if (callbackList.getRegisteredCallbackCount() == 0) {
+ mScoreCaches.remove(networkType);
}
- mScoreCaches.put(networkType, scoreCache);
}
}
@Override
- protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ public RecommendationResult requestRecommendation(RecommendationRequest request) {
+ // TODO(jjoslin): 11/25/16 - Update with real impl.
+ WifiConfiguration selectedConfig = null;
+ if (request != null) {
+ selectedConfig = request.getCurrentSelectedConfig();
+ }
+ return new RecommendationResult(selectedConfig);
+ }
+
+ @Override
+ protected void dump(final FileDescriptor fd, final PrintWriter writer, final String[] args) {
mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer();
if (currentScorer == null) {
@@ -426,13 +481,17 @@
}
writer.println("Current scorer: " + currentScorer.mPackageName);
- for (INetworkScoreCache scoreCache : getScoreCaches()) {
- try {
- TransferPipe.dumpAsync(scoreCache.asBinder(), fd, args);
- } catch (IOException | RemoteException e) {
- writer.println("Failed to dump score cache: " + e);
+ sendCallback(new Consumer<INetworkScoreCache>() {
+ @Override
+ public void accept(INetworkScoreCache networkScoreCache) {
+ try {
+ TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args);
+ } catch (IOException | RemoteException e) {
+ writer.println("Failed to dump score cache: " + e);
+ }
}
- }
+ }, getScoreCacheLists());
+
if (mServiceConnection != null) {
mServiceConnection.dump(fd, writer, args);
} else {
@@ -442,14 +501,30 @@
}
/**
- * Returns a set of all score caches that are currently active.
+ * Returns a {@link Collection} of all {@link RemoteCallbackList}s that are currently active.
*
* <p>May be used to perform an action on all score caches without potentially strange behavior
* if a new scorer is registered during that action's execution.
*/
- private Set<INetworkScoreCache> getScoreCaches() {
+ private Collection<RemoteCallbackList<INetworkScoreCache>> getScoreCacheLists() {
synchronized (mScoreCaches) {
- return new HashSet<>(mScoreCaches.values());
+ return new ArrayList<>(mScoreCaches.values());
+ }
+ }
+
+ private void sendCallback(Consumer<INetworkScoreCache> consumer,
+ Collection<RemoteCallbackList<INetworkScoreCache>> remoteCallbackLists) {
+ for (RemoteCallbackList<INetworkScoreCache> callbackList : remoteCallbackLists) {
+ synchronized (callbackList) { // Ensure only one active broadcast per RemoteCallbackList
+ final int count = callbackList.beginBroadcast();
+ try {
+ for (int i = 0; i < count; i++) {
+ consumer.accept(callbackList.getBroadcastItem(i));
+ }
+ } finally {
+ callbackList.finishBroadcast();
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 96bab0e..8a0d4df 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -47,6 +47,8 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Service for reading and writing blocks to a persistent partition.
@@ -80,6 +82,7 @@
private final Context mContext;
private final String mDataBlockFile;
private final Object mLock = new Object();
+ private final CountDownLatch mInitDoneSignal = new CountDownLatch(1);
private int mAllowedUid = -1;
private long mBlockDeviceSize;
@@ -112,9 +115,29 @@
@Override
public void onStart() {
- enforceChecksumValidity();
- formatIfOemUnlockEnabled();
- publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService);
+ // Do init on a separate thread, will join in PHASE_ACTIVITY_MANAGER_READY
+ FgThread.getHandler().post(() -> {
+ enforceChecksumValidity();
+ formatIfOemUnlockEnabled();
+ publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService);
+ mInitDoneSignal.countDown();
+ });
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ // Wait for initialization in onStart to finish
+ if (phase == PHASE_SYSTEM_SERVICES_READY) {
+ try {
+ if (!mInitDoneSignal.await(10, TimeUnit.SECONDS)) {
+ throw new IllegalStateException("Service " + TAG + " init timeout");
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("Service " + TAG + " init interrupted", e);
+ }
+ }
+ super.onBootPhase(phase);
}
private void formatIfOemUnlockEnabled() {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 136e02c..7661127 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -75,6 +75,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
+import android.webkit.WebViewZygote;
public final class ActiveServices {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM;
@@ -1704,6 +1705,7 @@
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
+ String hostingType = "service";
ProcessRecord app;
if (!isolated) {
@@ -1732,13 +1734,17 @@
// in the service any current isolated process it is running in or
// waiting to have come up.
app = r.isolatedProc;
+ if (WebViewZygote.isMultiprocessEnabled()
+ && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
+ hostingType = "webview_service";
+ }
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
- "service", r.name, false, isolated, false)) == null) {
+ hostingType, r.name, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 229a68b..3990a8b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -43,7 +43,6 @@
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.TransferPipe;
import com.android.internal.os.Zygote;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
@@ -62,6 +61,7 @@
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.firewall.IntentFirewall;
import com.android.server.pm.Installer;
+import com.android.server.pm.Installer.InstallerException;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.vr.VrManagerInternal;
import com.android.server.wm.WindowManagerService;
@@ -269,7 +269,6 @@
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
@@ -362,7 +361,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBLE_BEHIND;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.FORCE_NEW_TASK_FLAGS;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
@@ -1386,6 +1384,8 @@
final long[] mTmpLong = new long[2];
+ private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet();
+
static final class ProcessChangeItem {
static final int CHANGE_ACTIVITIES = 1<<0;
static final int CHANGE_PROCESS_STATE = 1<<1;
@@ -3695,10 +3695,18 @@
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
- Process.ProcessStartResult startResult = Process.start(entryPoint,
- app.processName, uid, uid, gids, debugFlags, mountExternal,
- app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
- app.info.dataDir, entryPointArgs);
+ Process.ProcessStartResult startResult;
+ if (hostingType.equals("webview_service")) {
+ startResult = Process.startWebView(entryPoint,
+ app.processName, uid, uid, gids, debugFlags, mountExternal,
+ app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+ app.info.dataDir, entryPointArgs);
+ } else {
+ startResult = Process.start(entryPoint,
+ app.processName, uid, uid, gids, debugFlags, mountExternal,
+ app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+ app.info.dataDir, entryPointArgs);
+ }
checkTime(startTime, "startProcess: returned from zygote!");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -6195,8 +6203,19 @@
}
private final ProcessRecord removeProcessNameLocked(final String name, final int uid) {
- ProcessRecord old = mProcessNames.remove(name, uid);
- if (old != null) {
+ return removeProcessNameLocked(name, uid, null);
+ }
+
+ private final ProcessRecord removeProcessNameLocked(final String name, final int uid,
+ final ProcessRecord expecting) {
+ ProcessRecord old = mProcessNames.get(name, uid);
+ // Only actually remove when the currently recorded value matches the
+ // record that we expected; if it doesn't match then we raced with a
+ // newly created process and we don't want to destroy the new one.
+ if ((expecting == null) || (old == expecting)) {
+ mProcessNames.remove(name, uid);
+ }
+ if (old != null && old.uidRecord != null) {
old.uidRecord.numProcs--;
if (old.uidRecord.numProcs == 0) {
// No more processes using this uid, tell clients it is gone.
@@ -7486,45 +7505,51 @@
@Override
public void enterPictureInPictureMode(IBinder token) {
- enterPictureInPictureMode(token, DEFAULT_DISPLAY, null /* aspectRatio */);
+ enterPictureInPictureMode(token, DEFAULT_DISPLAY, -1f /* aspectRatio */,
+ false /* checkAspectRatio */);
}
@Override
public void enterPictureInPictureModeWithAspectRatio(IBinder token, float aspectRatio) {
- enterPictureInPictureMode(token, DEFAULT_DISPLAY, aspectRatio);
+ enterPictureInPictureMode(token, DEFAULT_DISPLAY, aspectRatio, true /* checkAspectRatio */);
}
- public void enterPictureInPictureMode(IBinder token, int displayId, Float aspectRatio) {
+ private void enterPictureInPictureMode(IBinder token, int displayId, float aspectRatio,
+ boolean checkAspectRatio) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized(this) {
- if (!mSupportsPictureInPicture) {
- throw new IllegalStateException("enterPictureInPictureMode: "
- + "Device doesn't support picture-in-picture mode.");
- }
+ final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
+ "enterPictureInPictureMode", token, aspectRatio, checkAspectRatio,
+ true /* checkActivityVisibility */);
- final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- if (r == null) {
- throw new IllegalStateException("enterPictureInPictureMode: "
- + "Can't find activity for token=" + token);
- }
+ enterPictureInPictureModeLocked(r, displayId, aspectRatio,
+ true /* moveHomeStackToFront */, "enterPictureInPictureMode");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
- if (!r.supportsPictureInPicture()) {
- throw new IllegalArgumentException("enterPictureInPictureMode: "
- + "Picture-In-Picture not supported for r=" + r);
- }
+ void enterPictureInPictureModeLocked(ActivityRecord r, int displayId, float aspectRatio,
+ boolean moveHomeStackToFront, String reason) {
+ final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio)
+ ? mWindowManager.getPictureInPictureBounds(displayId, aspectRatio)
+ : mWindowManager.getPictureInPictureDefaultBounds(displayId);
+ mStackSupervisor.moveActivityToPinnedStackLocked(r, reason, bounds, moveHomeStackToFront);
+ }
- if (aspectRatio != null && !isValidPictureInPictureAspectRatio(aspectRatio)) {
- throw new IllegalArgumentException(String.format("enterPictureInPictureMode: "
- + "Aspect ratio is too extreme (must be between %f and %f).",
- mMinPipAspectRatio, mMaxPipAspectRatio));
- }
+ @Override
+ public void enterPictureInPictureModeOnMoveToBackground(IBinder token,
+ boolean enterPictureInPictureOnMoveToBg) {
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized(this) {
+ final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
+ "requestAutoEnterPictureInPicture", token, -1f /* aspectRatio */,
+ false /* checkAspectRatio */, false /* checkActivityVisibility */);
- final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio)
- ? mWindowManager.getPictureInPictureBounds(displayId, aspectRatio)
- : mWindowManager.getPictureInPictureDefaultBounds(displayId);
- mStackSupervisor.moveActivityToPinnedStackLocked(r, "enterPictureInPictureMode",
- bounds);
+ r.supportsPipOnMoveToBackground = enterPictureInPictureOnMoveToBg;
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -7536,33 +7561,68 @@
final long origId = Binder.clearCallingIdentity();
try {
synchronized(this) {
- final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- if (r == null || r.getStack().mStackId != PINNED_STACK_ID) {
- throw new IllegalStateException("setPictureInPictureAspectRatio: "
- + "Requesting activity must be in picture-in-picture mode.");
- }
+ final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
+ "setPictureInPictureAspectRatio", token, aspectRatio,
+ true /* checkAspectRatio */, false /* checkActivityVisibility */);
- if (!isValidPictureInPictureAspectRatio(aspectRatio)) {
- throw new IllegalArgumentException(String.format(
- "setPictureInPictureAspectRatio: Aspect ratio is too extreme (must be "
- + "between %f and %f).", mMinPipAspectRatio,
- mMaxPipAspectRatio));
+ if (r.getStack().getStackId() == PINNED_STACK_ID) {
+ // If the activity is already in picture-in-picture, update the pinned stack now
+ mWindowManager.setPictureInPictureAspectRatio(aspectRatio);
}
-
- mWindowManager.setPictureInPictureAspectRatio(aspectRatio);
+ r.pictureInPictureAspectRatio = aspectRatio;
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
- private boolean isValidPictureInPictureAspectRatio(Float aspectRatio) {
- if (aspectRatio == null) {
- return false;
- }
+ private boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
return mMinPipAspectRatio <= aspectRatio && aspectRatio <= mMaxPipAspectRatio;
}
+ /**
+ * Checks the state of the system and the activity associated with the given {@param token} to
+ * verify that picture-in-picture is supported for that activity.
+ *
+ * @param checkAspectRatio whether or not to check {@param aspectRatio} is within a valid range
+ * @param checkActivityVisibility whether or not to enforce that the activity is currently
+ * visible
+ *
+ * @return the activity record for the given {@param token} if all the checks pass.
+ */
+ private ActivityRecord ensureValidPictureInPictureActivityLocked(String caller, IBinder token,
+ float aspectRatio, boolean checkAspectRatio, boolean checkActivityVisibility) {
+ if (!mSupportsPictureInPicture) {
+ throw new IllegalStateException(caller
+ + ": Device doesn't support picture-in-picture mode.");
+ }
+
+ final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r == null) {
+ throw new IllegalStateException(caller
+ + ": Can't find activity for token=" + token);
+ }
+
+ if (!r.canEnterPictureInPicture(checkActivityVisibility)) {
+ throw new IllegalArgumentException(caller
+ + "Current activity does not support picture-in-picture or is not "
+ + "visible r=" + r);
+ }
+
+ if (r.getStack().isHomeStack()) {
+ throw new IllegalStateException(caller
+ + ": Activities on the home stack not supported");
+ }
+
+ if (checkAspectRatio && !isValidPictureInPictureAspectRatio(aspectRatio)) {
+ throw new IllegalArgumentException(String.format(caller
+ + ": Aspect ratio is too extreme (must be between %f and %f).",
+ mMinPipAspectRatio, mMaxPipAspectRatio));
+ }
+
+ return r;
+ }
+
// =========================================================
// PROCESS INFO
// =========================================================
@@ -9183,10 +9243,10 @@
}
}
final ActivityStack stack = tr.getStack();
- if ((flags & ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS) != 0) {
- if (stack != null && stack.isHomeStack()) {
+ if ((flags & ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS) != 0) {
+ if (stack != null && stack.isHomeOrRecentsStack()) {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, home stack task: " + tr);
+ "Skipping, home or recents stack task: " + tr);
continue;
}
}
@@ -9608,8 +9668,8 @@
@Override
public void removeStack(int stackId) {
enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS, "removeStack()");
- if (stackId == HOME_STACK_ID) {
- throw new IllegalArgumentException("Removing home stack is not allowed.");
+ if (StackId.isHomeOrRecentsStack(stackId)) {
+ throw new IllegalArgumentException("Removing home or recents stack is not allowed.");
}
synchronized (this) {
@@ -9837,9 +9897,9 @@
@Override
public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
- if (stackId == HOME_STACK_ID) {
+ if (StackId.isHomeOrRecentsStack(stackId)) {
throw new IllegalArgumentException(
- "moveTaskToStack: Attempt to move task " + taskId + " to home stack");
+ "moveTaskToStack: Attempt to move task " + taskId + " to stack " + stackId);
}
synchronized (this) {
long ident = Binder.clearCallingIdentity();
@@ -9854,8 +9914,7 @@
!FORCE_FOCUS, "moveTaskToStack", ANIMATE);
if (result && stackId == DOCKED_STACK_ID) {
// If task moved to docked stack - show recents if needed.
- mStackSupervisor.moveHomeStackTaskToTop(RECENTS_ACTIVITY_TYPE,
- "moveTaskToDockedStack");
+ mWindowManager.showRecentApps(false /* fromHome */);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -10039,10 +10098,10 @@
@Override
public void positionTaskInStack(int taskId, int stackId, int position) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
- if (stackId == HOME_STACK_ID) {
+ if (StackId.isHomeOrRecentsStack(stackId)) {
throw new IllegalArgumentException(
"positionTaskInStack: Attempt to change the position of task "
- + taskId + " in/to home stack");
+ + taskId + " in/to home/recents stack");
}
synchronized (this) {
long ident = Binder.clearCallingIdentity();
@@ -10084,22 +10143,6 @@
}
@Override
- public boolean isInHomeStack(int taskId) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
- long ident = Binder.clearCallingIdentity();
- try {
- synchronized (this) {
- final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(
- taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
- final ActivityStack stack = tr != null ? tr.getStack() : null;
- return stack != null && stack.isHomeStack();
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- @Override
public int getTaskForActivity(IBinder token, boolean onlyRoot) {
synchronized(this) {
return ActivityRecord.getTaskForActivityLocked(token, onlyRoot);
@@ -17009,7 +17052,7 @@
if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing non-persistent process during cleanup: " + app);
if (!replacingPid) {
- removeProcessNameLocked(app.processName, app.uid);
+ removeProcessNameLocked(app.processName, app.uid, app);
}
if (mHeavyWeightProcess == app) {
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
@@ -18845,8 +18888,8 @@
@Override
public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTasksToFullscreenStack()");
- if (fromStackId == HOME_STACK_ID) {
- throw new IllegalArgumentException("You can't move tasks from the home stack.");
+ if (StackId.isHomeOrRecentsStack(fromStackId)) {
+ throw new IllegalArgumentException("You can't move tasks from the home/recents stack.");
}
synchronized (this) {
final long origId = Binder.clearCallingIdentity();
@@ -19530,7 +19573,7 @@
int schedGroup;
int procState;
boolean foregroundActivities = false;
- final ArraySet<BroadcastQueue> queues = new ArraySet<BroadcastQueue>();
+ mTmpBroadcastQueue.clear();
if (app == TOP_APP) {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
@@ -19544,13 +19587,13 @@
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
- } else if (isReceivingBroadcastLocked(app, queues)) {
+ } else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
// An app that is currently receiving a broadcast also
// counts as being in the foreground for OOM killer purposes.
// It's placed in a sched group based on the nature of the
// broadcast as reflected by which queue it's active in.
adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = (queues.contains(mFgBroadcastQueue))
+ schedGroup = (mTmpBroadcastQueue.contains(mFgBroadcastQueue))
? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "broadcast";
procState = ActivityManager.PROCESS_STATE_RECEIVER;
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index facfeb6..32dec96 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -5,6 +5,8 @@
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
@@ -78,7 +80,7 @@
if (stack.mStackId == PINNED_STACK_ID) {
stack = mSupervisor.findStackBehind(stack);
}
- if (stack.mStackId == HOME_STACK_ID
+ if (StackId.isHomeOrRecentsStack(stack.mStackId)
|| stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
mWindowState = WINDOW_STATE_STANDARD;
} else if (stack.mStackId == DOCKED_STACK_ID) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 214a357..13c422b 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -19,6 +19,7 @@
import static android.app.ActivityManager.StackId;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
@@ -82,7 +83,6 @@
import android.util.TimeUtils;
import android.view.AppTransitionAnimationSpec;
import android.view.IApplicationToken;
-import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import com.android.internal.app.ResolverActivity;
@@ -216,6 +216,14 @@
boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
boolean immersive; // immersive mode (don't interrupt if possible)
boolean forceNewConfig; // force re-create with new config next time
+ boolean supportsPipOnMoveToBackground; // Supports automatically entering picture-in-picture
+ // when this activity is hidden. This flag is requested by the activity.
+ private boolean enterPipOnMoveToBackground; // Flag to enter picture in picture when this
+ // activity is made invisible. This flag is set specifically when another task is being
+ // launched or moved to the front which may cause this activity to try and enter PiP
+ // when it is next made invisible.
+ float pictureInPictureAspectRatio; // The aspect ratio to use when auto-entering
+ // picture-in-picture
int launchCount; // count of launches since last state
long lastLaunchTime; // time of last launch of this activity
ComponentName requestedVrComponent; // the requested component for handling VR mode.
@@ -432,6 +440,11 @@
if (info != null) {
pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
}
+ if (supportsPipOnMoveToBackground) {
+ pw.println(prefix + "supportsPipOnMoveToBackground=1 "
+ + "enterPipOnMoveToBackground="
+ + (enterPipOnMoveToBackground ? 1 : 0));
+ }
}
private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
@@ -840,6 +853,23 @@
}
/**
+ * If this activity has requested that it auto-enter picture-in-picture and we can actually do
+ * this, then mark it to enter picture in picture at that point.
+ */
+ void setEnterPipOnMoveToBackground(boolean enterPipOnInvisible) {
+ if (supportsPipOnMoveToBackground) {
+ enterPipOnMoveToBackground = enterPipOnInvisible;
+ }
+ }
+
+ /**
+ * @return whether to enter PiP when this activity is made invisible.
+ */
+ public boolean shouldEnterPictureInPictureOnInvisible() {
+ return enterPipOnMoveToBackground;
+ }
+
+ /**
* @return Stack value from current task, null if there is no task.
*/
ActivityStack getStack() {
@@ -920,10 +950,34 @@
&& info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
}
+ /**
+ * @return whether this activity's resize mode supports PIP.
+ */
boolean supportsPictureInPicture() {
return !isHomeActivity() && info.resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
}
+ /**
+ * @return whether this activity is currently allowed to enter PIP, if
+ * {@param checkActivityVisibility} is set, then the current activity visibility is taken into
+ * account.
+ */
+ boolean canEnterPictureInPicture(boolean checkActivityVisibility) {
+ if (!checkActivityVisibility) {
+ return supportsPictureInPicture();
+ }
+
+ if (supportsPictureInPicture() && visible) {
+ switch (state) {
+ case RESUMED:
+ case PAUSING:
+ case PAUSED:
+ return true;
+ }
+ }
+ return false;
+ }
+
boolean canGoInDockedStack() {
return !isHomeActivity() && isResizeableOrForced();
}
@@ -1197,10 +1251,11 @@
}
final ActivityStack stack = getStack();
- if (stack.isHomeStack()) {
+ if (stack.isHomeOrRecentsStack()) {
// This is an optimization -- since we never show Home or Recents within Recents itself,
// we can just go ahead and skip taking the screenshot if this is the home stack.
- if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tHome stack");
+ if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, stack.getStackId() == HOME_STACK_ID ?
+ "\tHome stack" : "\tRecents stack");
return null;
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 005b8aa..d160a46 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -690,6 +690,10 @@
return mStackId == HOME_STACK_ID;
}
+ final boolean isHomeOrRecentsStack() {
+ return StackId.isHomeOrRecentsStack(mStackId);
+ }
+
final boolean isDockedStack() {
return mStackId == DOCKED_STACK_ID;
}
@@ -718,7 +722,6 @@
mStacks.remove(this);
int addIndex = mStacks.size();
-
if (addIndex > 0) {
final ActivityStack topStack = mStacks.get(addIndex - 1);
if (StackId.isAlwaysOnTop(topStack.mStackId) && topStack != this) {
@@ -1450,10 +1453,10 @@
return false;
}
- if (!isHomeStack() && r.frontOfTask
- && task.isOverHomeStack() && stackBehindId != HOME_STACK_ID) {
+ if (!isHomeOrRecentsStack() && r.frontOfTask
+ && task.isOverHomeStack() && !StackId.isHomeOrRecentsStack(stackBehindId)) {
// Stack isn't translucent if it's top activity should have the home stack
- // behind it and the stack currently behind it isn't the home stack.
+ // behind it and the stack currently behind it isn't the home or recents stack.
return false;
}
}
@@ -1519,10 +1522,10 @@
}
if (mStackId == FULLSCREEN_WORKSPACE_STACK_ID
- && hasVisibleBehindActivity() && focusedStackId == HOME_STACK_ID
+ && hasVisibleBehindActivity() && StackId.isHomeOrRecentsStack(focusedStackId)
&& !focusedStack.topActivity().fullscreen) {
// The fullscreen stack should be visible if it has a visible behind activity behind
- // the home stack that is translucent.
+ // the home or recents stack that is translucent.
return STACK_VISIBLE_ACTIVITY_BEHIND;
}
@@ -1713,7 +1716,9 @@
+ stackInvisible + " behindFullscreenActivity="
+ behindFullscreenActivity + " mLaunchTaskBehind="
+ r.mLaunchTaskBehind);
- makeInvisible(r, visibleBehind);
+ if (!enterPictureInPictureOnActivityInvisible(r)) {
+ makeInvisible(r, visibleBehind);
+ }
}
}
if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
@@ -1825,11 +1830,10 @@
// If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
// right away.
return shouldBeVisible && mStackSupervisor.mKeyguardController
- .canShowActivityWhileKeyguardShowing(dismissKeyguard);
+ .canShowActivityWhileKeyguardShowing(r, dismissKeyguard);
} else if (keyguardLocked) {
-
- // Show when locked windows above keyguard.
- return shouldBeVisible && showWhenLocked;
+ return shouldBeVisible && mStackSupervisor.mKeyguardController.canShowWhileOccluded(
+ dismissKeyguard, showWhenLocked);
} else {
return shouldBeVisible;
}
@@ -1872,6 +1876,32 @@
return false;
}
+ /**
+ * Attempts to enter picture-in-picture if the activity that is being made invisible supports
+ * it. If not, then
+ *
+ * @return whether or not picture-in-picture mode was entered.
+ */
+ private boolean enterPictureInPictureOnActivityInvisible(ActivityRecord r) {
+ final boolean hasPinnedStack =
+ mStackSupervisor.getStack(PINNED_STACK_ID) != null;
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, " enterPictureInPictureOnInvisible="
+ + r.shouldEnterPictureInPictureOnInvisible()
+ + " hasPinnedStack=" + hasPinnedStack);
+ if (!hasPinnedStack && r.visible && r.shouldEnterPictureInPictureOnInvisible()) {
+ r.setEnterPipOnMoveToBackground(false);
+
+ // Enter picture in picture, but don't move the home stack to the front
+ // since it will affect the focused stack's visibility and occlude
+ // starting activities
+ mService.enterPictureInPictureModeLocked(r, r.getDisplayId(),
+ r.pictureInPictureAspectRatio, false /* moveHomeStackToFront */,
+ "ensureActivitiesVisibleLocked");
+ return true;
+ }
+ return false;
+ }
+
private void makeInvisible(ActivityRecord r, ActivityRecord visibleBehind) {
if (!r.visible) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + r);
@@ -1922,7 +1952,7 @@
+ " behindFullscreenActivity=" + behindFullscreenActivity);
// At this point, nothing else needs to be shown in this task.
behindFullscreenActivity = true;
- } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) {
+ } else if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack()) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Showing home: at " + r
+ " stackInvisible=" + stackInvisible
+ " behindFullscreenActivity=" + behindFullscreenActivity);
@@ -2096,9 +2126,7 @@
if (next == null) {
// There are no more activities!
final String reason = "noMoreActivities";
- final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack()
- ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
- if (!mFullscreen && adjustFocusToNextFocusableStackLocked(returnTaskType, reason)) {
+ if (!mFullscreen && adjustFocusToNextFocusableStackLocked(reason)) {
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen.
return mStackSupervisor.resumeFocusedStackTopActivityLocked(
@@ -2112,7 +2140,7 @@
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
return isOnHomeDisplay() &&
- mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
+ mStackSupervisor.resumeHomeStackTask(prev, reason);
}
next.delayedResume = false;
@@ -2147,10 +2175,8 @@
} else if (!isHomeStack()){
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Launching home next");
- final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
- HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
- mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
+ mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
}
}
@@ -2567,7 +2593,7 @@
// activity, set mTaskToReturnTo accordingly.
if (isOnHomeDisplay()) {
ActivityStack lastStack = mStackSupervisor.getLastStack();
- final boolean fromHome = lastStack.isHomeStack();
+ final boolean fromHomeOrRecents = lastStack.isHomeOrRecentsStack();
final boolean fromOnTopLauncher = lastStack.topTask() != null &&
lastStack.topTask().isOnTopLauncher();
if (fromOnTopLauncher) {
@@ -2576,12 +2602,12 @@
// This also makes sure that non-home activities are visible under a transparent
// non-home activity.
task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
- } else if (!isHomeStack() && (fromHome || topTask() != task)) {
+ } else if (!isHomeOrRecentsStack() && (fromHomeOrRecents || topTask() != task)) {
// If it's a last task over home - we default to keep its return to type not to
// make underlying task focused when this one will be finished.
int returnToType = isLastTaskOverHome
? task.getTaskToReturnTo() : APPLICATION_ACTIVITY_TYPE;
- if (fromHome && StackId.allowTopTaskToReturnHome(mStackId)) {
+ if (fromHomeOrRecents && StackId.allowTopTaskToReturnHome(mStackId)) {
returnToType = lastStack.topTask() == null
? HOME_ACTIVITY_TYPE : lastStack.topTask().taskType;
}
@@ -2613,8 +2639,8 @@
mWindowManager.moveTaskToTop(task.taskId);
}
- final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
- ActivityOptions options) {
+ final void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
+ boolean newTask, boolean keepCurTransition, ActivityOptions options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
// mLaunchTaskBehind tasks get placed at the back of the task stack.
@@ -2675,7 +2701,7 @@
task.setFrontOfTask();
r.putInHistory();
- if (!isHomeStack() || numActivities() > 0) {
+ if (!isHomeOrRecentsStack() || numActivities() > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
// not currently running.
@@ -2693,11 +2719,20 @@
mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
mNoAnimActivities.add(r);
} else {
- mWindowManager.prepareAppTransition(newTask
- ? r.mLaunchTaskBehind
- ? TRANSIT_TASK_OPEN_BEHIND
- : TRANSIT_TASK_OPEN
- : TRANSIT_ACTIVITY_OPEN, keepCurTransition);
+ int transit = TRANSIT_ACTIVITY_OPEN;
+ if (newTask) {
+ if (r.mLaunchTaskBehind) {
+ transit = TRANSIT_TASK_OPEN_BEHIND;
+ } else {
+ // If a new task is being launched, then mark the existing top activity to
+ // enter picture-in-picture if it supports auto-entering PiP
+ if (focusedTopActivity != null) {
+ focusedTopActivity.setEnterPipOnMoveToBackground(true);
+ }
+ transit = TRANSIT_TASK_OPEN;
+ }
+ }
+ mWindowManager.prepareAppTransition(transit, keepCurTransition);
mNoAnimActivities.remove(r);
}
addConfigOverride(r, task);
@@ -3114,18 +3149,16 @@
} else {
final TaskRecord task = r.task;
if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
- final int taskToReturnTo = task.getTaskToReturnTo();
-
// For non-fullscreen stack, we want to move the focus to the next visible
// stack to prevent the home screen from moving to the top and obscuring
// other visible stacks.
if (!mFullscreen
- && adjustFocusToNextFocusableStackLocked(taskToReturnTo, myReason)) {
+ && adjustFocusToNextFocusableStackLocked(myReason)) {
return;
}
// Move the home stack to the top if this stack is fullscreen or there is no
// other visible stack.
- if (mStackSupervisor.moveHomeStackTaskToTop(taskToReturnTo, myReason)) {
+ if (mStackSupervisor.moveHomeStackTaskToTop(myReason)) {
// Activity focus was already adjusted. Nothing else to do...
return;
}
@@ -3137,7 +3170,7 @@
mStackSupervisor.topRunningActivityLocked(), myReason);
}
- private boolean adjustFocusToNextFocusableStackLocked(int taskToReturnTo, String reason) {
+ private boolean adjustFocusToNextFocusableStackLocked(String reason) {
final ActivityStack stack = getNextFocusableStackLocked();
final String myReason = reason + " adjustFocusToNextFocusableStack";
if (stack == null) {
@@ -3146,10 +3179,10 @@
final ActivityRecord top = stack.topRunningActivityLocked();
- if (stack.isHomeStack() && (top == null || !top.visible)) {
+ if (stack.isHomeOrRecentsStack() && (top == null || !top.visible)) {
// If we will be focusing on the home stack next and its current top activity isn't
// visible, then use the task return to value to determine the home task to display next.
- return mStackSupervisor.moveHomeStackTaskToTop(taskToReturnTo, reason);
+ return mStackSupervisor.moveHomeStackTaskToTop(reason);
}
stack.moveToFront(myReason);
@@ -3754,7 +3787,7 @@
"removeActivityFromHistoryLocked: last activity removed from " + this);
if (mStackSupervisor.isFocusedStack(this) && task == topTask() &&
task.isOverHomeStack()) {
- mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason);
+ mStackSupervisor.moveHomeStackTaskToTop(reason);
}
removeTask(task, reason);
}
@@ -4176,11 +4209,11 @@
mStackSupervisor.invalidateTaskLayers();
}
- void moveHomeStackTaskToTop(int homeStackTaskType) {
+ void moveHomeStackTaskToTop() {
final int top = mTaskHistory.size() - 1;
for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
- if (task.taskType == homeStackTaskType) {
+ if (task.taskType == HOME_ACTIVITY_TYPE) {
if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG_STACK,
"moveHomeStackTaskToTop: moving " + task);
mTaskHistory.remove(taskNdx);
@@ -4195,6 +4228,8 @@
AppTimeTracker timeTracker, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
+ final ActivityRecord focusedTopActivity = mStackSupervisor.getFocusedStack() != null
+ ? mStackSupervisor.getFocusedStack().topActivity() : null;
final int numTasks = mTaskHistory.size();
final int index = mTaskHistory.indexOf(tr);
if (numTasks == 0 || index < 0) {
@@ -4240,6 +4275,11 @@
} else {
updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
}
+ // If a new task is moved to the front, then mark the existing top activity to enter
+ // picture-in-picture if it supports auto-entering PiP
+ if (focusedTopActivity != null) {
+ focusedTopActivity.setEnterPipOnMoveToBackground(true);
+ }
mStackSupervisor.resumeFocusedStackTopActivityLocked();
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
@@ -4306,7 +4346,7 @@
moveToBack(topTask());
// Resume an activity in the next focusable stack.
- adjustFocusToNextFocusableStackLocked(APPLICATION_ACTIVITY_TYPE, "moveTaskToBack");
+ adjustFocusToNextFocusableStackLocked("moveTaskToBack");
mStackSupervisor.resumeFocusedStackTopActivityLocked();
return true;
}
@@ -4365,9 +4405,8 @@
// Not ready yet!
return false;
}
- final int taskToReturnTo = tr.getTaskToReturnTo();
tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
- return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null, "moveTaskToBack");
+ return mStackSupervisor.resumeHomeStackTask(null, "moveTaskToBack");
}
mStackSupervisor.resumeFocusedStackTopActivityLocked();
@@ -4840,9 +4879,7 @@
if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
&& mStackSupervisor.isFocusedStack(this)) {
String myReason = reason + " leftTaskHistoryEmpty";
- if (mFullscreen
- || !adjustFocusToNextFocusableStackLocked(
- task.getTaskToReturnTo(), myReason)) {
+ if (mFullscreen || !adjustFocusToNextFocusableStackLocked(myReason)) {
mStackSupervisor.moveHomeStackToFront(myReason);
}
}
@@ -4850,7 +4887,7 @@
mStacks.remove(this);
mStacks.add(0, this);
}
- if (!isHomeStack()) {
+ if (!isHomeOrRecentsStack()) {
mActivityContainer.onTaskListEmptyLocked();
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 48108fe..281812c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -33,6 +33,7 @@
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -72,7 +73,6 @@
import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
-import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
@@ -661,13 +661,8 @@
}
/** Returns true if the focus activity was adjusted to the home stack top activity. */
- boolean moveHomeStackTaskToTop(int homeStackTaskType, String reason) {
- if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
- mWindowManager.showRecentApps(false /* fromHome */);
- return false;
- }
-
- mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
+ boolean moveHomeStackTaskToTop(String reason) {
+ mHomeStack.moveHomeStackTaskToTop();
final ActivityRecord top = getHomeActivity();
if (top == null) {
@@ -677,22 +672,17 @@
return true;
}
- boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev, String reason) {
+ boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
- if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
- mWindowManager.showRecentApps(false /* fromHome */);
- return false;
- }
-
if (prev != null) {
prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
- mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
+ mHomeStack.moveHomeStackTaskToTop();
ActivityRecord r = getHomeActivity();
final String myReason = reason + " resumeHomeStackTask";
@@ -2332,6 +2322,11 @@
return true;
}
+ if (!task.canResizeToBounds(bounds)) {
+ throw new IllegalArgumentException("resizeTaskLocked: Can not resize task=" + task
+ + " to bounds=" + bounds + " resizeMode=" + task.mResizeMode);
+ }
+
// Do not move the task to another stack here.
// This method assumes that the task is already placed in the right stack.
// we do not mess with that decision and we only do the resize!
@@ -2648,11 +2643,13 @@
return false;
}
- moveActivityToPinnedStackLocked(r, "moveTopActivityToPinnedStack", bounds);
+ moveActivityToPinnedStackLocked(r, "moveTopActivityToPinnedStack", bounds,
+ true /* moveHomeStackToFront */);
return true;
}
- void moveActivityToPinnedStackLocked(ActivityRecord r, String reason, Rect bounds) {
+ void moveActivityToPinnedStackLocked(ActivityRecord r, String reason, Rect bounds,
+ boolean moveHomeStackToFront) {
mWindowManager.deferSurfaceLayout();
try {
final TaskRecord task = r.task;
@@ -2676,7 +2673,7 @@
if (task.mActivities.size() == 1) {
// There is only one activity in the task. So, we can just move the task over to
// the stack without re-parenting the activity in a different task.
- if (task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
+ if (moveHomeStackToFront && task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
// Move the home stack forward if the task we just moved to the pinned stack
// was launched from home so home should be visible behind it.
moveHomeStackToFront(reason);
@@ -2684,6 +2681,8 @@
moveTaskToStackLocked(
task.taskId, PINNED_STACK_ID, ON_TOP, FORCE_FOCUS, reason, !ANIMATE);
} else {
+ // There are multiple activities in the task and moving the top activity should
+ // reveal/leave the other activities in their original task
stack.moveActivityToStack(r);
}
} finally {
@@ -2754,7 +2753,7 @@
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
- if (!r.isApplicationActivity() && !stack.isHomeStack()) {
+ if (!r.isApplicationActivity() && !stack.isHomeOrRecentsStack()) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (home activity) " + stack);
continue;
}
@@ -3178,7 +3177,7 @@
stack.moveToFront("switchUserOnHomeDisplay");
} else {
// Stack was moved to another display while user was swapped out.
- resumeHomeStackTask(HOME_ACTIVITY_TYPE, null, "switchUserOnOtherDisplay");
+ resumeHomeStackTask(null, "switchUserOnOtherDisplay");
}
return homeInFront;
}
@@ -4597,9 +4596,9 @@
? new ActivityOptions(bOptions) : null;
final int launchStackId = (activityOptions != null)
? activityOptions.getLaunchStackId() : INVALID_STACK_ID;
- if (launchStackId == HOME_STACK_ID) {
+ if (StackId.isHomeOrRecentsStack(launchStackId)) {
throw new IllegalArgumentException("startActivityFromRecentsInner: Task "
- + taskId + " can't be launch in the home stack.");
+ + taskId + " can't be launch in the home/recents stack.");
}
if (launchStackId == DOCKED_STACK_ID) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index dff7cef..d0960a0 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -32,6 +32,7 @@
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.isStaticStack;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
@@ -589,7 +590,7 @@
}
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
- mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
+ mSupervisor.moveHomeStackTaskToTop(reason);
startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
@@ -1067,6 +1068,7 @@
// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
final ActivityStack topStack = mSupervisor.mFocusedStack;
+ final ActivityRecord topFocused = topStack.topActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
@@ -1138,7 +1140,8 @@
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
- mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
+ mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
+ mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
if (!mTargetStack.isFocusable()
@@ -1524,8 +1527,8 @@
private void updateTaskReturnToType(
TaskRecord task, int launchFlags, ActivityStack focusedStack) {
- if (focusedStack != null && focusedStack.isHomeStack() && focusedStack.topTask() != null
- && focusedStack.topTask().isOnTopLauncher()) {
+ if (focusedStack != null && focusedStack.isHomeOrRecentsStack()
+ && focusedStack.topTask() != null && focusedStack.topTask().isOnTopLauncher()) {
// Since an on-top launcher will is moved to back when tasks are launched from it,
// those tasks should first try to return to a non-home activity.
// This also makes sure that non-home activities are visible under a transparent
@@ -1869,7 +1872,10 @@
private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
int launchFlags, ActivityOptions aOptions) {
final TaskRecord task = r.task;
- if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
+ if (r.isRecentsActivity()) {
+ return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
+ }
+ if (r.isHomeActivity()) {
return mSupervisor.mHomeStack;
}
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 5e02597..19bf536 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -57,6 +57,7 @@
private boolean mKeyguardShowing;
private boolean mKeyguardGoingAway;
private boolean mOccluded;
+ private boolean mDismissalRequested;
private ActivityRecord mDismissingKeyguardActivity;
private int mBeforeUnoccludeTransit;
private int mVisibilityTransactionDepth;
@@ -95,9 +96,7 @@
mKeyguardShowing = showing;
if (showing) {
mKeyguardGoingAway = false;
-
- // Allow an activity to redismiss Keyguard.
- mDismissingKeyguardActivity = null;
+ mDismissalRequested = false;
}
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mService.updateSleepIfNeededLocked();
@@ -183,8 +182,20 @@
* @return True if we may show an activity while Keyguard is showing because we are in the
* process of dismissing it anyways, false otherwise.
*/
- boolean canShowActivityWhileKeyguardShowing(boolean dismissKeyguard) {
- return dismissKeyguard && canDismissKeyguard();
+ boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) {
+
+ // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
+ // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
+ // Keyguard.
+ return dismissKeyguard && canDismissKeyguard() &&
+ (mDismissalRequested || r != mDismissingKeyguardActivity);
+ }
+
+ /**
+ * @return True if we may show an activity while Keyguard is occluded, false otherwise.
+ */
+ boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) {
+ return showWhenLocked || dismissKeyguard && !mWindowManager.isKeyguardSecure();
}
private void visibilitiesUpdated() {
@@ -199,7 +210,14 @@
// Only the very top activity may control occluded state
if (stackNdx == topStackNdx) {
- mOccluded = stack.topActivityOccludesKeyguard();
+
+ // A dismissing activity occludes Keyguard in the insecure case for legacy reasons.
+ final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
+ mOccluded = stack.topActivityOccludesKeyguard()
+ || (topDismissing != null
+ && stack.topRunningActivityLocked() == topDismissing
+ && canShowWhileOccluded(true /* dismissKeyguard */,
+ false /* showWhenLocked */));
}
if (mDismissingKeyguardActivity == null
&& stack.getTopDismissingKeyguardActivity() != null) {
@@ -239,8 +257,13 @@
* Called when somebody might want to dismiss the Keyguard.
*/
private void handleDismissKeyguard() {
- if (mDismissingKeyguardActivity != null) {
+ // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
+ // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
+ // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
+ if (!mOccluded && mDismissingKeyguardActivity != null
+ && mWindowManager.isKeyguardSecure()) {
mWindowManager.dismissKeyguard(null /* callback */);
+ mDismissalRequested = true;
// If we are about to unocclude the Keyguard, but we can dismiss it without security,
// we immediately dismiss the Keyguard so the activity gets shown without a flicker.
@@ -296,6 +319,7 @@
pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
pw.println(prefix + " mOccluded=" + mOccluded);
pw.println(prefix + " mDismissingKeyguardActivity=" + mDismissingKeyguardActivity);
+ pw.println(prefix + " mDismissalRequested=" + mDismissalRequested);
pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
}
}
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index bc9bda2f..6a13d36 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -130,8 +130,8 @@
void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
final ActivityStack stack = task != null ? task.getStack() : null;
- if (stack != null && stack.isHomeStack()) {
- // Never persist the home stack.
+ if (stack != null && stack.isHomeOrRecentsStack()) {
+ // Never persist the home or recents stack.
return;
}
syncPersistentTaskIdsLocked();
@@ -150,7 +150,7 @@
for (int i = size() - 1; i >= 0; i--) {
final TaskRecord task = get(i);
final ActivityStack stack = task.getStack();
- if (task.isPersistable && (stack == null || !stack.isHomeStack())) {
+ if (task.isPersistable && (stack == null || !stack.isHomeOrRecentsStack())) {
// Set of persisted taskIds for task.userId should not be null here
// TODO Investigate why it can happen. For now initialize with an empty set
if (mPersistedTaskIds.get(task.userId) == null) {
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 1ecb2e9..7a62f2c 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -643,7 +643,7 @@
" persistable=" + task.isPersistable);
final ActivityStack stack = task.getStack();
if ((task.isPersistable || task.inRecents)
- && (stack == null || !stack.isHomeStack())) {
+ && (stack == null || !stack.isHomeOrRecentsStack())) {
if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
persistentTaskIds.add(task.taskId);
} else {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 0bc12ee..383f106 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -64,6 +64,7 @@
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
@@ -72,6 +73,9 @@
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
@@ -1068,7 +1072,7 @@
}
boolean isOverHomeStack() {
- return mTaskToReturnTo == HOME_ACTIVITY_TYPE || mTaskToReturnTo == RECENTS_ACTIVITY_TYPE;
+ return mTaskToReturnTo == HOME_ACTIVITY_TYPE;
}
boolean isResizeable() {
@@ -1076,12 +1080,32 @@
&& !mTemporarilyUnresizable;
}
+ /**
+ * Check that a given bounds matches the application requested orientation.
+ *
+ * @param bounds The bounds to be tested.
+ * @return True if the requested bounds are okay for a resizing request.
+ */
+ boolean canResizeToBounds(Rect bounds) {
+ if (bounds == null || getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
+ // Note: If not on the freeform workspace, we ignore the bounds.
+ return true;
+ }
+ final boolean landscape = bounds.width() > bounds.height();
+ if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
+ return mBounds == null || landscape == (mBounds.width() > mBounds.height());
+ }
+ return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
+ && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
+ }
+
boolean isOnTopLauncher() {
return isHomeTask() && mIsOnTopLauncher;
}
boolean canGoInDockedStack() {
- return isResizeable();
+ return isResizeable() &&
+ !ActivityInfo.isPreserveOrientationMode(mResizeMode);
}
/**
@@ -1685,7 +1709,10 @@
* The task will be moved (and stack focus changed) later if necessary.
*/
int getLaunchStackId() {
- if (!isApplicationTask()) {
+ if (isRecentsTask()) {
+ return RECENTS_STACK_ID;
+ }
+ if (isHomeTask()) {
return HOME_STACK_ID;
}
if (mBounds != null) {
@@ -1707,6 +1734,7 @@
final int stackId = mStack.mStackId;
if (stackId == HOME_STACK_ID
+ || stackId == RECENTS_STACK_ID
|| stackId == FULLSCREEN_WORKSPACE_STACK_ID
|| (stackId == DOCKED_STACK_ID && !isResizeable())) {
return isResizeable() ? mStack.mBounds : null;
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index aa66917..5e98859 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -97,6 +97,24 @@
private static final int SOCKET_TIMEOUT_MS = 10000;
private static final int PROBE_TIMEOUT_MS = 3000;
+ static enum EvaluationResult {
+ VALIDATED(true),
+ CAPTIVE_PORTAL(false);
+ final boolean isValidated;
+ EvaluationResult(boolean isValidated) {
+ this.isValidated = isValidated;
+ }
+ }
+
+ static enum ValidationStage {
+ FIRST_VALIDATION(true),
+ REVALIDATION(false);
+ final boolean isFirstValidation;
+ ValidationStage(boolean isFirstValidation) {
+ this.isFirstValidation = isFirstValidation;
+ }
+ }
+
public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
"android.net.conn.NETWORK_CONDITIONS_MEASURED";
public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type";
@@ -216,6 +234,8 @@
protected boolean mIsCaptivePortalCheckEnabled;
private boolean mUseHttps;
+ // The total number of captive portal detection attempts for this NetworkMonitor instance.
+ private int mValidations = 0;
// Set if the user explicitly selected "Do not use this network" in captive portal sign-in app.
private boolean mUserDoesNotWant = false;
@@ -290,6 +310,10 @@
return validationLogs.readOnlyLocalLog();
}
+ private ValidationStage validationStage() {
+ return 0 == mValidations ? ValidationStage.FIRST_VALIDATION : ValidationStage.REVALIDATION;
+ }
+
// DefaultState is the parent of all States. It exists only to handle CMD_* messages but
// does not entail any real state (hence no enter() or exit() routines).
private class DefaultState extends State {
@@ -366,9 +390,11 @@
private class ValidatedState extends State {
@Override
public void enter() {
- maybeLogEvaluationResult(NetworkEvent.NETWORK_VALIDATED);
+ maybeLogEvaluationResult(
+ networkEventType(validationStage(), EvaluationResult.VALIDATED));
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
NETWORK_TEST_RESULT_VALID, mNetworkAgentInfo.network.netId, null));
+ mValidations++;
}
@Override
@@ -584,7 +610,8 @@
@Override
public void enter() {
- maybeLogEvaluationResult(NetworkEvent.NETWORK_CAPTIVE_PORTAL_FOUND);
+ maybeLogEvaluationResult(
+ networkEventType(validationStage(), EvaluationResult.CAPTIVE_PORTAL));
// Don't annoy user with sign-in notifications.
if (mDontDisplaySigninNotification) return;
// Create a CustomIntentReceiver that sends us a
@@ -604,6 +631,7 @@
// Retest for captive portal occasionally.
sendMessageDelayed(CMD_CAPTIVE_PORTAL_RECHECK, 0 /* no UID */,
CAPTIVE_PORTAL_REEVALUATE_DELAY_MS);
+ mValidations++;
}
@Override
@@ -679,48 +707,13 @@
long startTime = SystemClock.elapsedRealtime();
- // Pre-resolve the captive portal server host so we can log it.
- // Only do this if HttpURLConnection is about to, to avoid any potentially
- // unnecessary resolution.
- String hostToResolve = null;
+ final CaptivePortalProbeResult result;
if (pacUrl != null) {
- hostToResolve = pacUrl.getHost();
- } else if (proxyInfo != null) {
- hostToResolve = proxyInfo.getHost();
- } else {
- hostToResolve = httpUrl.getHost();
- }
-
- if (!TextUtils.isEmpty(hostToResolve)) {
- String probeName = ValidationProbeEvent.getProbeName(ValidationProbeEvent.PROBE_DNS);
- final Stopwatch dnsTimer = new Stopwatch().start();
- int dnsResult;
- long dnsLatency;
- try {
- InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(hostToResolve);
- dnsResult = ValidationProbeEvent.DNS_SUCCESS;
- dnsLatency = dnsTimer.stop();
- final StringBuffer connectInfo = new StringBuffer(", " + hostToResolve + "=");
- for (InetAddress address : addresses) {
- connectInfo.append(address.getHostAddress());
- if (address != addresses[addresses.length-1]) connectInfo.append(",");
- }
- validationLog(probeName + " OK " + dnsLatency + "ms" + connectInfo);
- } catch (UnknownHostException e) {
- dnsResult = ValidationProbeEvent.DNS_FAILURE;
- dnsLatency = dnsTimer.stop();
- validationLog(probeName + " FAIL " + dnsLatency + "ms, " + hostToResolve);
- }
- logValidationProbe(dnsLatency, ValidationProbeEvent.PROBE_DNS, dnsResult);
- }
-
- CaptivePortalProbeResult result;
- if (pacUrl != null) {
- result = sendHttpProbe(pacUrl, ValidationProbeEvent.PROBE_PAC);
+ result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC);
} else if (mUseHttps) {
- result = sendParallelHttpProbes(httpsUrl, httpUrl, fallbackUrl);
+ result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl, fallbackUrl);
} else {
- result = sendHttpProbe(httpUrl, ValidationProbeEvent.PROBE_HTTP);
+ result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP);
}
long endTime = SystemClock.elapsedRealtime();
@@ -733,8 +726,50 @@
}
/**
- * Do a URL fetch on a known server to see if we get the data we expect.
- * Returns HTTP response code.
+ * Do a DNS resolution and URL fetch on a known web server to see if we get the data we expect.
+ * @return a CaptivePortalProbeResult inferred from the HTTP response.
+ */
+ private CaptivePortalProbeResult sendDnsAndHttpProbes(ProxyInfo proxy, URL url, int probeType) {
+ // Pre-resolve the captive portal server host so we can log it.
+ // Only do this if HttpURLConnection is about to, to avoid any potentially
+ // unnecessary resolution.
+ final String host = (proxy != null) ? proxy.getHost() : url.getHost();
+ sendDnsProbe(host);
+ return sendHttpProbe(url, probeType);
+ }
+
+ /** Do a DNS resolution of the given server. */
+ private void sendDnsProbe(String host) {
+ if (TextUtils.isEmpty(host)) {
+ return;
+ }
+
+ final String name = ValidationProbeEvent.getProbeName(ValidationProbeEvent.PROBE_DNS);
+ final Stopwatch watch = new Stopwatch().start();
+ int result;
+ String connectInfo;
+ try {
+ InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(host);
+ result = ValidationProbeEvent.DNS_SUCCESS;
+ StringBuffer buffer = new StringBuffer(host).append("=");
+ for (InetAddress address : addresses) {
+ buffer.append(address.getHostAddress());
+ if (address != addresses[addresses.length-1]) buffer.append(",");
+ }
+ connectInfo = buffer.toString();
+ } catch (UnknownHostException e) {
+ result = ValidationProbeEvent.DNS_FAILURE;
+ connectInfo = host;
+ }
+ final long latency = watch.stop();
+ String resultString = (ValidationProbeEvent.DNS_SUCCESS == result) ? "OK" : "FAIL";
+ validationLog(String.format("%s %s %dms, %s", name, resultString, latency, connectInfo));
+ logValidationProbe(latency, ValidationProbeEvent.PROBE_DNS, result);
+ }
+
+ /**
+ * Do a URL fetch on a known web server to see if we get the data we expect.
+ * @return a CaptivePortalProbeResult inferred from the HTTP response.
*/
@VisibleForTesting
protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType) {
@@ -801,7 +836,7 @@
}
private CaptivePortalProbeResult sendParallelHttpProbes(
- URL httpsUrl, URL httpUrl, URL fallbackUrl) {
+ ProxyInfo proxy, URL httpsUrl, URL httpUrl, URL fallbackUrl) {
// Number of probes to wait for. If a probe completes with a conclusive answer
// it shortcuts the latch immediately by forcing the count to 0.
final CountDownLatch latch = new CountDownLatch(2);
@@ -821,9 +856,10 @@
@Override
public void run() {
if (mIsHttps) {
- mResult = sendHttpProbe(httpsUrl, ValidationProbeEvent.PROBE_HTTPS);
+ mResult =
+ sendDnsAndHttpProbes(proxy, httpsUrl, ValidationProbeEvent.PROBE_HTTPS);
} else {
- mResult = sendHttpProbe(httpUrl, ValidationProbeEvent.PROBE_HTTP);
+ mResult = sendDnsAndHttpProbes(proxy, httpUrl, ValidationProbeEvent.PROBE_HTTP);
}
if ((mIsHttps && mResult.isSuccessful()) || (!mIsHttps && mResult.isPortal())) {
// Stop waiting immediately if https succeeds or if http finds a portal.
@@ -974,6 +1010,22 @@
mMetricsLog.log(new NetworkEvent(mNetId, evtype));
}
+ private int networkEventType(ValidationStage s, EvaluationResult r) {
+ if (s.isFirstValidation) {
+ if (r.isValidated) {
+ return NetworkEvent.NETWORK_FIRST_VALIDATION_SUCCESS;
+ } else {
+ return NetworkEvent.NETWORK_FIRST_VALIDATION_PORTAL_FOUND;
+ }
+ } else {
+ if (r.isValidated) {
+ return NetworkEvent.NETWORK_REVALIDATION_SUCCESS;
+ } else {
+ return NetworkEvent.NETWORK_REVALIDATION_PORTAL_FOUND;
+ }
+ }
+ }
+
private void maybeLogEvaluationResult(int evtype) {
if (mEvaluationTimer.isRunning()) {
mMetricsLog.log(new NetworkEvent(mNetId, evtype, mEvaluationTimer.stop()));
@@ -982,6 +1034,8 @@
}
private void logValidationProbe(long durationMs, int probeType, int probeResult) {
+ probeType =
+ ValidationProbeEvent.makeProbeType(probeType, validationStage().isFirstValidation);
mMetricsLog.log(new ValidationProbeEvent(mNetId, durationMs, probeType, probeResult));
}
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 45f54a9..54366e6 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -95,7 +95,8 @@
import java.util.Date;
import java.util.Map.Entry;
import java.util.Properties;
-
+import java.util.Map;
+import java.util.HashMap;
import libcore.io.IoUtils;
/**
@@ -211,24 +212,18 @@
private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
- // Request ref location
- private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
- private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
+ //TODO(b/33112647): Create gps_debug.conf with commented career parameters.
+ private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf";
// ref. location info
private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
- private static final int AGPS_REG_LOCATION_TYPE_MAC = 3;
// set id info
private static final int AGPS_SETID_TYPE_NONE = 0;
private static final int AGPS_SETID_TYPE_IMSI = 1;
private static final int AGPS_SETID_TYPE_MSISDN = 2;
- private static final String PROPERTIES_FILE_PREFIX = "/etc/gps";
- private static final String PROPERTIES_FILE_SUFFIX = ".conf";
- private static final String DEFAULT_PROPERTIES_FILE = PROPERTIES_FILE_PREFIX + PROPERTIES_FILE_SUFFIX;
-
private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
@@ -501,10 +496,6 @@
startNavigating(false);
} else if (action.equals(ALARM_TIMEOUT)) {
hibernate();
- } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
- checkSmsSuplInit(intent);
- } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
- checkWapSuplInit(intent);
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
|| PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)
|| Intent.ACTION_SCREEN_OFF.equals(action)
@@ -557,31 +548,6 @@
}
}
- private void checkSmsSuplInit(Intent intent) {
- SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
- if (messages == null) {
- Log.e(TAG, "Message does not exist in the intent.");
- return;
- }
-
- for (SmsMessage message : messages) {
- if (message != null && message.mWrappedSmsMessage != null) {
- byte[] suplInit = message.getUserData();
- if (suplInit != null) {
- native_agps_ni_message(suplInit, suplInit.length);
- }
- }
- }
- }
-
- private void checkWapSuplInit(Intent intent) {
- byte[] suplInit = intent.getByteArrayExtra("data");
- if (suplInit == null) {
- return;
- }
- native_agps_ni_message(suplInit,suplInit.length);
- }
-
private void updateLowPowerMode() {
// Disable GPS if we are in device idle mode.
boolean disableGps = mPowerManager.isDeviceIdleMode();
@@ -602,23 +568,14 @@
return native_is_supported();
}
+ interface SetCarrierProperty {
+ public boolean set(int value);
+ }
+
private void reloadGpsProperties(Context context, Properties properties) {
if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
loadPropertiesFromResource(context, properties);
- boolean isPropertiesLoadedFromFile = false;
- final String gpsHardware = SystemProperties.get("ro.hardware.gps");
-
- if (!TextUtils.isEmpty(gpsHardware)) {
- final String propFilename =
- PROPERTIES_FILE_PREFIX + "." + gpsHardware + PROPERTIES_FILE_SUFFIX;
- isPropertiesLoadedFromFile =
- loadPropertiesFromFile(propFilename, properties);
- }
- if (!isPropertiesLoadedFromFile) {
- loadPropertiesFromFile(DEFAULT_PROPERTIES_FILE, properties);
- }
- if (DEBUG) Log.d(TAG, "GPS properties reloaded, size = " + properties.size());
String lpp_prof = SystemProperties.get(LPP_PROFILE);
if (!TextUtils.isEmpty(lpp_prof)) {
// override default value of this if lpp_prof is not empty
@@ -636,16 +593,37 @@
Log.e(TAG, "unable to parse C2K_PORT: " + portString);
}
}
-
+ /*
+ * Allow carrier properties to be loaded from a debug configuration file.
+ */
+ loadPropertiesFromFile(DEBUG_PROPERTIES_FILE, properties);
if (native_is_gnss_configuration_supported()) {
- try {
- // Convert properties to string contents and send it to HAL.
- ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
- properties.store(baos, null);
- native_configuration_update(baos.toString());
- if (DEBUG) Log.d(TAG, "final config = " + baos.toString());
- } catch (IOException ex) {
- Log.e(TAG, "failed to dump properties contents");
+ Map<String, SetCarrierProperty> map = new HashMap<String, SetCarrierProperty>() {
+ {
+ put("SUPL_VER", (val) -> native_set_supl_version(val));
+ put("SUPL_MODE", (val) -> native_set_supl_mode(val));
+ put("SUPL_ES", (val) -> native_set_supl_es(val));
+ put("LPP_PROFILE", (val) -> native_set_lpp_profile(val));
+ put("A_GLONASS_POS_PROTOCOL_SELECT", (val) -> native_set_gnss_pos_protocol_select(val));
+ put("USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL", (val) -> native_set_emergency_supl_pdn(val));
+ put("GPS_LOCK", (val) -> native_set_gps_lock(val));
+ }
+ };
+
+ for(Entry<String, SetCarrierProperty> entry : map.entrySet()) {
+ String propertyName = entry.getKey();
+ String propertyValueString = properties.getProperty(propertyName);
+ if (propertyValueString != null) {
+ try {
+ int propertyValueInt = Integer.decode(propertyValueString);
+ boolean result = entry.getValue().set(propertyValueInt);
+ if (result == false) {
+ Log.e(TAG, "Unable to set " + propertyName);
+ }
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "unable to parse propertyName: " + propertyValueString);
+ }
+ }
}
} else if (DEBUG) {
Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not"
@@ -692,7 +670,7 @@
}
} catch (IOException e) {
- Log.w(TAG, "Could not open GPS configuration file " + filename);
+ Log.v(TAG, "Could not open GPS configuration file " + filename);
return false;
}
return true;
@@ -1973,8 +1951,7 @@
String requestorId,
String text,
int requestorIdEncoding,
- int textEncoding,
- String extras // Encoded extra data
+ int textEncoding
)
{
Log.i(TAG, "reportNiNotification: entered");
@@ -2003,28 +1980,6 @@
notification.requestorIdEncoding = requestorIdEncoding;
notification.textEncoding = textEncoding;
- // Process extras, assuming the format is
- // one of more lines of "key = value"
- Bundle bundle = new Bundle();
-
- if (extras == null) extras = "";
- Properties extraProp = new Properties();
-
- try {
- extraProp.load(new StringReader(extras));
- }
- catch (IOException e)
- {
- Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
- }
-
- for (Entry<Object, Object> ent : extraProp.entrySet())
- {
- bundle.putString((String) ent.getKey(), (String) ent.getValue());
- }
-
- notification.extras = bundle;
-
mNIHandler.handleNiNotification(notification);
}
@@ -2075,7 +2030,7 @@
* Called from native code to request reference location info
*/
- private void requestRefLocation(int flags) {
+ private void requestRefLocation() {
TelephonyManager phone = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
final int phoneType = phone.getPhoneType();
@@ -2547,5 +2502,12 @@
private native boolean native_stop_navigation_message_collection();
// GNSS Configuration
- private static native void native_configuration_update(String configData);
+ private static native boolean native_set_supl_version(int version);
+ private static native boolean native_set_supl_mode(int mode);
+ private static native boolean native_set_supl_es(int es);
+ private static native boolean native_set_lpp_profile(int lppProfile);
+ private static native boolean native_set_gnss_pos_protocol_select(int gnssPosProtocolSelect);
+ private static native boolean native_set_gps_lock(int gpsLock);
+ private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
+
}
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 9740935..d8fd6e2 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -74,7 +74,7 @@
try {
List<ActivityManager.RecentTaskInfo> tasks =
ActivityManager.getService().getRecentTasks(1,
- ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
+ ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS |
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
ActivityManager.RECENT_INCLUDE_PROFILES |
ActivityManager.RECENT_WITH_EXCLUDED, record.getUserId()).getList();
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 533307e..ac3a025 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -139,6 +139,7 @@
import android.os.MessageQueue.IdleHandler;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
+import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -197,6 +198,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Service that maintains low-level network policy rules, using
@@ -565,9 +568,12 @@
}
}
- public void systemReady() {
+ private void initService(CountDownLatch initCompleteSignal) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "systemReady");
+ final int oldPriority = Process.getThreadPriority(Process.myTid());
try {
+ // Boost thread's priority during system server init
+ Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
if (!isBandwidthControlEnabled()) {
Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
return;
@@ -672,11 +678,33 @@
mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
+ // tell systemReady() that the service has been initialized
+ initCompleteSignal.countDown();
} finally {
+ // Restore the default priority after init is done
+ Process.setThreadPriority(oldPriority);
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
}
+ public CountDownLatch networkScoreAndNetworkManagementServiceReady() {
+ final CountDownLatch initCompleteSignal = new CountDownLatch(1);
+ mHandler.post(() -> initService(initCompleteSignal));
+ return initCompleteSignal;
+ }
+
+ public void systemReady(CountDownLatch initCompleteSignal) {
+ // wait for initService to complete
+ try {
+ if (!initCompleteSignal.await(30, TimeUnit.SECONDS)) {
+ throw new IllegalStateException("Service " + TAG +" init timeout");
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("Service " + TAG + " init interrupted", e);
+ }
+ }
+
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "onUidStateChanged");
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c78a0f5..f58522b5 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -110,6 +110,7 @@
import android.service.notification.NotificationAssistantService;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationRankingUpdate;
+import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
import android.telephony.PhoneStateListener;
@@ -1020,7 +1021,7 @@
synchronized (mNotificationList) {
addAutogroupKeyLocked(key);
}
- mRankingHandler.requestSort();
+ mRankingHandler.requestSort(false);
}
@Override
@@ -1028,7 +1029,7 @@
synchronized (mNotificationList) {
removeAutogroupKeyLocked(key);
}
- mRankingHandler.requestSort();
+ mRankingHandler.requestSort(false);
}
@Override
@@ -2390,7 +2391,7 @@
mNotificationAssistants.checkServiceTokenLocked(token);
applyAdjustmentLocked(adjustment);
}
- mRankingHandler.requestSort();
+ mRankingHandler.requestSort(true);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2408,7 +2409,7 @@
applyAdjustmentLocked(adjustment);
}
}
- mRankingHandler.requestSort();
+ mRankingHandler.requestSort(true);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2420,12 +2421,20 @@
if (n == null) {
return;
}
- if (adjustment.getImportance() != IMPORTANCE_NONE) {
- n.setImportance(adjustment.getImportance(), adjustment.getExplanation());
- }
if (adjustment.getSignals() != null) {
Bundle.setDefusable(adjustment.getSignals(), true);
- // TODO: apply signals
+ final String overrideChannelId =
+ adjustment.getSignals().getString(Adjustment.KEY_CHANNEL_ID, null);
+ final ArrayList<String> people =
+ adjustment.getSignals().getStringArrayList(Adjustment.KEY_PEOPLE);
+ final ArrayList<SnoozeCriterion> snoozeCriterionList =
+ adjustment.getSignals().getParcelableArrayList(Adjustment.KEY_SNOOZE_CRITERIA);
+ if (!TextUtils.isEmpty(overrideChannelId)) {
+ n.setNotificationChannelOverride(mRankingHelper.getNotificationChannel(
+ n.sbn.getPackageName(), n.sbn.getUid(), overrideChannelId));
+ }
+ n.setPeopleOverride(people);
+ n.setSnoozeCriteria(snoozeCriterionList);
}
}
@@ -3309,27 +3318,27 @@
}
}
- private void handleRankingSort() {
+ private void handleRankingSort(Message msg) {
+ if (!(msg.obj instanceof Boolean)) return;
+ boolean forceUpdate = ((Boolean) msg.obj == null) ? false : (boolean) msg.obj;
synchronized (mNotificationList) {
final int N = mNotificationList.size();
ArrayList<String> orderBefore = new ArrayList<String>(N);
ArrayList<String> groupOverrideBefore = new ArrayList<>(N);
int[] visibilities = new int[N];
- int[] importances = new int[N];
for (int i = 0; i < N; i++) {
final NotificationRecord r = mNotificationList.get(i);
orderBefore.add(r.getKey());
groupOverrideBefore.add(r.sbn.getGroupKey());
visibilities[i] = r.getPackageVisibilityOverride();
- importances[i] = r.getImportance();
mRankingHelper.extractSignals(r);
}
mRankingHelper.sort(mNotificationList);
for (int i = 0; i < N; i++) {
final NotificationRecord r = mNotificationList.get(i);
- if (!orderBefore.get(i).equals(r.getKey())
+ if (forceUpdate
+ || !orderBefore.get(i).equals(r.getKey())
|| visibilities[i] != r.getPackageVisibilityOverride()
- || importances[i] != r.getImportance()
|| !groupOverrideBefore.get(i).equals(r.sbn.getGroupKey())) {
scheduleSendRankingUpdate();
return;
@@ -3439,14 +3448,17 @@
handleRankingReconsideration(msg);
break;
case MESSAGE_RANKING_SORT:
- handleRankingSort();
+ handleRankingSort(msg);
break;
}
}
- public void requestSort() {
+ public void requestSort(boolean forceUpdate) {
removeMessages(MESSAGE_RANKING_SORT);
- sendEmptyMessage(MESSAGE_RANKING_SORT);
+ Message msg = Message.obtain();
+ msg.what = MESSAGE_RANKING_SORT;
+ msg.obj = forceUpdate;
+ sendMessage(msg);
}
public void requestReconsideration(RankingReconsideration recon) {
@@ -3987,6 +3999,9 @@
Bundle visibilityOverrides = new Bundle();
Bundle suppressedVisualEffects = new Bundle();
Bundle explanation = new Bundle();
+ Bundle overrideChannels = new Bundle();
+ Bundle overridePeople = new Bundle();
+ Bundle snoozeCriteria = new Bundle();
for (int i = 0; i < N; i++) {
NotificationRecord record = mNotificationList.get(i);
if (!isVisibleToListener(record.sbn, info)) {
@@ -4008,6 +4023,9 @@
visibilityOverrides.putInt(key, record.getPackageVisibilityOverride());
}
overrideGroupKeys.putString(key, record.sbn.getOverrideGroupKey());
+ overrideChannels.putParcelable(key, record.getChannel());
+ overridePeople.putStringArrayList(key, record.getPeopleOverride());
+ snoozeCriteria.putParcelableArrayList(key, record.getSnoozeCriteria());
}
final int M = keys.size();
String[] keysAr = keys.toArray(new String[M]);
@@ -4017,7 +4035,8 @@
importanceAr[i] = importance.get(i);
}
return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
- suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys);
+ suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
+ overrideChannels, overridePeople, snoozeCriteria);
}
private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 0213258..4fcc987 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -36,6 +36,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
+import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.util.Slog;
@@ -45,6 +46,7 @@
import java.io.PrintWriter;
import java.lang.reflect.Array;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
@@ -110,6 +112,9 @@
private Uri mSound;
private long[] mVibration;
private AudioAttributes mAttributes;
+ private NotificationChannel mOverrideChannel;
+ private ArrayList<String> mPeopleOverride;
+ private ArrayList<SnoozeCriterion> mSnoozeCriteria;
@VisibleForTesting
public NotificationRecord(Context context, StatusBarNotification sbn)
@@ -626,7 +631,14 @@
}
public NotificationChannel getChannel() {
- return sbn.getNotificationChannel();
+ return mOverrideChannel == null ? sbn.getNotificationChannel() : mOverrideChannel;
+ }
+
+ protected void setNotificationChannelOverride(NotificationChannel channel) {
+ mOverrideChannel = channel;
+ if (mOverrideChannel != null) {
+ calculateImportance();
+ }
}
public Uri getSound() {
@@ -640,4 +652,20 @@
public AudioAttributes getAudioAttributes() {
return mAttributes;
}
+
+ public ArrayList<String> getPeopleOverride() {
+ return mPeopleOverride;
+ }
+
+ protected void setPeopleOverride(ArrayList<String> people) {
+ mPeopleOverride = people;
+ }
+
+ public ArrayList<SnoozeCriterion> getSnoozeCriteria() {
+ return mSnoozeCriteria;
+ }
+
+ protected void setSnoozeCriteria(ArrayList<SnoozeCriterion> snoozeCriteria) {
+ mSnoozeCriteria = snoozeCriteria;
+ }
}
diff --git a/services/core/java/com/android/server/notification/RankingHandler.java b/services/core/java/com/android/server/notification/RankingHandler.java
index 80bb4f0..656d727 100644
--- a/services/core/java/com/android/server/notification/RankingHandler.java
+++ b/services/core/java/com/android/server/notification/RankingHandler.java
@@ -16,6 +16,6 @@
package com.android.server.notification;
public interface RankingHandler {
- public void requestSort();
+ public void requestSort(boolean forceUpdate);
public void requestReconsideration(RankingReconsideration recon);
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index a41231d..5073b1b 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -328,7 +328,7 @@
for (int i = 0; i < N; i++) {
mSignalExtractors[i].setConfig(this);
}
- mRankingHandler.requestSort();
+ mRankingHandler.requestSort(false);
}
public void sort(ArrayList<NotificationRecord> notificationList) {
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index c9e1315..5dd651f 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -31,13 +31,17 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.LruCache;
import android.util.Slog;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -157,7 +161,8 @@
if (context == null) {
return NONE;
}
- final PeopleRankingReconsideration prr = validatePeople(context, key, extras, affinityOut);
+ final PeopleRankingReconsideration prr =
+ validatePeople(context, key, extras, null, affinityOut);
float affinity = affinityOut[0];
if (prr != null) {
@@ -207,7 +212,8 @@
final String key = record.getKey();
final Bundle extras = record.getNotification().extras;
final float[] affinityOut = new float[1];
- final PeopleRankingReconsideration rr = validatePeople(context, key, extras, affinityOut);
+ final PeopleRankingReconsideration rr =
+ validatePeople(context, key, extras, record.getPeopleOverride(), affinityOut);
final float affinity = affinityOut[0];
record.setContactAffinity(affinity);
if (rr == null) {
@@ -220,22 +226,22 @@
}
private PeopleRankingReconsideration validatePeople(Context context, String key, Bundle extras,
- float[] affinityOut) {
+ List<String> peopleOverride, float[] affinityOut) {
long start = SystemClock.elapsedRealtime();
float affinity = NONE;
if (extras == null) {
return null;
}
-
- final String[] people = getExtraPeople(extras);
- if (people == null || people.length == 0) {
- return null;
+ final Set<String> people = new ArraySet<>(peopleOverride);
+ final String[] notificationPeople = getExtraPeople(extras);
+ if (notificationPeople != null ) {
+ people.addAll(Arrays.asList(getExtraPeople(extras)));
}
if (VERBOSE) Slog.i(TAG, "Validating: " + key + " for " + context.getUserId());
final LinkedList<String> pendingLookups = new LinkedList<String>();
- for (int personIdx = 0; personIdx < people.length && personIdx < MAX_PEOPLE; personIdx++) {
- final String handle = people[personIdx];
+ int personIdx = 0;
+ for (String handle : people) {
if (TextUtils.isEmpty(handle)) continue;
synchronized (mPeopleCache) {
@@ -250,6 +256,9 @@
affinity = Math.max(affinity, lookupResult.getAffinity());
}
}
+ if (++personIdx == MAX_PEOPLE) {
+ break;
+ }
}
// record the best available data, so far:
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 2e18b1c..6aeb49c 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -20,17 +20,17 @@
import android.content.Context;
import android.content.pm.PackageStats;
import android.os.Build;
+import android.os.IInstalld;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import android.util.Slog;
-import com.android.internal.os.InstallerConnection;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.server.SystemService;
import dalvik.system.VMRuntime;
-import java.util.Arrays;
-
-public final class Installer extends SystemService {
+public class Installer extends SystemService {
private static final String TAG = "Installer";
/* ***************************************************************************
@@ -47,25 +47,29 @@
public static final int DEXOPT_BOOTCOMPLETE = 1 << 4;
/** Hint that the dexopt type is profile-guided. */
public static final int DEXOPT_PROFILE_GUIDED = 1 << 5;
- /** This is an OTA update dexopt */
- public static final int DEXOPT_OTA = 1 << 6;
// NOTE: keep in sync with installd
public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
- private final InstallerConnection mInstaller;
+ private final boolean mIsolated;
+
+ // TODO: reconnect if installd restarts
+ private volatile IInstalld mInstalld;
+ private volatile Object mWarnIfHeld;
public Installer(Context context) {
- super(context);
- mInstaller = new InstallerConnection();
+ this(context, false);
}
- // Package-private installer that accepts a custom InstallerConnection. Used for
- // OtaDexoptService.
- Installer(Context context, InstallerConnection connection) {
+ /**
+ * @param isolated indicates if this object should <em>not</em> connect to
+ * the real {@code installd}. All remote calls will be ignored
+ * unless you extend this class and intercept them.
+ */
+ public Installer(Context context, boolean isolated) {
super(context);
- mInstaller = connection;
+ mIsolated = isolated;
}
/**
@@ -73,136 +77,239 @@
* the given object.
*/
public void setWarnIfHeld(Object warnIfHeld) {
- mInstaller.setWarnIfHeld(warnIfHeld);
+ mWarnIfHeld = warnIfHeld;
}
@Override
public void onStart() {
- Slog.i(TAG, "Waiting for installd to be ready.");
- mInstaller.waitForConnection();
+ if (mIsolated) {
+ mInstalld = null;
+ } else {
+ mInstalld = IInstalld.Stub.asInterface(ServiceManager.getService("installd"));
+ }
}
- public void createAppData(String uuid, String pkgname, int userid, int flags, int appid,
- String seinfo, int targetSdkVersion) throws InstallerException {
- mInstaller.execute("create_app_data", uuid, pkgname, userid, flags, appid, seinfo,
- targetSdkVersion);
+ /**
+ * Do several pre-flight checks before making a remote call.
+ *
+ * @return if the remote call should continue.
+ */
+ private boolean checkBeforeRemote() {
+ if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
+ Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+ + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
+ }
+ if (mIsolated) {
+ Slog.i(TAG, "Ignoring request because this installer is isolated");
+ return false;
+ } else {
+ return true;
+ }
}
- public void restoreconAppData(String uuid, String pkgname, int userid, int flags, int appid,
- String seinfo) throws InstallerException {
- mInstaller.execute("restorecon_app_data", uuid, pkgname, userid, flags, appid,
- seinfo);
+ public void createAppData(String uuid, String packageName, int userId, int flags, int appId,
+ String seInfo, int targetSdkVersion) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
+ targetSdkVersion);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
- public void migrateAppData(String uuid, String pkgname, int userid, int flags)
+ public void restoreconAppData(String uuid, String packageName, int userId, int flags, int appId,
+ String seInfo) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.restoreconAppData(uuid, packageName, userId, flags, appId, seInfo);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public void migrateAppData(String uuid, String packageName, int userId, int flags)
throws InstallerException {
- mInstaller.execute("migrate_app_data", uuid, pkgname, userid, flags);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.migrateAppData(uuid, packageName, userId, flags);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
- public void clearAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)
+ public void clearAppData(String uuid, String packageName, int userId, int flags,
+ long ceDataInode) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.clearAppData(uuid, packageName, userId, flags, ceDataInode);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public void destroyAppData(String uuid, String packageName, int userId, int flags,
+ long ceDataInode) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.destroyAppData(uuid, packageName, userId, flags, ceDataInode);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public void moveCompleteApp(String fromUuid, String toUuid, String packageName,
+ String dataAppName, int appId, String seInfo, int targetSdkVersion)
throws InstallerException {
- mInstaller.execute("clear_app_data", uuid, pkgname, userid, flags, ceDataInode);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, dataAppName, appId, seInfo,
+ targetSdkVersion);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
- public void destroyAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)
- throws InstallerException {
- mInstaller.execute("destroy_app_data", uuid, pkgname, userid, flags, ceDataInode);
- }
-
- public void moveCompleteApp(String from_uuid, String to_uuid, String package_name,
- String data_app_name, int appid, String seinfo, int targetSdkVersion)
- throws InstallerException {
- mInstaller.execute("move_complete_app", from_uuid, to_uuid, package_name,
- data_app_name, appid, seinfo, targetSdkVersion);
- }
-
- public void getAppSize(String uuid, String pkgname, int userid, int flags, long ceDataInode,
+ public void getAppSize(String uuid, String packageName, int userId, int flags, long ceDataInode,
String codePath, PackageStats stats) throws InstallerException {
- final String[] res = mInstaller.execute("get_app_size", uuid, pkgname, userid, flags,
- ceDataInode, codePath);
+ if (!checkBeforeRemote()) return;
try {
- stats.codeSize += Long.parseLong(res[1]);
- stats.dataSize += Long.parseLong(res[2]);
- stats.cacheSize += Long.parseLong(res[3]);
- } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
- throw new InstallerException("Invalid size result: " + Arrays.toString(res));
+ final long[] res = mInstalld.getAppSize(uuid, packageName, userId, flags, ceDataInode,
+ codePath);
+ stats.codeSize += res[0];
+ stats.dataSize += res[1];
+ stats.cacheSize += res[2];
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
}
}
- public long getAppDataInode(String uuid, String pkgname, int userid, int flags)
+ public long getAppDataInode(String uuid, String packageName, int userId, int flags)
throws InstallerException {
- final String[] res = mInstaller.execute("get_app_data_inode", uuid, pkgname, userid, flags);
+ if (!checkBeforeRemote()) return -1;
try {
- return Long.parseLong(res[1]);
- } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
- throw new InstallerException("Invalid inode result: " + Arrays.toString(res));
+ return mInstalld.getAppDataInode(uuid, packageName, userId, flags);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
}
}
- public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
- int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)
- throws InstallerException {
- assertValidInstructionSet(instructionSet);
- mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags,
- compilerFilter, volumeUuid, sharedLibraries);
- }
-
- public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
+ public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet,
int dexoptNeeded, @Nullable String outputPath, int dexFlags,
- String compilerFilter, String volumeUuid, String sharedLibraries)
+ String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries)
throws InstallerException {
assertValidInstructionSet(instructionSet);
- mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded,
- outputPath, dexFlags, compilerFilter, volumeUuid, sharedLibraries);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath,
+ dexFlags, compilerFilter, volumeUuid, sharedLibraries);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
- public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
- return mInstaller.mergeProfiles(uid, pkgName);
+ public boolean mergeProfiles(int uid, String packageName) throws InstallerException {
+ if (!checkBeforeRemote()) return false;
+ try {
+ return mInstalld.mergeProfiles(uid, packageName);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
- public boolean dumpProfiles(String gid, String packageName, String codePaths)
+ public boolean dumpProfiles(int uid, String packageName, String codePaths)
throws InstallerException {
- return mInstaller.dumpProfiles(gid, packageName, codePaths);
+ if (!checkBeforeRemote()) return false;
+ try {
+ return mInstalld.dumpProfiles(uid, packageName, codePaths);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void idmap(String targetApkPath, String overlayApkPath, int uid)
throws InstallerException {
- mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.idmap(targetApkPath, overlayApkPath, uid);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void rmdex(String codePath, String instructionSet) throws InstallerException {
assertValidInstructionSet(instructionSet);
- mInstaller.execute("rmdex", codePath, instructionSet);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.rmdex(codePath, instructionSet);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void rmPackageDir(String packageDir) throws InstallerException {
- mInstaller.execute("rmpackagedir", packageDir);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.rmPackageDir(packageDir);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
- public void clearAppProfiles(String pkgName) throws InstallerException {
- mInstaller.execute("clear_app_profiles", pkgName);
+ public void clearAppProfiles(String packageName) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.clearAppProfiles(packageName);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
- public void destroyAppProfiles(String pkgName) throws InstallerException {
- mInstaller.execute("destroy_app_profiles", pkgName);
+ public void destroyAppProfiles(String packageName) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.destroyAppProfiles(packageName);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void createUserData(String uuid, int userId, int userSerial, int flags)
throws InstallerException {
- mInstaller.execute("create_user_data", uuid, userId, userSerial, flags);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.createUserData(uuid, userId, userSerial, flags);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void destroyUserData(String uuid, int userId, int flags) throws InstallerException {
- mInstaller.execute("destroy_user_data", uuid, userId, flags);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.destroyUserData(uuid, userId, flags);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void markBootComplete(String instructionSet) throws InstallerException {
assertValidInstructionSet(instructionSet);
- mInstaller.execute("markbootcomplete", instructionSet);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.markBootComplete(instructionSet);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void freeCache(String uuid, long freeStorageSize) throws InstallerException {
- mInstaller.execute("freecache", uuid, freeStorageSize);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.freeCache(uuid, freeStorageSize);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
/**
@@ -210,29 +317,54 @@
* directory to the real location for backward compatibility. Note that no
* such symlink is created for 64 bit shared libraries.
*/
- public void linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32,
+ public void linkNativeLibraryDirectory(String uuid, String packageName, String nativeLibPath32,
int userId) throws InstallerException {
- mInstaller.execute("linklib", uuid, dataPath, nativeLibPath32, userId);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.linkNativeLibraryDirectory(uuid, packageName, nativeLibPath32, userId);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void createOatDir(String oatDir, String dexInstructionSet)
throws InstallerException {
- mInstaller.execute("createoatdir", oatDir, dexInstructionSet);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.createOatDir(oatDir, dexInstructionSet);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void linkFile(String relativePath, String fromBase, String toBase)
throws InstallerException {
- mInstaller.execute("linkfile", relativePath, fromBase, toBase);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.linkFile(relativePath, fromBase, toBase);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void moveAb(String apkPath, String instructionSet, String outputPath)
throws InstallerException {
- mInstaller.execute("move_ab", apkPath, instructionSet, outputPath);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.moveAb(apkPath, instructionSet, outputPath);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
public void deleteOdex(String apkPath, String instructionSet, String outputPath)
throws InstallerException {
- mInstaller.execute("delete_odex", apkPath, instructionSet, outputPath);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.deleteOdex(apkPath, instructionSet, outputPath);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw InstallerException.from(e);
+ }
}
private static void assertValidInstructionSet(String instructionSet)
@@ -244,4 +376,14 @@
}
throw new InstallerException("Invalid instruction set: " + instructionSet);
}
+
+ public static class InstallerException extends Exception {
+ public InstallerException(String detailMessage) {
+ super(detailMessage);
+ }
+
+ public static InstallerException from(Exception e) throws InstallerException {
+ throw new InstallerException(e.getMessage());
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index f777aae..bbd227e 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -16,11 +16,11 @@
package com.android.server.pm;
-import static com.android.server.pm.Installer.DEXOPT_OTA;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.IOtaDexopt;
import android.content.pm.PackageParser;
@@ -30,15 +30,17 @@
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.storage.StorageManager;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
+
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.os.InstallerConnection;
-import com.android.internal.os.InstallerConnection.InstallerException;
+import com.android.server.pm.Installer.InstallerException;
import java.io.File;
import java.io.FileDescriptor;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -277,9 +279,27 @@
*/
private synchronized List<String> generatePackageDexopts(PackageParser.Package pkg,
int compilationReason) {
- // Use our custom connection that just collects the commands.
- RecordingInstallerConnection collectingConnection = new RecordingInstallerConnection();
- Installer collectingInstaller = new Installer(mContext, collectingConnection);
+ // Intercept and collect dexopt requests
+ final List<String> commands = new ArrayList<String>();
+ final Installer collectingInstaller = new Installer(mContext, true) {
+ @Override
+ public void dexopt(String apkPath, int uid, @Nullable String pkgName,
+ String instructionSet, int dexoptNeeded, @Nullable String outputPath,
+ int dexFlags, String compilerFilter, @Nullable String volumeUuid,
+ @Nullable String sharedLibraries) throws InstallerException {
+ commands.add(buildCommand("dexopt",
+ apkPath,
+ uid,
+ pkgName,
+ instructionSet,
+ dexoptNeeded,
+ outputPath,
+ dexFlags,
+ compilerFilter,
+ volumeUuid,
+ sharedLibraries));
+ }
+ };
// Use the package manager install and install lock here for the OTA dex optimizer.
PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
@@ -296,7 +316,7 @@
getCompilerFilterForReason(compilationReason),
null /* CompilerStats.PackageStats */);
- return collectingConnection.commands;
+ return commands;
}
@Override
@@ -401,53 +421,33 @@
private static class OTADexoptPackageDexOptimizer extends
PackageDexOptimizer.ForcedUpdatePackageDexOptimizer {
-
public OTADexoptPackageDexOptimizer(Installer installer, Object installLock,
Context context) {
super(installer, installLock, context, "*otadexopt*");
}
-
- @Override
- protected int adjustDexoptFlags(int dexoptFlags) {
- // Add the OTA flag.
- return dexoptFlags | DEXOPT_OTA;
- }
-
}
- private static class RecordingInstallerConnection extends InstallerConnection {
- public List<String> commands = new ArrayList<String>(1);
-
- @Override
- public void setWarnIfHeld(Object warnIfHeld) {
- throw new IllegalStateException("Should not reach here");
+ /**
+ * Cook up argument list in the format that {@code installd} expects.
+ */
+ private static String buildCommand(Object... args) {
+ final StringBuilder builder = new StringBuilder();
+ for (Object arg : args) {
+ String escaped;
+ if (arg == null) {
+ escaped = "";
+ } else {
+ escaped = String.valueOf(arg);
+ }
+ if (escaped.indexOf('\0') != -1 || escaped.indexOf(' ') != -1 || "!".equals(escaped)) {
+ throw new IllegalArgumentException(
+ "Invalid argument while executing " + Arrays.toString(args));
+ }
+ if (TextUtils.isEmpty(escaped)) {
+ escaped = "!";
+ }
+ builder.append(' ').append(escaped);
}
-
- @Override
- public synchronized String transact(String cmd) {
- commands.add(cmd);
- return "0";
- }
-
- @Override
- public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
- throw new IllegalStateException("Should not reach here");
- }
-
- @Override
- public boolean dumpProfiles(String gid, String packageName, String codePaths)
- throws InstallerException {
- throw new IllegalStateException("Should not reach here");
- }
-
- @Override
- public void disconnect() {
- throw new IllegalStateException("Should not reach here");
- }
-
- @Override
- public void waitForConnection() {
- throw new IllegalStateException("Should not reach here");
- }
+ return builder.toString();
}
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index acdcc72..2e0199b 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -27,8 +27,8 @@
import android.util.Log;
import android.util.Slog;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.pm.Installer.InstallerException;
import java.io.File;
import java.io.IOException;
@@ -251,7 +251,7 @@
Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
+ pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
+ " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
- + " target-filter=" + targetCompilerFilter + " oatDir = " + oatDir
+ + " target-filter=" + targetCompilerFilter + " oatDir=" + oatDir
+ " sharedLibraries=" + sharedLibrariesPath);
// Profile guide compiled oat files should not be public.
final boolean isPublic = !pkg.isForwardLocked() && !isProfileGuidedFilter;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 2ece99f..c85e1d8 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -72,10 +72,10 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
+import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
import java.io.File;
diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java
index f243e63..0e3f173 100644
--- a/services/core/java/com/android/server/pm/PackageManagerException.java
+++ b/services/core/java/com/android/server/pm/PackageManagerException.java
@@ -19,7 +19,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageParser.PackageParserException;
-import com.android.internal.os.InstallerConnection.InstallerException;
+import com.android.server.pm.Installer.InstallerException;
/** {@hide} */
public class PackageManagerException extends Exception {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dc25ce4..ed405e9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -237,7 +237,6 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.IParcelFileDescriptorFactory;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.os.RoSystemProperties;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
@@ -257,6 +256,7 @@
import com.android.server.SystemConfig;
import com.android.server.Watchdog;
import com.android.server.net.NetworkPolicyManagerInternal;
+import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PermissionsState.PermissionState;
import com.android.server.pm.Settings.DatabaseVersion;
import com.android.server.pm.Settings.VersionInfo;
@@ -558,7 +558,8 @@
Manifest.permission.RECEIVE_WAP_PUSH,
Manifest.permission.RECEIVE_MMS,
Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.READ_PHONE_NUMBER);
final ServiceThread mHandlerThread;
@@ -2228,6 +2229,18 @@
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ // Clean up orphaned packages for which the code path doesn't exist
+ // and they are an update to a system app - caused by bug/32321269
+ final int packageSettingCount = mSettings.mPackages.size();
+ for (int i = packageSettingCount - 1; i >= 0; i--) {
+ PackageSetting ps = mSettings.mPackages.valueAt(i);
+ if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
+ && mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
+ mSettings.mPackages.removeAt(i);
+ mSettings.enableSystemPackageLPw(ps.name);
+ }
+ }
+
if (mFirstBoot) {
requestCopyPreoptedFiles();
}
@@ -2286,8 +2299,9 @@
getCompilerFilterForReason(REASON_SHARED_APK),
false /* newProfile */);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
- dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
+ mInstaller.dexopt(lib, Process.SYSTEM_UID, "*",
+ dexCodeInstructionSet, dexoptNeeded, null,
+ DEXOPT_PUBLIC,
getCompilerFilterForReason(REASON_SHARED_APK),
StorageManager.UUID_PRIVATE_INTERNAL,
SKIP_SHARED_LIBRARY_CHECK);
@@ -3208,8 +3222,12 @@
flags = updateFlagsForPackage(flags, userId, packageName);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */, "get package info");
+
// reader
synchronized (mPackages) {
+ // Normalize package name to hanlde renamed packages
+ packageName = normalizePackageNameLPr(packageName);
+
final boolean matchFactoryOnly = (flags & MATCH_FACTORY_ONLY) != 0;
PackageParser.Package p = null;
if (matchFactoryOnly) {
@@ -3412,8 +3430,12 @@
flags = updateFlagsForApplication(flags, userId, packageName);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */, "get application info");
+
// writer
synchronized (mPackages) {
+ // Normalize package name to hanlde renamed packages
+ packageName = normalizePackageNameLPr(packageName);
+
PackageParser.Package p = mPackages.get(packageName);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getApplicationInfo " + packageName
@@ -3435,6 +3457,11 @@
return null;
}
+ private String normalizePackageNameLPr(String packageName) {
+ String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName);
+ return normalizedPackageName != null ? normalizedPackageName : packageName;
+ }
+
@Override
public void freeStorageAndNotify(final String volumeUuid, final long freeStorageSize,
final IPackageDataObserver observer) {
@@ -7732,9 +7759,8 @@
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
try {
List<String> allCodePaths = pkg.getAllCodePathsExcludingResourceOnly();
- String gid = Integer.toString(sharedGid);
String codePaths = TextUtils.join(";", allCodePaths);
- mInstaller.dumpProfiles(gid, packageName, codePaths);
+ mInstaller.dumpProfiles(sharedGid, packageName, codePaths);
} catch (InstallerException e) {
Slog.w(TAG, "Failed to dump profiles", e);
}
@@ -9086,6 +9112,13 @@
PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
final String curPackageName = cur == null ? null : cur.info.packageName;
+ // Dont allow ephemeral apps to define new permission groups.
+ if (pkg.applicationInfo.isEphemeralApp()) {
+ Slog.w(TAG, "Permission group " + pg.info.name + " from package "
+ + pg.info.packageName
+ + " ignored: ephemeral apps cannot define new permission groups.");
+ continue;
+ }
final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName);
if (cur == null || isPackageUpdate) {
mPermissionGroups.put(pg.info.name, pg);
@@ -9124,6 +9157,14 @@
for (i=0; i<N; i++) {
PackageParser.Permission p = pkg.permissions.get(i);
+ // Dont allow ephemeral apps to define new permissions.
+ if (pkg.applicationInfo.isEphemeralApp()) {
+ Slog.w(TAG, "Permission " + p.info.name + " from package "
+ + p.info.packageName
+ + " ignored: ephemeral apps cannot define new permissions.");
+ continue;
+ }
+
// Assume by default that we did not install this permission into the system.
p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
@@ -20089,6 +20130,9 @@
private void assertPackageKnown(String volumeUuid, String packageName)
throws PackageManagerException {
synchronized (mPackages) {
+ // Normalize package name to handle renamed packages
+ packageName = normalizePackageNameLPr(packageName);
+
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null) {
throw new PackageManagerException("Package " + packageName + " is unknown");
@@ -20103,6 +20147,9 @@
private void assertPackageKnownAndInstalled(String volumeUuid, String packageName, int userId)
throws PackageManagerException {
synchronized (mPackages) {
+ // Normalize package name to handle renamed packages
+ packageName = normalizePackageNameLPr(packageName);
+
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null) {
throw new PackageManagerException("Package " + packageName + " is unknown");
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index fd2b504..2751742 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -51,9 +51,11 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.PrintWriterPrinter;
import com.android.internal.content.PackageHelper;
import com.android.internal.util.SizedInputStream;
+import com.android.server.SystemConfig;
import dalvik.system.DexFile;
@@ -135,6 +137,8 @@
return runSuspend(false);
case "set-home-activity":
return runSetHomeActivity();
+ case "get-privapp-permissions":
+ return runGetPrivappPermissions();
default:
return handleDefaultCommands(cmd);
}
@@ -1105,7 +1109,7 @@
sessionParams.abiOverride = checkAbiArgument(getNextArg());
break;
case "--ephemeral":
- sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL;
+ sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
break;
case "--user":
params.userId = UserHandle.parseUserArg(getNextArgRequired());
@@ -1164,6 +1168,18 @@
}
}
+ private int runGetPrivappPermissions() {
+ final String pkg = getNextArg();
+ if (pkg == null) {
+ System.err.println("Error: no package specified.");
+ return 1;
+ }
+ ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
+ getOutPrintWriter().println(privAppPermissions == null
+ ? "{}" : privAppPermissions.toString());
+ return 0;
+ }
+
private static String checkAbiArgument(String abi) {
if (TextUtils.isEmpty(abi)) {
throw new IllegalArgumentException("Missing ABI argument");
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index e330585..7187fc2 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -80,13 +80,13 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.XmlUtils;
import com.android.server.backup.PreferredActivityBackupHelper;
+import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PackageManagerService.DumpState;
import com.android.server.pm.PermissionsState.PermissionState;
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index d558b07..2eb0778 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -259,6 +259,11 @@
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
+ if (si.isFloating()) {
+ si.setRank(0);
+ si.setActivity(null);
+ }
+
if (si.isAlive()) continue;
if (removeList == null) {
@@ -288,6 +293,7 @@
si.setTimestamp(now);
si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
si.setRank(0); // It may still be pinned, so clear the rank.
+ si.setActivity(null);
}
}
if (changed) {
@@ -355,6 +361,7 @@
if (oldShortcut.isPinned()) {
oldShortcut.setRank(0);
+ oldShortcut.setActivity(null);
oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
if (disable) {
oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
@@ -595,6 +602,10 @@
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
+
+ if (si.isFloating()) {
+ continue; // Ignore floating shortcuts, which are not tied to any activities.
+ }
final ComponentName activity = si.getActivity();
if (checked.contains(activity)) {
@@ -1356,6 +1367,10 @@
case TAG_SHORTCUT:
final ShortcutInfo si = parseShortcut(parser, packageName,
shortcutUser.getUserId());
+ // Floating shortcut used to have target activities, but not anymore.
+ if (si.isFloating()) { // Not really needed by just in case.
+ si.setActivity(null);
+ }
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
@@ -1462,7 +1477,6 @@
intents.clear();
intents.add(intentLegacy);
}
-
return new ShortcutInfo(
userId, id, packageName, activityComponent, /* icon =*/ null,
title, titleResId, titleResName, text, textResId, textResName,
@@ -1553,12 +1567,17 @@
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " is both dynamic and manifest at the same time.");
}
- if (si.getActivity() == null) {
+ if (!si.isFloating() && si.getActivity() == null) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " has null activity.");
+ + " is not floating, but has null activity.");
}
- if ((si.isDynamic() || si.isManifestShortcut()) && !si.isEnabled()) {
+ if (si.isFloating() && si.getActivity() != null) {
+ failed = true;
+ Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ + " is floating, but has non-null activity.");
+ }
+ if (!si.isFloating() && !si.isEnabled()) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " is not floating, but is disabled.");
@@ -1581,7 +1600,7 @@
}
if (failed) {
- throw new IllegalStateException("See logcat for errors");
+ mShortcutUser.mService.verifyError();
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
index 4de15de..e5a2f5a 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
@@ -23,7 +23,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.backup.BackupUtils;
-import libcore.io.Base64;
import libcore.util.HexEncoding;
import org.xmlpull.v1.XmlPullParser;
@@ -33,6 +32,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Base64;
/**
* Package information used by {@link android.content.pm.ShortcutManager} for backup / restore.
@@ -161,7 +161,8 @@
for (int i = 0; i < mSigHashes.size(); i++) {
out.startTag(null, TAG_SIGNATURE);
- ShortcutService.writeAttr(out, ATTR_SIGNATURE_HASH, Base64.encode(mSigHashes.get(i)));
+ final String encoded = Base64.getEncoder().encodeToString(mSigHashes.get(i));
+ ShortcutService.writeAttr(out, ATTR_SIGNATURE_HASH, encoded);
out.endTag(null, TAG_SIGNATURE);
}
out.endTag(null, TAG_ROOT);
@@ -196,7 +197,9 @@
case TAG_SIGNATURE: {
final String hash = ShortcutService.parseStringAttribute(
parser, ATTR_SIGNATURE_HASH);
- hashes.add(Base64.decode(hash.getBytes()));
+ // Throws IllegalArgumentException if hash is invalid base64 data
+ final byte[] decoded = Base64.getDecoder().decode(hash);
+ hashes.add(decoded);
continue;
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 16f209b..c5c1c0c 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -124,6 +124,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -401,6 +402,9 @@
@VisibleForTesting
ShortcutService(Context context, Looper looper, boolean onlyForPackageManagerApis) {
+ if (DEBUG) {
+ Binder.LOG_RUNTIME_EXCEPTION = true;
+ }
mContext = Preconditions.checkNotNull(context);
LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
mHandler = new Handler(looper);
@@ -1604,7 +1608,7 @@
}
if (!forUpdate) {
- shortcut.enforceMandatoryFields();
+ shortcut.enforceMandatoryFields(/* forPinned= */ false);
Preconditions.checkArgument(
injectIsMainActivity(shortcut.getActivity(), shortcut.getUserId()),
"Cannot publish shortcut: " + shortcut.getActivity() + " is not main activity");
@@ -1752,6 +1756,9 @@
// Note copyNonNullFieldsFrom() does the "updatable with?" check too.
target.copyNonNullFieldsFrom(source);
+ if (target.isFloating()) {
+ target.setActivity(null);
+ }
target.setTimestamp(injectCurrentTimeMillis());
if (replacingIcon) {
@@ -2320,8 +2327,7 @@
return false;
}
if (componentName != null) {
- if (si.getActivity() != null
- && !si.getActivity().equals(componentName)) {
+ if (!Objects.equals(componentName, si.getActivity())) {
return false;
}
}
@@ -3771,4 +3777,8 @@
forEachLoadedUserLocked(u -> u.forAllPackageItems(ShortcutPackageItem::verifyStates));
}
}
+
+ void verifyError() {
+ Slog.e(TAG, "See logcat for errors");
+ }
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index c4241e7..bac7a76 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -913,17 +913,36 @@
@Override
public boolean isUserUnlockingOrUnlocked(int userId) {
- int callingUserId = UserHandle.getCallingUserId();
- if (callingUserId != userId && !hasManageUsersPermission()) {
- if (!isSameProfileGroupNoChecks(callingUserId, userId)) {
- throw new SecurityException(
- "You need MANAGE_USERS permission to: check isUserUnlockingOrUnlocked");
- }
- }
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserUnlockingOrUnlocked");
return mLocalService.isUserUnlockingOrUnlocked(userId);
}
@Override
+ public boolean isUserUnlocked(int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserUnlocked");
+ return mLocalService.isUserUnlockingOrUnlocked(userId);
+ }
+
+ @Override
+ public boolean isUserRunning(int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserRunning");
+ return mLocalService.isUserRunning(userId);
+ }
+
+ private void checkManageOrInteractPermIfCallerInOtherProfileGroup(int userId, String name) {
+ int callingUserId = UserHandle.getCallingUserId();
+ if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId) ||
+ hasManageUsersPermission()) {
+ return;
+ }
+ if (ActivityManager.checkComponentPermission(Manifest.permission.INTERACT_ACROSS_USERS,
+ Binder.getCallingUid(), -1, true) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("You need INTERACT_ACROSS_USERS or MANAGE_USERS permission "
+ + "to: check " + name);
+ }
+ }
+
+ @Override
public boolean isDemoUser(int userId) {
int callingUserId = UserHandle.getCallingUserId();
if (callingUserId != userId && !hasManageUsersPermission()) {
@@ -3641,6 +3660,14 @@
|| (state == UserState.STATE_RUNNING_UNLOCKED);
}
}
+
+ @Override
+ public boolean isUserUnlocked(int userId) {
+ synchronized (mUserStates) {
+ int state = mUserStates.get(userId, -1);
+ return state == UserState.STATE_RUNNING_UNLOCKED;
+ }
+ }
}
/* Remove all the users except of the system one. */
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 9fe0922..7ec3c19 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -71,6 +71,7 @@
UserManager.DISALLOW_SHARE_LOCATION,
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
UserManager.DISALLOW_CONFIG_BLUETOOTH,
+ UserManager.DISALLOW_BLUETOOTH,
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_CREDENTIALS,
UserManager.DISALLOW_REMOVE_USER,
@@ -117,6 +118,7 @@
* User restrictions that can not be set by profile owners.
*/
private static final Set<String> DEVICE_OWNER_ONLY_RESTRICTIONS = Sets.newArraySet(
+ UserManager.DISALLOW_BLUETOOTH,
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_TETHERING,
UserManager.DISALLOW_NETWORK_RESET,
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index a1cce2b..afad328 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -265,7 +265,6 @@
static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
static final int SHORT_PRESS_POWER_GO_HOME = 4;
- static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5;
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
@@ -1346,14 +1345,6 @@
case SHORT_PRESS_POWER_GO_HOME:
launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
break;
- case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME:
- if (mWindowManagerFuncs.isInputMethodWindowVisible()) {
- mWindowManagerFuncs.hideCurrentInputMethod();
- } else {
- launchHomeFromHotKey(true /* awakenFromDreams */,
- false /*respectKeyguard*/);
- }
- break;
}
}
}
@@ -7609,6 +7600,32 @@
return vis;
}
+ private int updateLightNavigationBarLw(int vis, WindowState opaque,
+ WindowState opaqueOrDimming) {
+ final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
+
+ final WindowState navColorWin;
+ if (imeWin != null && imeWin.isVisibleLw()) {
+ navColorWin = imeWin;
+ } else {
+ navColorWin = opaqueOrDimming;
+ }
+
+ if (navColorWin != null) {
+ if (navColorWin == opaque) {
+ // If the top fullscreen-or-dimming window is also the top fullscreen, respect
+ // its light flag.
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
+ & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ } else if (navColorWin.isDimming() || navColorWin == imeWin) {
+ // Otherwise if it's dimming or it's the IME window, clear the light flag.
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ }
+ }
+ return vis;
+ }
+
private boolean drawsSystemBarBackground(WindowState win) {
return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
}
@@ -7739,6 +7756,9 @@
vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
+ vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
+ mTopFullscreenOpaqueOrDimmingWindowState);
+
return vis;
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 9d02940..cca8cc8 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -169,7 +169,7 @@
CharSequence label;
Drawable icon;
ComponentName component; // service that implements ITrustAgent
- ComponentName settings; // setting to launch to modify agent.
+ SettingsAttrs settings; // setting to launch to modify agent.
TrustAgentWrapper agent;
int userId;
@@ -258,11 +258,6 @@
+ ": switchToByUser=false");
continue;
}
- if (!StorageManager.isUserKeyUnlocked(userInfo.id)) {
- if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
- + ": FDE still locked");
- continue;
- }
if (!mActivityManager.isUserRunning(userInfo.id)) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ ": user not started");
@@ -273,13 +268,7 @@
+ ": no secure credential");
continue;
}
- if (!mStrongAuthTracker.canAgentsRunForUser(userInfo.id)) {
- if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
- + ": prevented by StrongAuthTracker = 0x"
- + Integer.toHexString(mStrongAuthTracker.getStrongAuthForUser(
- userInfo.id)));
- continue;
- }
+
DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
final boolean disableTrustAgents =
@@ -312,16 +301,49 @@
continue;
}
}
-
AgentInfo agentInfo = new AgentInfo();
agentInfo.component = name;
agentInfo.userId = userInfo.id;
if (!mActiveAgents.contains(agentInfo)) {
agentInfo.label = resolveInfo.loadLabel(pm);
agentInfo.icon = resolveInfo.loadIcon(pm);
- agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
+ agentInfo.settings = getSettingsAttrs(pm, resolveInfo);
agentInfo.agent = new TrustAgentWrapper(mContext, this,
new Intent().setComponent(name), userInfo.getUserHandle());
+ } else {
+ int index = mActiveAgents.indexOf(agentInfo);
+ agentInfo = mActiveAgents.valueAt(index);
+ }
+
+ boolean directUnlock = resolveInfo.serviceInfo.directBootAware
+ && agentInfo.settings.canUnlockProfile;
+
+ if (directUnlock) {
+ if (DEBUG) Slog.d(TAG, "refreshAgentList: trustagent " + name
+ + "of user " + userInfo.id + "can unlock user profile.");
+ }
+
+ if (!StorageManager.isUserKeyUnlocked(userInfo.id)
+ && !directUnlock) {
+ if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ + "'s trust agent " + name + ": FDE still locked and "
+ + " the agent cannot unlock user profile.");
+ continue;
+ }
+
+ if (!mStrongAuthTracker.canAgentsRunForUser(userInfo.id)) {
+ int flag = mStrongAuthTracker.getStrongAuthForUser(userInfo.id);
+ if (flag != StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
+ || !directUnlock) {
+ if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ + ": prevented by StrongAuthTracker = 0x"
+ + Integer.toHexString(mStrongAuthTracker.getStrongAuthForUser(
+ userInfo.id)));
+ continue;
+ }
+ }
+
+ if (!mActiveAgents.contains(agentInfo)) {
mActiveAgents.add(agentInfo);
} else {
obsoleteAgents.remove(agentInfo);
@@ -468,10 +490,12 @@
refreshAgentList(userId);
}
- private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
+ private SettingsAttrs getSettingsAttrs(PackageManager pm, ResolveInfo resolveInfo) {
if (resolveInfo == null || resolveInfo.serviceInfo == null
|| resolveInfo.serviceInfo.metaData == null) return null;
String cn = null;
+ boolean canUnlockProfile = false;
+
XmlResourceParser parser = null;
Exception caughtException = null;
try {
@@ -496,6 +520,8 @@
TypedArray sa = res
.obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
+ canUnlockProfile = sa.getBoolean(
+ com.android.internal.R.styleable.TrustAgent_unlockProfile, false);
sa.recycle();
} catch (PackageManager.NameNotFoundException e) {
caughtException = e;
@@ -516,7 +542,7 @@
if (cn.indexOf('/') < 0) {
cn = resolveInfo.serviceInfo.packageName + "/" + cn;
}
- return ComponentName.unflattenFromString(cn);
+ return new SettingsAttrs(ComponentName.unflattenFromString(cn), canUnlockProfile);
}
private ComponentName getComponentName(ResolveInfo resolveInfo) {
@@ -554,6 +580,7 @@
private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
+ PackageManager.GET_META_DATA |
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
userId);
ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
@@ -991,6 +1018,18 @@
}
};
+ private static class SettingsAttrs {
+ public ComponentName componentName;
+ public boolean canUnlockProfile;
+
+ public SettingsAttrs(
+ ComponentName componentName,
+ boolean canUnlockProfile) {
+ this.componentName = componentName;
+ this.canUnlockProfile = canUnlockProfile;
+ }
+ };
+
private class Receiver extends BroadcastReceiver {
@Override
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index db7df25..bb4d67e 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -59,17 +59,17 @@
private final Handler mHandler;
- private AlarmManager mAlarmManager;
+ protected AlarmManager mAlarmManager;
private LocationManager mLocationManager;
private boolean mBootCompleted;
private boolean mHasListeners;
private BroadcastReceiver mTimeChangedReceiver;
- private Location mLastLocation;
+ protected Location mLastLocation;
@GuardedBy("mListeners")
- private TwilightState mLastTwilightState;
+ protected TwilightState mLastTwilightState;
public TwilightService(Context context) {
super(context);
@@ -247,7 +247,11 @@
@Override
public void onLocationChanged(Location location) {
- if (location != null) {
+ // Location providers may erroneously return (0.0, 0.0) when they fail to determine the
+ // device's location. These location updates can be safely ignored since the chance of a
+ // user actually being at these coordinates is quite low.
+ if (location != null
+ && !(location.getLongitude() == 0.0 && location.getLatitude() == 0.0)) {
Slog.d(TAG, "onLocationChanged:"
+ " provider=" + location.getProvider()
+ " accuracy=" + location.getAccuracy()
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index e1b598a..c42647e 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -411,7 +411,7 @@
}
if (mService.mInputMethodTarget != null
&& mService.mInputMethodTarget.mAppToken == mAppToken) {
- mAppToken.getDisplayContent().moveInputMethodWindowsIfNeeded(true);
+ mAppToken.getDisplayContent().computeImeTarget(true /* updateImeTarget */);
}
if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + mAppToken
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 5838a37..00c37d2 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -42,7 +42,6 @@
import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.logWithStack;
@@ -62,12 +61,10 @@
import android.view.IApplicationToken;
import android.view.View;
import android.view.WindowManager;
-import android.view.animation.Animation;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.function.Function;
class AppTokenList extends ArrayList<AppWindowToken> {
}
@@ -390,10 +387,10 @@
@Override
void removeIfPossible() {
mIsExiting = false;
- removeAllWindows();
+ removeAllWindowsIfPossible();
if (mTask != null) {
mTask.mStack.mExitingAppTokens.remove(this);
- mTask.removeChild(this);
+ removeImmediately();
}
}
@@ -1006,10 +1003,7 @@
tStartingWindow.mToken = this;
tStartingWindow.mAppToken = this;
- if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
- "Removing starting window: " + tStartingWindow);
- getDisplayContent().removeFromWindowList(tStartingWindow);
- if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+ if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
"Removing starting " + tStartingWindow + " from " + fromToken);
fromToken.removeChild(tStartingWindow);
fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
@@ -1259,23 +1253,12 @@
mService.mAnimator.mAppWindowAnimating = true;
} else if (mAppAnimator.wasAnimating) {
// stopped animating, do one more pass through the layout
- setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER, "appToken " + this + " done");
+ setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
+ DEBUG_LAYOUT_REPEATS ? "appToken " + this + " done" : null);
if (DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating " + this);
}
}
- int rebuildWindowListUnchecked(int addIndex) {
- return super.rebuildWindowList(addIndex);
- }
-
- @Override
- int rebuildWindowList(int addIndex) {
- if (mIsExiting && !waitingForReplacement()) {
- return addIndex;
- }
- return rebuildWindowListUnchecked(addIndex);
- }
-
@Override
boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
// For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
@@ -1337,6 +1320,32 @@
mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
}
+ WindowState getImeTargetBelowWindow(WindowState w) {
+ final int index = mChildren.indexOf(w);
+ if (index > 0) {
+ final WindowState target = mChildren.get(index - 1);
+ if (target.canBeImeTarget()) {
+ return target;
+ }
+ }
+ return null;
+ }
+
+ WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
+ WindowState candidate = null;
+ for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
+ final WindowState w = mChildren.get(i);
+ if (w.mRemoved) {
+ continue;
+ }
+ if (candidate == null || w.mWinAnimator.mAnimLayer >
+ candidate.mWinAnimator.mAnimLayer) {
+ candidate = w;
+ }
+ }
+ return candidate;
+ }
+
@Override
void dump(PrintWriter pw, String prefix) {
super.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e73acde..203137d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -33,10 +33,6 @@
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
-import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
-import static android.view.WindowManager.INPUT_CONSUMER_PIP;
-import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -44,13 +40,10 @@
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -64,7 +57,6 @@
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
@@ -77,10 +69,8 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -94,7 +84,6 @@
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
import static com.android.server.wm.WindowManagerService.dipToPixel;
-import static com.android.server.wm.WindowManagerService.localLOGV;
import static com.android.server.wm.WindowManagerService.logSurface;
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
@@ -120,29 +109,23 @@
import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.IWindow;
-import android.view.InputChannel;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowManagerPolicy;
-import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.view.IInputMethodClient;
-import com.android.server.input.InputWindowHandle;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.io.StringWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
-import java.util.function.Function;
+import java.util.function.Predicate;
/**
* Utility class for keeping track of the WindowStates and other pertinent contents of a
@@ -174,8 +157,12 @@
private final NonAppWindowContainers mImeWindowsContainers =
new NonAppWindowContainers("mImeWindowsContainers");
- // Z-ordered (bottom-most first) list of all Window objects.
- private final WindowList mWindows = new WindowList();
+ private WindowState mTmpWindow;
+ private WindowState mTmpWindow2;
+ private WindowAnimator mTmpWindowAnimator;
+ private boolean mTmpRecoveringMemory;
+ private boolean mUpdateImeTarget;
+ private boolean mTmpInitial;
// Mapping from a token IBinder to a WindowToken object on this display.
private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
@@ -198,7 +185,7 @@
private boolean mLayoutNeeded;
int pendingLayoutChanges;
// TODO(multi-display): remove some of the usages.
- final boolean isDefaultDisplay;
+ boolean isDefaultDisplay;
/** Window tokens that are in the process of exiting, but still on screen for animations. */
final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
@@ -220,7 +207,7 @@
private final Matrix mTmpMatrix = new Matrix();
private final Region mTmpRegion = new Region();
- final WindowManagerService mService;
+ WindowManagerService mService;
/** Remove this display when animation on it has completed. */
private boolean mDeferredRemoval;
@@ -228,34 +215,413 @@
final DockedStackDividerController mDividerControllerLocked;
final PinnedStackController mPinnedStackControllerLocked;
- final DimLayerController mDimLayerController;
+ DimLayerController mDimLayerController;
final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
- /** Used when rebuilding window list to keep track of windows that have been removed. */
- private WindowState[] mRebuildTmp = new WindowState[20];
-
- /**
- * Temporary list for comparison. Always clear this after use so we don't end up with
- * orphaned windows references
- */
- private final ArrayList<WindowState> mTmpWindows = new ArrayList<>();
+ private boolean mHaveBootMsg = false;
+ private boolean mHaveApp = false;
+ private boolean mHaveWallpaper = false;
+ private boolean mHaveKeyguard = true;
private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
new TaskForResizePointSearchResult();
- private final GetWindowOnDisplaySearchResult mTmpGetWindowOnDisplaySearchResult =
- new GetWindowOnDisplaySearchResult();
+ private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState =
+ new ApplySurfaceChangesTransactionState();
+ private final ScreenshotApplicationState mScreenshotApplicationState =
+ new ScreenshotApplicationState();
// True if this display is in the process of being removed. Used to determine if the removal of
// the display's direct children should be allowed.
private boolean mRemovingDisplay = false;
private final WindowLayersController mLayersController;
- final WallpaperController mWallpaperController;
+ WallpaperController mWallpaperController;
int mInputMethodAnimLayerAdjustment;
+ private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
+ WindowStateAnimator winAnimator = w.mWinAnimator;
+ if (winAnimator.hasSurface()) {
+ final boolean wasAnimating = winAnimator.mWasAnimating;
+ final boolean nowAnimating = winAnimator.stepAnimationLocked(
+ mTmpWindowAnimator.mCurrentTime);
+ winAnimator.mWasAnimating = nowAnimating;
+ mTmpWindowAnimator.orAnimating(nowAnimating);
+
+ if (DEBUG_WALLPAPER) Slog.v(TAG,
+ w + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
+
+ if (wasAnimating && !winAnimator.mAnimating
+ && mWallpaperController.isWallpaperTarget(w)) {
+ mTmpWindowAnimator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
+ pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ if (DEBUG_LAYOUT_REPEATS) {
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
+ }
+ }
+ }
+
+ final AppWindowToken atoken = w.mAppToken;
+ if (winAnimator.mDrawState == READY_TO_SHOW) {
+ if (atoken == null || atoken.allDrawn) {
+ if (w.performShowLocked()) {
+ pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
+ if (DEBUG_LAYOUT_REPEATS) {
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
+ }
+ }
+ }
+ }
+ final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
+ if (appAnimator != null && appAnimator.thumbnail != null) {
+ if (appAnimator.thumbnailTransactionSeq
+ != mTmpWindowAnimator.mAnimTransactionSequence) {
+ appAnimator.thumbnailTransactionSeq =
+ mTmpWindowAnimator.mAnimTransactionSequence;
+ appAnimator.thumbnailLayer = 0;
+ }
+ if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
+ appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
+ }
+ }
+ };
+
+ private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> {
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
+ if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
+ return;
+ }
+
+ final int flags = w.mAttrs.flags;
+
+ // If this window is animating, make a note that we have an animating window and take
+ // care of a request to run a detached wallpaper animation.
+ if (winAnimator.mAnimating) {
+ if (winAnimator.mAnimation != null) {
+ if ((flags & FLAG_SHOW_WALLPAPER) != 0
+ && winAnimator.mAnimation.getDetachWallpaper()) {
+ mTmpWindow = w;
+ }
+ final int color = winAnimator.mAnimation.getBackgroundColor();
+ if (color != 0) {
+ final TaskStack stack = w.getStack();
+ if (stack != null) {
+ stack.setAnimationBackground(winAnimator, color);
+ }
+ }
+ }
+ mTmpWindowAnimator.setAnimating(true);
+ }
+
+ // If this window's app token is running a detached wallpaper animation, make a note so
+ // we can ensure the wallpaper is displayed behind it.
+ final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
+ if (appAnimator != null && appAnimator.animation != null
+ && appAnimator.animating) {
+ if ((flags & FLAG_SHOW_WALLPAPER) != 0
+ && appAnimator.animation.getDetachWallpaper()) {
+ mTmpWindow = w;
+ }
+
+ final int color = appAnimator.animation.getBackgroundColor();
+ if (color != 0) {
+ final TaskStack stack = w.getStack();
+ if (stack != null) {
+ stack.setAnimationBackground(winAnimator, color);
+ }
+ }
+ }
+ };
+
+ private final Consumer<WindowState> mSetInputMethodAnimLayerAdjustment =
+ w -> w.adjustAnimLayer(mInputMethodAnimLayerAdjustment);
+
+ private final Consumer<WindowState> mScheduleToastTimeout = w -> {
+ final int lostFocusUid = mTmpWindow.mOwnerUid;
+ final Handler handler = mService.mH;
+ if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) {
+ if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) {
+ handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w),
+ w.mAttrs.hideTimeoutMilliseconds);
+ }
+ }
+ };
+
+ private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
+ final AppWindowToken focusedApp = mService.mFocusedApp;
+ if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w
+ + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys());
+
+ if (!w.canReceiveKeys()) {
+ return false;
+ }
+
+ final AppWindowToken wtoken = w.mAppToken;
+
+ // If this window's application has been removed, just skip it.
+ if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
+ if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
+ + (wtoken.removed ? "removed" : "sendingToBottom"));
+ return false;
+ }
+
+ if (focusedApp == null) {
+ if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
+ + " using new focus @ " + w);
+ mTmpWindow = w;
+ return true;
+ }
+
+ if (!focusedApp.windowsAreFocusable()) {
+ // Current focused app windows aren't focusable...
+ if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
+ + " focusable using new focus @ " + w);
+ mTmpWindow = w;
+ return true;
+ }
+
+ // Descend through all of the app tokens and find the first that either matches
+ // win.mAppToken (return win) or mFocusedApp (return null).
+ if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
+ if (focusedApp.compareTo(wtoken) > 0) {
+ // App stack below focused app stack. No focus for you!!!
+ if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
+ "findFocusedWindow: Reached focused app=" + focusedApp);
+ mTmpWindow = null;
+ return true;
+ }
+ }
+
+ if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w);
+ mTmpWindow = w;
+ return true;
+ };
+
+ private final Consumer<WindowState> mPrepareWindowSurfaces =
+ w -> w.mWinAnimator.prepareSurfaceLocked(true);
+
+ private final Consumer<WindowState> mPerformLayout = w -> {
+ // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
+ // wasting time and funky changes while a window is animating away.
+ final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w))
+ || w.isGoneForLayoutLw();
+
+ if (DEBUG_LAYOUT && !w.mLayoutAttached) {
+ Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
+ + " mLayoutAttached=" + w.mLayoutAttached
+ + " screen changed=" + w.isConfigChanged());
+ final AppWindowToken atoken = w.mAppToken;
+ if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility
+ + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
+ + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
+ + " parentHidden=" + w.isParentWindowHidden());
+ else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility
+ + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
+ + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
+ + " parentHidden=" + w.isParentWindowHidden());
+ }
+
+ // If this view is GONE, then skip it -- keep the current frame, and let the caller know
+ // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows,
+ // since that means "perform layout as normal, just don't display").
+ if (!gone || !w.mHaveFrame || w.mLayoutNeeded
+ || ((w.isConfigChanged() || w.setReportResizeHints())
+ && !w.isGoneForLayoutLw() &&
+ ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
+ (w.mHasSurface && w.mAppToken != null &&
+ w.mAppToken.layoutConfigChanges)))) {
+ if (!w.mLayoutAttached) {
+ if (mTmpInitial) {
+ //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
+ w.mContentChanged = false;
+ }
+ if (w.mAttrs.type == TYPE_DREAM) {
+ // Don't layout windows behind a dream, so that if it does stuff like hide
+ // the status bar we won't get a bad transition when it goes away.
+ mTmpWindow = w;
+ }
+ w.mLayoutNeeded = false;
+ w.prelayout();
+ mService.mPolicy.layoutWindowLw(w, null);
+ w.mLayoutSeq = mService.mLayoutSeq;
+
+ // Window frames may have changed. Update dim layer with the new bounds.
+ final Task task = w.getTask();
+ if (task != null) {
+ mDimLayerController.updateDimLayer(task);
+ }
+
+ if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame
+ + " mContainingFrame=" + w.mContainingFrame
+ + " mDisplayFrame=" + w.mDisplayFrame);
+ }
+ }
+ };
+
+ private final Consumer<WindowState> mPerformLayoutAttached = w -> {
+ if (w.mLayoutAttached) {
+ if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
+ + " mViewVisibility=" + w.mViewVisibility
+ + " mRelayoutCalled=" + w.mRelayoutCalled);
+ // If this view is GONE, then skip it -- keep the current frame, and let the caller
+ // know so they can ignore it if they want. (We do the normal layout for INVISIBLE
+ // windows, since that means "perform layout as normal, just don't display").
+ if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) {
+ return;
+ }
+ if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
+ || w.mLayoutNeeded) {
+ if (mTmpInitial) {
+ //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
+ w.mContentChanged = false;
+ }
+ w.mLayoutNeeded = false;
+ w.prelayout();
+ mService.mPolicy.layoutWindowLw(w, w.getParentWindow());
+ w.mLayoutSeq = mService.mLayoutSeq;
+ if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame
+ + " mContainingFrame=" + w.mContainingFrame
+ + " mDisplayFrame=" + w.mDisplayFrame);
+ }
+ } else if (w.mAttrs.type == TYPE_DREAM) {
+ // Don't layout windows behind a dream, so that if it does stuff like hide the
+ // status bar we won't get a bad transition when it goes away.
+ mTmpWindow = mTmpWindow2;
+ }
+ };
+
+ private final Predicate<WindowState> mComputeImeTargetPredicate = w -> {
+ if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w
+ + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
+ return w.canBeImeTarget();
+ };
+
+ private final Consumer<WindowState> mApplyPostLayoutPolicy =
+ w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
+ mService.mInputMethodTarget);
+
+ private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
+ final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
+ final boolean obscuredChanged = w.mObscured !=
+ mTmpApplySurfaceChangesTransactionState.obscured;
+ final RootWindowContainer root = mService.mRoot;
+ // Only used if default window
+ final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
+
+ // Update effect.
+ w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
+ if (!mTmpApplySurfaceChangesTransactionState.obscured) {
+ final boolean isDisplayed = w.isDisplayedLw();
+
+ if (isDisplayed && w.isObscuringDisplay()) {
+ // This window completely covers everything behind it, so we want to leave all
+ // of them as undimmed (for performance reasons).
+ root.mObscuringWindow = w;
+ mTmpApplySurfaceChangesTransactionState.obscured = true;
+ }
+
+ mTmpApplySurfaceChangesTransactionState.displayHasContent |=
+ root.handleNotObscuredLocked(w,
+ mTmpApplySurfaceChangesTransactionState.obscured,
+ mTmpApplySurfaceChangesTransactionState.syswin);
+
+ if (w.mHasSurface && isDisplayed) {
+ final int type = w.mAttrs.type;
+ if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
+ || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+ mTmpApplySurfaceChangesTransactionState.syswin = true;
+ }
+ if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
+ && w.mAttrs.preferredRefreshRate != 0) {
+ mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
+ = w.mAttrs.preferredRefreshRate;
+ }
+ if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
+ && w.mAttrs.preferredDisplayModeId != 0) {
+ mTmpApplySurfaceChangesTransactionState.preferredModeId
+ = w.mAttrs.preferredDisplayModeId;
+ }
+ }
+ }
+
+ w.applyDimLayerIfNeeded();
+
+ if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
+ && mWallpaperController.isWallpaperTarget(w)) {
+ // This is the wallpaper target and its obscured state changed... make sure the
+ // current wallpaper's visibility has been updated accordingly.
+ mWallpaperController.updateWallpaperVisibility();
+ }
+
+ w.handleWindowMovedIfNeeded();
+
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
+
+ //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
+ w.mContentChanged = false;
+
+ // Moved from updateWindowsAndWallpaperLocked().
+ if (w.mHasSurface) {
+ // Take care of the window being ready to display.
+ final boolean committed = winAnimator.commitFinishDrawingLocked();
+ if (isDefaultDisplay && committed) {
+ if (w.mAttrs.type == TYPE_DREAM) {
+ // HACK: When a dream is shown, it may at that point hide the lock screen.
+ // So we need to redo the layout to let the phone window manager make this
+ // happen.
+ pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
+ if (DEBUG_LAYOUT_REPEATS) {
+ surfacePlacer.debugLayoutRepeats(
+ "dream and commitFinishDrawingLocked true",
+ pendingLayoutChanges);
+ }
+ }
+ if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "First draw done in potential wallpaper target " + w);
+ root.mWallpaperMayChange = true;
+ pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ if (DEBUG_LAYOUT_REPEATS) {
+ surfacePlacer.debugLayoutRepeats(
+ "wallpaper and commitFinishDrawingLocked true",
+ pendingLayoutChanges);
+ }
+ }
+ }
+ if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
+ // Updates the shown frame before we set up the surface. This is needed
+ // because the resizing could change the top-left position (in addition to
+ // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
+ // position the surface.
+ //
+ // If an animation is being started, we can't call this method because the
+ // animation hasn't processed its initial transformation yet, but in general
+ // we do want to update the position if the window is animating.
+ winAnimator.computeShownFrameLocked();
+ }
+ winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */);
+ }
+
+ final AppWindowToken atoken = w.mAppToken;
+ if (atoken != null) {
+ final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
+ if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
+ mTmpUpdateAllDrawn.add(atoken);
+ }
+ }
+
+ if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
+ && w.isDisplayedLw()) {
+ mTmpApplySurfaceChangesTransactionState.focusDisplayed = true;
+ }
+
+ w.updateResizingWindowIfNeeded();
+ };
+
/**
* @param display May not be null.
* @param service You know.
@@ -302,7 +668,7 @@
return token.asAppWindowToken();
}
- void setWindowToken(IBinder binder, WindowToken token) {
+ void addWindowToken(IBinder binder, WindowToken token) {
final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
if (dc != null) {
// We currently don't support adding a window token to the display if the display
@@ -335,20 +701,33 @@
WindowToken removeWindowToken(IBinder binder) {
final WindowToken token = mTokenMap.remove(binder);
if (token != null && token.asAppWindowToken() == null) {
+ token.setExiting();
+ }
+ return token;
+ }
+
+ /** Changes the display the input window token is housed on to this one. */
+ void reParentWindowToken(WindowToken token) {
+ final DisplayContent prevDc = token.getDisplayContent();
+ if (prevDc == this) {
+ return;
+ }
+ if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null) {
switch (token.windowType) {
case TYPE_WALLPAPER:
- mBelowAppWindowsContainers.removeChild(token);
+ prevDc.mBelowAppWindowsContainers.removeChild(token);
break;
case TYPE_INPUT_METHOD:
case TYPE_INPUT_METHOD_DIALOG:
- mImeWindowsContainers.removeChild(token);
+ prevDc.mImeWindowsContainers.removeChild(token);
break;
default:
- mAboveAppWindowsContainers.removeChild(token);
+ prevDc.mAboveAppWindowsContainers.removeChild(token);
break;
}
}
- return token;
+
+ addWindowToken(token.token, token);
}
void removeAppToken(IBinder binder) {
@@ -455,17 +834,50 @@
@Override
void onAppTransitionDone() {
super.onAppTransitionDone();
- rebuildAppWindowList();
+ mService.mWindowsChanged = true;
+ }
+
+ @Override
+ boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
+ // Special handling so we can process IME windows with #forAllImeWindows above their IME
+ // target, or here in order if there isn't an IME target.
+ if (traverseTopToBottom) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final DisplayChildWindowContainer child = mChildren.get(i);
+ if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
+ // In this case the Ime windows will be processed above their target so we skip
+ // here.
+ continue;
+ }
+ if (child.forAllWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ }
+ } else {
+ final int count = mChildren.size();
+ for (int i = 0; i < count; i++) {
+ final DisplayChildWindowContainer child = mChildren.get(i);
+ if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
+ // In this case the Ime windows will be processed above their target so we skip
+ // here.
+ continue;
+ }
+ if (child.forAllWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
+ return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
}
@Override
int getOrientation() {
final WindowManagerPolicy policy = mService.mPolicy;
- // TODO: All the logic before the last return statement in this method should really go in
- // #NonAppWindowContainer.getOrientation() since it is trying to decide orientation based
- // on non-app windows. But, we can not do that until the window list is always correct in
- // terms of z-ordering based on layers.
if (mService.mDisplayFrozen) {
if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
@@ -486,31 +898,9 @@
return mService.mLastOrientation;
}
} else {
- for (int pos = mWindows.size() - 1; pos >= 0; --pos) {
- final WindowState win = mWindows.get(pos);
- if (win.mAppToken != null) {
- // We hit an application window. so the orientation will be determined by the
- // app window. No point in continuing further.
- break;
- }
- if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
- continue;
- }
- int req = win.mAttrs.screenOrientation;
- if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) {
- continue;
- }
-
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
- if (policy.isKeyguardHostWindow(win.mAttrs)) {
- mService.mLastKeyguardForcedOrientation = req;
- }
- return (mService.mLastWindowForcedOrientation = req);
- }
- mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
-
- if (policy.isKeyguardShowingAndNotOccluded()) {
- return mService.mLastKeyguardForcedOrientation;
+ final int orientation = mAboveAppWindowsContainers.getOrientation();
+ if (orientation != SCREEN_ORIENTATION_UNSET) {
+ return orientation;
}
}
@@ -738,22 +1128,10 @@
}
}
+ @Override
void switchUser() {
- final int count = mWindows.size();
- for (int i = 0; i < count; i++) {
- final WindowState win = mWindows.get(i);
- if (win.isHiddenFromUserLocked()) {
- if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win
- + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid);
- win.hideLw(false);
- }
- }
-
- for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
- mTaskStackContainers.get(stackNdx).switchUser();
- }
-
- rebuildAppWindowList();
+ super.switchUser();
+ mService.mWindowsChanged = true;
}
private void resetAnimationBackgroundAnimator() {
@@ -915,19 +1293,8 @@
void setInputMethodAnimLayerAdjustment(int adj) {
if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
mInputMethodAnimLayerAdjustment = adj;
- final WindowState imw = mService.mInputMethodWindow;
- if (imw != null) {
- imw.adjustAnimLayer(adj);
- }
- for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) {
- final WindowState dialog = mService.mInputMethodDialogs.get(i);
- // TODO: This and other places setting mAnimLayer can probably use WS.adjustAnimLayer,
- // but need to make sure we are not setting things twice for child windows that are
- // already in the list.
- dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj;
- if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw
- + " anim layer: " + dialog.mWinAnimator.mAnimLayer);
- }
+ mImeWindowsContainers.forAllWindows(mSetInputMethodAnimLayerAdjustment,
+ true /* traverseTopToBottom */);
}
/**
@@ -936,11 +1303,11 @@
* suddenly disappear.
*/
int getLayerForAnimationBackground(WindowStateAnimator winAnimator) {
- for (int i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState win = mWindows.get(i);
- if (win.mIsWallpaper && win.isVisibleNow()) {
- return win.mWinAnimator.mAnimLayer;
- }
+ final WindowState visibleWallpaper = mBelowAppWindowsContainers.getWindow(
+ w -> w.mIsWallpaper && w.isVisibleNow());
+
+ if (visibleWallpaper != null) {
+ return visibleWallpaper.mWinAnimator.mAnimLayer;
}
return winAnimator.mAnimLayer;
}
@@ -1088,317 +1455,60 @@
/** Find the visible, touch-deliverable window under the given point */
WindowState getTouchableWinAtPointLocked(float xf, float yf) {
- WindowState touchedWin = null;
final int x = (int) xf;
final int y = (int) yf;
-
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- WindowState window = mWindows.get(i);
- final int flags = window.mAttrs.flags;
- if (!window.isVisibleLw()) {
- continue;
+ final WindowState touchedWin = getWindow(w -> {
+ final int flags = w.mAttrs.flags;
+ if (!w.isVisibleLw()) {
+ return false;
}
if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
- continue;
+ return false;
}
- window.getVisibleBounds(mTmpRect);
+ w.getVisibleBounds(mTmpRect);
if (!mTmpRect.contains(x, y)) {
- continue;
+ return false;
}
- window.getTouchableRegion(mTmpRegion);
+ w.getTouchableRegion(mTmpRegion);
final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
- if (mTmpRegion.contains(x, y) || touchFlags == 0) {
- touchedWin = window;
- break;
- }
- }
+ return mTmpRegion.contains(x, y) || touchFlags == 0;
+ });
return touchedWin;
}
boolean canAddToastWindowForUid(int uid) {
// We allow one toast window per UID being shown at a time.
- final int windowCount = mWindows.size();
- for (int i = 0; i < windowCount; i++) {
- final WindowState window = mWindows.get(i);
- if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
- && !window.mPermanentlyHidden && !window.mWindowRemovalAllowed) {
- return false;
- }
- }
- return true;
+ final WindowState win = getWindow(w ->
+ w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden
+ && !w.mWindowRemovalAllowed);
+ return win == null;
}
void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
return;
}
- final int lostFocusUid = oldFocus.mOwnerUid;
- final int windowCount = mWindows.size();
- final Handler handler = mService.mH;
- for (int i = 0; i < windowCount; i++) {
- final WindowState window = mWindows.get(i);
- if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
- if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, window)) {
- handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, window),
- window.mAttrs.hideTimeoutMilliseconds);
- }
- }
- }
+
+ // Used to communicate the old focus to the callback method.
+ mTmpWindow = oldFocus;
+
+ forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */);
}
WindowState findFocusedWindow() {
- final AppWindowToken focusedApp = mService.mFocusedApp;
+ mTmpWindow = null;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState win = mWindows.get(i);
+ forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */);
- if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win
- + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys());
-
- if (!win.canReceiveKeys()) {
- continue;
- }
-
- final AppWindowToken wtoken = win.mAppToken;
-
- // If this window's application has been removed, just skip it.
- if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
- if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
- + (wtoken.removed ? "removed" : "sendingToBottom"));
- continue;
- }
-
- if (focusedApp == null) {
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
- + " using new focus @ " + i + " = " + win);
- return win;
- }
-
- if (!focusedApp.windowsAreFocusable()) {
- // Current focused app windows aren't focusable...
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
- + " focusable using new focus @ " + i + " = " + win);
- return win;
- }
-
- // Descend through all of the app tokens and find the first that either matches
- // win.mAppToken (return win) or mFocusedApp (return null).
- if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
- if (focusedApp.compareTo(wtoken) > 0) {
- // App stack below focused app stack. No focus for you!!!
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
- "findFocusedWindow: Reached focused app=" + focusedApp);
- return null;
- }
- }
-
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ "
- + i + " = " + win);
- return win;
+ if (mTmpWindow == null) {
+ if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
+ return null;
}
-
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
- return null;
- }
-
- void addAppWindowToWindowList(final WindowState win) {
- final IWindow client = win.mClient;
-
- WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken);
- if (!tokenWindowList.isEmpty()) {
- addAppWindowExisting(win, tokenWindowList);
- return;
- }
-
- // No windows from this token on this display
- if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
- + client.asBinder() + " (token=" + this + ")");
-
- final WindowToken wToken = win.mToken;
-
- // Figure out where the window should go, based on the order of applications.
- mTmpGetWindowOnDisplaySearchResult.reset();
- for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.get(i);
- stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
- if (mTmpGetWindowOnDisplaySearchResult.reachedToken) {
- // We have reach the token we are interested in. End search.
- break;
- }
- }
-
- WindowState pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
-
- // We now know the index into the apps. If we found an app window above, that gives us the
- // position; else we need to look some more.
- if (pos != null) {
- // Move behind any windows attached to this one.
- final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
- if (atoken != null) {
- tokenWindowList = getTokenWindowsOnDisplay(atoken);
- final int NC = tokenWindowList.size();
- if (NC > 0) {
- WindowState bottom = tokenWindowList.get(0);
- if (bottom.mSubLayer < 0) {
- pos = bottom;
- }
- }
- }
- addWindowToListBefore(win, pos);
- return;
- }
-
- // Continue looking down until we find the first token that has windows on this display.
- mTmpGetWindowOnDisplaySearchResult.reset();
- for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.get(i);
- stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
- if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) {
- // We have found a window after the token. End search.
- break;
- }
- }
-
- pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
-
- if (pos != null) {
- // Move in front of any windows attached to this one.
- final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
- if (atoken != null) {
- final WindowState top = atoken.getTopWindow();
- if (top != null && top.mSubLayer >= 0) {
- pos = top;
- }
- }
- addWindowToListAfter(win, pos);
- return;
- }
-
- // Just search for the start of this layer.
- final int myLayer = win.mBaseLayer;
- int i;
- for (i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState w = mWindows.get(i);
- // Dock divider shares the base layer with application windows, but we want to always
- // keep it above the application windows. The sharing of the base layer is intended
- // for window animations, which need to be above the dock divider for the duration
- // of the animation.
- if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
- break;
- }
- }
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
- + mWindows.size());
- mWindows.add(i + 1, win);
- mService.mWindowsChanged = true;
- }
-
- /** Adds this non-app window to the window list. */
- void addNonAppWindowToWindowList(WindowState win) {
- // Figure out where window should go, based on layer.
- int i;
- for (i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState otherWin = mWindows.get(i);
- if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) {
- // Wallpaper wanders through the window list, for example to position itself
- // directly behind keyguard. Because of this it will break the ordering based on
- // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
- // we don't want the new window to appear above them. An example of this is adding
- // of the docked stack divider. Consider a scenario with the following ordering (top
- // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
- // to land below the assist preview, so the dock divider must ignore the wallpaper,
- // with which it shares the base layer.
- break;
- }
- }
-
- i++;
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Free window: Adding window " + this + " at " + i + " of " + mWindows.size());
- mWindows.add(i, win);
- mService.mWindowsChanged = true;
- }
-
- void addToWindowList(WindowState win, int index) {
- mService.mWindowsChanged = true;
- mWindows.add(index, win);
- }
-
- boolean removeFromWindowList(WindowState win) {
- mService.mWindowsChanged = true;
- return mWindows.remove(win);
- }
-
- private int removeWindowAndChildrenFromWindowList(WindowState win, int interestingPos) {
- int wpos = mWindows.indexOf(win);
- if (wpos < 0) {
- return interestingPos;
- }
-
- if (wpos < interestingPos) interestingPos--;
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + this);
- mWindows.remove(wpos);
- mService.mWindowsChanged = true;
- int childWinCount = win.mChildren.size();
- while (childWinCount > 0) {
- childWinCount--;
- final WindowState cw = win.mChildren.get(childWinCount);
- int cpos = mWindows.indexOf(cw);
- if (cpos >= 0) {
- if (cpos < interestingPos) interestingPos--;
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
- "Temp removing child at " + cpos + ": " + cw);
- mWindows.remove(cpos);
- }
- }
- return interestingPos;
- }
-
- void addChildWindowToWindowList(WindowState win) {
- final WindowState parentWindow = win.getParentWindow();
-
- WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken);
-
- // Figure out this window's ordering relative to the parent window.
- final int wCount = windowsOnSameDisplay.size();
- final int sublayer = win.mSubLayer;
- int largestSublayer = Integer.MIN_VALUE;
- WindowState windowWithLargestSublayer = null;
- int i;
- for (i = 0; i < wCount; i++) {
- WindowState w = windowsOnSameDisplay.get(i);
- final int wSublayer = w.mSubLayer;
- if (wSublayer >= largestSublayer) {
- largestSublayer = wSublayer;
- windowWithLargestSublayer = w;
- }
- if (sublayer < 0) {
- // For negative sublayers, we go below all windows in the same sublayer.
- if (wSublayer >= sublayer) {
- addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w);
- break;
- }
- } else {
- // For positive sublayers, we go above all windows in the same sublayer.
- if (wSublayer > sublayer) {
- addWindowToListBefore(win, w);
- break;
- }
- }
- }
- if (i >= wCount) {
- if (sublayer < 0) {
- addWindowToListBefore(win, parentWindow);
- } else {
- addWindowToListAfter(win,
- largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow);
- }
- }
+ return mTmpWindow;
}
/** Updates the layer assignment of windows on this display. */
@@ -1409,136 +1519,9 @@
}
}
- void adjustWallpaperWindows() {
- mWallpaperController.adjustWallpaperWindows(this);
- }
-
- /**
- * Z-orders the display window list so that:
- * <ul>
- * <li>Any windows that are currently below the wallpaper window stay below the wallpaper
- * window.
- * <li>Exiting application windows are at the bottom, but above the wallpaper window.
- * <li>All other application windows are above the exiting application windows and ordered based
- * on the ordering of their stacks and tasks on the display.
- * <li>Non-application windows are at the very top.
- * </ul>
- * <p>
- * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window
- * surface layering is done in {@link WindowLayersController}.
- */
- void rebuildAppWindowList() {
- int count = mWindows.size();
- int i;
- int lastBelow = -1;
- int numRemoved = 0;
-
- if (mRebuildTmp.length < count) {
- mRebuildTmp = new WindowState[count + 10];
- }
-
- // First remove all existing app windows.
- i = 0;
- while (i < count) {
- final WindowState w = mWindows.get(i);
- if (w.mAppToken != null) {
- final WindowState win = mWindows.remove(i);
- win.mRebuilding = true;
- mRebuildTmp[numRemoved] = win;
- mService.mWindowsChanged = true;
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
- count--;
- numRemoved++;
- continue;
- } else if (lastBelow == i-1) {
- if (w.mAttrs.type == TYPE_WALLPAPER) {
- lastBelow = i;
- }
- }
- i++;
- }
-
- // Keep whatever windows were below the app windows still below, by skipping them.
- lastBelow++;
- i = lastBelow;
-
- // First add all of the exiting app tokens... these are no longer in the main app list,
- // but still have windows shown. We put them in the back because now that the animation is
- // over we no longer will care about them.
- final int numStacks = mTaskStackContainers.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- AppTokenList exitingAppTokens = mTaskStackContainers.get(stackNdx).mExitingAppTokens;
- int NT = exitingAppTokens.size();
- for (int j = 0; j < NT; j++) {
- i = exitingAppTokens.get(j).rebuildWindowListUnchecked(i);
- }
- }
-
- // And add in the still active app tokens in Z order.
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- i = mTaskStackContainers.get(stackNdx).rebuildWindowList(i);
- }
-
- i -= lastBelow;
- if (i != numRemoved) {
- setLayoutNeeded();
- Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved
- + " windows but added " + i + " rebuildAppWindowListLocked() "
- + " callers=" + Debug.getCallers(10));
- for (i = 0; i < numRemoved; i++) {
- WindowState ws = mRebuildTmp[i];
- if (ws.mRebuilding) {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new FastPrintWriter(sw, false, 1024);
- ws.dump(pw, "", true);
- pw.flush();
- Slog.w(TAG_WM, "This window was lost: " + ws);
- Slog.w(TAG_WM, sw.toString());
- ws.mWinAnimator.destroySurfaceLocked();
- }
- }
- Slog.w(TAG_WM, "Current window hierarchy:");
- dumpChildrenNames();
- Slog.w(TAG_WM, "Final window list:");
- dumpWindows();
- }
- Arrays.fill(mRebuildTmp, null);
- }
-
- /** Rebuilds the display's window list and does a relayout if something changed. */
- void rebuildAppWindowsAndLayoutIfNeeded() {
- mTmpWindows.clear();
- mTmpWindows.addAll(mWindows);
-
- rebuildAppWindowList();
-
- // Set displayContent.mLayoutNeeded if window order changed.
- final int tmpSize = mTmpWindows.size();
- final int winSize = mWindows.size();
- int tmpNdx = 0, winNdx = 0;
- while (tmpNdx < tmpSize && winNdx < winSize) {
- // Skip over all exiting windows, they've been moved out of order.
- WindowState tmp;
- do {
- tmp = mTmpWindows.get(tmpNdx++);
- } while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting);
-
- WindowState win;
- do {
- win = mWindows.get(winNdx++);
- } while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting);
-
- if (tmp != win) {
- // Window order changed.
- setLayoutNeeded();
- break;
- }
- }
- if (tmpNdx != winNdx) {
- // One list was different from the other.
- setLayoutNeeded();
- }
- mTmpWindows.clear();
+ void layoutAndAssignWindowLayersIfNeeded() {
+ mService.mWindowsChanged = true;
+ setLayoutNeeded();
if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
false /*updateInputWindows*/)) {
@@ -1550,321 +1533,76 @@
mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
}
- void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
- final InputConsumerImpl navInputConsumer =
- mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_NAVIGATION, mDisplayId);
- final InputConsumerImpl pipInputConsumer =
- mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_PIP, mDisplayId);
- final InputConsumerImpl wallpaperInputConsumer =
- mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_WALLPAPER, mDisplayId);
- boolean addInputConsumerHandle = navInputConsumer != null;
- boolean addPipInputConsumerHandle = pipInputConsumer != null;
- boolean addWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
- final Rect pipTouchableBounds = addPipInputConsumerHandle ? new Rect() : null;
- boolean disableWallpaperTouchEvents = false;
-
- for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState child = mWindows.get(winNdx);
- final InputChannel inputChannel = child.mInputChannel;
- final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
- if (inputChannel == null || inputWindowHandle == null || child.mRemoved
- || child.isAdjustedForMinimizedDock()) {
- // Skip this window because it cannot possibly receive input.
- continue;
- }
-
- if (addPipInputConsumerHandle
- && child.getStackId() == PINNED_STACK_ID
- && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
- // Update the bounds of the Pip input consumer to match the Pinned stack
- child.getStack().getBounds(pipTouchableBounds);
- pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
- inputMonitor.addInputWindowHandle(pipInputConsumer.mWindowHandle);
- addPipInputConsumerHandle = false;
- }
-
- if (addInputConsumerHandle
- && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
- inputMonitor.addInputWindowHandle(navInputConsumer.mWindowHandle);
- addInputConsumerHandle = false;
- }
-
- if (addWallpaperInputConsumerHandle) {
- if (child.mAttrs.type == TYPE_WALLPAPER && child.isVisibleLw()) {
- // Add the wallpaper input consumer above the first visible wallpaper.
- inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
- addWallpaperInputConsumerHandle = false;
- }
- }
-
- final int flags = child.mAttrs.flags;
- final int privateFlags = child.mAttrs.privateFlags;
- final int type = child.mAttrs.type;
-
- final boolean hasFocus = child == inputFocus;
- final boolean isVisible = child.isVisibleLw();
- if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
- disableWallpaperTouchEvents = true;
- }
- final boolean hasWallpaper = mWallpaperController.isWallpaperTarget(child)
- && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
- && !disableWallpaperTouchEvents;
-
- // If there's a drag in progress and 'child' is a potential drop target,
- // make sure it's been told about the drag
- if (inDrag && isVisible && isDefaultDisplay) {
- mService.mDragState.sendDragStartedIfNeededLw(child);
- }
-
- inputMonitor.addInputWindowHandle(
- inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
- }
-
- if (addWallpaperInputConsumerHandle) {
- // No visible wallpaper found, add the wallpaper input consumer at the end.
- inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
- }
- }
-
/** Returns true if a leaked surface was destroyed */
boolean destroyLeakedSurfaces() {
- boolean leakedSurface = false;
- final int numWindows = mWindows.size();
- for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
- final WindowState ws = mWindows.get(winNdx);
- final WindowStateAnimator wsa = ws.mWinAnimator;
+ // Used to indicate that a surface was leaked.
+ mTmpWindow = null;
+ forAllWindows(w -> {
+ final WindowStateAnimator wsa = w.mWinAnimator;
if (wsa.mSurfaceController == null) {
- continue;
+ return;
}
if (!mService.mSessions.contains(wsa.mSession)) {
Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
- + ws + " surface=" + wsa.mSurfaceController
- + " token=" + ws.mToken
- + " pid=" + ws.mSession.mPid
- + " uid=" + ws.mSession.mUid);
+ + w + " surface=" + wsa.mSurfaceController
+ + " token=" + w.mToken
+ + " pid=" + w.mSession.mPid
+ + " uid=" + w.mSession.mUid);
wsa.destroySurface();
- mService.mForceRemoves.add(ws);
- leakedSurface = true;
- } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
+ mService.mForceRemoves.add(w);
+ mTmpWindow = w;
+ } else if (w.mAppToken != null && w.mAppToken.clientHidden) {
Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
- + ws + " surface=" + wsa.mSurfaceController
- + " token=" + ws.mAppToken
- + " saved=" + ws.hasSavedSurface());
- if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
+ + w + " surface=" + wsa.mSurfaceController
+ + " token=" + w.mAppToken
+ + " saved=" + w.hasSavedSurface());
+ if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false);
wsa.destroySurface();
- leakedSurface = true;
+ mTmpWindow = w;
}
- }
+ }, false /* traverseTopToBottom */);
- return leakedSurface;
- }
-
- /** Return the list of Windows on this display associated with the input token. */
- WindowList getTokenWindowsOnDisplay(WindowToken token) {
- final WindowList windowList = new WindowList();
- final int count = mWindows.size();
- for (int i = 0; i < count; i++) {
- final WindowState win = mWindows.get(i);
- if (win.mToken == token) {
- windowList.add(win);
- }
- }
- return windowList;
- }
-
- private void reAddToWindowList(WindowState win) {
- win.mToken.addWindow(win);
- // This is a hack to get all of the child windows added as well at the right position. Child
- // windows should be rare and this case should be rare, so it shouldn't be that big a deal.
- int wpos = mWindows.indexOf(win);
- if (wpos >= 0) {
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win);
- mWindows.remove(wpos);
- mService.mWindowsChanged = true;
- win.reAddWindow(wpos);
- }
- }
-
- void moveInputMethodDialogs(int pos) {
- ArrayList<WindowState> dialogs = mService.mInputMethodDialogs;
-
- final int N = dialogs.size();
- if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos);
- for (int i = 0; i < N; i++) {
- pos = removeWindowAndChildrenFromWindowList(dialogs.get(i), pos);
- }
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "Window list w/pos=" + pos);
- logWindowList(mWindows, " ");
- }
-
- WindowState ime = mService.mInputMethodWindow;
- if (pos >= 0) {
- // Skip windows owned by the input method.
- if (ime != null) {
- while (pos < mWindows.size()) {
- WindowState wp = mWindows.get(pos);
- if (wp == ime || wp.getParentWindow() == ime) {
- pos++;
- continue;
- }
- break;
- }
- }
- if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos);
- for (int i=0; i<N; i++) {
- WindowState win = dialogs.get(i);
- pos = win.reAddWindow(pos);
- }
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "Final window list:");
- logWindowList(mWindows, " ");
- }
- return;
- }
- for (int i=0; i<N; i++) {
- WindowState win = dialogs.get(i);
- reAddToWindowList(win);
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "No IM target, final list:");
- logWindowList(mWindows, " ");
- }
- }
- }
-
- boolean moveInputMethodWindowsIfNeeded(boolean needAssignLayers) {
- final WindowState imWin = mService.mInputMethodWindow;
- final int DN = mService.mInputMethodDialogs.size();
- if (imWin == null && DN == 0) {
- return false;
- }
-
- // TODO(multidisplay): IMEs are only supported on the default display.
- int imPos = findDesiredInputMethodWindowIndex(true);
- if (imPos >= 0) {
- // In this case, the input method windows are to be placed
- // immediately above the window they are targeting.
-
- // First check to see if the input method windows are already
- // located here, and contiguous.
- final int N = mWindows.size();
- final WindowState firstImWin = imPos < N ? mWindows.get(imPos) : null;
-
- // Figure out the actual input method window that should be
- // at the bottom of their stack.
- WindowState baseImWin = imWin != null ? imWin : mService.mInputMethodDialogs.get(0);
- final WindowState cw = baseImWin.getBottomChild();
- if (cw != null && cw.mSubLayer < 0) {
- baseImWin = cw;
- }
-
- if (firstImWin == baseImWin) {
- // The windows haven't moved... but are they still contiguous?
- // First find the top IM window.
- int pos = imPos+1;
- while (pos < N) {
- if (!(mWindows.get(pos)).mIsImWindow) {
- break;
- }
- pos++;
- }
- pos++;
- // Now there should be no more input method windows above.
- while (pos < N) {
- if ((mWindows.get(pos)).mIsImWindow) {
- break;
- }
- pos++;
- }
- if (pos >= N) {
- return false;
- }
- }
-
- if (imWin != null) {
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "Moving IM from " + imPos);
- logWindowList(mWindows, " ");
- }
- imPos = removeWindowAndChildrenFromWindowList(imWin, imPos);
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":");
- logWindowList(mWindows, " ");
- }
- imWin.reAddWindow(imPos);
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "List after moving IM to " + imPos + ":");
- logWindowList(mWindows, " ");
- }
- if (DN > 0) moveInputMethodDialogs(imPos+1);
- } else {
- moveInputMethodDialogs(imPos);
- }
-
- } else {
- // In this case, the input method windows go in a fixed layer,
- // because they aren't currently associated with a focus window.
-
- if (imWin != null) {
- if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos);
- removeWindowAndChildrenFromWindowList(imWin, 0);
- reAddToWindowList(imWin);
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "List with no IM target:");
- logWindowList(mWindows, " ");
- }
- if (DN > 0) moveInputMethodDialogs(-1);
- } else {
- moveInputMethodDialogs(-1);
- }
-
- }
-
- if (needAssignLayers) {
- assignWindowLayers(false /* setLayoutNeeded */);
- }
-
- return true;
+ return mTmpWindow != null;
}
/**
- * Dig through the WindowStates and find the one that the Input Method will target.
- * @param willMove
- * @return The index+1 in mWindows of the discovered target.
+ * Determine and return the window that should be the IME target.
+ * @param updateImeTarget If true the system IME target will be updated to match what we found.
+ * @return The window that should be used as the IME target or null if there isn't any.
*/
- int findDesiredInputMethodWindowIndex(boolean willMove) {
+ WindowState computeImeTarget(boolean updateImeTarget) {
+ if (mService.mInputMethodWindow == null) {
+ // There isn't an IME so there shouldn't be a target...That was easy!
+ if (updateImeTarget) {
+ if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
+ + mService.mInputMethodTarget + " to null since mInputMethodWindow is null");
+ setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0);
+ }
+ return null;
+ }
+
// TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
// same display. Or even when the current IME/target are not on the same screen as the next
// IME/target. For now only look for input windows on the main screen.
- WindowState w = null;
- int i;
- for (i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState win = mWindows.get(i);
+ mUpdateImeTarget = updateImeTarget;
+ WindowState target = getWindow(mComputeImeTargetPredicate);
- if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i
- + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
- if (canBeImeTarget(win)) {
- w = win;
- //Slog.i(TAG_WM, "Putting input method here!");
- // Yet more tricksyness! If this window is a "starting" window, we do actually want
- // to be on top of it, but it is not -really- where input will go. So if the caller
- // is not actually looking to move the IME, look down below for a real window to
- // target...
- if (!willMove && w.mAttrs.type == TYPE_APPLICATION_STARTING && i > 0) {
- final WindowState wb = mWindows.get(i-1);
- if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
- i--;
- w = wb;
- }
+ // Yet more tricksyness! If this window is a "starting" window, we do actually want
+ // to be on top of it, but it is not -really- where input will go. So look down below
+ // for a real window to target...
+ if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) {
+ final AppWindowToken token = target.mAppToken;
+ if (token != null) {
+ final WindowState betterTarget = token.getImeTargetBelowWindow(target);
+ if (betterTarget != null) {
+ target = betterTarget;
}
- break;
}
}
- // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
-
- if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w);
+ if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
+ "Proposed new IME target: " + target);
// Now, a special case -- if the last target's window is in the process of exiting, and is
// above the new target, keep on the last target to avoid flicker. Consider for example a
@@ -1872,18 +1610,28 @@
// until it is completely gone so it doesn't drop behind the dialog or its full-screen
// scrim.
final WindowState curTarget = mService.mInputMethodTarget;
- if (curTarget != null
- && curTarget.isDisplayedLw()
- && curTarget.isClosing()
- && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
+ if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing()
+ && (target == null
+ || curTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer)) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
- return mWindows.indexOf(curTarget) + 1;
+ return curTarget;
}
- if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target="
- + w + " willMove=" + willMove);
+ if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target
+ + " updateImeTarget=" + updateImeTarget);
- if (willMove && w != null) {
+ if (target == null) {
+ if (updateImeTarget) {
+ if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
+ + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
+ + Debug.getCallers(4) : ""));
+ setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0);
+ }
+
+ return null;
+ }
+
+ if (updateImeTarget) {
AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
if (token != null) {
@@ -1891,24 +1639,8 @@
// to look at all windows below the current target that are in this app, finding the
// highest visible one in layering.
WindowState highestTarget = null;
- int highestPos = 0;
if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
- WindowList curWindows = token.getDisplayContent().mWindows;
- int pos = curWindows.indexOf(curTarget);
- while (pos >= 0) {
- WindowState win = curWindows.get(pos);
- if (win.mAppToken != token) {
- break;
- }
- if (!win.mRemoved) {
- if (highestTarget == null || win.mWinAnimator.mAnimLayer >
- highestTarget.mWinAnimator.mAnimLayer) {
- highestTarget = win;
- highestPos = pos;
- }
- }
- pos--;
- }
+ highestTarget = token.getHighestAnimLayerWindow(curTarget);
}
if (highestTarget != null) {
@@ -1916,121 +1648,76 @@
if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget
+ " animating=" + highestTarget.mWinAnimator.isAnimationSet()
+ " layer=" + highestTarget.mWinAnimator.mAnimLayer
- + " new layer=" + w.mWinAnimator.mAnimLayer);
+ + " new layer=" + target.mWinAnimator.mAnimLayer);
if (appTransition.isTransitionSet()) {
// If we are currently setting up for an animation, hold everything until we
// can find out what will happen.
- mService.mInputMethodTargetWaitingAnim = true;
- mService.mInputMethodTarget = highestTarget;
- return highestPos + 1;
+ setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment);
+ return highestTarget;
} else if (highestTarget.mWinAnimator.isAnimationSet() &&
- highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
+ highestTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer) {
// If the window we are currently targeting is involved with an animation,
// and it is on top of the next target we will be over, then hold off on
// moving until that is done.
- mService.mInputMethodTargetWaitingAnim = true;
- mService.mInputMethodTarget = highestTarget;
- return highestPos + 1;
+ setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment);
+ return highestTarget;
}
}
}
+
+ if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
+ + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
+ setInputMethodTarget(target, false, target.mAppToken != null
+ ? target.mAppToken.mAppAnimator.animLayerAdjustment : 0);
}
- //Slog.i(TAG_WM, "Placing input method @" + (i+1));
- if (w != null) {
- if (willMove) {
- if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
- + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
- mService.mInputMethodTarget = w;
- mService.mInputMethodTargetWaitingAnim = false;
- if (w.mAppToken != null) {
- setInputMethodAnimLayerAdjustment(
- w.mAppToken.mAppAnimator.animLayerAdjustment);
- } else {
- setInputMethodAnimLayerAdjustment(0);
- }
- }
-
- // If the docked divider is visible, we still need to go through this whole excercise to
- // find the appropriate input method target (used for animations and dialog
- // adjustments), but for purposes of Z ordering we simply wish to place it above the
- // docked divider. Unless it is already above the divider.
- final WindowState dockedDivider = mDividerControllerLocked.getWindow();
- if (dockedDivider != null && dockedDivider.isVisibleLw()) {
- int dividerIndex = mWindows.indexOf(dockedDivider);
- if (dividerIndex > 0 && dividerIndex > i) {
- return dividerIndex + 1;
- }
- }
- return i+1;
- }
- if (willMove) {
- if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
- + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
- mService.mInputMethodTarget = null;
- setInputMethodAnimLayerAdjustment(0);
- }
- return -1;
+ return target;
}
- private static boolean canBeImeTarget(WindowState w) {
- final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
- final int type = w.mAttrs.type;
-
- if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
- && type != TYPE_APPLICATION_STARTING) {
- return false;
+ private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim, int layerAdj) {
+ if (target == mService.mInputMethodTarget
+ && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim
+ && mInputMethodAnimLayerAdjustment == layerAdj) {
+ return;
}
- if (DEBUG_INPUT_METHOD) {
- Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
- if (!w.isVisibleOrAdding()) {
- Slog.i(TAG_WM, " mSurfaceController=" + w.mWinAnimator.mSurfaceController
- + " relayoutCalled=" + w.mRelayoutCalled
- + " viewVis=" + w.mViewVisibility
- + " policyVis=" + w.mPolicyVisibility
- + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
- + " parentHidden=" + w.isParentWindowHidden()
- + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying);
- if (w.mAppToken != null) {
- Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
- }
+ mService.mInputMethodTarget = target;
+ mService.mInputMethodTargetWaitingAnim = targetWaitingAnim;
+ setInputMethodAnimLayerAdjustment(layerAdj);
+ assignWindowLayers(false /* setLayoutNeeded */);
+ }
+
+ boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
+ if (top.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
+ return top.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
+ }
+
+ // Used to indicate we have reached the first window in the range we are interested in.
+ mTmpWindow = null;
+
+ // TODO: Figure-out a more efficient way to do this.
+ final WindowState candidate = getWindow(w -> {
+ if (w == top) {
+ // Reached the first window in the range we are interested in.
+ mTmpWindow = w;
}
- }
- return w.isVisibleOrAdding();
- }
+ if (mTmpWindow == null) {
+ return false;
+ }
- private void logWindowList(final WindowList windows, String prefix) {
- int N = windows.size();
- while (N > 0) {
- N--;
- Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N));
- }
- }
-
- boolean getNeedsMenu(WindowState win, WindowManagerPolicy.WindowState bottom) {
- int index = -1;
- while (true) {
- if (win.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
- return win.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
+ if (w.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
+ return true;
}
// If we reached the bottom of the range of windows we are considering,
// assume no menu is needed.
- if (win == bottom) {
- return false;
+ if (w == bottom) {
+ return true;
}
- // The current window hasn't specified whether menu key is needed; look behind it.
- // First, we may need to determine the starting position.
- if (index < 0) {
- index = mWindows.indexOf(win);
- }
- index--;
- if (index < 0) {
- return false;
- }
- win = mWindows.get(index);
- }
+ return false;
+ });
+
+ return candidate != null && candidate.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
}
void setLayoutNeeded() {
@@ -2047,85 +1734,6 @@
return mLayoutNeeded;
}
- private void addAppWindowExisting(WindowState win, WindowList tokenWindowList) {
-
- // If this application has existing windows, we simply place the new window on top of
- // them... but keep the starting window on top.
- if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
- // Base windows go behind everything else.
- final WindowState lowestWindow = tokenWindowList.get(0);
- addWindowToListBefore(win, lowestWindow);
- } else {
- final AppWindowToken atoken = win.mAppToken;
- final int windowListPos = tokenWindowList.size();
- final WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
- if (atoken != null && lastWindow == atoken.startingWindow) {
- addWindowToListBefore(win, lastWindow);
- } else {
- int newIdx = findIdxBasedOnAppTokens(win);
- // There is a window above this one associated with the same apptoken note that the
- // window could be a floating window that was created later or a window at the top
- // of the list of windows associated with this token.
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
- + mWindows.size());
- mWindows.add(newIdx + 1, win);
- mService.mWindowsChanged = true;
- }
- }
- }
-
- /** Places the first input window after the second input window in the window list. */
- private void addWindowToListAfter(WindowState first, WindowState second) {
- final int i = mWindows.indexOf(second);
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size()
- + " (after " + second + ")");
- mWindows.add(i + 1, first);
- mService.mWindowsChanged = true;
- }
-
- /** Places the first input window before the second input window in the window list. */
- private void addWindowToListBefore(WindowState first, WindowState second) {
- int i = mWindows.indexOf(second);
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Adding window " + this + " at " + i + " of " + mWindows.size()
- + " (before " + second + ")");
- if (i < 0) {
- Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows);
- i = 0;
- }
- mWindows.add(i, first);
- mService.mWindowsChanged = true;
- }
-
- /**
- * This method finds out the index of a window that has the same app token as win. used for z
- * ordering the windows in mWindows
- */
- private int findIdxBasedOnAppTokens(WindowState win) {
- for(int j = mWindows.size() - 1; j >= 0; j--) {
- final WindowState wentry = mWindows.get(j);
- if(wentry.mAppToken == win.mAppToken) {
- return j;
- }
- }
- return -1;
- }
-
- private void dumpChildrenNames() {
- StringBuilder output = new StringBuilder();
- dumpChildrenNames(output, " ");
- Slog.v(TAG_WM, output.toString());
- }
-
- private void dumpWindows() {
- Slog.v(TAG_WM, " Display #" + mDisplayId);
- for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
- Slog.v(TAG_WM, " #" + winNdx + ": " + mWindows.get(winNdx));
- }
- }
-
void dumpTokens(PrintWriter pw, boolean dumpAll) {
if (mTokenMap.isEmpty()) {
return;
@@ -2146,25 +1754,24 @@
}
void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
- final int count = mWindows.size();
- for (int j = 0; j < count; j++) {
- final WindowStateAnimator wAnim = mWindows.get(j).mWinAnimator;
- pw.println(subPrefix + "Window #" + j + ": " + wAnim);
- }
+ final int[] index = new int[1];
+ forAllWindows(w -> {
+ final WindowStateAnimator wAnim = w.mWinAnimator;
+ pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim);
+ index[0] = index[0] + 1;
+ }, false /* traverseTopToBottom */);
}
void enableSurfaceTrace(FileDescriptor fd) {
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState win = mWindows.get(i);
- win.mWinAnimator.enableSurfaceTrace(fd);
- }
+ forAllWindows(w -> {
+ w.mWinAnimator.enableSurfaceTrace(fd);
+ }, true /* traverseTopToBottom */);
}
void disableSurfaceTrace() {
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState win = mWindows.get(i);
- win.mWinAnimator.disableSurfaceTrace();
- }
+ forAllWindows(w -> {
+ w.mWinAnimator.disableSurfaceTrace();
+ }, true /* traverseTopToBottom */);
}
/**
@@ -2172,63 +1779,68 @@
*/
void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) {
final WindowManagerPolicy policy = mService.mPolicy;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState window = mWindows.get(i);
- if (window.mAppToken == null && policy.canBeHiddenByKeyguardLw(window)) {
- window.mWinAnimator.setAnimation(
+ forAllWindows(w -> {
+ if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)) {
+ w.mWinAnimator.setAnimation(
policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
}
- }
+ }, true /* traverseTopToBottom */);
}
boolean checkWaitingForWindows() {
- boolean haveBootMsg = false;
- boolean haveApp = false;
- // if the wallpaper service is disabled on the device, we're never going to have
- // wallpaper, don't bother waiting for it
- boolean haveWallpaper = false;
- boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_enableWallpaperService)
- && !mService.mOnlyCore;
- boolean haveKeyguard = true;
- final int count = mWindows.size();
- for (int i = 0; i < count; i++) {
- final WindowState w = mWindows.get(i);
+ mHaveBootMsg = false;
+ mHaveApp = false;
+ mHaveWallpaper = false;
+ mHaveKeyguard = true;
+
+ final WindowState visibleWindow = getWindow(w -> {
if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
return true;
}
if (w.isDrawnLw()) {
if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
- haveBootMsg = true;
+ mHaveBootMsg = true;
} else if (w.mAttrs.type == TYPE_APPLICATION
|| w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
- haveApp = true;
+ mHaveApp = true;
} else if (w.mAttrs.type == TYPE_WALLPAPER) {
- haveWallpaper = true;
+ mHaveWallpaper = true;
} else if (w.mAttrs.type == TYPE_STATUS_BAR) {
- haveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
+ mHaveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
}
}
+ return false;
+ });
+
+ if (visibleWindow != null) {
+ // We have a visible window.
+ return true;
}
+ // if the wallpaper service is disabled on the device, we're never going to have
+ // wallpaper, don't bother waiting for it
+ boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableWallpaperService)
+ && !mService.mOnlyCore;
+
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
"******** booted=" + mService.mSystemBooted
+ " msg=" + mService.mShowingBootMessages
- + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
- + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
- + " haveKeyguard=" + haveKeyguard);
+ + " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp
+ + " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled
+ + " haveKeyguard=" + mHaveKeyguard);
// If we are turning on the screen to show the boot message, don't do it until the boot
// message is actually displayed.
- if (!mService.mSystemBooted && !haveBootMsg) {
+ if (!mService.mSystemBooted && !mHaveBootMsg) {
return true;
}
// If we are turning on the screen after the boot is completed normally, don't do so until
// we have the application and wallpaper.
- if (mService.mSystemBooted && ((!haveApp && !haveKeyguard) ||
- (wallpaperEnabled && !haveWallpaper))) {
+ if (mService.mSystemBooted
+ && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) {
return true;
}
@@ -2236,152 +1848,41 @@
}
void updateWindowsForAnimator(WindowAnimator animator) {
- final WallpaperController wallpaperController = mWallpaperController;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- WindowState win = mWindows.get(i);
- WindowStateAnimator winAnimator = win.mWinAnimator;
- if (winAnimator.hasSurface()) {
- final boolean wasAnimating = winAnimator.mWasAnimating;
- final boolean nowAnimating = winAnimator.stepAnimationLocked(animator.mCurrentTime);
- winAnimator.mWasAnimating = nowAnimating;
- animator.orAnimating(nowAnimating);
-
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- win + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
-
- if (wasAnimating && !winAnimator.mAnimating
- && wallpaperController.isWallpaperTarget(win)) {
- animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(
- "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
- }
- }
- }
-
- final AppWindowToken atoken = win.mAppToken;
- if (winAnimator.mDrawState == READY_TO_SHOW) {
- if (atoken == null || atoken.allDrawn) {
- if (win.performShowLocked()) {
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
- if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(
- "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
- }
- }
- }
- }
- final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
- if (appAnimator != null && appAnimator.thumbnail != null) {
- if (appAnimator.thumbnailTransactionSeq != animator.mAnimTransactionSequence) {
- appAnimator.thumbnailTransactionSeq = animator.mAnimTransactionSequence;
- appAnimator.thumbnailLayer = 0;
- }
- if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
- appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
- }
- }
- } // end forall windows
+ mTmpWindowAnimator = animator;
+ forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
}
void updateWallpaperForAnimator(WindowAnimator animator) {
resetAnimationBackgroundAnimator();
- final WindowList windows = mWindows;
- WindowState detachedWallpaper = null;
+ // Used to indicate a detached wallpaper.
+ mTmpWindow = null;
+ mTmpWindowAnimator = animator;
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState win = windows.get(i);
- final WindowStateAnimator winAnimator = win.mWinAnimator;
- if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
- continue;
- }
+ forAllWindows(mUpdateWallpaperForAnimator, true /* traverseTopToBottom */);
- final int flags = win.mAttrs.flags;
-
- // If this window is animating, make a note that we have an animating window and take
- // care of a request to run a detached wallpaper animation.
- if (winAnimator.mAnimating) {
- if (winAnimator.mAnimation != null) {
- if ((flags & FLAG_SHOW_WALLPAPER) != 0
- && winAnimator.mAnimation.getDetachWallpaper()) {
- detachedWallpaper = win;
- }
- final int color = winAnimator.mAnimation.getBackgroundColor();
- if (color != 0) {
- final TaskStack stack = win.getStack();
- if (stack != null) {
- stack.setAnimationBackground(winAnimator, color);
- }
- }
- }
- animator.setAnimating(true);
- }
-
- // If this window's app token is running a detached wallpaper animation, make a note so
- // we can ensure the wallpaper is displayed behind it.
- final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
- if (appAnimator != null && appAnimator.animation != null
- && appAnimator.animating) {
- if ((flags & FLAG_SHOW_WALLPAPER) != 0
- && appAnimator.animation.getDetachWallpaper()) {
- detachedWallpaper = win;
- }
-
- final int color = appAnimator.animation.getBackgroundColor();
- if (color != 0) {
- final TaskStack stack = win.getStack();
- if (stack != null) {
- stack.setAnimationBackground(winAnimator, color);
- }
- }
- }
- } // end forall windows
-
- if (animator.mWindowDetachedWallpaper != detachedWallpaper) {
+ if (animator.mWindowDetachedWallpaper != mTmpWindow) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from "
- + animator.mWindowDetachedWallpaper + " to " + detachedWallpaper);
- animator.mWindowDetachedWallpaper = detachedWallpaper;
+ + animator.mWindowDetachedWallpaper + " to " + mTmpWindow);
+ animator.mWindowDetachedWallpaper = mTmpWindow;
animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
}
}
void prepareWindowSurfaces() {
- final int count = mWindows.size();
- for (int j = 0; j < count; j++) {
- mWindows.get(j).mWinAnimator.prepareSurfaceLocked(true);
- }
+ forAllWindows(mPrepareWindowSurfaces, false /* traverseTopToBottom */);
}
boolean inputMethodClientHasFocus(IInputMethodClient client) {
- // The focus for the client is the window immediately below where we would place the input
- // method window.
- int idx = findDesiredInputMethodWindowIndex(false);
- if (idx <= 0) {
- return false;
- }
-
- WindowState imFocus = mWindows.get(idx - 1);
- if (DEBUG_INPUT_METHOD) {
- Slog.i(TAG_WM, "Desired input method target: " + imFocus);
- Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
- Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
- }
-
+ final WindowState imFocus = computeImeTarget(false /* updateImeTarget */);
if (imFocus == null) {
return false;
}
- // This may be a starting window, in which case we still want to count it as okay.
- if (imFocus.mAttrs.type == TYPE_APPLICATION_STARTING && imFocus.mAppToken != null) {
- // The client has definitely started, so it really should have a window in this app
- // token. Let's look for it.
- final WindowState w = imFocus.mAppToken.getFirstNonStartingWindow();
- if (w != null) {
- if (DEBUG_INPUT_METHOD) Slog.i(TAG_WM, "Switching to real app window: " + w);
- imFocus = w;
- }
+ if (DEBUG_INPUT_METHOD) {
+ Slog.i(TAG_WM, "Desired input method target: " + imFocus);
+ Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
+ Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
}
final IInputMethodClient imeClient = imFocus.mSession.mClient;
@@ -2398,75 +1899,63 @@
}
boolean hasSecureWindowOnScreen() {
- for (int i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState ws = mWindows.get(i);
- if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
- return true;
- }
- }
- return false;
+ final WindowState win = getWindow(
+ w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0);
+ return win != null;
}
void updateSystemUiVisibility(int visibility, int globalDiff) {
- for (int i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState ws = mWindows.get(i);
+ forAllWindows(w -> {
try {
- int curValue = ws.mSystemUiVisibility;
- int diff = (curValue ^ visibility) & globalDiff;
- int newValue = (curValue & ~diff) | (visibility & diff);
+ final int curValue = w.mSystemUiVisibility;
+ final int diff = (curValue ^ visibility) & globalDiff;
+ final int newValue = (curValue & ~diff) | (visibility & diff);
if (newValue != curValue) {
- ws.mSeq++;
- ws.mSystemUiVisibility = newValue;
+ w.mSeq++;
+ w.mSystemUiVisibility = newValue;
}
- if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
- ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
+ if (newValue != curValue || w.mAttrs.hasSystemUiListeners) {
+ w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq,
visibility, newValue, diff);
}
} catch (RemoteException e) {
// so sorry
}
- }
+ }, true /* traverseTopToBottom */);
}
void onWindowFreezeTimeout() {
Slog.w(TAG_WM, "Window freeze timeout expired.");
mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
- for (int i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState w = mWindows.get(i);
+
+ forAllWindows(w -> {
if (!w.mOrientationChanging) {
- continue;
+ return;
}
w.mOrientationChanging = false;
w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- mService.mDisplayFreezeTime);
Slog.w(TAG_WM, "Force clearing orientation change: " + w);
- }
+ }, true /* traverseTopToBottom */);
mService.mWindowPlacerLocked.performSurfacePlacement();
}
void waitForAllWindowsDrawn() {
final WindowManagerPolicy policy = mService.mPolicy;
- for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = mWindows.get(winNdx);
- final boolean keyguard = policy.isKeyguardHostWindow(win.mAttrs);
- if (win.isVisibleLw() && (win.mAppToken != null || keyguard)) {
- win.mWinAnimator.mDrawState = DRAW_PENDING;
+ forAllWindows(w -> {
+ final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
+ if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
+ w.mWinAnimator.mDrawState = DRAW_PENDING;
// Force add to mResizingWindows.
- win.mLastContentInsets.set(-1, -1, -1, -1);
- mService.mWaitingForDrawn.add(win);
+ w.mLastContentInsets.set(-1, -1, -1, -1);
+ mService.mWaitingForDrawn.add(w);
}
- }
+ }, true /* traverseTopToBottom */);
}
// TODO: Super crazy long method that should be broken down...
boolean applySurfaceChangesTransaction(boolean recoveringMemory) {
- boolean focusDisplayed = false;
- boolean displayHasContent = false;
- float preferredRefreshRate = 0;
- int preferredModeId = 0;
-
-
final int dw = mDisplayInfo.logicalWidth;
final int dh = mDisplayInfo.logicalHeight;
final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
@@ -2490,7 +1979,7 @@
// Remove check for default display when there will be support for multiple wallpaper
// targets (on different displays).
if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
- adjustWallpaperWindows();
+ mWallpaperController.adjustWallpaperWindows(this);
}
if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
@@ -2517,137 +2006,23 @@
if (isDefaultDisplay) {
mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState w = mWindows.get(i);
- mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
- mService.mInputMethodTarget);
- }
+ forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
"after finishPostLayoutPolicyLw", pendingLayoutChanges);
}
} while (pendingLayoutChanges != 0);
- RootWindowContainer root = mService.mRoot;
- boolean obscured = false;
- boolean syswin = false;
+ mTmpApplySurfaceChangesTransactionState.reset();
resetDimming();
- // Only used if default window
- final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
-
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState w = mWindows.get(i);
- final Task task = w.getTask();
- final boolean obscuredChanged = w.mObscured != obscured;
-
- // Update effect.
- w.mObscured = obscured;
- if (!obscured) {
- final boolean isDisplayed = w.isDisplayedLw();
-
- if (isDisplayed && w.isObscuringFullscreen(mDisplayInfo)) {
- // This window completely covers everything behind it, so we want to leave all
- // of them as undimmed (for performance reasons).
- root.mObscuringWindow = w;
- obscured = true;
- }
-
- displayHasContent |= root.handleNotObscuredLocked(w, obscured, syswin);
-
- if (w.mHasSurface && isDisplayed) {
- final int type = w.mAttrs.type;
- if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
- || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
- syswin = true;
- }
- if (preferredRefreshRate == 0 && w.mAttrs.preferredRefreshRate != 0) {
- preferredRefreshRate = w.mAttrs.preferredRefreshRate;
- }
- if (preferredModeId == 0 && w.mAttrs.preferredDisplayModeId != 0) {
- preferredModeId = w.mAttrs.preferredDisplayModeId;
- }
- }
- }
-
- w.applyDimLayerIfNeeded();
-
- if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
- && mWallpaperController.isWallpaperTarget(w)) {
- // This is the wallpaper target and its obscured state changed... make sure the
- // current wallpaper's visibility has been updated accordingly.
- mWallpaperController.updateWallpaperVisibility();
- }
-
- w.handleWindowMovedIfNeeded();
-
- final WindowStateAnimator winAnimator = w.mWinAnimator;
-
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
- w.mContentChanged = false;
-
- // Moved from updateWindowsAndWallpaperLocked().
- if (w.mHasSurface) {
- // Take care of the window being ready to display.
- final boolean committed = winAnimator.commitFinishDrawingLocked();
- if (isDefaultDisplay && committed) {
- if (w.mAttrs.type == TYPE_DREAM) {
- // HACK: When a dream is shown, it may at that point hide the lock screen.
- // So we need to redo the layout to let the phone window manager make this
- // happen.
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS) {
- surfacePlacer.debugLayoutRepeats(
- "dream and commitFinishDrawingLocked true",
- pendingLayoutChanges);
- }
- }
- if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
- if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
- "First draw done in potential wallpaper target " + w);
- root.mWallpaperMayChange = true;
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- if (DEBUG_LAYOUT_REPEATS) {
- surfacePlacer.debugLayoutRepeats(
- "wallpaper and commitFinishDrawingLocked true",
- pendingLayoutChanges);
- }
- }
- }
- if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
- // Updates the shown frame before we set up the surface. This is needed
- // because the resizing could change the top-left position (in addition to
- // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
- // position the surface.
- //
- // If an animation is being started, we can't call this method because the
- // animation hasn't processed its initial transformation yet, but in general
- // we do want to update the position if the window is animating.
- winAnimator.computeShownFrameLocked();
- }
- winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
- }
-
- final AppWindowToken atoken = w.mAppToken;
- if (atoken != null) {
- final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
- if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
- mTmpUpdateAllDrawn.add(atoken);
- }
- }
-
- if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
- && w.isDisplayedLw()) {
- focusDisplayed = true;
- }
-
- w.updateResizingWindowIfNeeded();
- }
+ mTmpRecoveringMemory = recoveringMemory;
+ forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
- displayHasContent,
- preferredRefreshRate,
- preferredModeId,
+ mTmpApplySurfaceChangesTransactionState.displayHasContent,
+ mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
+ mTmpApplySurfaceChangesTransactionState.preferredModeId,
true /* inTraversal, must call performTraversalInTrans... below */);
stopDimmingIfNeeded();
@@ -2659,7 +2034,7 @@
atoken.updateAllDrawn(this);
}
- return focusDisplayed;
+ return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
}
void performLayout(boolean initial, boolean updateInputWindows) {
@@ -2671,8 +2046,6 @@
final int dw = mDisplayInfo.logicalWidth;
final int dh = mDisplayInfo.logicalHeight;
- int i;
-
if (DEBUG_LAYOUT) {
Slog.v(TAG, "-------------------------------------");
Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh);
@@ -2692,110 +2065,23 @@
if (seq < 0) seq = 0;
mService.mLayoutSeq = seq;
- boolean behindDream = false;
+ // Used to indicate that we have processed the dream window and all additional windows are
+ // behind it.
+ mTmpWindow = null;
+ mTmpInitial = initial;
// First perform layout of any root windows (not attached to another window).
- int topAttached = -1;
- for (i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState win = mWindows.get(i);
+ forAllWindows(mPerformLayout, true /* traverseTopToBottom */);
- // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
- // wasting time and funky changes while a window is animating away.
- final boolean gone = (behindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win))
- || win.isGoneForLayoutLw();
-
- if (DEBUG_LAYOUT && !win.mLayoutAttached) {
- Slog.v(TAG, "1ST PASS " + win + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
- + " mLayoutAttached=" + win.mLayoutAttached
- + " screen changed=" + win.isConfigChanged());
- final AppWindowToken atoken = win.mAppToken;
- if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + win.mViewVisibility
- + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden
- + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
- + " parentHidden=" + win.isParentWindowHidden());
- else Slog.v(TAG, " VIS: mViewVisibility=" + win.mViewVisibility
- + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden
- + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
- + " parentHidden=" + win.isParentWindowHidden());
- }
-
- // If this view is GONE, then skip it -- keep the current frame, and let the caller know
- // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows,
- // since that means "perform layout as normal, just don't display").
- if (!gone || !win.mHaveFrame || win.mLayoutNeeded
- || ((win.isConfigChanged() || win.setReportResizeHints())
- && !win.isGoneForLayoutLw() &&
- ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
- (win.mHasSurface && win.mAppToken != null &&
- win.mAppToken.layoutConfigChanges)))) {
- if (!win.mLayoutAttached) {
- if (initial) {
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
- win.mContentChanged = false;
- }
- if (win.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it does stuff like hide
- // the status bar we won't get a bad transition when it goes away.
- behindDream = true;
- }
- win.mLayoutNeeded = false;
- win.prelayout();
- mService.mPolicy.layoutWindowLw(win, null);
- win.mLayoutSeq = seq;
-
- // Window frames may have changed. Update dim layer with the new bounds.
- final Task task = win.getTask();
- if (task != null) {
- mDimLayerController.updateDimLayer(task);
- }
-
- if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + win.mFrame
- + " mContainingFrame=" + win.mContainingFrame
- + " mDisplayFrame=" + win.mDisplayFrame);
- } else {
- if (topAttached < 0) topAttached = i;
- }
- }
- }
-
- boolean attachedBehindDream = false;
+ // Used to indicate that we have processed the dream window and all additional attached
+ // windows are behind it.
+ mTmpWindow2 = mTmpWindow;
+ mTmpWindow = null;
// Now perform layout of attached windows, which usually depend on the position of the
// window they are attached to. XXX does not deal with windows that are attached to windows
// that are themselves attached.
- for (i = topAttached; i >= 0; i--) {
- final WindowState win = mWindows.get(i);
-
- if (win.mLayoutAttached) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win + " mHaveFrame=" + win.mHaveFrame
- + " mViewVisibility=" + win.mViewVisibility
- + " mRelayoutCalled=" + win.mRelayoutCalled);
- // If this view is GONE, then skip it -- keep the current frame, and let the caller
- // know so they can ignore it if they want. (We do the normal layout for INVISIBLE
- // windows, since that means "perform layout as normal, just don't display").
- if (attachedBehindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win)) {
- continue;
- }
- if ((win.mViewVisibility != GONE && win.mRelayoutCalled) || !win.mHaveFrame
- || win.mLayoutNeeded) {
- if (initial) {
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
- win.mContentChanged = false;
- }
- win.mLayoutNeeded = false;
- win.prelayout();
- mService.mPolicy.layoutWindowLw(win, win.getParentWindow());
- win.mLayoutSeq = seq;
- if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + win.mFrame
- + " mContainingFrame=" + win.mContainingFrame
- + " mDisplayFrame=" + win.mDisplayFrame);
- }
- } else if (win.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it does stuff like hide the
- // status bar we won't get a bad transition when it goes away.
- attachedBehindDream = behindDream;
- }
- }
+ forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);
// Window frames may have changed. Tell the input dispatcher about it.
mService.mInputMonitor.layoutInputConsumers(dw, dh);
@@ -2819,7 +2105,7 @@
* @param config of the output bitmap
* @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
*/
- Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height,
+ Bitmap screenshotApplications(IBinder appToken, int width, int height,
boolean includeFullDisplay, float frameScale, Bitmap.Config config,
boolean wallpaperOnly) {
int dw = mDisplayInfo.logicalWidth;
@@ -2832,22 +2118,10 @@
Bitmap bm = null;
- int maxLayer = 0;
+ mScreenshotApplicationState.reset(appToken == null && !wallpaperOnly);
final Rect frame = new Rect();
final Rect stackBounds = new Rect();
- boolean screenshotReady;
- int minLayer;
- if (appToken == null && !wallpaperOnly) {
- screenshotReady = true;
- minLayer = 0;
- } else {
- screenshotReady = false;
- minLayer = Integer.MAX_VALUE;
- }
-
- WindowState appWin = null;
-
boolean includeImeInScreenshot;
synchronized(mService.mWindowMap) {
final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null
@@ -2868,70 +2142,69 @@
synchronized(mService.mWindowMap) {
// Figure out the part of the screen that is actually the app.
- appWin = null;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState ws = mWindows.get(i);
- if (!ws.mHasSurface) {
- continue;
+ mScreenshotApplicationState.appWin = null;
+ forAllWindows(w -> {
+ if (!w.mHasSurface) {
+ return false;
}
- if (ws.mLayer >= aboveAppLayer) {
- continue;
+ if (w.mLayer >= aboveAppLayer) {
+ return false;
}
- if (wallpaperOnly && !ws.mIsWallpaper) {
- continue;
+ if (wallpaperOnly && !w.mIsWallpaper) {
+ return false;
}
- if (ws.mIsImWindow) {
+ if (w.mIsImWindow) {
if (!includeImeInScreenshot) {
- continue;
+ return false;
}
- } else if (ws.mIsWallpaper) {
+ } else if (w.mIsWallpaper) {
// If this is the wallpaper layer and we're only looking for the wallpaper layer
// then the target window state is this one.
if (wallpaperOnly) {
- appWin = ws;
+ mScreenshotApplicationState.appWin = w;
}
- if (appWin == null) {
+ if (mScreenshotApplicationState.appWin == null) {
// We have not ran across the target window yet, so it is probably behind
// the wallpaper. This can happen when the keyguard is up and all windows
// are moved behind the wallpaper. We don't want to include the wallpaper
// layer in the screenshot as it will cover-up the layer of the target
// window.
- continue;
+ return false;
}
// Fall through. The target window is in front of the wallpaper. For this
// case we want to include the wallpaper layer in the screenshot because
// the target window might have some transparent areas.
} else if (appToken != null) {
- if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
+ if (w.mAppToken == null || w.mAppToken.token != appToken) {
// This app window is of no interest if it is not associated with the
// screenshot app.
- continue;
+ return false;
}
- appWin = ws;
+ mScreenshotApplicationState.appWin = w;
}
// Include this window.
- final WindowStateAnimator winAnim = ws.mWinAnimator;
+ final WindowStateAnimator winAnim = w.mWinAnimator;
int layer = winAnim.mSurfaceController.getLayer();
- if (maxLayer < layer) {
- maxLayer = layer;
+ if (mScreenshotApplicationState.maxLayer < layer) {
+ mScreenshotApplicationState.maxLayer = layer;
}
- if (minLayer > layer) {
- minLayer = layer;
+ if (mScreenshotApplicationState.minLayer > layer) {
+ mScreenshotApplicationState.minLayer = layer;
}
// Don't include wallpaper in bounds calculation
- if (!includeFullDisplay && !ws.mIsWallpaper) {
- final Rect wf = ws.mFrame;
- final Rect cr = ws.mContentInsets;
+ if (!includeFullDisplay && !w.mIsWallpaper) {
+ final Rect wf = w.mFrame;
+ final Rect cr = w.mContentInsets;
int left = wf.left + cr.left;
int top = wf.top + cr.top;
int right = wf.right - cr.right;
int bottom = wf.bottom - cr.bottom;
frame.union(left, top, right, bottom);
- ws.getVisibleBounds(stackBounds);
+ w.getVisibleBounds(stackBounds);
if (!Rect.intersects(frame, stackBounds)) {
// Set frame empty if there's no intersection.
frame.setEmpty();
@@ -2939,16 +2212,22 @@
}
final boolean foundTargetWs =
- (ws.mAppToken != null && ws.mAppToken.token == appToken)
- || (appWin != null && wallpaperOnly);
- if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) {
- screenshotReady = true;
+ (w.mAppToken != null && w.mAppToken.token == appToken)
+ || (mScreenshotApplicationState.appWin != null && wallpaperOnly);
+ if (foundTargetWs && w.isDisplayedLw() && winAnim.getShown()) {
+ mScreenshotApplicationState.screenshotReady = true;
}
- if (ws.isObscuringFullscreen(mDisplayInfo)){
- break;
+ if (w.isObscuringDisplay()){
+ return true;
}
- }
+ return false;
+ }, true /* traverseTopToBottom */);
+
+ final WindowState appWin = mScreenshotApplicationState.appWin;
+ final boolean screenshotReady = mScreenshotApplicationState.screenshotReady;
+ final int maxLayer = mScreenshotApplicationState.maxLayer;
+ final int minLayer = mScreenshotApplicationState.minLayer;
if (appToken != null && appWin == null) {
// Can't find a window to snapshot.
@@ -3020,14 +2299,13 @@
if (DEBUG_SCREENSHOT) {
Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
+ maxLayer + " appToken=" + appToken);
- for (int i = 0; i < mWindows.size(); i++) {
- final WindowState win = mWindows.get(i);
- final WindowSurfaceController controller = win.mWinAnimator.mSurfaceController;
- Slog.i(TAG_WM, win + ": " + win.mLayer
- + " animLayer=" + win.mWinAnimator.mAnimLayer
+ forAllWindows(w -> {
+ final WindowSurfaceController controller = w.mWinAnimator.mSurfaceController;
+ Slog.i(TAG_WM, w + ": " + w.mLayer
+ + " animLayer=" + w.mWinAnimator.mAnimLayer
+ " surfaceLayer=" + ((controller == null)
? "null" : controller.getLayer()));
- }
+ }, false /* traverseTopToBottom */);
}
final ScreenRotationAnimation screenRotationAnimation =
@@ -3064,6 +2342,9 @@
}
}
if (allBlack) {
+ final WindowState appWin = mScreenshotApplicationState.appWin;
+ final int maxLayer = mScreenshotApplicationState.maxLayer;
+ final int minLayer = mScreenshotApplicationState.minLayer;
Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
(appWin != null ?
@@ -3104,32 +2385,23 @@
}
void onSeamlessRotationTimeout() {
- boolean layoutNeeded = false;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState w = mWindows.get(i);
+ // Used to indicate the layout is needed.
+ mTmpWindow = null;
+
+ forAllWindows(w -> {
if (!w.mSeamlesslyRotated) {
- continue;
+ return;
}
- layoutNeeded = true;
+ mTmpWindow = w;
w.setDisplayLayoutNeeded();
mService.markForSeamlessRotation(w, false);
- }
+ }, true /* traverseTopToBottom */);
- if (layoutNeeded) {
+ if (mTmpWindow != null) {
mService.mWindowPlacerLocked.performSurfacePlacement();
}
}
- static final class GetWindowOnDisplaySearchResult {
- boolean reachedToken;
- WindowState foundWindow;
-
- void reset() {
- reachedToken = false;
- foundWindow = null;
- }
- }
-
static final class TaskForResizePointSearchResult {
boolean searchDone;
Task taskForResize;
@@ -3140,6 +2412,39 @@
}
}
+ private static final class ApplySurfaceChangesTransactionState {
+ boolean displayHasContent;
+ boolean obscured;
+ boolean syswin;
+ boolean focusDisplayed;
+ float preferredRefreshRate;
+ int preferredModeId;
+
+ void reset() {
+ displayHasContent = false;
+ obscured = false;
+ syswin = false;
+ focusDisplayed = false;
+ preferredRefreshRate = 0;
+ preferredModeId = 0;
+ }
+ }
+
+ private static final class ScreenshotApplicationState {
+ WindowState appWin;
+ int maxLayer;
+ int minLayer;
+ boolean screenshotReady;
+
+ void reset(boolean screenshotReady) {
+ appWin = null;
+ maxLayer = 0;
+ minLayer = 0;
+ this.screenshotReady = screenshotReady;
+ minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE;
+ }
+ }
+
/**
* Base class for any direct child window container of {@link #DisplayContent} need to inherit
* from. This is mainly a pass through class that allows {@link #DisplayContent} to have
@@ -3192,15 +2497,6 @@
void removeStackFromDisplay(TaskStack stack) {
removeChild(stack);
stack.onRemovedFromDisplay();
- // TODO: remove when window list will be gone.
- // Manually remove records from window list and tap excluded windows list.
- for (int i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState windowState = mWindows.get(i);
- if (stack == windowState.getStack()) {
- mWindows.remove(i);
- mTapExcludedWindows.remove(windowState);
- }
- }
}
void moveStack(TaskStack stack, boolean toTop) {
@@ -3330,11 +2626,23 @@
* Compares two child window tokens returns -1 if the first is lesser than the second in
* terms of z-order and 1 otherwise.
*/
- final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
+ private final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
// Tokens with higher base layer are z-ordered on-top.
mService.mPolicy.windowTypeToLayerLw(token1.windowType)
< mService.mPolicy.windowTypeToLayerLw(token2.windowType) ? -1 : 1;
+ private final Predicate<WindowState> mGetOrientingWindow = w -> {
+ if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) {
+ return false;
+ }
+ final int req = w.mAttrs.screenOrientation;
+ if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND
+ || req == SCREEN_ORIENTATION_UNSET) {
+ return false;
+ }
+ return true;
+ };
+
private final String mName;
NonAppWindowContainers(String name) {
mName = name;
@@ -3345,6 +2653,30 @@
}
@Override
+ int getOrientation() {
+ final WindowManagerPolicy policy = mService.mPolicy;
+ // Find a window requesting orientation.
+ final WindowState win = getWindow(mGetOrientingWindow);
+
+ if (win != null) {
+ final int req = win.mAttrs.screenOrientation;
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
+ if (policy.isKeyguardHostWindow(win.mAttrs)) {
+ mService.mLastKeyguardForcedOrientation = req;
+ }
+ return (mService.mLastWindowForcedOrientation = req);
+ }
+
+ mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+
+ if (policy.isKeyguardShowingAndNotOccluded()) {
+ return mService.mLastKeyguardForcedOrientation;
+ }
+
+ return SCREEN_ORIENTATION_UNSET;
+ }
+
+ @Override
String getName() {
return mName;
}
diff --git a/services/core/java/com/android/server/wm/DragResizeMode.java b/services/core/java/com/android/server/wm/DragResizeMode.java
index 08acf9d..8ab0406 100644
--- a/services/core/java/com/android/server/wm/DragResizeMode.java
+++ b/services/core/java/com/android/server/wm/DragResizeMode.java
@@ -20,6 +20,7 @@
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
/**
* Describes the mode in which a window is drag resizing.
@@ -45,7 +46,8 @@
case DRAG_RESIZE_MODE_DOCKED_DIVIDER:
return stackId == DOCKED_STACK_ID
|| stackId == FULLSCREEN_WORKSPACE_STACK_ID
- || stackId == HOME_STACK_ID;
+ || stackId == HOME_STACK_ID
+ || stackId == RECENTS_STACK_ID;
default:
return false;
}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 40b737d..0e4add8 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -68,7 +68,8 @@
* Drag/drop state
*/
class DragState {
- private static final long ANIMATION_DURATION_MS = 500;
+ private static final long MIN_ANIMATION_DURATION_MS = 195;
+ private static final long MAX_ANIMATION_DURATION_MS = 375;
private static final int DRAG_FLAGS_URI_ACCESS = View.DRAG_FLAG_GLOBAL_URI_READ |
View.DRAG_FLAG_GLOBAL_URI_WRITE;
@@ -103,6 +104,7 @@
private Animation mAnimation;
final Transformation mTransformation = new Transformation();
private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
+ private Point mDisplaySize = new Point();
DragState(WindowManagerService service, IBinder token, SurfaceControl surface,
int flags, IBinder localWin) {
@@ -171,10 +173,8 @@
// The drag window covers the entire display
mDragWindowHandle.frameLeft = 0;
mDragWindowHandle.frameTop = 0;
- Point p = new Point();
- display.getRealSize(p);
- mDragWindowHandle.frameRight = p.x;
- mDragWindowHandle.frameBottom = p.y;
+ mDragWindowHandle.frameRight = mDisplaySize.x;
+ mDragWindowHandle.frameBottom = mDisplaySize.y;
// Pause rotations before a drag.
if (DEBUG_ORIENTATION) {
@@ -215,6 +215,7 @@
* @param display The Display that the window being dragged is on.
*/
void register(Display display) {
+ display.getRealSize(mDisplaySize);
if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel");
if (mInputInterceptor != null) {
Slog.e(TAG_WM, "Duplicate register of drag input channel");
@@ -583,10 +584,17 @@
private Animation createReturnAnimationLocked() {
final AnimationSet set = new AnimationSet(false);
- set.addAnimation(new TranslateAnimation(
- 0, mOriginalX - mCurrentX, 0, mOriginalY - mCurrentY));
+ final float translateX = mOriginalX - mCurrentX;
+ final float translateY = mOriginalY - mCurrentY;
+ set.addAnimation(new TranslateAnimation( 0, translateX, 0, translateY));
set.addAnimation(new AlphaAnimation(mOriginalAlpha, mOriginalAlpha / 2));
- set.setDuration(ANIMATION_DURATION_MS);
+ // Adjust the duration to the travel distance.
+ final double travelDistance = Math.sqrt(translateX * translateX + translateY * translateY);
+ final double displayDiagonal =
+ Math.sqrt(mDisplaySize.x * mDisplaySize.x + mDisplaySize.y * mDisplaySize.y);
+ final long duration = MIN_ANIMATION_DURATION_MS + (long) (travelDistance / displayDiagonal
+ * (MAX_ANIMATION_DURATION_MS - MIN_ANIMATION_DURATION_MS));
+ set.setDuration(duration);
set.setInterpolator(mCubicEaseOutInterpolator);
set.initialize(0, 0, 0, 0);
set.start(); // Will start on the first call to getTransformation.
@@ -597,7 +605,7 @@
final AnimationSet set = new AnimationSet(false);
set.addAnimation(new ScaleAnimation(1, 0, 1, 0, mThumbOffsetX, mThumbOffsetY));
set.addAnimation(new AlphaAnimation(mOriginalAlpha, 0));
- set.setDuration(ANIMATION_DURATION_MS);
+ set.setDuration(MIN_ANIMATION_DURATION_MS);
set.setInterpolator(mCubicEaseOutInterpolator);
set.initialize(0, 0, 0, 0);
set.start(); // Will start on the first call to getTransformation.
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 12c72e9..495be09 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,10 +16,15 @@
package com.android.server.wm;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
@@ -40,12 +45,14 @@
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
+
import com.android.server.input.InputApplicationHandle;
import com.android.server.input.InputManagerService;
import com.android.server.input.InputWindowHandle;
import java.io.PrintWriter;
import java.util.Arrays;
+import java.util.function.Consumer;
final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
private final WindowManagerService mService;
@@ -70,6 +77,13 @@
// Array of window handles to provide to the input dispatcher.
private InputWindowHandle[] mInputWindowHandles;
private int mInputWindowHandleCount;
+ private boolean mAddInputConsumerHandle;
+ private boolean mAddPipInputConsumerHandle;
+ private boolean mAddWallpaperInputConsumerHandle;
+ private boolean mDisableWallpaperTouchEvents;
+ private final Rect mTmpRect = new Rect();
+ private final UpdateInputForAllWindowsConsumer mUpdateInputForAllWindowsConsumer =
+ new UpdateInputForAllWindowsConsumer();
// Set to true when the first input device configuration change notification
// is received to indicate that the input devices are ready.
@@ -323,12 +337,12 @@
}
}
- public void setUpdateInputWindowsNeededLw() {
+ void setUpdateInputWindowsNeededLw() {
mUpdateInputWindowsNeeded = true;
}
/* Updates the cached window information provided to the input dispatcher. */
- public void updateInputWindowsLw(boolean force) {
+ void updateInputWindowsLw(boolean force) {
if (!force && !mUpdateInputWindowsNeeded) {
return;
}
@@ -372,13 +386,7 @@
}
// Add all windows on the default display.
- mService.mRoot.updateInputWindows(this, mInputFocus, inDrag);
-
- // Send windows to native code.
- mService.mInputManager.setInputWindows(mInputWindowHandles);
-
- // Clear the list in preparation for the next round.
- clearInputWindowHandlesLw();
+ mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
}
@@ -571,4 +579,98 @@
pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason);
}
}
+
+ private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
+
+ InputConsumerImpl navInputConsumer;
+ InputConsumerImpl pipInputConsumer;
+ InputConsumerImpl wallpaperInputConsumer;
+ Rect pipTouchableBounds;
+ boolean inDrag;
+ WallpaperController wallpaperController;
+
+ private void updateInputWindows(boolean inDrag) {
+
+ clearInputWindowHandlesLw();
+
+ // TODO: multi-display
+ navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY);
+ pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY);
+ wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY);
+ mAddInputConsumerHandle = navInputConsumer != null;
+ mAddPipInputConsumerHandle = pipInputConsumer != null;
+ mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
+ mTmpRect.setEmpty();
+ pipTouchableBounds = mAddPipInputConsumerHandle ? mTmpRect : null;
+ mDisableWallpaperTouchEvents = false;
+ this.inDrag = inDrag;
+ wallpaperController = mService.mRoot.mWallpaperController;
+
+ mService.mRoot.forAllWindows(this, true /* traverseTopToBottom */);
+ if (mAddWallpaperInputConsumerHandle) {
+ // No visible wallpaper found, add the wallpaper input consumer at the end.
+ addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
+ }
+
+ // Send windows to native code.
+ mService.mInputManager.setInputWindows(mInputWindowHandles);
+ }
+
+ @Override
+ public void accept(WindowState w) {
+ final InputChannel inputChannel = w.mInputChannel;
+ final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
+ if (inputChannel == null || inputWindowHandle == null || w.mRemoved
+ || w.isAdjustedForMinimizedDock()) {
+ // Skip this window because it cannot possibly receive input.
+ return;
+ }
+
+ if (mAddPipInputConsumerHandle
+ && w.getStackId() == PINNED_STACK_ID
+ && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
+ // Update the bounds of the Pip input consumer to match the Pinned stack
+ w.getStack().getBounds(pipTouchableBounds);
+ pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
+ addInputWindowHandle(pipInputConsumer.mWindowHandle);
+ mAddPipInputConsumerHandle = false;
+ }
+
+ if (mAddInputConsumerHandle
+ && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
+ addInputWindowHandle(navInputConsumer.mWindowHandle);
+ mAddInputConsumerHandle = false;
+ }
+
+ if (mAddWallpaperInputConsumerHandle) {
+ if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
+ // Add the wallpaper input consumer above the first visible wallpaper.
+ addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
+ mAddWallpaperInputConsumerHandle = false;
+ }
+ }
+
+ final int flags = w.mAttrs.flags;
+ final int privateFlags = w.mAttrs.privateFlags;
+ final int type = w.mAttrs.type;
+
+ final boolean hasFocus = w == mInputFocus;
+ final boolean isVisible = w.isVisibleLw();
+ if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
+ mDisableWallpaperTouchEvents = true;
+ }
+ final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w)
+ && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
+ && !mDisableWallpaperTouchEvents;
+
+ // If there's a drag in progress and 'child' is a potential drop target,
+ // make sure it's been told about the drag
+ if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
+ mService.mDragState.sendDragStartedIfNeededLw(w);
+ }
+
+ addInputWindowHandle(
+ inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 01a50b7..0ad4e0a 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -135,7 +135,7 @@
mService = service;
mDisplayContent = displayContent;
mSnapAlgorithm = new PipSnapAlgorithm(service.mContext);
- mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
+ mMotionHelper = new PipMotionHelper(UiThread.getHandler());
mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
reloadResources();
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 88986e3..349740b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -40,6 +40,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.function.Consumer;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
@@ -129,6 +130,23 @@
private final WindowLayersController mLayersController;
final WallpaperController mWallpaperController;
+ private String mCloseSystemDialogsReason;
+ private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
+ if (w.mHasSurface) {
+ try {
+ w.mClient.closeSystemDialogs(mCloseSystemDialogsReason);
+ } catch (RemoteException e) {
+ }
+ }
+ };
+
+ private static final Consumer<WindowState> sRemoveReplacedWindowsConsumer = w -> {
+ final AppWindowToken aToken = w.mAppToken;
+ if (aToken != null) {
+ aToken.removeReplacedWindowIfNeeded(w);
+ }
+ };
+
RootWindowContainer(WindowManagerService service) {
mService = service;
mLayersController = new WindowLayersController(mService);
@@ -219,7 +237,7 @@
return false;
}
- void getWindowsByName(WindowList output, String name) {
+ void getWindowsByName(ArrayList<WindowState> output, String name) {
int objectId = 0;
// See if this is an object ID.
try {
@@ -231,7 +249,7 @@
getWindowsByName(output, name, objectId);
}
- private void getWindowsByName(WindowList output, String name, int objectId) {
+ private void getWindowsByName(ArrayList<WindowState> output, String name, int objectId) {
forAllWindows((w) -> {
if (name != null) {
if (w.mAttrs.getTitle().toString().contains(name)) {
@@ -276,15 +294,6 @@
return null;
}
- // TODO: Users would have their own window containers under the display container?
- void switchUser() {
- final int count = mChildren.size();
- for (int i = 0; i < count; ++i) {
- final DisplayContent dc = mChildren.get(i);
- dc.switchUser();
- }
- }
-
/**
* Set new display override config and return array of ids of stacks that were changed during
* update. If called for the default display, global configuration will also be updated.
@@ -385,26 +394,15 @@
}
void closeSystemDialogs(String reason) {
- forAllWindows((w) -> {
- if (w.mHasSurface) {
- try {
- w.mClient.closeSystemDialogs(reason);
- } catch (RemoteException e) {
- }
- }
- }, false /* traverseTopToBottom */);
+ mCloseSystemDialogsReason = reason;
+ forAllWindows(mCloseSystemDialogsConsumer, false /* traverseTopToBottom */);
}
void removeReplacedWindows() {
if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
mService.openSurfaceTransaction();
try {
- forAllWindows((w) -> {
- final AppWindowToken aToken = w.mAppToken;
- if (aToken != null) {
- aToken.removeReplacedWindowIfNeeded(w);
- }
- }, true /* traverseTopToBottom */);
+ forAllWindows(sRemoveReplacedWindowsConsumer, true /* traverseTopToBottom */);
} finally {
mService.closeSurfaceTransaction();
if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
@@ -429,14 +427,6 @@
return hasChanges;
}
- void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
- final int count = mChildren.size();
- for (int i = 0; i < count; ++i) {
- final DisplayContent dc = mChildren.get(i);
- dc.updateInputWindows(inputMonitor, inputFocus, inDrag);
- }
- }
-
boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
boolean secure) {
final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
@@ -662,7 +652,7 @@
WindowState win = mService.mDestroySurface.get(i);
win.mDestroying = false;
if (mService.mInputMethodWindow == win) {
- mService.mInputMethodWindow = null;
+ mService.setInputMethodWindowLocked(null);
}
if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
wallpaperDestroyed = true;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b889db2..612af75 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -19,7 +19,9 @@
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -146,11 +148,11 @@
if (content != null) {
content.mDimLayerController.removeDimLayerUser(this);
}
- getParent().removeChild(this);
+ removeImmediately();
mService.mTaskIdToTask.delete(mTaskId);
}
- // Change to use reparenting in WC when TaskStack is switched to use WC.
+ // Change to use re-parenting in WC when TaskStack is switched to use WC.
void moveTaskToStack(TaskStack stack, boolean toTop) {
if (stack == mStack) {
return;
@@ -280,6 +282,17 @@
return ActivityInfo.isResizeableMode(mResizeMode) || mService.mForceResizableTasks;
}
+ /**
+ * Tests if the orientation should be preserved upon user interactive resizig operations.
+
+ * @return true if orientation should not get changed upon resizing operation.
+ */
+ boolean preserveOrientationOnResize() {
+ return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
+ || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
+ || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+ }
+
boolean isOnTopLauncher() {
return mIsOnTopLauncher;
}
@@ -526,10 +539,6 @@
return (tokensCount != 0) && mChildren.get(tokensCount - 1).showForAllUsers;
}
- boolean inHomeStack() {
- return mStack != null && mStack.mStackId == HOME_STACK_ID;
- }
-
boolean inFreeformWorkspace() {
return mStack != null && mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
}
@@ -589,46 +598,6 @@
}
}
- void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
- DisplayContent.GetWindowOnDisplaySearchResult result) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final AppWindowToken current = mChildren.get(i);
- if (current == token) {
- // We have reach the token we are interested in. End search.
- result.reachedToken = true;
- return;
- }
-
- // We haven't reached the token yet; if this token is not going to the bottom and
- // has windows on this display, then it is a candidate for what we are looking for.
- final WindowList tokenWindowList = dc.getTokenWindowsOnDisplay(current);
- if (!current.sendingToBottom && tokenWindowList.size() > 0) {
- result.foundWindow = tokenWindowList.get(0);
- }
- }
- }
-
- void getWindowOnDisplayAfterToken(DisplayContent dc, WindowToken token,
- DisplayContent.GetWindowOnDisplaySearchResult result) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final AppWindowToken current = mChildren.get(i);
- if (!result.reachedToken) {
- if (current == token) {
- // We have reached the token we are interested in. Get whichever window occurs
- // after it that is on the same display.
- result.reachedToken = true;
- }
- continue;
- }
-
- final WindowList tokenWindowList = dc.getTokenWindowsOnDisplay(current);
- if (tokenWindowList.size() > 0) {
- result.foundWindow = tokenWindowList.get(tokenWindowList.size() - 1);
- return;
- }
- }
- }
-
@Override
boolean fillsParent() {
return mFillsParent || !StackId.isTaskResizeAllowed(mStack.mStackId);
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 6887312..267566b 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -50,9 +50,9 @@
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.MotionEvent;
-import android.view.SurfaceControl;
import android.view.WindowManager;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.input.InputApplicationHandle;
import com.android.server.input.InputWindowHandle;
import com.android.server.wm.WindowManagerService.H;
@@ -61,6 +61,7 @@
import java.lang.annotation.RetentionPolicy;
class TaskPositioner implements DimLayer.DimLayerUser {
+ private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false;
private static final String TAG_LOCAL = "TaskPositioner";
private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM;
@@ -89,6 +90,12 @@
public static final int RESIZING_HINT_DURATION_MS = 0;
+ // The minimal aspect ratio which needs to be met to count as landscape (or 1/.. for portrait).
+ // Note: We do not use the 1.33 from the CDD here since the user is allowed to use what ever
+ // aspect he desires.
+ @VisibleForTesting
+ static final float MIN_ASPECT = 1.2f;
+
private final WindowManagerService mService;
private WindowPositionerEventReceiver mInputEventReceiver;
private Display mDisplay;
@@ -103,8 +110,11 @@
private Task mTask;
private boolean mResizing;
+ private boolean mPreserveOrientation;
+ private boolean mStartOrientationWasLandscape;
private final Rect mWindowOriginalBounds = new Rect();
private final Rect mWindowDragBounds = new Rect();
+ private final Point mMaxVisibleSize = new Point();
private float mStartDragX;
private float mStartDragY;
@CtrlType
@@ -226,6 +236,11 @@
mService = service;
}
+ @VisibleForTesting
+ Rect getWindowDragBounds() {
+ return mWindowDragBounds;
+ }
+
/**
* @param display The Display that the window being dragged is on.
*/
@@ -294,6 +309,7 @@
mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
+ mDisplay.getRealSize(mMaxVisibleSize);
mDragEnded = false;
}
@@ -335,44 +351,57 @@
mService.resumeRotationLocked();
}
- void startDragLocked(WindowState win, boolean resize, float startX, float startY) {
+ void startDrag(WindowState win, boolean resize, boolean preserveOrientation, float startX,
+ float startY) {
if (DEBUG_TASK_POSITIONING) {
- Slog.d(TAG, "startDragLocked: win=" + win + ", resize=" + resize
- + ", {" + startX + ", " + startY + "}");
+ Slog.d(TAG, "startDrag: win=" + win + ", resize=" + resize
+ + ", preserveOrientation=" + preserveOrientation + ", {" + startX + ", "
+ + startY + "}");
}
- mCtrlType = CTRL_NONE;
mTask = win.getTask();
- mStartDragX = startX;
- mStartDragY = startY;
-
// Use the dim bounds, not the original task bounds. The cursor
// movement should be calculated relative to the visible bounds.
// Also, use the dim bounds of the task which accounts for
// multiple app windows. Don't use any bounds from win itself as it
// may not be the same size as the task.
mTask.getDimBounds(mTmpRect);
+ startDrag(resize, preserveOrientation, startX, startY, mTmpRect);
+ }
+
+ @VisibleForTesting
+ void startDrag(boolean resize, boolean preserveOrientation,
+ float startX, float startY, Rect startBounds) {
+ mCtrlType = CTRL_NONE;
+ mStartDragX = startX;
+ mStartDragY = startY;
+ mPreserveOrientation = preserveOrientation;
if (resize) {
- if (startX < mTmpRect.left) {
+ if (startX < startBounds.left) {
mCtrlType |= CTRL_LEFT;
}
- if (startX > mTmpRect.right) {
+ if (startX > startBounds.right) {
mCtrlType |= CTRL_RIGHT;
}
- if (startY < mTmpRect.top) {
+ if (startY < startBounds.top) {
mCtrlType |= CTRL_TOP;
}
- if (startY > mTmpRect.bottom) {
+ if (startY > startBounds.bottom) {
mCtrlType |= CTRL_BOTTOM;
}
- mResizing = true;
+ mResizing = mCtrlType != CTRL_NONE;
}
- mWindowOriginalBounds.set(mTmpRect);
+ // In case of !isDockedInEffect we are using the union of all task bounds. These might be
+ // made up out of multiple windows which are only partially overlapping. When that happens,
+ // the orientation from the window of interest to the entire stack might diverge. However
+ // for now we treat them as the same.
+ mStartOrientationWasLandscape = startBounds.width() >= startBounds.height();
+ mWindowOriginalBounds.set(startBounds);
// Make sure we always have valid drag bounds even if the drag ends before any move events
// have been handled.
- mWindowDragBounds.set(mTmpRect);
+ mWindowDragBounds.set(startBounds);
}
private void endDragLocked() {
@@ -387,26 +416,7 @@
}
if (mCtrlType != CTRL_NONE) {
- // This is a resizing operation.
- final int deltaX = Math.round(x - mStartDragX);
- final int deltaY = Math.round(y - mStartDragY);
- int left = mWindowOriginalBounds.left;
- int top = mWindowOriginalBounds.top;
- int right = mWindowOriginalBounds.right;
- int bottom = mWindowOriginalBounds.bottom;
- if ((mCtrlType & CTRL_LEFT) != 0) {
- left = Math.min(left + deltaX, right - mMinVisibleWidth);
- }
- if ((mCtrlType & CTRL_TOP) != 0) {
- top = Math.min(top + deltaY, bottom - mMinVisibleHeight);
- }
- if ((mCtrlType & CTRL_RIGHT) != 0) {
- right = Math.max(left + mMinVisibleWidth, right + deltaX);
- }
- if ((mCtrlType & CTRL_BOTTOM) != 0) {
- bottom = Math.max(top + mMinVisibleHeight, bottom + deltaY);
- }
- mWindowDragBounds.set(left, top, right, bottom);
+ resizeDrag(x, y);
mTask.setDragResizing(true, DRAG_RESIZE_MODE_FREEFORM);
return false;
}
@@ -428,6 +438,168 @@
return false;
}
+ /**
+ * The user is drag - resizing the window.
+ *
+ * @param x The x coordinate of the current drag coordinate.
+ * @param y the y coordinate of the current drag coordinate.
+ */
+ @VisibleForTesting
+ void resizeDrag(float x, float y) {
+ // This is a resizing operation.
+ // We need to keep various constraints:
+ // 1. mMinVisible[Width/Height] <= [width/height] <= mMaxVisibleSize.[x/y]
+ // 2. The orientation is kept - if required.
+ final int deltaX = Math.round(x - mStartDragX);
+ final int deltaY = Math.round(y - mStartDragY);
+ int left = mWindowOriginalBounds.left;
+ int top = mWindowOriginalBounds.top;
+ int right = mWindowOriginalBounds.right;
+ int bottom = mWindowOriginalBounds.bottom;
+
+ // The aspect which we have to respect. Note that if the orientation does not need to be
+ // preserved the aspect will be calculated as 1.0 which neutralizes the following
+ // computations.
+ final float minAspect = !mPreserveOrientation
+ ? 1.0f
+ : (mStartOrientationWasLandscape ? MIN_ASPECT : (1.0f / MIN_ASPECT));
+ // Calculate the resulting width and height of the drag operation.
+ int width = right - left;
+ int height = bottom - top;
+ if ((mCtrlType & CTRL_LEFT) != 0) {
+ width = Math.max(mMinVisibleWidth, width - deltaX);
+ } else if ((mCtrlType & CTRL_RIGHT) != 0) {
+ width = Math.max(mMinVisibleWidth, width + deltaX);
+ }
+ if ((mCtrlType & CTRL_TOP) != 0) {
+ height = Math.max(mMinVisibleHeight, height - deltaY);
+ } else if ((mCtrlType & CTRL_BOTTOM) != 0) {
+ height = Math.max(mMinVisibleHeight, height + deltaY);
+ }
+
+ // If we have to preserve the orientation - check that we are doing so.
+ final float aspect = (float) width / (float) height;
+ if (mPreserveOrientation && ((mStartOrientationWasLandscape && aspect < MIN_ASPECT)
+ || (!mStartOrientationWasLandscape && aspect > (1.0 / MIN_ASPECT)))) {
+ // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major
+ // drag axis. What ever is producing the bigger rectangle will be chosen.
+ int width1;
+ int width2;
+ int height1;
+ int height2;
+ if (mStartOrientationWasLandscape) {
+ // Assuming that the width is our target we calculate the height.
+ width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width));
+ height1 = Math.min(height, Math.round((float)width1 / MIN_ASPECT));
+ if (height1 < mMinVisibleHeight) {
+ // If the resulting height is too small we adjust to the minimal size.
+ height1 = mMinVisibleHeight;
+ width1 = Math.max(mMinVisibleWidth,
+ Math.min(mMaxVisibleSize.x, Math.round((float)height1 * MIN_ASPECT)));
+ }
+ // Assuming that the height is our target we calculate the width.
+ height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height));
+ width2 = Math.max(width, Math.round((float)height2 * MIN_ASPECT));
+ if (width2 < mMinVisibleWidth) {
+ // If the resulting width is too small we adjust to the minimal size.
+ width2 = mMinVisibleWidth;
+ height2 = Math.max(mMinVisibleHeight,
+ Math.min(mMaxVisibleSize.y, Math.round((float)width2 / MIN_ASPECT)));
+ }
+ } else {
+ // Assuming that the width is our target we calculate the height.
+ width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width));
+ height1 = Math.max(height, Math.round((float)width1 * MIN_ASPECT));
+ if (height1 < mMinVisibleHeight) {
+ // If the resulting height is too small we adjust to the minimal size.
+ height1 = mMinVisibleHeight;
+ width1 = Math.max(mMinVisibleWidth,
+ Math.min(mMaxVisibleSize.x, Math.round((float)height1 / MIN_ASPECT)));
+ }
+ // Assuming that the height is our target we calculate the width.
+ height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height));
+ width2 = Math.min(width, Math.round((float)height2 / MIN_ASPECT));
+ if (width2 < mMinVisibleWidth) {
+ // If the resulting width is too small we adjust to the minimal size.
+ width2 = mMinVisibleWidth;
+ height2 = Math.max(mMinVisibleHeight,
+ Math.min(mMaxVisibleSize.y, Math.round((float)width2 * MIN_ASPECT)));
+ }
+ }
+
+ // Use the bigger of the two rectangles if the major change was positive, otherwise
+ // do the opposite.
+ final boolean grows = width > (right - left) || height > (bottom - top);
+ if (grows == (width1 * height1 > width2 * height2)) {
+ width = width1;
+ height = height1;
+ } else {
+ width = width2;
+ height = height2;
+ }
+ }
+
+ // Update mWindowDragBounds to the new drag size.
+ updateDraggedBounds(left, top, right, bottom, width, height);
+ }
+
+ /**
+ * Given the old coordinates and the new width and height, update the mWindowDragBounds.
+ *
+ * @param left The original left bound before the user started dragging.
+ * @param top The original top bound before the user started dragging.
+ * @param right The original right bound before the user started dragging.
+ * @param bottom The original bottom bound before the user started dragging.
+ * @param newWidth The new dragged width.
+ * @param newHeight The new dragged height.
+ */
+ void updateDraggedBounds(int left, int top, int right, int bottom, int newWidth,
+ int newHeight) {
+ // Generate the final bounds by keeping the opposite drag edge constant.
+ if ((mCtrlType & CTRL_LEFT) != 0) {
+ left = right - newWidth;
+ } else { // Note: The right might have changed - if we pulled at the right or not.
+ right = left + newWidth;
+ }
+ if ((mCtrlType & CTRL_TOP) != 0) {
+ top = bottom - newHeight;
+ } else { // Note: The height might have changed - if we pulled at the bottom or not.
+ bottom = top + newHeight;
+ }
+
+ mWindowDragBounds.set(left, top, right, bottom);
+
+ checkBoundsForOrientationViolations(mWindowDragBounds);
+ }
+
+ /**
+ * Validate bounds against orientation violations (if DEBUG_ORIENTATION_VIOLATIONS is set).
+ *
+ * @param bounds The bounds to be checked.
+ */
+ private void checkBoundsForOrientationViolations(Rect bounds) {
+ // When using debug check that we are not violating the given constraints.
+ if (DEBUG_ORIENTATION_VIOLATIONS) {
+ if (mStartOrientationWasLandscape != (bounds.width() >= bounds.height())) {
+ Slog.e(TAG, "Orientation violation detected! should be "
+ + (mStartOrientationWasLandscape ? "landscape" : "portrait")
+ + " but is the other");
+ } else {
+ Slog.v(TAG, "new bounds size: " + bounds.width() + " x " + bounds.height());
+ }
+ if (mMinVisibleWidth > bounds.width() || mMinVisibleHeight > bounds.height()) {
+ Slog.v(TAG, "Minimum requirement violated: Width(min, is)=(" + mMinVisibleWidth
+ + ", " + bounds.width() + ") Height(min,is)=("
+ + mMinVisibleHeight + ", " + bounds.height() + ")");
+ }
+ if (mMaxVisibleSize.x < bounds.width() || mMaxVisibleSize.y < bounds.height()) {
+ Slog.v(TAG, "Maximum requirement violated: Width(min, is)=(" + mMaxVisibleSize.x
+ + ", " + bounds.width() + ") Height(min,is)=("
+ + mMaxVisibleSize.y + ", " + bounds.height() + ")");
+ }
+ }
+ }
+
private void updateWindowDragBounds(int x, int y, Rect stackBounds) {
final int offsetX = Math.round(x - mStartDragX);
final int offsetY = Math.round(y - mStartDragY);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 203ba72..74c0919 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -859,7 +859,9 @@
}
// TODO: Should each user have there own stacks?
+ @Override
void switchUser() {
+ super.switchUser();
int top = mChildren.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
Task task = mChildren.get(taskNdx);
@@ -1183,7 +1185,7 @@
@Override
public boolean dimFullscreen() {
- return mStackId == HOME_STACK_ID || fillsParent();
+ return StackId.isHomeOrRecentsStack(mStackId) || fillsParent();
}
@Override
@@ -1488,30 +1490,6 @@
}
}
- void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
- DisplayContent.GetWindowOnDisplaySearchResult result) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task task = mChildren.get(i);
- task.getWindowOnDisplayBeforeToken(dc, token, result);
- if (result.reachedToken) {
- // We have reach the token we are interested in. End search.
- return;
- }
- }
- }
-
- void getWindowOnDisplayAfterToken(DisplayContent dc, WindowToken token,
- DisplayContent.GetWindowOnDisplaySearchResult result) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task task = mChildren.get(i);
- task.getWindowOnDisplayAfterToken(dc, token, result);
- if (result.foundWindow != null) {
- // We have found a window after the token. End search.
- return;
- }
- }
- }
-
@Override
int getOrientation() {
return (StackId.canSpecifyOrientation(mStackId))
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 8dbf2b3..feceb8e 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import com.android.internal.util.ToBooleanFunction;
+
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -51,7 +53,7 @@
*/
class WallpaperController {
private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperController" : TAG_WM;
- final private WindowManagerService mService;
+ private WindowManagerService mService;
private final ArrayList<WallpaperWindowToken> mWallpaperTokens = new ArrayList<>();
@@ -97,6 +99,78 @@
private final FindWallpaperTargetResult mFindResults = new FindWallpaperTargetResult();
+ private final ToBooleanFunction<WindowState> mFindWallpaperTargetFunction = w -> {
+ final WindowAnimator winAnimator = mService.mAnimator;
+ if ((w.mAttrs.type == TYPE_WALLPAPER)) {
+ if (mFindResults.topWallpaper == null || mFindResults.resetTopWallpaper) {
+ mFindResults.setTopWallpaper(w);
+ mFindResults.resetTopWallpaper = false;
+ }
+ return false;
+ }
+
+ mFindResults.resetTopWallpaper = true;
+ if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
+ // If this window's app token is hidden and not animating, it is of no interest to us.
+ if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG,
+ "Skipping hidden and not animating token: " + w);
+ return false;
+ }
+ }
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": isOnScreen=" + w.isOnScreen()
+ + " mDrawState=" + w.mWinAnimator.mDrawState);
+
+ if (w.mWillReplaceWindow && mWallpaperTarget == null
+ && !mFindResults.useTopWallpaperAsTarget) {
+ // When we are replacing a window and there was wallpaper before replacement, we want to
+ // keep the window until the new windows fully appear and can determine the visibility,
+ // to avoid flickering.
+ mFindResults.setUseTopWallpaperAsTarget(true);
+ }
+
+ final boolean keyguardGoingAwayWithWallpaper = (w.mAppToken != null
+ && AppTransition.isKeyguardGoingAwayTransit(
+ w.mAppToken.mAppAnimator.getTransit())
+ && (w.mAppToken.mAppAnimator.getTransitFlags()
+ & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
+
+ boolean needsShowWhenLockedWallpaper = false;
+ if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
+ && mService.mPolicy.isKeyguardLocked()
+ && mService.mPolicy.isKeyguardOccluded()) {
+ // The lowest show when locked window decides whether we need to put the wallpaper
+ // behind.
+ needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
+ || (w.mAppToken != null && !w.mAppToken.fillsParent());
+ }
+
+ if (keyguardGoingAwayWithWallpaper || needsShowWhenLockedWallpaper) {
+ // Keep the wallpaper during Keyguard exit but also when it's needed for a
+ // non-fullscreen show when locked activity.
+ mFindResults.setUseTopWallpaperAsTarget(true);
+ }
+
+ final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
+ if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: " + w);
+ mFindResults.setWallpaperTarget(w);
+ if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
+ // The current wallpaper target is animating, so we'll look behind it for
+ // another possible target and figure out what is going on later.
+ if (DEBUG_WALLPAPER) Slog.v(TAG,
+ "Win " + w + ": token animating, looking behind.");
+ }
+ // Found a target! End search.
+ return true;
+ } else if (w == winAnimator.mWindowDetachedWallpaper) {
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "Found animating detached wallpaper target win: " + w);
+ mFindResults.setUseTopWallpaperAsTarget(true);
+ }
+ return false;
+ };
+
public WallpaperController(WindowManagerService service) {
mService = service;
}
@@ -371,89 +445,18 @@
return mWallpaperAnimLayerAdjustment;
}
- private void findWallpaperTarget(DisplayContent dc , FindWallpaperTargetResult result) {
- final WindowAnimator winAnimator = mService.mAnimator;
- result.reset();
+ private void findWallpaperTarget(DisplayContent dc) {
+ mFindResults.reset();
if (mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
// In freeform mode we set the wallpaper as its own target, so we don't need an
// additional window to make it visible.
- result.setUseTopWallpaperAsTarget(true);
+ mFindResults.setUseTopWallpaperAsTarget(true);
}
- dc.forAllWindows(w -> {
- if ((w.mAttrs.type == TYPE_WALLPAPER)) {
- if (result.topWallpaper == null || result.resetTopWallpaper) {
- result.setTopWallpaper(w);
- result.resetTopWallpaper = false;
- }
- return false;
- }
+ dc.forAllWindows(mFindWallpaperTargetFunction, true /* traverseTopToBottom */);
- result.resetTopWallpaper = true;
- if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
- // If this window's app token is hidden and not animating,
- // it is of no interest to us.
- if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "Skipping hidden and not animating token: " + w);
- return false;
- }
- }
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": isOnScreen=" + w.isOnScreen()
- + " mDrawState=" + w.mWinAnimator.mDrawState);
-
- if (w.mWillReplaceWindow && mWallpaperTarget == null
- && !result.useTopWallpaperAsTarget) {
- // When we are replacing a window and there was wallpaper before replacement, we
- // want to keep the window until the new windows fully appear and can determine the
- // visibility, to avoid flickering.
- result.setUseTopWallpaperAsTarget(true);
- }
-
- final boolean keyguardGoingAwayWithWallpaper = (w.mAppToken != null
- && AppTransition.isKeyguardGoingAwayTransit(
- w.mAppToken.mAppAnimator.getTransit())
- && (w.mAppToken.mAppAnimator.getTransitFlags()
- & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
-
- boolean needsShowWhenLockedWallpaper = false;
- if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
- && mService.mPolicy.isKeyguardLocked()
- && mService.mPolicy.isKeyguardOccluded()) {
- // The lowest show when locked window decides whether we need to put the wallpaper
- // behind.
- needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
- || (w.mAppToken != null && !w.mAppToken.fillsParent());
- }
-
- if (keyguardGoingAwayWithWallpaper || needsShowWhenLockedWallpaper) {
- // Keep the wallpaper during Keyguard exit but also when it's needed for a
- // non-fullscreen show when locked activity.
- result.setUseTopWallpaperAsTarget(true);
- }
-
- final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
- if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: " + w);
- result.setWallpaperTarget(w);
- if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
- // The current wallpaper target is animating, so we'll look behind it for
- // another possible target and figure out what is going on later.
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "Win " + w + ": token animating, looking behind.");
- }
- // Found a target! End search.
- return true;
- } else if (w == winAnimator.mWindowDetachedWallpaper) {
- if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
- "Found animating detached wallpaper target win: " + w);
- result.setUseTopWallpaperAsTarget(true);
- }
- return false;
- }, true /* traverseTopToBottom */);
-
- if (result.wallpaperTarget == null && result.useTopWallpaperAsTarget) {
- result.setWallpaperTarget(result.topWallpaper);
+ if (mFindResults.wallpaperTarget == null && mFindResults.useTopWallpaperAsTarget) {
+ mFindResults.setWallpaperTarget(mFindResults.topWallpaper);
}
}
@@ -552,7 +555,7 @@
// First find top-most window that has asked to be on top of the wallpaper;
// all wallpapers go behind it.
- findWallpaperTarget(dc, mFindResults);
+ findWallpaperTarget(dc);
updateWallpaperWindowsTarget(dc, mFindResults);
// The window is visible to the compositor...but is it visible to the user?
@@ -683,24 +686,6 @@
}
}
- void dumpTokens(PrintWriter pw, String prefix, boolean dumpAll) {
- if (!mWallpaperTokens.isEmpty()) {
- pw.println();
- pw.print(prefix); pw.println("Wallpaper tokens:");
- for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
- WindowToken token = mWallpaperTokens.get(i);
- pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
- pw.print(' '); pw.print(token);
- if (dumpAll) {
- pw.println(':');
- token.dump(pw, " ");
- } else {
- pw.println();
- }
- }
- }
- }
-
/** Helper class for storing the results of a wallpaper target find operation. */
final private static class FindWallpaperTargetResult {
WindowState topWallpaper = null;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a6a907c..02376e9 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -18,13 +18,13 @@
import android.annotation.CallSuper;
import android.content.res.Configuration;
-import android.view.animation.Animation;
+import android.util.Pools;
+
import com.android.internal.util.ToBooleanFunction;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
@@ -69,6 +69,9 @@
// The specified orientation for this window container.
protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+ private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
+ new Pools.SynchronizedPool<>(3);
+
final protected WindowContainer getParent() {
return mParent;
}
@@ -483,19 +486,11 @@
return false;
}
- /**
- * Rebuilds the WindowList for the input display content.
- * @param addIndex The index in the window list to add the next entry to.
- * @return The next index in the window list to.
- */
- // TODO: Hoping we can get rid of WindowList so this method wouldn't be needed.
- int rebuildWindowList(int addIndex) {
- final int count = mChildren.size();
- for (int i = 0; i < count; i++) {
- final WindowContainer wc = mChildren.get(i);
- addIndex = wc.rebuildWindowList(addIndex);
+ // TODO: Users would have their own window containers under the display container?
+ void switchUser() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ mChildren.get(i).switchUser();
}
- return addIndex;
}
/**
@@ -505,7 +500,7 @@
* @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
* z-order, else from bottom-to-top.
* @return True if the search ended before we reached the end of the hierarchy due to
- * {@link Function#apply} returning true.
+ * {@link ToBooleanFunction#apply} returning true.
*/
boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
if (traverseTopToBottom) {
@@ -526,10 +521,9 @@
}
void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
- forAllWindows(w -> {
- callback.accept(w);
- return false;
- }, traverseTopToBottom);
+ ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
+ forAllWindows(wrapper, traverseTopToBottom);
+ wrapper.release();
}
WindowState getWindow(Predicate<WindowState> callback) {
@@ -622,4 +616,32 @@
return toString();
}
+ private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
+ ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
+ if (wrapper == null) {
+ wrapper = new ForAllWindowsConsumerWrapper();
+ }
+ wrapper.setConsumer(consumer);
+ return wrapper;
+ }
+
+ private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
+
+ private Consumer<WindowState> mConsumer;
+
+ void setConsumer(Consumer<WindowState> consumer) {
+ mConsumer = consumer;
+ }
+
+ @Override
+ public boolean apply(WindowState w) {
+ mConsumer.accept(w);
+ return false;
+ }
+
+ void release() {
+ mConsumer = null;
+ mConsumerWrapperPool.release(this);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index 32373f9..e0c3d60 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -20,6 +20,7 @@
import android.view.Display;
import java.util.ArrayDeque;
+import java.util.function.Consumer;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
@@ -66,46 +67,50 @@
private boolean mAnyLayerChanged;
private int mHighestLayerInImeTargetBaseLayer;
private WindowState mImeTarget;
+ private boolean mAboveImeTarget;
+ private ArrayDeque<WindowState> mAboveImeTargetAppWindows = new ArrayDeque();
+
+ private final Consumer<WindowState> mAssignWindowLayersConsumer = w -> {
+ boolean layerChanged = false;
+
+ int oldLayer = w.mLayer;
+ if (w.mBaseLayer == mCurBaseLayer) {
+ mCurLayer += WINDOW_LAYER_MULTIPLIER;
+ } else {
+ mCurBaseLayer = mCurLayer = w.mBaseLayer;
+ }
+ assignAnimLayer(w, mCurLayer);
+
+ // TODO: Preserved old behavior of code here but not sure comparing oldLayer to
+ // mAnimLayer and mLayer makes sense...though the worst case would be unintentional
+ // layer reassignment.
+ if (w.mLayer != oldLayer || w.mWinAnimator.mAnimLayer != oldLayer) {
+ layerChanged = true;
+ mAnyLayerChanged = true;
+ }
+
+ if (w.mAppToken != null) {
+ mHighestApplicationLayer = Math.max(mHighestApplicationLayer,
+ w.mWinAnimator.mAnimLayer);
+ }
+ if (mImeTarget != null && w.mBaseLayer == mImeTarget.mBaseLayer) {
+ mHighestLayerInImeTargetBaseLayer = Math.max(mHighestLayerInImeTargetBaseLayer,
+ w.mWinAnimator.mAnimLayer);
+ }
+
+ collectSpecialWindows(w);
+
+ if (layerChanged) {
+ w.scheduleAnimationIfDimming();
+ }
+ };
final void assignWindowLayers(DisplayContent dc) {
if (DEBUG_LAYERS) Slog.v(TAG_WM, "Assigning layers based",
new RuntimeException("here").fillInStackTrace());
reset();
- dc.forAllWindows((w) -> {
- boolean layerChanged = false;
-
- int oldLayer = w.mLayer;
- if (w.mBaseLayer == mCurBaseLayer) {
- mCurLayer += WINDOW_LAYER_MULTIPLIER;
- } else {
- mCurBaseLayer = mCurLayer = w.mBaseLayer;
- }
- assignAnimLayer(w, mCurLayer);
-
- // TODO: Preserved old behavior of code here but not sure comparing oldLayer to
- // mAnimLayer and mLayer makes sense...though the worst case would be unintentional
- // layer reassignment.
- if (w.mLayer != oldLayer || w.mWinAnimator.mAnimLayer != oldLayer) {
- layerChanged = true;
- mAnyLayerChanged = true;
- }
-
- if (w.mAppToken != null) {
- mHighestApplicationLayer = Math.max(mHighestApplicationLayer,
- w.mWinAnimator.mAnimLayer);
- }
- if (mImeTarget != null && w.mBaseLayer == mImeTarget.mBaseLayer) {
- mHighestLayerInImeTargetBaseLayer = Math.max(mHighestLayerInImeTargetBaseLayer,
- w.mWinAnimator.mAnimLayer);
- }
-
- collectSpecialWindows(w);
-
- if (layerChanged) {
- w.scheduleAnimationIfDimming();
- }
- }, false /* traverseTopToBottom */);
+ dc.forAllWindows(mAssignWindowLayersConsumer, false /* traverseTopToBottom */);
adjustSpecialWindows();
@@ -143,6 +148,8 @@
mImeTarget = mService.mInputMethodTarget;
mHighestLayerInImeTargetBaseLayer = (mImeTarget != null) ? mImeTarget.mBaseLayer : 0;
+ mAboveImeTarget = false;
+ mAboveImeTargetAppWindows.clear();
}
private void collectSpecialWindows(WindowState w) {
@@ -157,6 +164,20 @@
mInputMethodWindows.add(w);
return;
}
+ if (mImeTarget != null) {
+ if (w.getParentWindow() == mImeTarget && w.mSubLayer > 0) {
+ // Child windows of the ime target with a positive sub-layer should be placed above
+ // the IME.
+ mAboveImeTargetAppWindows.add(w);
+ } else if (mAboveImeTarget && w.mAppToken != null) {
+ // windows of apps above the IME target should be placed above the IME.
+ mAboveImeTargetAppWindows.add(w);
+ }
+ if (w == mImeTarget) {
+ mAboveImeTarget = true;
+ }
+ }
+
final Task task = w.getTask();
if (task == null) {
return;
@@ -211,6 +232,12 @@
while (!mInputMethodWindows.isEmpty()) {
layer = assignAndIncreaseLayerIfNeeded(mInputMethodWindows.remove(), layer);
}
+
+ // Adjust app windows the should be displayed above the IME since they are above the IME
+ // target.
+ while (!mAboveImeTargetAppWindows.isEmpty()) {
+ layer = assignAndIncreaseLayerIfNeeded(mAboveImeTargetAppWindows.remove(), layer);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 51e8a56..e68960c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -604,17 +604,6 @@
boolean mInputMethodTargetWaitingAnim;
WindowState mInputMethodWindow = null;
- // TODO: Remove with extreme prejudice! This list is maintained so that we can keep track of
- // dialogs that should go on top of the IME so they can be re-arranged in the window list any
- // time the IME changes position in the window list. Normally you would have a dialog be a child
- // window of the IME, but they don't share the same token since they are added by different
- // clients. This doesn't really affect what the user sees on screen since this dialogs have an
- // higher base layer than the IME window, but it will affect users of the window list that
- // expect the list to represent the order of things on-screen (e.g input service). This makes
- // the code for managing the window list hard to follow (see all the places it is used).
- // We can remove the use of this field when we automatically assign layers and z-order the
- // window list before it is used whenever window container order changes.
- final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<>();
boolean mHardKeyboardAvailable;
WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
@@ -1375,19 +1364,15 @@
boolean imMayMove = true;
+ win.mToken.addWindow(win);
if (type == TYPE_INPUT_METHOD) {
win.mGivenInsetsPending = true;
- mInputMethodWindow = win;
- win.mToken.addImeWindow(win);
+ setInputMethodWindowLocked(win);
imMayMove = false;
} else if (type == TYPE_INPUT_METHOD_DIALOG) {
- mInputMethodDialogs.add(win);
- win.mToken.addWindow(win);
- displayContent.moveInputMethodDialogs(
- displayContent.findDesiredInputMethodWindowIndex(true));
+ displayContent.computeImeTarget(true /* updateImeTarget */);
imMayMove = false;
} else {
- win.mToken.addWindow(win);
if (type == TYPE_WALLPAPER) {
displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
@@ -1461,7 +1446,7 @@
}
if (imMayMove) {
- displayContent.moveInputMethodWindowsIfNeeded(false);
+ displayContent.computeImeTarget(true /* updateImeTarget */);
}
// Don't do layout here, the window must call
@@ -1644,9 +1629,7 @@
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
if (mInputMethodWindow == win) {
- mInputMethodWindow = null;
- } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
- mInputMethodDialogs.remove(win);
+ setInputMethodWindowLocked(null);
}
final WindowToken token = win.mToken;
@@ -1654,7 +1637,7 @@
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token);
// Window will already be removed from token before this post clean-up method is called.
if (token.isEmpty()) {
- if (!token.explicit) {
+ if (!token.mPersistOnEmpty) {
token.removeImmediately();
} else if (atoken != null) {
// TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after
@@ -1676,19 +1659,24 @@
dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
- if (dc != null && dc.removeFromWindowList(win)) {
- if (!mWindowPlacerLocked.isInLayout()) {
- dc.assignWindowLayers(true /* setLayoutNeeded */);
- mWindowPlacerLocked.performSurfacePlacement();
- if (win.mAppToken != null) {
- win.mAppToken.updateReportedVisibilityLocked();
- }
+ if (dc != null && !mWindowPlacerLocked.isInLayout()) {
+ dc.assignWindowLayers(true /* setLayoutNeeded */);
+ mWindowPlacerLocked.performSurfacePlacement();
+ if (win.mAppToken != null) {
+ win.mAppToken.updateReportedVisibilityLocked();
}
}
mInputMonitor.updateInputWindowsLw(true /*force*/);
}
+ void setInputMethodWindowLocked(WindowState win) {
+ mInputMethodWindow = win;
+ final DisplayContent dc = win != null
+ ? win.getDisplayContent() : getDefaultDisplayContentLocked();
+ dc.computeImeTarget(true /* updateImeTarget */);
+ }
+
private void updateAppOpsState() {
synchronized(mWindowMap) {
mRoot.updateAppOpsState();
@@ -1997,7 +1985,7 @@
focusMayChange = isDefaultDisplay;
}
if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
- mInputMethodWindow = win;
+ setInputMethodWindowLocked(win);
imMayMove = true;
}
win.adjustStartingWindowFlags();
@@ -2063,14 +2051,15 @@
// reassign them at this point if the IM window state gets shuffled
boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
final DisplayContent dc = win.getDisplayContent();
- if (imMayMove && (dc.moveInputMethodWindowsIfNeeded(false) || toBeDisplayed)) {
- // Little hack here -- we -should- be able to rely on the function to return true if
- // the IME has moved and needs its layer recomputed. However, if the IME was hidden
- // and isn't actually moved in the list, its layer may be out of data so we make
- // sure to recompute it.
- // TODO: Probably not needed once the window list always has the right z-ordering
- // when the window hierarchy is updated.
- dc.assignWindowLayers(false /* setLayoutNeeded */);
+ if (imMayMove) {
+ dc.computeImeTarget(true /* updateImeTarget */);
+ if (toBeDisplayed) {
+ // Little hack here -- we -should- be able to rely on the function to return
+ // true if the IME has moved and needs its layer recomputed. However, if the IME
+ // was hidden and isn't actually moved in the list, its layer may be out of data
+ // so we make sure to recompute it.
+ dc.assignWindowLayers(false /* setLayoutNeeded */);
+ }
}
if (wallpaperMayMove) {
@@ -2164,7 +2153,7 @@
win.mWinAnimator.mAnimating = true;
} else {
if (mInputMethodWindow == win) {
- mInputMethodWindow = null;
+ setInputMethodWindowLocked(null);
}
win.destroyOrSaveSurface();
}
@@ -2443,8 +2432,6 @@
return;
}
- token.setExiting();
-
mInputMonitor.updateInputWindowsLw(true /*force*/);
}
} finally {
@@ -3350,7 +3337,7 @@
if (mAppTransition.isTransitionSet()) {
task.setSendingToBottom(false);
}
- displayContent.rebuildAppWindowsAndLayoutIfNeeded();
+ displayContent.layoutAndAssignWindowLayersIfNeeded();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -3372,7 +3359,7 @@
if (mAppTransition.isTransitionSet()) {
task.setSendingToBottom(true);
}
- stack.getDisplayContent().rebuildAppWindowsAndLayoutIfNeeded();
+ stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -3615,6 +3602,11 @@
}
@Override
+ public WindowManagerPolicy.WindowState getInputMethodWindowLw() {
+ return mInputMethodWindow;
+ }
+
+ @Override
public void notifyKeyguardTrustedChanged() {
mH.sendEmptyMessage(H.NOTIFY_KEYGUARD_TRUSTED_CHANGED);
}
@@ -4090,24 +4082,6 @@
}
}
- // Called by window manager policy. Not exposed externally.
- @Override
- public boolean isInputMethodWindowVisible() {
- synchronized (mWindowMap) {
- return mInputMethodWindow != null && mInputMethodWindow.isVisibleLw();
- }
- }
-
- // Called by window manager policy. Not exposed externally.
- @Override
- public void hideCurrentInputMethod() {
- final InputMethodManagerInternal inputMethodManagerInternal =
- LocalServices.getService(InputMethodManagerInternal.class);
- if (inputMethodManagerInternal != null) {
- inputMethodManagerInternal.hideCurrentInputMethod();
- }
- }
-
// Called by window manager policy. Not exposed externally.
@Override
public void lockDeviceNow() {
@@ -4629,7 +4603,7 @@
return null;
}
}
- return displayContent.screenshotApplications(appToken, displayId, width, height,
+ return displayContent.screenshotApplications(appToken, width, height,
includeFullDisplay, frameScale, config, wallpaperOnly);
}
@@ -5191,7 +5165,7 @@
boolean result = true;
- final WindowList windows = new WindowList();
+ final ArrayList<WindowState> windows = new ArrayList();
synchronized (mWindowMap) {
mRoot.forAllWindows(w -> {
windows.add(w);
@@ -5757,7 +5731,8 @@
win = windowForClientLocked(null, window, false);
// win shouldn't be null here, pass it down to startPositioningLocked
// to get warning if it's null.
- if (!startPositioningLocked(win, false /*resize*/, startX, startY)) {
+ if (!startPositioningLocked(
+ win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
return false;
}
}
@@ -5772,8 +5747,8 @@
synchronized (mWindowMap) {
final Task task = displayContent.findTaskForResizePoint(x, y);
if (task != null) {
- if (!startPositioningLocked(
- task.getTopVisibleAppMainWindow(), true /*resize*/, x, y)) {
+ if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
+ task.preserveOrientationOnResize(), x, y)) {
return;
}
taskId = task.mTaskId;
@@ -5788,10 +5763,12 @@
}
}
- private boolean startPositioningLocked(
- WindowState win, boolean resize, float startX, float startY) {
- if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "startPositioningLocked: "
- + "win=" + win + ", resize=" + resize + ", {" + startX + ", " + startY + "}");
+ private boolean startPositioningLocked(WindowState win, boolean resize,
+ boolean preserveOrientation, float startX, float startY) {
+ if (DEBUG_TASK_POSITIONING)
+ Slog.d(TAG_WM, "startPositioningLocked: "
+ + "win=" + win + ", resize=" + resize + ", preserveOrientation="
+ + preserveOrientation + ", {" + startX + ", " + startY + "}");
if (win == null || win.getAppToken() == null) {
Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
@@ -5832,7 +5809,7 @@
return false;
}
- mTaskPositioner.startDragLocked(win, resize, startX, startY);
+ mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
return true;
}
@@ -7286,7 +7263,7 @@
changes |= FINISH_LAYOUT_REDO_LAYOUT;
if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
"Wallpaper layer changed: assigning layers + relayout");
- dc.moveInputMethodWindowsIfNeeded(true);
+ dc.computeImeTarget(true /* updateImeTarget */);
mRoot.mWallpaperMayChange = true;
// Since the window list has been rebuilt, focus might have to be recomputed since the
// actual order of windows might have changed again.
@@ -7379,10 +7356,25 @@
mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
// TODO(multidisplay): Focused windows on default display only.
final DisplayContent displayContent = getDefaultDisplayContentLocked();
- final boolean imWindowChanged = displayContent.moveInputMethodWindowsIfNeeded(
- mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
- && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
+ boolean imWindowChanged = false;
+ if (mInputMethodWindow != null) {
+ final WindowState prevTarget = mInputMethodTarget;
+ final WindowState newTarget =
+ displayContent.computeImeTarget(true /* updateImeTarget*/);
+
+ imWindowChanged = prevTarget != newTarget;
+
+ if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
+ && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
+ final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer;
+ displayContent.assignWindowLayers(false /* setLayoutNeeded */);
+ imWindowChanged |=
+ prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer;
+ }
+ }
+
if (imWindowChanged) {
+ mWindowsChanged = true;
displayContent.setLayoutNeeded();
newFocus = mRoot.computeFocusedWindow();
}
@@ -7857,7 +7849,6 @@
private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
mRoot.dumpTokens(pw, dumpAll);
- mRoot.mWallpaperController.dumpTokens(pw, " ", dumpAll);
if (!mFinishedStarting.isEmpty()) {
pw.println();
pw.println(" Finishing start of application tokens:");
@@ -7903,16 +7894,6 @@
ArrayList<WindowState> windows) {
mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
- if (mInputMethodDialogs.size() > 0) {
- pw.println();
- pw.println(" Input method dialogs:");
- for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
- WindowState w = mInputMethodDialogs.get(i);
- if (windows == null || windows.contains(w)) {
- pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
- }
- }
- }
if (mPendingRemove.size() > 0) {
pw.println();
pw.println(" Remove pending for:");
@@ -8071,7 +8052,7 @@
private boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti,
boolean dumpAll) {
- final WindowList windows = new WindowList();
+ final ArrayList<WindowState> windows = new ArrayList();
if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
final boolean appsOnly = name.contains("apps");
final boolean visibleOnly = name.contains("visible");
@@ -8924,7 +8905,7 @@
return;
}
- token.removeAllWindows();
+ token.removeAllWindowsIfPossible();
}
WindowManagerService.this.removeWindowToken(binder, displayId);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 572581e..e2027fd 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -60,8 +60,6 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
-import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
import static android.app.ActivityManager.StackId;
@@ -76,6 +74,7 @@
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
@@ -91,7 +90,6 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
@@ -115,6 +113,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -140,9 +139,6 @@
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
-class WindowList extends ArrayList<WindowState> {
-}
-
/** A window in the window manager. */
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState {
static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM;
@@ -448,12 +444,6 @@
*/
boolean mWindowRemovalAllowed;
- /**
- * Temp for keeping track of windows that have been removed when
- * rebuilding window list.
- */
- boolean mRebuilding;
-
// Input channel and input window handle used by the input dispatcher.
final InputWindowHandle mInputWindowHandle;
InputChannel mInputChannel;
@@ -1654,18 +1644,16 @@
&& (!mIsChildWindow || !getParentWindow().hasMoved());
}
- boolean isObscuringFullscreen(final DisplayInfo displayInfo) {
+ boolean isObscuringDisplay() {
Task task = getTask();
if (task != null && task.mStack != null && !task.mStack.fillsParent()) {
return false;
}
- if (!isOpaqueDrawn() || !isFrameFullscreen(displayInfo)) {
- return false;
- }
- return true;
+ return isOpaqueDrawn() && fillsDisplay();
}
- boolean isFrameFullscreen(final DisplayInfo displayInfo) {
+ boolean fillsDisplay() {
+ final DisplayInfo displayInfo = getDisplayInfo();
return mFrame.left <= 0 && mFrame.top <= 0
&& mFrame.right >= displayInfo.appWidth && mFrame.bottom >= displayInfo.appHeight;
}
@@ -1726,7 +1714,7 @@
final DisplayContent dc = getDisplayContent();
if (mService.mInputMethodTarget == this) {
- dc.moveInputMethodWindowsIfNeeded(false);
+ dc.computeImeTarget(true /* updateImeTarget */);
}
final int type = mAttrs.type;
@@ -1936,6 +1924,41 @@
return mLayer + specialAdjustment;
}
+ boolean canBeImeTarget() {
+ if (mIsImWindow) {
+ // IME windows can't be IME targets. IME targets are required to be below the IME
+ // windows and that wouldn't be possible if the IME window is its own target...silly.
+ return false;
+ }
+
+ final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
+ final int type = mAttrs.type;
+
+ // Can only be an IME target if both FLAG_NOT_FOCUSABLE and FLAG_ALT_FOCUSABLE_IM are set or
+ // both are cleared...and not a starting window.
+ if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
+ && type != TYPE_APPLICATION_STARTING) {
+ return false;
+ }
+
+ if (DEBUG_INPUT_METHOD) {
+ Slog.i(TAG_WM, "isVisibleOrAdding " + this + ": " + isVisibleOrAdding());
+ if (!isVisibleOrAdding()) {
+ Slog.i(TAG_WM, " mSurfaceController=" + mWinAnimator.mSurfaceController
+ + " relayoutCalled=" + mRelayoutCalled
+ + " viewVis=" + mViewVisibility
+ + " policyVis=" + mPolicyVisibility
+ + " policyVisAfterAnim=" + mPolicyVisibilityAfterAnim
+ + " parentHidden=" + isParentWindowHidden()
+ + " exiting=" + mAnimatingExit + " destroying=" + mDestroying);
+ if (mAppToken != null) {
+ Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + mAppToken.hiddenRequested);
+ }
+ }
+ }
+ return isVisibleOrAdding();
+ }
+
void scheduleAnimationIfDimming() {
final DisplayContent dc = getDisplayContent();
if (dc == null) {
@@ -2090,7 +2113,7 @@
return false;
}
- void removeReplacedWindow() {
+ private void removeReplacedWindow() {
if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + this);
if (isDimming()) {
transferDimToReplacement();
@@ -2143,6 +2166,16 @@
}
}
+ @Override
+ void switchUser() {
+ super.switchUser();
+ if (isHiddenFromUserLocked()) {
+ if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + this
+ + ", attrs=" + mAttrs.type + ", belonging to " + mOwnerUid);
+ hideLw(false);
+ }
+ }
+
int getTouchableRegion(Region region, int flags) {
final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
if (modal && mAppToken != null) {
@@ -2850,7 +2883,7 @@
mShowToOwnerOnly = showToOwnerOnly;
}
- boolean isHiddenFromUserLocked() {
+ private boolean isHiddenFromUserLocked() {
// Child windows are evaluated based on their parent window.
final WindowState win = getTopParentWindow();
if (win.mAttrs.type < FIRST_SYSTEM_WINDOW
@@ -3256,7 +3289,7 @@
pw.print(mPolicyVisibilityAfterAnim);
pw.print(" mAppOpVisibility=");
pw.print(mAppOpVisibility);
- pw.print(" parentHidden="); pw.println(isParentWindowHidden());
+ pw.print(" parentHidden="); pw.print(isParentWindowHidden());
pw.print(" mPermanentlyHidden="); pw.println(mPermanentlyHidden);
}
if (!mRelayoutCalled || mLayoutNeeded) {
@@ -3505,16 +3538,6 @@
return mIsChildWindow;
}
- /**
- * Returns the bottom child window in regards to z-order of this window or null if no children.
- */
- WindowState getBottomChild() {
- // Child windows are z-ordered based on sub-layer using {@link #sWindowSubLayerComparator}
- // and the child with the lowest z-order will be at the head of the list.
- WindowState c = mChildren.peekFirst();
- return c == null ? null : c;
- }
-
boolean layoutInParentFrame() {
return mIsChildWindow
&& (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
@@ -3529,16 +3552,23 @@
/** Returns the topmost parent window if this is a child of another window, else this. */
WindowState getTopParentWindow() {
- WindowState w = this;
- while (w != null && w.mIsChildWindow) {
- w = w.getParentWindow();
+ WindowState current = this;
+ WindowState topParent = current;
+ while (current != null && current.mIsChildWindow) {
+ current = current.getParentWindow();
+ // Parent window can be null if the child is detached from it's parent already, but
+ // someone still has a reference to access it. So, we return the top parent value we
+ // already have instead of null.
+ if (current != null) {
+ topParent = current;
+ }
}
- return w;
+ return topParent;
}
boolean isParentWindowHidden() {
final WindowState parent = getParentWindow();
- return (parent == null) ? false : parent.mHidden;
+ return parent != null && parent.mHidden;
}
void setWillReplaceWindow(boolean animate) {
@@ -3801,48 +3831,10 @@
}
@Override
- int rebuildWindowList(int addIndex) {
- return reAddWindow(addIndex);
- }
-
- // TODO: come-up with a better name for this method that represents what it does.
- // Or, it is probably not going to matter anyways if we are successful in getting rid of
- // the WindowList concept.
- int reAddWindow(int index) {
- final DisplayContent dc = getDisplayContent();
- // Adding child windows relies on child windows being ordered by mSubLayer using
- // {@link #sWindowSubLayerComparator}.
- final int childCount = mChildren.size();
- boolean winAdded = false;
- for (int j = 0; j < childCount; j++) {
- final WindowState child = mChildren.get(j);
- if (!winAdded && child.mSubLayer >= 0) {
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
- "Re-adding child window at " + index + ": " + child);
- mRebuilding = false;
- dc.addToWindowList(this, index);
- index++;
- winAdded = true;
- }
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at " + index + ": " + child);
- child.mRebuilding = false;
- dc.addToWindowList(child, index);
- index++;
- }
- if (!winAdded) {
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at " + index + ": " + this);
- mRebuilding = false;
- dc.addToWindowList(this, index);
- index++;
- }
- return index;
- }
-
- @Override
boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
if (mChildren.isEmpty()) {
// The window has no children so we just return it.
- return callback.apply(this);
+ return applyInOrderWithImeWindows(callback, traverseTopToBottom);
}
if (traverseTopToBottom) {
@@ -3871,7 +3863,7 @@
child = mChildren.get(i);
}
- if (callback.apply(this)) {
+ if (applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
return true;
}
@@ -3907,7 +3899,7 @@
child = mChildren.get(i);
}
- if (callback.apply(this)) {
+ if (applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
return true;
}
@@ -3925,6 +3917,35 @@
return false;
}
+ private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback,
+ boolean traverseTopToBottom) {
+ if (traverseTopToBottom) {
+ if (mService.mInputMethodTarget == this) {
+ // This window is the current IME target, so we need to process the IME windows
+ // directly above it.
+ if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ }
+ if (callback.apply(this)) {
+ return true;
+ }
+ } else {
+ if (callback.apply(this)) {
+ return true;
+ }
+ if (mService.mInputMethodTarget == this) {
+ // This window is the current IME target, so we need to process the IME windows
+ // directly above it.
+ if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
WindowState getWindow(Predicate<WindowState> callback) {
if (callback.test(this)) {
return this;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 04db499..37bd402 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -57,7 +57,6 @@
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.MagnificationSpec;
-import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -1108,10 +1107,9 @@
/**
* Calculate the window-space crop rect and fill clipRect.
- * @return true if clipRect has been filled otherwise, no window space
- * crop should be applied.
+ * @return true if clipRect has been filled otherwise, no window space crop should be applied.
*/
- boolean calculateCrop(Rect clipRect) {
+ private boolean calculateCrop(Rect clipRect) {
final WindowState w = mWin;
final DisplayContent displayContent = w.getDisplayContent();
clipRect.setEmpty();
@@ -1130,7 +1128,6 @@
return false;
}
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (DEBUG_WINDOW_CROP) Slog.d(TAG,
"Updating crop win=" + w + " mLastCrop=" + mLastClipRect);
@@ -1139,7 +1136,7 @@
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
+ w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
- final boolean fullscreen = w.isFrameFullscreen(displayInfo);
+ final boolean fullscreen = w.fillsDisplay();
final boolean isFreeformResizing =
w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 7e1880f..de80837 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -239,7 +239,8 @@
mService.mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
- displayContent.rebuildAppWindowList();
+ // TODO: Don't believe this is really needed...
+ //mService.mWindowsChanged = true;
mService.mRoot.mWallpaperMayChange = false;
@@ -356,12 +357,8 @@
displayContent.setLayoutNeeded();
// TODO(multidisplay): IMEs are only supported on the default display.
- // TODO: Probably not needed once the window list always has the right z-ordering
- // when the window hierarchy is updated.
final DisplayContent dc = mService.getDefaultDisplayContentLocked();
- if (!dc.moveInputMethodWindowsIfNeeded(true)) {
- dc.assignWindowLayers(false /*setLayoutNeeded*/);
- }
+ dc.computeImeTarget(true /* updateImeTarget */);
mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
true /*updateInputWindows*/);
mService.mFocusMayChange = false;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index a2eebc3..4b94d15 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -18,25 +18,18 @@
import java.util.Comparator;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-import android.os.Bundle;
import android.os.Debug;
import android.os.IBinder;
-import android.os.RemoteException;
import android.util.Slog;
-import android.view.DisplayInfo;
-import android.view.animation.Animation;
import java.io.PrintWriter;
@@ -58,8 +51,8 @@
final int windowType;
// Set if this token was explicitly added by a client, so should
- // not be removed when all windows are removed.
- final boolean explicit;
+ // persist (not be removed) when all windows are removed.
+ boolean mPersistOnEmpty;
// For printing.
String stringName;
@@ -104,27 +97,28 @@
return isFirstChildWindowGreaterThanSecond(newWindow, existingWindow) ? 1 : -1;
};
- WindowToken(WindowManagerService service, IBinder _token, int type, boolean _explicit,
+ WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
DisplayContent dc) {
mService = service;
token = _token;
windowType = type;
- explicit = _explicit;
+ mPersistOnEmpty = persistOnEmpty;
onDisplayChanged(dc);
}
- void removeAllWindows() {
+ void removeAllWindowsIfPossible() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState win = mChildren.get(i);
- if (DEBUG_WINDOW_MOVEMENT) Slog.w(TAG_WM, "removeAllWindows: removing win=" + win);
+ if (DEBUG_WINDOW_MOVEMENT) Slog.w(TAG_WM,
+ "removeAllWindowsIfPossible: removing win=" + win);
win.removeIfPossible();
- if (mChildren.contains(win)) {
- removeChild(win);
- }
}
}
void setExiting() {
+ // This token is exiting, so allow it to be removed when it no longer contains any windows.
+ mPersistOnEmpty = false;
+
if (hidden) {
return;
}
@@ -168,13 +162,6 @@
return highestAnimLayer;
}
- WindowState getTopWindow() {
- if (mChildren.isEmpty()) {
- return null;
- }
- return (WindowState) mChildren.get(mChildren.size() - 1).getTop();
- }
-
/**
* Returns true if the new window is considered greater than the existing window in terms of
* z-order.
@@ -189,51 +176,16 @@
if (DEBUG_FOCUS) Slog.d(TAG_WM,
"addWindow: win=" + win + " Callers=" + Debug.getCallers(5));
- if (!win.isChildWindow()) {
- if (asAppWindowToken() != null) {
- mDisplayContent.addAppWindowToWindowList(win);
- } else {
- mDisplayContent.addNonAppWindowToWindowList(win);
- }
-
- if (!mChildren.contains(win)) {
- if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
- addChild(win, mWindowComparator);
- }
- } else {
- mDisplayContent.addChildWindowToWindowList(win);
- }
- }
-
- void addImeWindow(WindowState win) {
- int pos = mDisplayContent.findDesiredInputMethodWindowIndex(true);
-
- if (pos < 0) {
- addWindow(win);
- mDisplayContent.moveInputMethodDialogs(pos);
+ if (win.isChildWindow()) {
+ // Child windows are added to their parent windows.
return;
}
-
- if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Adding input method window " + win + " at " + pos);
- mDisplayContent.addToWindowList(win, pos);
if (!mChildren.contains(win)) {
- addChild(win, null);
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
+ addChild(win, mWindowComparator);
+ mService.mWindowsChanged = true;
+ // TODO: Should we also be setting layout needed here and other places?
}
- mDisplayContent.moveInputMethodDialogs(pos + 1);
- }
-
- /** Return the first window in the token window list that isn't a starting window or null. */
- WindowState getFirstNonStartingWindow() {
- final int count = mChildren.size();
- // We only care about parent windows so no need to loop through child windows.
- for (int i = 0; i < count; i++) {
- final WindowState w = mChildren.get(i);
- if (w.mAttrs.type != TYPE_APPLICATION_STARTING) {
- return w;
- }
- }
- return null;
}
/** Returns true if the token windows list is empty. */
@@ -297,16 +249,8 @@
}
void onDisplayChanged(DisplayContent dc) {
- if (mDisplayContent == dc) {
- return;
- }
-
- if (mDisplayContent != null) {
- mDisplayContent.removeWindowToken(token);
- }
+ dc.reParentWindowToken(this);
mDisplayContent = dc;
- mDisplayContent.setWindowToken(token, this);
-
super.onDisplayChanged(dc);
}
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index ac0e622..50a6095 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -73,6 +73,7 @@
libhwbinder \
libutils \
android.hardware.audio.common@2.0 \
+ android.hardware.gnss@1.0 \
android.hardware.light@2.0 \
android.hardware.power@1.0 \
android.hardware.thermal@1.0 \
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 25e819c..7db6d42 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -18,10 +18,13 @@
#define LOG_NDEBUG 0
+#include <android/hardware/gnss/1.0/IGnss.h>
+
+#include <hwbinder/IPCThreadState.h>
+#include <hwbinder/ProcessState.h>
+
#include "JNIHelp.h"
#include "jni.h"
-#include "hardware/hardware.h"
-#include "hardware/gps_internal.h"
#include "hardware_legacy/power.h"
#include "utils/Log.h"
#include "utils/misc.h"
@@ -34,6 +37,7 @@
#include <linux/in6.h>
#include <pthread.h>
#include <string.h>
+#include <cinttypes>
static jobject mCallbacksObj = NULL;
@@ -58,978 +62,65 @@
static jmethodID method_reportMeasurementData;
static jmethodID method_reportNavigationMessages;
-static const GpsInterface* sGpsInterface = NULL;
-static const GpsXtraInterface* sGpsXtraInterface = NULL;
-static const AGpsInterface* sAGpsInterface = NULL;
-static const GpsNiInterface* sGpsNiInterface = NULL;
-static const GpsDebugInterface* sGpsDebugInterface = NULL;
-static const AGpsRilInterface* sAGpsRilInterface = NULL;
-static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
-static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
-static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
-static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::String16;
-#define GPS_MAX_SATELLITE_COUNT 32
-#define GNSS_MAX_SATELLITE_COUNT 64
+using android::hardware::IPCThreadState;
+using android::hardware::ProcessState;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::hidl_vec;
-// Let these through, with ID remapped down to 1, 2... by offset
-#define GLONASS_SVID_OFFSET 64
-#define GLONASS_SVID_COUNT 24
-#define BEIDOU_SVID_OFFSET 200
-#define BEIDOU_SVID_COUNT 35
+using android::hardware::gnss::V1_0::IAGnss;
+using android::hardware::gnss::V1_0::IAGnssCallback;
+using android::hardware::gnss::V1_0::IAGnssCallback;
+using android::hardware::gnss::V1_0::IAGnssRil;
+using android::hardware::gnss::V1_0::IAGnssRilCallback;
+using android::hardware::gnss::V1_0::IGnss;
+using android::hardware::gnss::V1_0::IGnssCallback;
+using android::hardware::gnss::V1_0::IGnssConfiguration;
+using android::hardware::gnss::V1_0::IGnssDebug;
+using android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using android::hardware::gnss::V1_0::IGnssGeofencing;
+using android::hardware::gnss::V1_0::IGnssMeasurement;
+using android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using android::hardware::gnss::V1_0::IGnssNavigationMessage;
+using android::hardware::gnss::V1_0::IGnssNavigationMessageCallback;
+using android::hardware::gnss::V1_0::IGnssNi;
+using android::hardware::gnss::V1_0::IGnssNiCallback;
+using android::hardware::gnss::V1_0::IGnssXtra;
+using android::hardware::gnss::V1_0::IGnssXtraCallback;
-// Let these through, with ID remapped up (33->120 ... 64->151, etc.)
-#define SBAS_SVID_MIN 33
-#define SBAS_SVID_MAX 64
-#define SBAS_SVID_ADD 87
-// Let these through, with no ID remapping
-#define QZSS_SVID_MIN 193
-#define QZSS_SVID_MAX 200
-
-#define SVID_SHIFT_WIDTH 7
-#define CONSTELLATION_TYPE_SHIFT_WIDTH 3
-
-// temporary storage for GPS callbacks
-static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
-static size_t sGnssSvListSize;
-static const char* sNmeaString;
-static int sNmeaStringLength;
+sp<IGnss> gnssHal = nullptr;
+sp<IGnssXtra> gnssXtraIface = nullptr;
+sp<IAGnssRil> agnssRilIface = nullptr;
+sp<IGnssGeofencing> gnssGeofencingIface = nullptr;
+sp<IAGnss> agnssIface = nullptr;
+sp<IGnssDebug> gnssDebugIface = nullptr;
+sp<IGnssConfiguration> gnssConfigurationIface = nullptr;
+sp<IGnssNi> gnssNiIface = nullptr;
+sp<IGnssMeasurement> gnssMeasurementIface = nullptr;
+sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
#define WAKE_LOCK_NAME "GPS"
namespace android {
-static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
- if (env->ExceptionCheck()) {
- ALOGE("An exception was thrown by callback '%s'.", methodName);
- LOGE_EX(env);
- env->ExceptionClear();
- }
-}
-
-static void location_callback(GpsLocation* location)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
- (jdouble)location->latitude, (jdouble)location->longitude,
- (jdouble)location->altitude,
- (jfloat)location->speed, (jfloat)location->bearing,
- (jfloat)location->accuracy, (jlong)location->timestamp);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void status_callback(GpsStatus* status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void sv_status_callback(GpsSvStatus* sv_status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- size_t status_size = sv_status->size;
- // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
- // if it doesn't provide a valid size.
- if (status_size == 0) {
- ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
- }
- sGnssSvListSize = sv_status->num_svs;
- // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
- if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
- ALOGW("Too many satellites %zd. Clamps to %d.",
- sGnssSvListSize,
- GPS_MAX_SATELLITE_COUNT);
- sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
- }
- uint32_t ephemeris_mask = sv_status->ephemeris_mask;
- uint32_t almanac_mask = sv_status->almanac_mask;
- uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
- for (size_t i = 0; i < sGnssSvListSize; i++) {
- GnssSvInfo& info = sGnssSvList[i];
- info.svid = sv_status->sv_list[i].prn;
- // Defacto mapping from the overused API that was designed for GPS-only
- if (info.svid >=1 && info.svid <= 32) {
- info.constellation = GNSS_CONSTELLATION_GPS;
- } else if (info.svid > GLONASS_SVID_OFFSET &&
- info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
- info.constellation = GNSS_CONSTELLATION_GLONASS;
- info.svid -= GLONASS_SVID_OFFSET;
- } else if (info.svid > BEIDOU_SVID_OFFSET &&
- info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
- info.constellation = GNSS_CONSTELLATION_BEIDOU;
- info.svid -= BEIDOU_SVID_OFFSET;
- } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
- info.constellation = GNSS_CONSTELLATION_SBAS;
- info.svid += SBAS_SVID_ADD;
- } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
- info.constellation = GNSS_CONSTELLATION_QZSS;
- } else {
- ALOGD("Unknown constellation type with Svid = %d.", info.svid);
- info.constellation = GNSS_CONSTELLATION_UNKNOWN;
- }
- info.c_n0_dbhz = sv_status->sv_list[i].snr;
- info.elevation = sv_status->sv_list[i].elevation;
- info.azimuth = sv_status->sv_list[i].azimuth;
- info.flags = GNSS_SV_FLAGS_NONE;
- // Only GPS info is valid for these fields, as these masks are just 32 bits, by GPS prn
- if (info.constellation == GNSS_CONSTELLATION_GPS) {
- int32_t this_svid_mask = (1 << (info.svid - 1));
- if ((ephemeris_mask & this_svid_mask) != 0) {
- info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
- }
- if ((almanac_mask & this_svid_mask) != 0) {
- info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
- }
- if ((used_in_fix_mask & this_svid_mask) != 0) {
- info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
- }
- }
- }
- env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- size_t status_size = sv_status->size;
- // Check the size, and reject the object that has invalid size.
- if (status_size != sizeof(GnssSvStatus)) {
- ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
- return;
- }
- sGnssSvListSize = sv_status->num_svs;
- // Clamp the list size
- if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
- ALOGD("Too many satellites %zd. Clamps to %d.",
- sGnssSvListSize,
- GNSS_MAX_SATELLITE_COUNT);
- sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
- }
- // Copy GNSS SV info into sGnssSvList, if any.
- if (sGnssSvListSize > 0) {
- memcpy(sGnssSvList,
- sv_status->gnss_sv_list,
- sizeof(GnssSvInfo) * sGnssSvListSize);
- }
- env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- // The Java code will call back to read these values
- // We do this to avoid creating unnecessary String objects
- sNmeaString = nmea;
- sNmeaStringLength = length;
- env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void set_system_info_callback(const GnssSystemInfo* info) {
- ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
- info->year_of_hw);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void set_capabilities_callback(uint32_t capabilities)
-{
- ALOGD("set_capabilities_callback: %du\n", capabilities);
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void acquire_wakelock_callback()
-{
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
-}
-
-static void release_wakelock_callback()
-{
- release_wake_lock(WAKE_LOCK_NAME);
-}
-
-static void request_utc_time_callback()
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
-{
- return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
-}
-
-GpsCallbacks sGpsCallbacks = {
- sizeof(GpsCallbacks),
- location_callback,
- status_callback,
- sv_status_callback,
- nmea_callback,
- set_capabilities_callback,
- acquire_wakelock_callback,
- release_wakelock_callback,
- create_thread_callback,
- request_utc_time_callback,
- set_system_info_callback,
- gnss_sv_status_callback,
-};
-
-static void xtra_download_request_callback()
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-GpsXtraCallbacks sGpsXtraCallbacks = {
- xtra_download_request_callback,
- create_thread_callback,
-};
-
-static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order)
-{
- if (INADDR_NONE == ip) {
- return NULL;
- }
-
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jbyteArray byteArray = env->NewByteArray(4);
- if (byteArray == NULL) {
- ALOGE("Unable to allocate byte array for IPv4 address");
- return NULL;
- }
-
- jbyte ipv4[4];
- if (net_order) {
- ALOGV("Converting IPv4 address(net_order) %x", ip);
- memcpy(ipv4, &ip, sizeof(ipv4));
- } else {
- ALOGV("Converting IPv4 address(host_order) %x", ip);
- //endianess transparent conversion from int to char[]
- ipv4[0] = (jbyte) (ip & 0xFF);
- ipv4[1] = (jbyte)((ip>>8) & 0xFF);
- ipv4[2] = (jbyte)((ip>>16) & 0xFF);
- ipv4[3] = (jbyte) (ip>>24);
- }
-
- env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4);
- return byteArray;
-}
-
-static void agps_status_callback(AGpsStatus* agps_status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jbyteArray byteArray = NULL;
- bool isSupported = false;
-
- size_t status_size = agps_status->size;
- if (status_size == sizeof(AGpsStatus)) {
- ALOGV("AGpsStatus is V3: %zd", status_size);
- switch (agps_status->addr.ss_family)
- {
- case AF_INET:
- {
- struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr);
- uint32_t ipAddr = *(uint32_t*)&(in->sin_addr);
- byteArray = convert_to_ipv4(ipAddr, true /* net_order */);
- if (ipAddr == INADDR_NONE || byteArray != NULL) {
- isSupported = true;
- }
- IF_ALOGD() {
- // log the IP for reference in case there is a bogus value pushed by HAL
- char str[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
- ALOGD("AGPS IP is v4: %s", str);
- }
- }
- break;
- case AF_INET6:
- {
- struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr);
- byteArray = env->NewByteArray(16);
- if (byteArray != NULL) {
- env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr));
- isSupported = true;
- } else {
- ALOGE("Unable to allocate byte array for IPv6 address.");
- }
- IF_ALOGD() {
- // log the IP for reference in case there is a bogus value pushed by HAL
- char str[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
- ALOGD("AGPS IP is v6: %s", str);
- }
- }
- break;
- default:
- ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family);
- break;
- }
- } else if (status_size >= sizeof(AGpsStatus_v2)) {
- ALOGV("AGpsStatus is V2+: %zd", status_size);
- // for back-compatibility reasons we check in v2 that the data structure size is greater or
- // equal to the declared size in gps.h
- uint32_t ipaddr = agps_status->ipaddr;
- ALOGV("AGPS IP is v4: %x", ipaddr);
- byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
- if (ipaddr == INADDR_NONE || byteArray != NULL) {
- isSupported = true;
- }
- } else if (status_size >= sizeof(AGpsStatus_v1)) {
- ALOGV("AGpsStatus is V1+: %zd", status_size);
- // because we have to check for >= with regards to v2, we also need to relax the check here
- // and only make sure that the size is at least what we expect
- isSupported = true;
- } else {
- ALOGE("Invalid size of AGpsStatus found: %zd.", status_size);
- }
-
- if (isSupported) {
- jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
- ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
- env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
- agps_status->status, byteArray);
-
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
- } else {
- ALOGD("Skipping calling method_reportAGpsStatus.");
- }
-
- if (byteArray) {
- env->DeleteLocalRef(byteArray);
- }
-}
-
-AGpsCallbacks sAGpsCallbacks = {
- agps_status_callback,
- create_thread_callback,
-};
-
-static void gps_ni_notify_callback(GpsNiNotification *notification)
-{
- ALOGD("gps_ni_notify_callback\n");
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jstring requestor_id = env->NewStringUTF(notification->requestor_id);
- jstring text = env->NewStringUTF(notification->text);
- jstring extras = env->NewStringUTF(notification->extras);
-
- if (requestor_id && text && extras) {
- env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
- notification->notification_id, notification->ni_type,
- notification->notify_flags, notification->timeout,
- notification->default_response, requestor_id, text,
- notification->requestor_id_encoding,
- notification->text_encoding, extras);
- } else {
- ALOGE("out of memory in gps_ni_notify_callback\n");
- }
-
- if (requestor_id)
- env->DeleteLocalRef(requestor_id);
- if (text)
- env->DeleteLocalRef(text);
- if (extras)
- env->DeleteLocalRef(extras);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-GpsNiCallbacks sGpsNiCallbacks = {
- gps_ni_notify_callback,
- create_thread_callback,
-};
-
-static void agps_request_set_id(uint32_t flags)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void agps_request_ref_location(uint32_t flags)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-AGpsRilCallbacks sAGpsRilCallbacks = {
- agps_request_set_id,
- agps_request_ref_location,
- create_thread_callback,
-};
-
-static void gps_geofence_transition_callback(int32_t geofence_id, GpsLocation* location,
- int32_t transition, GpsUtcTime timestamp)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
-
- env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
- location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
- (jdouble)location->altitude,
- (jfloat)location->speed, (jfloat)location->bearing,
- (jfloat)location->accuracy, (jlong)location->timestamp,
- transition, timestamp);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jint flags = 0;
- jdouble latitude = 0;
- jdouble longitude = 0;
- jdouble altitude = 0;
- jfloat speed = 0;
- jfloat bearing = 0;
- jfloat accuracy = 0;
- jlong timestamp = 0;
- if (location != NULL) {
- flags = location->flags;
- latitude = location->latitude;
- longitude = location->longitude;
- altitude = location->altitude;
- speed = location->speed;
- bearing = location->bearing;
- accuracy = location->accuracy;
- timestamp = location->timestamp;
- }
-
- env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
- flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
- ALOGE("Error in geofence_add_callback: %d\n", status);
- }
- env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
- ALOGE("Error in geofence_remove_callback: %d\n", status);
- }
- env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
- ALOGE("Error in geofence_resume_callback: %d\n", status);
- }
- env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
- ALOGE("Error in geofence_pause_callback: %d\n", status);
- }
- env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
- gps_geofence_transition_callback,
- gps_geofence_status_callback,
- gps_geofence_add_callback,
- gps_geofence_remove_callback,
- gps_geofence_pause_callback,
- gps_geofence_resume_callback,
- create_thread_callback,
-};
-
-static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
- int err;
- hw_module_t* module;
-
- method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
- method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
- method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
- method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
- method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
- method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
- method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
- method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
- method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
- "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
- method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
- method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
- method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
- method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
- "(IIDDDFFFJIJ)V");
- method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
- "(IIDDDFFFJ)V");
- method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
- "(II)V");
- method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
- "(II)V");
- method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
- "(II)V");
- method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
- "(II)V");
- method_reportMeasurementData = env->GetMethodID(
- clazz,
- "reportMeasurementData",
- "(Landroid/location/GnssMeasurementsEvent;)V");
- method_reportNavigationMessages = env->GetMethodID(
- clazz,
- "reportNavigationMessage",
- "(Landroid/location/GnssNavigationMessage;)V");
-
- err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
- if (err == 0) {
- hw_device_t* device;
- err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
- if (err == 0) {
- gps_device_t* gps_device = (gps_device_t *)device;
- sGpsInterface = gps_device->get_gps_interface(gps_device);
- }
- }
- if (sGpsInterface) {
- sGpsXtraInterface =
- (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
- sAGpsInterface =
- (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
- sGpsNiInterface =
- (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
- sGpsDebugInterface =
- (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
- sAGpsRilInterface =
- (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
- sGpsGeofencingInterface =
- (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
- sGpsMeasurementInterface =
- (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
- sGpsNavigationMessageInterface =
- (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
- GPS_NAVIGATION_MESSAGE_INTERFACE);
- sGnssConfigurationInterface =
- (const GnssConfigurationInterface*)sGpsInterface->get_extension(
- GNSS_CONFIGURATION_INTERFACE);
- }
-}
-
-static jboolean android_location_GnssLocationProvider_is_supported(
- JNIEnv* /* env */, jclass /* clazz */)
-{
- return (sGpsInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
- JNIEnv* /* env */, jclass /* clazz */)
-{
- return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
- JNIEnv* /* env */, jclass /* jclazz */)
-{
- return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj)
-{
- // this must be set before calling into the HAL library
- if (!mCallbacksObj)
- mCallbacksObj = env->NewGlobalRef(obj);
-
- // fail if the main interface fails to initialize
- if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
- return JNI_FALSE;
-
- // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
- // but continue to allow the rest of the GPS interface to work.
- if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
- sGpsXtraInterface = NULL;
- if (sAGpsInterface)
- sAGpsInterface->init(&sAGpsCallbacks);
- if (sGpsNiInterface)
- sGpsNiInterface->init(&sGpsNiCallbacks);
- if (sAGpsRilInterface)
- sAGpsRilInterface->init(&sAGpsRilCallbacks);
- if (sGpsGeofencingInterface)
- sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
-
- return JNI_TRUE;
-}
-
-static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
-{
- if (sGpsInterface)
- sGpsInterface->cleanup();
-}
-
-static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
- jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
- jint preferred_time)
-{
- if (sGpsInterface) {
- if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
- preferred_time) == 0) {
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
- }
- else
- return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
-{
- if (sGpsInterface) {
- if (sGpsInterface->start() == 0) {
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
- }
- else
- return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
-{
- if (sGpsInterface) {
- if (sGpsInterface->stop() == 0) {
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
- }
- else
- return JNI_FALSE;
-}
-
-static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
- jobject /* obj */,
- jint flags)
-{
- if (sGpsInterface)
- sGpsInterface->delete_aiding_data(flags);
-}
-
-static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
- jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
- jfloatArray azumArray)
-{
- // this should only be called from within a call to reportSvStatus
- jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
- jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
- jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
- jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
-
- // GNSS SV info.
- for (size_t i = 0; i < sGnssSvListSize; ++i) {
- const GnssSvInfo& info = sGnssSvList[i];
- svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
- (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
- info.flags;
- cn0s[i] = info.c_n0_dbhz;
- elev[i] = info.elevation;
- azim[i] = info.azimuth;
- }
-
- env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
- env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
- env->ReleaseFloatArrayElements(elevArray, elev, 0);
- env->ReleaseFloatArrayElements(azumArray, azim, 0);
- return (jint) sGnssSvListSize;
-}
-
-static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
- JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
-{
- AGpsRefLocation location;
-
- if (!sAGpsRilInterface) {
- ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
- return;
- }
-
- switch(type) {
- case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
- case AGPS_REF_LOCATION_TYPE_UMTS_CELLID:
- location.type = type;
- location.u.cellID.mcc = mcc;
- location.u.cellID.mnc = mnc;
- location.u.cellID.lac = lac;
- location.u.cellID.cid = cid;
- break;
- default:
- ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__);
- return;
- break;
- }
- sAGpsRilInterface->set_ref_location(&location, sizeof(location));
-}
-
-static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env,
- jobject /* obj */, jbyteArray ni_msg, jint size)
-{
- size_t sz;
-
- if (!sAGpsRilInterface) {
- ALOGE("no AGPS RIL interface in send_ni_message");
- return;
- }
- if (size < 0)
- return;
- sz = (size_t)size;
- jbyte* b = env->GetByteArrayElements(ni_msg, 0);
- sAGpsRilInterface->ni_message((uint8_t *)b,sz);
- env->ReleaseByteArrayElements(ni_msg,b,0);
-}
-
-static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
- jint type, jstring setid_string)
-{
- if (!sAGpsRilInterface) {
- ALOGE("no AGPS RIL interface in agps_set_id");
- return;
- }
-
- const char *setid = env->GetStringUTFChars(setid_string, NULL);
- sAGpsRilInterface->set_set_id(type, setid);
- env->ReleaseStringUTFChars(setid_string, setid);
-}
-
-static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
- jbyteArray nmeaArray, jint buffer_size)
-{
- // this should only be called from within a call to reportNmea
- jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0);
- int length = sNmeaStringLength;
- if (length > buffer_size)
- length = buffer_size;
- memcpy(nmea, sNmeaString, length);
- env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
- return (jint) length;
-}
-
-static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
- jlong time, jlong timeReference, jint uncertainty)
-{
- if (sGpsInterface)
- sGpsInterface->inject_time(time, timeReference, uncertainty);
-}
-
-static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
- jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
-{
- if (sGpsInterface)
- sGpsInterface->inject_location(latitude, longitude, accuracy);
-}
-
-static jboolean android_location_GnssLocationProvider_supports_xtra(
- JNIEnv* /* env */, jobject /* obj */)
-{
- return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
- jbyteArray data, jint length)
-{
- if (!sGpsXtraInterface) {
- ALOGE("no XTRA interface in inject_xtra_data");
- return;
- }
-
- jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0);
- sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
- env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_open(
- JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType)
-{
- if (!sAGpsInterface) {
- ALOGE("no AGPS interface in agps_data_conn_open");
- return;
- }
- if (apn == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- return;
- }
-
- const char *apnStr = env->GetStringUTFChars(apn, NULL);
-
- size_t interface_size = sAGpsInterface->size;
- if (interface_size == sizeof(AGpsInterface)) {
- sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
- } else if (interface_size == sizeof(AGpsInterface_v1)) {
- sAGpsInterface->data_conn_open(apnStr);
- } else {
- ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size);
- }
-
- env->ReleaseStringUTFChars(apn, apnStr);
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
- jobject /* obj */)
-{
- if (!sAGpsInterface) {
- ALOGE("no AGPS interface in agps_data_conn_closed");
- return;
- }
- sAGpsInterface->data_conn_closed();
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
- jobject /* obj */)
-{
- if (!sAGpsInterface) {
- ALOGE("no AGPS interface in agps_data_conn_failed");
- return;
- }
- sAGpsInterface->data_conn_failed();
-}
-
-static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
- jint type, jstring hostname, jint port)
-{
- if (!sAGpsInterface) {
- ALOGE("no AGPS interface in set_agps_server");
- return;
- }
- const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
- sAGpsInterface->set_server(type, c_hostname, port);
- env->ReleaseStringUTFChars(hostname, c_hostname);
-}
-
-static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
- jobject /* obj */, jint notifId, jint response)
-{
- if (!sGpsNiInterface) {
- ALOGE("no NI interface in send_ni_response");
- return;
- }
-
- sGpsNiInterface->respond(notifId, response);
-}
-
-static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
- jobject /* obj */) {
- jstring result = NULL;
- if (sGpsDebugInterface) {
- const size_t maxLength = 2047;
- char buffer[maxLength+1];
- size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength);
- if (length > maxLength) length = maxLength;
- buffer[length] = 0;
- result = env->NewStringUTF(buffer);
- }
- return result;
-}
-
-static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
- jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
-{
-
- if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
- if (extraInfo) {
- const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
- sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr);
- env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
- } else {
- sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
- }
-
- // update_network_availability callback was not included in original AGpsRilInterface
- if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
- && sAGpsRilInterface->update_network_availability) {
- const char *c_apn = env->GetStringUTFChars(apn, NULL);
- sAGpsRilInterface->update_network_availability(available, c_apn);
- env->ReleaseStringUTFChars(apn, c_apn);
- }
- }
-}
-
-static jboolean android_location_GnssLocationProvider_is_geofence_supported(
- JNIEnv* /* env */, jobject /* obj */)
-{
- return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
- jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
- jint last_transition, jint monitor_transition, jint notification_responsiveness,
- jint unknown_timer) {
- if (sGpsGeofencingInterface != NULL) {
- sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
- radius, last_transition, monitor_transition, notification_responsiveness,
- unknown_timer);
- return JNI_TRUE;
- } else {
- ALOGE("Geofence interface not available");
- }
- return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
- jobject /* obj */, jint geofence_id) {
- if (sGpsGeofencingInterface != NULL) {
- sGpsGeofencingInterface->remove_geofence_area(geofence_id);
- return JNI_TRUE;
- } else {
- ALOGE("Geofence interface not available");
- }
- return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
- jobject /* obj */, jint geofence_id) {
- if (sGpsGeofencingInterface != NULL) {
- sGpsGeofencingInterface->pause_geofence(geofence_id);
- return JNI_TRUE;
- } else {
- ALOGE("Geofence interface not available");
- }
- return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
- jobject /* obj */, jint geofence_id, jint monitor_transition) {
- if (sGpsGeofencingInterface != NULL) {
- sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
- return JNI_TRUE;
- } else {
- ALOGE("Geofence interface not available");
- }
- return JNI_FALSE;
-}
-
template<class T>
class JavaMethodHelper {
- public:
- // Helper function to call setter on a Java object.
- static void callJavaMethod(
+ public:
+ // Helper function to call setter on a Java object.
+ static void callJavaMethod(
JNIEnv* env,
jclass clazz,
jobject object,
const char* method_name,
T value);
- private:
+ private:
static const char *const signature_;
};
@@ -1045,20 +136,20 @@
}
class JavaObject {
- public:
- JavaObject(JNIEnv* env, const char* class_name);
- virtual ~JavaObject();
+ public:
+ JavaObject(JNIEnv* env, const char* class_name);
+ virtual ~JavaObject();
- template<class T>
- void callSetter(const char* method_name, T value);
- template<class T>
- void callSetter(const char* method_name, T* value, size_t size);
- jobject get();
+ template<class T>
+ void callSetter(const char* method_name, T value);
+ template<class T>
+ void callSetter(const char* method_name, T* value, size_t size);
+ jobject get();
- private:
- JNIEnv* env_;
- jclass clazz_;
- jobject object_;
+ private:
+ JNIEnv* env_;
+ jclass clazz_;
+ jobject object_;
};
JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
@@ -1081,7 +172,7 @@
void JavaObject::callSetter(
const char* method_name, uint8_t* value, size_t size) {
jbyteArray array = env_->NewByteArray(size);
- env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
+ env_->SetByteArrayRegion(array, 0, size, reinterpret_cast<jbyte*>(value));
jmethodID method = env_->GetMethodID(
clazz_,
method_name,
@@ -1095,7 +186,6 @@
}
// Define Java method signatures for all known types.
-
template<>
const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
template<>
@@ -1119,209 +209,460 @@
#define SET(setter, value) object.callSetter("set" # setter, (value))
-// If you want to check if a flag is not set, use SET_IF_NOT(FLAG, setter,
-// value) to do that. SET_IF(!FLAG, setter, value) won't compile.
-//
-// This macros generates compilation error if the provided 'flag' is not a
-// single token. For example, 'GNSS_CLOCK_HAS_BIAS' can be accepted, but
-// '!GNSS_CLOCK_HAS_DRIFT' will fail to compile.
-#define SET_IF(flag, setter, value) do { \
- if (flags & flag) { \
- JavaObject& name_check_##flag = object; \
- name_check_##flag.callSetter("set" # setter, (value)); \
- } \
- } while (false)
-#define SET_IF_NOT(flag, setter, value) do { \
- if (!(flags & flag)) { \
- JavaObject& name_check_##flag = object; \
- name_check_##flag.callSetter("set" # setter, (value)); \
- } \
- } while (false)
+static inline jboolean boolToJbool(bool value) {
+ return value ? JNI_TRUE : JNI_FALSE;
+}
-static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
- static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
- JavaObject object(env, "android/location/GnssClock");
- GpsClockFlags flags = clock->flags;
+static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+ if (env->ExceptionCheck()) {
+ ALOGE("An exception was thrown by callback '%s'.", methodName);
+ LOGE_EX(env);
+ env->ExceptionClear();
+ }
+}
- SET_IF(GPS_CLOCK_HAS_LEAP_SECOND,
- LeapSecond,
- static_cast<int32_t>(clock->leap_second));
+/*
+ * GnssCallback class implements the callback methods for IGnss interface.
+ */
+struct GnssCallback : public IGnssCallback {
+ Return<void> gnssLocationCb(
+ const android::hardware::gnss::V1_0::GnssLocation& location) override;
+ Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override;
+ Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
+ Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
+ Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
+ Return<void> gnssAcquireWakelockCb() override;
+ Return<void> gnssReleaseWakelockCb() override;
+ Return<void> gnssRequestTimeCb() override;
+ Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;
- // GnssClock only supports the more effective HW_CLOCK type, so type
- // handling and documentation complexity has been removed. To convert the
- // old GPS_CLOCK types (active only in a limited number of older devices),
- // the GPS time information is handled as an always discontinuous HW clock,
- // with the GPS time information put into the full_bias_ns instead - so that
- // time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
- // sign of full_bias_ns and bias_ns has flipped between GpsClock &
- // GnssClock, so that is also handled below.
- switch (clock->type) {
- case GPS_CLOCK_TYPE_UNKNOWN:
- // Clock type unsupported.
- ALOGE("Unknown clock type provided.");
- break;
- case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
- // Already local hardware time. No need to do anything.
- break;
- case GPS_CLOCK_TYPE_GPS_TIME:
- // GPS time, need to convert.
- flags |= GPS_CLOCK_HAS_FULL_BIAS;
- clock->full_bias_ns = clock->time_ns;
- clock->time_ns = 0;
- SET(HardwareClockDiscontinuityCount,
- discontinuity_count_to_handle_old_clock_type++);
- break;
+ static GnssSvInfo sGnssSvList[static_cast<uint32_t>(
+ android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)];
+ static size_t sGnssSvListSize;
+
+ static const char* sNmeaString;
+ static size_t sNmeaStringLength;
+};
+
+IGnssCallback::GnssSvInfo GnssCallback::sGnssSvList[static_cast<uint32_t>(
+ android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)];
+const char* GnssCallback::sNmeaString = nullptr;
+size_t GnssCallback::sNmeaStringLength = 0;
+size_t GnssCallback::sGnssSvListSize = 0;
+
+Return<void> GnssCallback::gnssLocationCb(
+ const ::android::hardware::gnss::V1_0::GnssLocation& location) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportLocation,
+ location.gnssLocationFlags,
+ static_cast<jdouble>(location.latitudeDegrees),
+ static_cast<jdouble>(location.longitudeDegrees),
+ static_cast<jdouble>(location.altitudeMeters),
+ static_cast<jfloat>(location.speedMetersPerSec),
+ static_cast<jfloat>(location.bearingDegrees),
+ static_cast<jfloat>(location.accuracyMeters),
+ static_cast<jlong>(location.timestamp));
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssStatusCb(const IGnssCallback::GnssStatusValue status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ sGnssSvListSize = svStatus.numSvs;
+ if (sGnssSvListSize > static_cast<uint32_t>(
+ android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)) {
+ ALOGD("Too many satellites %zd. Clamps to %u.", sGnssSvListSize,
+ static_cast<uint32_t>(android::hardware::gnss::V1_0::GnssMax::SVS_COUNT));
+ sGnssSvListSize = static_cast<uint32_t>(android::hardware::gnss::V1_0::GnssMax::SVS_COUNT);
}
- SET(TimeNanos, clock->time_ns);
- SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
- TimeUncertaintyNanos,
- clock->time_uncertainty_ns);
-
- // Definition of sign for full_bias_ns & bias_ns has been changed since N,
- // so flip signs here.
- SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, -(clock->full_bias_ns));
- SET_IF(GPS_CLOCK_HAS_BIAS, BiasNanos, -(clock->bias_ns));
-
- SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
- BiasUncertaintyNanos,
- clock->bias_uncertainty_ns);
- SET_IF(GPS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
- SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
- DriftUncertaintyNanosPerSecond,
- clock->drift_uncertainty_nsps);
-
- return object.get();
-}
-
-static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
- JavaObject object(env, "android/location/GnssClock");
- GnssClockFlags flags = clock->flags;
-
- SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
- LeapSecond,
- static_cast<int32_t>(clock->leap_second));
- SET(TimeNanos, clock->time_ns);
- SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
- TimeUncertaintyNanos,
- clock->time_uncertainty_ns);
- SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
- SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
- SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
- BiasUncertaintyNanos,
- clock->bias_uncertainty_ns);
- SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
- SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
- DriftUncertaintyNanosPerSecond,
- clock->drift_uncertainty_nsps);
-
- SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
-
- return object.get();
-}
-
-static jobject translate_gps_measurement(JNIEnv* env,
- GpsMeasurement* measurement) {
- JavaObject object(env, "android/location/GnssMeasurement");
- GpsMeasurementFlags flags = measurement->flags;
- SET(Svid, static_cast<int32_t>(measurement->prn));
- if (measurement->prn >= 1 && measurement->prn <= 32) {
- SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
- } else {
- ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
- SET(ConstellationType,
- static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
+ // Copy GNSS SV info into sGnssSvList, if any.
+ if (svStatus.numSvs > 0) {
+ memcpy(sGnssSvList, svStatus.gnssSvList.data(), sizeof(GnssSvInfo) * sGnssSvListSize);
}
- SET(TimeOffsetNanos, measurement->time_offset_ns);
- SET(State, static_cast<int32_t>(measurement->state));
- SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
- SET(ReceivedSvTimeUncertaintyNanos,
- measurement->received_gps_tow_uncertainty_ns);
- SET(Cn0DbHz, measurement->c_n0_dbhz);
- SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
- SET(PseudorangeRateUncertaintyMetersPerSecond,
- measurement->pseudorange_rate_uncertainty_mps);
- SET(AccumulatedDeltaRangeState,
- static_cast<int32_t>(measurement->accumulated_delta_range_state));
- SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
- SET(AccumulatedDeltaRangeUncertaintyMeters,
- measurement->accumulated_delta_range_uncertainty_m);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
- CarrierFrequencyHz,
- measurement->carrier_frequency_hz);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
- CarrierCycles,
- measurement->carrier_cycles);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
- CarrierPhase,
- measurement->carrier_phase);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
- CarrierPhaseUncertainty,
- measurement->carrier_phase_uncertainty);
- SET(MultipathIndicator,
- static_cast<int32_t>(measurement->multipath_indicator));
- SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
- return object.get();
+ env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
}
-static jobject translate_gnss_measurement(JNIEnv* env,
- GnssMeasurement* measurement) {
+Return<void> GnssCallback::gnssNmeaCb(
+ int64_t timestamp, const ::android::hardware::hidl_string& nmea) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ /*
+ * The Java code will call back to read these values.
+ * We do this to avoid creating unnecessary String objects.
+ */
+ sNmeaString = nmea.c_str();
+ sNmeaStringLength = nmea.size();
+
+ env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
+ ALOGD("%s: %du\n", __func__, capabilities);
+
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssAcquireWakelockCb() {
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssReleaseWakelockCb() {
+ release_wake_lock(WAKE_LOCK_NAME);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssRequestTimeCb() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) {
+ ALOGD("%s: yearOfHw=%d\n", __func__, info.yearOfHw);
+
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
+ info.yearOfHw);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+class GnssXtraCallback : public IGnssXtraCallback {
+ Return<void> downloadRequestCb() override;
+};
+
+/*
+ * GnssXtraCallback class implements the callback methods for the IGnssXtra
+ * interface.
+ */
+Return<void> GnssXtraCallback::downloadRequestCb() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+/*
+ * GnssGeofenceCallback class implements the callback methods for the
+ * IGnssGeofence interface.
+ */
+struct GnssGeofenceCallback : public IGnssGeofenceCallback {
+ // Methods from ::android::hardware::gps::V1_0::IGnssGeofenceCallback follow.
+ Return<void> gnssGeofenceTransitionCb(
+ int32_t geofenceId,
+ const android::hardware::gnss::V1_0::GnssLocation& location,
+ GeofenceTransition transition,
+ hardware::gnss::V1_0::GnssUtcTime timestamp) override;
+ Return<void> gnssGeofenceStatusCb(
+ GeofenceAvailability status,
+ const android::hardware::gnss::V1_0::GnssLocation& location) override;
+ Return<void> gnssGeofenceAddCb(int32_t geofenceId,
+ GeofenceStatus status) override;
+ Return<void> gnssGeofenceRemoveCb(int32_t geofenceId,
+ GeofenceStatus status) override;
+ Return<void> gnssGeofencePauseCb(int32_t geofenceId,
+ GeofenceStatus status) override;
+ Return<void> gnssGeofenceResumeCb(int32_t geofenceId,
+ GeofenceStatus status) override;
+};
+
+Return<void> GnssGeofenceCallback::gnssGeofenceTransitionCb(
+ int32_t geofenceId,
+ const android::hardware::gnss::V1_0::GnssLocation& location,
+ GeofenceTransition transition,
+ hardware::gnss::V1_0::GnssUtcTime timestamp) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofenceTransition,
+ geofenceId,
+ location.gnssLocationFlags,
+ static_cast<jdouble>(location.latitudeDegrees),
+ static_cast<jdouble>(location.longitudeDegrees),
+ static_cast<jdouble>(location.altitudeMeters),
+ static_cast<jfloat>(location.speedMetersPerSec),
+ static_cast<jfloat>(location.bearingDegrees),
+ static_cast<jfloat>(location.accuracyMeters),
+ static_cast<jlong>(location.timestamp),
+ transition,
+ timestamp);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceStatusCb(
+ GeofenceAvailability status,
+ const android::hardware::gnss::V1_0::GnssLocation& location) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofenceStatus,
+ status,
+ location.gnssLocationFlags,
+ static_cast<jdouble>(location.latitudeDegrees),
+ static_cast<jdouble>(location.longitudeDegrees),
+ static_cast<jdouble>(location.altitudeMeters),
+ static_cast<jfloat>(location.speedMetersPerSec),
+ static_cast<jfloat>(location.bearingDegrees),
+ static_cast<jfloat>(location.accuracyMeters),
+ static_cast<jlong>(location.timestamp));
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceAddCb(int32_t geofenceId,
+ GeofenceStatus status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+ ALOGE("%s: Error in adding a Geofence: %d\n", __func__, status);
+ }
+
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofenceAddStatus,
+ geofenceId,
+ status);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceRemoveCb(int32_t geofenceId,
+ GeofenceStatus status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+ ALOGE("%s: Error in removing a Geofence: %d\n", __func__, status);
+ }
+
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofenceRemoveStatus,
+ geofenceId, status);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofencePauseCb(int32_t geofenceId,
+ GeofenceStatus status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+ ALOGE("%s: Error in pausing Geofence: %d\n", __func__, status);
+ }
+
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofencePauseStatus,
+ geofenceId, status);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceResumeCb(int32_t geofenceId,
+ GeofenceStatus status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+ ALOGE("%s: Error in resuming Geofence: %d\n", __func__, status);
+ }
+
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofenceResumeStatus,
+ geofenceId, status);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+/*
+ * GnssNavigationMessageCallback interface implements the callback methods
+ * required by the IGnssNavigationMessage interface.
+ */
+struct GnssNavigationMessageCallback : public IGnssNavigationMessageCallback {
+ /*
+ * Methods from ::android::hardware::gps::V1_0::IGnssNavigationMessageCallback
+ * follow.
+ */
+ Return<void> gnssNavigationMessageCb(
+ const IGnssNavigationMessageCallback::GnssNavigationMessage& message) override;
+};
+
+Return<void> GnssNavigationMessageCallback::gnssNavigationMessageCb(
+ const IGnssNavigationMessageCallback::GnssNavigationMessage& message) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ size_t dataLength = message.data.size();
+
+ std::vector<uint8_t> navigationData = message.data;
+ uint8_t* data = &(navigationData[0]);
+ if (dataLength == 0 || data == NULL) {
+ ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data,
+ dataLength);
+ return Void();
+ }
+
+ JavaObject object(env, "android/location/GnssNavigationMessage");
+ SET(Type, static_cast<int32_t>(message.type));
+ SET(Svid, static_cast<int32_t>(message.svid));
+ SET(MessageId, static_cast<int32_t>(message.messageId));
+ SET(SubmessageId, static_cast<int32_t>(message.submessageId));
+ object.callSetter("setData", data, dataLength);
+ SET(Status, static_cast<int32_t>(message.status));
+
+ jobject navigationMessage = object.get();
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportNavigationMessages,
+ navigationMessage);
+ env->DeleteLocalRef(navigationMessage);
+ return Void();
+}
+
+/*
+ * GnssMeasurementCallback implements the callback methods required for the
+ * GnssMeasurement interface.
+ */
+struct GnssMeasurementCallback : public IGnssMeasurementCallback {
+ Return<void> GnssMeasurementCb(const IGnssMeasurementCallback::GnssData& data);
+ private:
+ jobject translateGnssMeasurement(
+ JNIEnv* env, const IGnssMeasurementCallback::GnssMeasurement* measurement);
+ jobject translateGnssClock(
+ JNIEnv* env, const IGnssMeasurementCallback::GnssClock* clock);
+ jobjectArray translateGnssMeasurements(
+ JNIEnv* env,
+ const IGnssMeasurementCallback::GnssMeasurement* measurements,
+ size_t count);
+ void setMeasurementData(JNIEnv* env, jobject clock, jobjectArray measurementArray);
+};
+
+
+Return<void> GnssMeasurementCallback::GnssMeasurementCb(
+ const IGnssMeasurementCallback::GnssData& data) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ jobject clock;
+ jobjectArray measurementArray;
+
+ clock = translateGnssClock(env, &data.clock);
+ measurementArray = translateGnssMeasurements(
+ env, data.measurements.data(), data.measurementCount);
+ setMeasurementData(env, clock, measurementArray);
+
+ env->DeleteLocalRef(clock);
+ env->DeleteLocalRef(measurementArray);
+ return Void();
+}
+
+jobject GnssMeasurementCallback::translateGnssMeasurement(
+ JNIEnv* env, const IGnssMeasurementCallback::GnssMeasurement* measurement) {
JavaObject object(env, "android/location/GnssMeasurement");
- GnssMeasurementFlags flags = measurement->flags;
+ uint32_t flags = static_cast<uint32_t>(measurement->flags);
SET(Svid, static_cast<int32_t>(measurement->svid));
SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
- SET(TimeOffsetNanos, measurement->time_offset_ns);
+ SET(TimeOffsetNanos, measurement->timeOffsetNs);
SET(State, static_cast<int32_t>(measurement->state));
- SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
+ SET(ReceivedSvTimeNanos, measurement->receivedSvTimeInNs);
SET(ReceivedSvTimeUncertaintyNanos,
- measurement->received_sv_time_uncertainty_in_ns);
- SET(Cn0DbHz, measurement->c_n0_dbhz);
- SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+ measurement->receivedSvTimeUncertaintyInNs);
+ SET(Cn0DbHz, measurement->cN0DbHz);
+ SET(PseudorangeRateMetersPerSecond, measurement->pseudorangeRateMps);
SET(PseudorangeRateUncertaintyMetersPerSecond,
- measurement->pseudorange_rate_uncertainty_mps);
+ measurement->pseudorangeRateUncertaintyMps);
SET(AccumulatedDeltaRangeState,
- static_cast<int32_t>(measurement->accumulated_delta_range_state));
- SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+ (static_cast<int32_t>(measurement->accumulatedDeltaRangeState)));
+ SET(AccumulatedDeltaRangeMeters, measurement->accumulatedDeltaRangeM);
SET(AccumulatedDeltaRangeUncertaintyMeters,
- measurement->accumulated_delta_range_uncertainty_m);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
- CarrierFrequencyHz,
- measurement->carrier_frequency_hz);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
- CarrierCycles,
- measurement->carrier_cycles);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
- CarrierPhase,
- measurement->carrier_phase);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
- CarrierPhaseUncertainty,
- measurement->carrier_phase_uncertainty);
- SET(MultipathIndicator,
- static_cast<int32_t>(measurement->multipath_indicator));
- SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
+ measurement->accumulatedDeltaRangeUncertaintyM);
+
+ if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) {
+ SET(CarrierFrequencyHz, measurement->carrierFrequencyHz);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_PHASE)) {
+ SET(CarrierPhase, measurement->carrierPhase);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY)) {
+ SET(CarrierPhaseUncertainty, measurement->carrierPhaseUncertainty);
+ }
+
+ SET(MultipathIndicator, static_cast<int32_t>(measurement->multipathIndicator));
+
+ if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_SNR)) {
+ SET(SnrInDb, measurement->snrDb);
+ }
return object.get();
}
-static jobjectArray translate_gps_measurements(JNIEnv* env,
- GpsMeasurement* measurements,
- size_t count) {
+jobject GnssMeasurementCallback::translateGnssClock(
+ JNIEnv* env, const IGnssMeasurementCallback::GnssClock* clock) {
+ JavaObject object(env, "android/location/GnssClock");
+
+ uint32_t flags = static_cast<uint32_t>(clock->gnssClockFlags);
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_LEAP_SECOND)) {
+ SET(LeapSecond, static_cast<int32_t>(clock->leapSecond));
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_TIME_UNCERTAINTY)) {
+ SET(TimeUncertaintyNanos, clock->timeUncertaintyNs);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_FULL_BIAS)) {
+ SET(FullBiasNanos, clock->fullBiasNs);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS)) {
+ SET(BiasNanos, clock->biasNs);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS_UNCERTAINTY)) {
+ SET(BiasUncertaintyNanos, clock->biasUncertaintyNs);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT)) {
+ SET(DriftNanosPerSecond, clock->driftNsps);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT_UNCERTAINTY)) {
+ SET(DriftUncertaintyNanosPerSecond, clock->driftUncertaintyNsps);
+ }
+
+ SET(TimeNanos, clock->timeNs);
+ SET(HardwareClockDiscontinuityCount, clock->hwClockDiscontinuityCount);
+
+ return object.get();
+}
+
+jobjectArray GnssMeasurementCallback::translateGnssMeasurements(JNIEnv* env,
+ const IGnssMeasurementCallback::GnssMeasurement*
+ measurements, size_t count) {
if (count == 0) {
return NULL;
}
- jclass gnssMeasurementClass = env->FindClass(
- "android/location/GnssMeasurement");
+ jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
jobjectArray gnssMeasurementArray = env->NewObjectArray(
count,
gnssMeasurementClass,
NULL /* initialElement */);
for (uint16_t i = 0; i < count; ++i) {
- jobject gnssMeasurement = translate_gps_measurement(
+ jobject gnssMeasurement = translateGnssMeasurement(
env,
&measurements[i]);
env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
@@ -1332,130 +673,789 @@
return gnssMeasurementArray;
}
-static jobjectArray translate_gnss_measurements(JNIEnv* env,
- GnssMeasurement* measurements,
- size_t count) {
- if (count == 0) {
- return NULL;
- }
+void GnssMeasurementCallback::setMeasurementData(JNIEnv* env, jobject clock,
+ jobjectArray measurementArray) {
+ jclass gnssMeasurementsEventClass =
+ env->FindClass("android/location/GnssMeasurementsEvent");
+ jmethodID gnssMeasurementsEventCtor =
+ env->GetMethodID(
+ gnssMeasurementsEventClass,
+ "<init>",
+ "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
- jclass gnssMeasurementClass = env->FindClass(
- "android/location/GnssMeasurement");
- jobjectArray gnssMeasurementArray = env->NewObjectArray(
- count,
- gnssMeasurementClass,
- NULL /* initialElement */);
+ jobject gnssMeasurementsEvent = env->NewObject(gnssMeasurementsEventClass,
+ gnssMeasurementsEventCtor,
+ clock,
+ measurementArray);
- for (uint16_t i = 0; i < count; ++i) {
- jobject gnssMeasurement = translate_gnss_measurement(
- env,
- &measurements[i]);
- env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
- env->DeleteLocalRef(gnssMeasurement);
- }
-
- env->DeleteLocalRef(gnssMeasurementClass);
- return gnssMeasurementArray;
-}
-
-static void set_measurement_data(JNIEnv *env,
- jobject clock,
- jobjectArray measurementArray) {
- jclass gnssMeasurementsEventClass = env->FindClass(
- "android/location/GnssMeasurementsEvent");
- jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
- gnssMeasurementsEventClass,
- "<init>",
- "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
-
- jobject gnssMeasurementsEvent = env->NewObject(
- gnssMeasurementsEventClass,
- gnssMeasurementsEventCtor,
- clock,
- measurementArray);
- env->CallVoidMethod(mCallbacksObj,
- method_reportMeasurementData,
- gnssMeasurementsEvent);
+ env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData,
+ gnssMeasurementsEvent);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
env->DeleteLocalRef(gnssMeasurementsEventClass);
env->DeleteLocalRef(gnssMeasurementsEvent);
}
-static void measurement_callback(GpsData* data) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (data == NULL) {
- ALOGE("Invalid data provided to gps_measurement_callback");
- return;
- }
- if (data->size != sizeof(GpsData)) {
- ALOGE("Invalid GpsData size found in gps_measurement_callback, "
- "size=%zd",
- data->size);
- return;
- }
-
- jobject clock;
- jobjectArray measurementArray;
- clock = translate_gps_clock(env, &data->clock);
- measurementArray = translate_gps_measurements(
- env, data->measurements, data->measurement_count);
- set_measurement_data(env, clock, measurementArray);
-
- env->DeleteLocalRef(clock);
- env->DeleteLocalRef(measurementArray);
-}
-
-static void gnss_measurement_callback(GnssData* data) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (data == NULL) {
- ALOGE("Invalid data provided to gps_measurement_callback");
- return;
- }
- if (data->size != sizeof(GnssData)) {
- ALOGE("Invalid GnssData size found in gnss_measurement_callback, "
- "size=%zd",
- data->size);
- return;
- }
-
- jobject clock;
- jobjectArray measurementArray;
- clock = translate_gnss_clock(env, &data->clock);
- measurementArray = translate_gnss_measurements(
- env, data->measurements, data->measurement_count);
- set_measurement_data(env, clock, measurementArray);
-
- env->DeleteLocalRef(clock);
- env->DeleteLocalRef(measurementArray);
-}
-
-GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
- sizeof(GpsMeasurementCallbacks),
- measurement_callback,
- gnss_measurement_callback,
+/*
+ * GnssNiCallback implements callback methods required by the IGnssNi interface.
+ */
+struct GnssNiCallback : public IGnssNiCallback {
+ Return<void> niNotifyCb(const IGnssNiCallback::GnssNiNotification& notification)
+ override;
};
+Return<void> GnssNiCallback::niNotifyCb(
+ const IGnssNiCallback::GnssNiNotification& notification) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jstring requestorId = env->NewStringUTF(notification.requestorId.c_str());
+ jstring text = env->NewStringUTF(notification.notificationMessage.c_str());
+
+ if (requestorId && text) {
+ env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
+ notification.notificationId, notification.niType,
+ notification.notifyFlags, notification.timeoutSec,
+ notification.defaultResponse, requestorId, text,
+ notification.requestorIdEncoding,
+ notification.notificationIdEncoding);
+ } else {
+ ALOGE("%s: OOM Error\n", __func__);
+ }
+
+ if (requestorId) {
+ env->DeleteLocalRef(requestorId);
+ }
+
+ if (text) {
+ env->DeleteLocalRef(text);
+ }
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+/*
+ * AGnssCallback implements callback methods required by the IAGnss interface.
+ */
+struct AGnssCallback : public IAGnssCallback {
+ // Methods from ::android::hardware::gps::V1_0::IAGnssCallback follow.
+ Return<void> agnssStatusIpV6Cb(
+ const IAGnssCallback::AGnssStatusIpV6& agps_status) override;
+
+ Return<void> agnssStatusIpV4Cb(
+ const IAGnssCallback::AGnssStatusIpV4& agps_status) override;
+ private:
+ jbyteArray convertToIpV4(uint32_t ip);
+};
+
+Return<void> AGnssCallback::agnssStatusIpV6Cb(
+ const IAGnssCallback::AGnssStatusIpV6& agps_status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jbyteArray byteArray = NULL;
+ bool isSupported = false;
+
+ byteArray = env->NewByteArray(16);
+ if (byteArray != NULL) {
+ env->SetByteArrayRegion(byteArray, 0, 16,
+ (const jbyte*)(agps_status.ipV6Addr.data()));
+ isSupported = true;
+ } else {
+ ALOGE("Unable to allocate byte array for IPv6 address.");
+ }
+
+ IF_ALOGD() {
+ // log the IP for reference in case there is a bogus value pushed by HAL
+ char str[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, agps_status.ipV6Addr.data(), str, INET6_ADDRSTRLEN);
+ ALOGD("AGPS IP is v6: %s", str);
+ }
+
+ jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
+ ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
+ env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus,
+ agps_status.type, agps_status.status, byteArray);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+ if (byteArray) {
+ env->DeleteLocalRef(byteArray);
+ }
+
+ return Void();
+}
+
+Return<void> AGnssCallback::agnssStatusIpV4Cb(
+ const IAGnssCallback::AGnssStatusIpV4& agps_status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jbyteArray byteArray = NULL;
+
+ uint32_t ipAddr = agps_status.ipV4Addr;
+ byteArray = convertToIpV4(ipAddr);
+
+ IF_ALOGD() {
+ /*
+ * log the IP for reference in case there is a bogus value pushed by
+ * HAL.
+ */
+ char str[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN);
+ ALOGD("AGPS IP is v4: %s", str);
+ }
+
+ jsize byteArrayLength =
+ byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
+ ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
+ env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus,
+ agps_status.type, agps_status.status, byteArray);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+ if (byteArray) {
+ env->DeleteLocalRef(byteArray);
+ }
+ return Void();
+}
+
+jbyteArray AGnssCallback::convertToIpV4(uint32_t ip) {
+ if (INADDR_NONE == ip) {
+ return NULL;
+ }
+
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jbyteArray byteArray = env->NewByteArray(4);
+ if (byteArray == NULL) {
+ ALOGE("Unable to allocate byte array for IPv4 address");
+ return NULL;
+ }
+
+ jbyte ipv4[4];
+ ALOGV("Converting IPv4 address byte array (net_order) %x", ip);
+ memcpy(ipv4, &ip, sizeof(ipv4));
+ env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*)ipv4);
+ return byteArray;
+}
+
+/*
+ * AGnssRilCallback implements the callback methods required by the AGnssRil
+ * interface.
+ */
+struct AGnssRilCallback : IAGnssRilCallback {
+ Return<void> requestSetIdCb(IAGnssRilCallback::ID setIdFlag) override;
+ Return<void> requestRefLocCb() override;
+};
+
+Return<void> AGnssRilCallback::requestSetIdCb(IAGnssRilCallback::ID setIdFlag) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_requestSetID, setIdFlag);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> AGnssRilCallback::requestRefLocCb() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_requestRefLocation);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
+ method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
+ method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
+ method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
+ method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
+ method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
+ method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
+ method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
+ method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
+ method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
+ "(IIIIILjava/lang/String;Ljava/lang/String;II)V");
+ method_requestRefLocation = env->GetMethodID(clazz, "requestRefLocation", "()V");
+ method_requestSetID = env->GetMethodID(clazz, "requestSetID", "(I)V");
+ method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
+ method_reportGeofenceTransition = env->GetMethodID(clazz, "reportGeofenceTransition",
+ "(IIDDDFFFJIJ)V");
+ method_reportGeofenceStatus = env->GetMethodID(clazz, "reportGeofenceStatus",
+ "(IIDDDFFFJ)V");
+ method_reportGeofenceAddStatus = env->GetMethodID(clazz, "reportGeofenceAddStatus",
+ "(II)V");
+ method_reportGeofenceRemoveStatus = env->GetMethodID(clazz, "reportGeofenceRemoveStatus",
+ "(II)V");
+ method_reportGeofenceResumeStatus = env->GetMethodID(clazz, "reportGeofenceResumeStatus",
+ "(II)V");
+ method_reportGeofencePauseStatus = env->GetMethodID(clazz, "reportGeofencePauseStatus",
+ "(II)V");
+ method_reportMeasurementData = env->GetMethodID(
+ clazz,
+ "reportMeasurementData",
+ "(Landroid/location/GnssMeasurementsEvent;)V");
+ method_reportNavigationMessages = env->GetMethodID(
+ clazz,
+ "reportNavigationMessage",
+ "(Landroid/location/GnssNavigationMessage;)V");
+
+ // TODO(b/31632518)
+ gnssHal = IGnss::getService("gnss");
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->getExtensionXtra([](const sp<IGnssXtra>& xtraIface) {
+ gnssXtraIface = xtraIface;
+ });
+
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to Xtra");
+ }
+
+ result = gnssHal->getExtensionAGnssRil([](const sp<IAGnssRil>& rilIface) {
+ agnssRilIface = rilIface;
+ });
+
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to AGnssRil");
+ }
+
+ result = gnssHal->getExtensionAGnss([](const sp<IAGnss>& assistedGnssIface) {
+ agnssIface = assistedGnssIface;
+ });
+
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to AGnss");
+ }
+
+ result = gnssHal->getExtensionGnssNavigationMessage(
+ [](const sp<IGnssNavigationMessage>& navigationMessageIface) {
+ gnssNavigationMessageIface = navigationMessageIface;
+ });
+
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssNavigationMessage");
+ }
+
+ result = gnssHal->getExtensionGnssMeasurement([](
+ const sp<IGnssMeasurement>& measurementIface) {
+ gnssMeasurementIface = measurementIface;
+ });
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssMeasurement");
+ }
+
+ result = gnssHal->getExtensionGnssDebug([](const sp<IGnssDebug>& debugIface) {
+ gnssDebugIface = debugIface;
+ });
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssDebug");
+ }
+
+ result = gnssHal->getExtensionGnssNi([](const sp<IGnssNi>& niIface) {
+ gnssNiIface = niIface;
+ });
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssNi");
+ }
+
+ result = gnssHal->getExtensionGnssConfiguration([](const sp<IGnssConfiguration>& configIface) {
+ gnssConfigurationIface = configIface;
+ });
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssConfiguration");
+ }
+
+ result = gnssHal->getExtensionGnssGeofencing([](const sp<IGnssGeofencing>& geofenceIface) {
+ gnssGeofencingIface = geofenceIface;
+ });
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssGeofencing");
+ }
+
+ } else {
+ ALOGE("Unable to get GPS service\n");
+ }
+ ProcessState::self()->setThreadPoolMaxThreadCount(0);
+ ProcessState::self()->startThreadPool();
+}
+
+static jboolean android_location_GnssLocationProvider_is_supported(
+ JNIEnv* /* env */, jclass /* clazz */) {
+ return (gnssHal != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
+ JNIEnv* /* env */, jclass /* clazz */) {
+ return (agnssRilIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
+ JNIEnv* /* env */, jclass /* jclazz */) {
+ return (gnssConfigurationIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) {
+ /*
+ * This must be set before calling into the HAL library.
+ */
+ if (!mCallbacksObj)
+ mCallbacksObj = env->NewGlobalRef(obj);
+
+ sp<IGnssCallback> gnssCbIface = new GnssCallback();
+ /*
+ * Fail if the main interface fails to initialize
+ */
+ if (gnssHal == nullptr) {
+ ALOGE("Unable to Initialize GNSS HAL\n");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssHal->setCallback(gnssCbIface);
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("SetCallback for Gnss Interface fails\n");
+ return JNI_FALSE;
+ }
+
+ sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
+ if (gnssXtraIface == nullptr) {
+ ALOGE("Unable to initialize GNSS Xtra interface\n");
+ } else {
+ result = gnssXtraIface->setCallback(gnssXtraCbIface);
+ if ((!result) || (!result.getStatus().isOk())) {
+ gnssXtraIface = nullptr;
+ ALOGE("SetCallback for Gnss Xtra Interface fails\n");
+ }
+ }
+
+ sp<IAGnssCallback> aGnssCbIface = new AGnssCallback();
+ if (agnssIface != nullptr) {
+ agnssIface->setCallback(aGnssCbIface);
+ } else {
+ ALOGE("Unable to Initialize AGnss interface\n");
+ }
+
+ sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
+ if (gnssGeofencingIface != nullptr) {
+ gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
+ } else {
+ ALOGE("Unable to initialize GNSS Geofencing interface\n");
+ }
+
+ sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
+ if (gnssNiCbIface != nullptr) {
+ gnssNiIface->setCallback(gnssNiCbIface);
+ } else {
+ ALOGE("Unable to initialize GNSS NI interface\n");
+ }
+
+ return JNI_TRUE;
+}
+
+static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */) {
+ if (gnssHal != nullptr) {
+ gnssHal->cleanup();
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
+ jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
+ jint preferred_time) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->setPositionMode(static_cast<IGnss::GnssPositionMode>(mode),
+ static_cast<IGnss::GnssPositionRecurrence>(recurrence),
+ min_interval,
+ preferred_accuracy,
+ preferred_time);
+ if (!result.getStatus().isOk()) {
+ ALOGE("%s: GNSS setPositionMode failed\n", __func__);
+ return JNI_FALSE;
+ } else {
+ return result;
+ }
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->start();
+ if (!result.getStatus().isOk()) {
+ return JNI_FALSE;
+ } else {
+ return result;
+ }
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->stop();
+ if (!result.getStatus().isOk()) {
+ return JNI_FALSE;
+ } else {
+ return result;
+ }
+ } else {
+ return JNI_FALSE;
+ }
+}
+static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
+ jobject /* obj */,
+ jint flags) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->deleteAidingData(static_cast<IGnss::GnssAidingData>(flags));
+ if (!result.getStatus().isOk()) {
+ ALOGE("Error in deleting aiding data");
+ }
+ }
+}
+
+/*
+ * This enum is used by the read_sv_status method to combine the svid,
+ * constellation and svFlag fields.
+ */
+enum ShiftWidth: uint8_t {
+ SVID_SHIFT_WIDTH = 7,
+ CONSTELLATION_TYPE_SHIFT_WIDTH = 3
+};
+
+static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
+ jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
+ jfloatArray azumArray) {
+ /*
+ * This method should only be called from within a call to reportSvStatus.
+ */
+ jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
+ jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
+ jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
+ jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
+
+ /*
+ * Read GNSS SV info.
+ */
+ for (size_t i = 0; i < GnssCallback::sGnssSvListSize; ++i) {
+ const IGnssCallback::GnssSvInfo& info = GnssCallback::sGnssSvList[i];
+ svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
+ (static_cast<uint32_t>(info.constellation) << CONSTELLATION_TYPE_SHIFT_WIDTH) |
+ static_cast<uint32_t>(info.svFlag);
+ cn0s[i] = info.cN0Dbhz;
+ elev[i] = info.elevationDegrees;
+ azim[i] = info.azimuthDegrees;
+ }
+
+ env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
+ env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
+ env->ReleaseFloatArrayElements(elevArray, elev, 0);
+ env->ReleaseFloatArrayElements(azumArray, azim, 0);
+ return static_cast<jint>(GnssCallback::sGnssSvListSize);
+}
+
+static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
+ JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid) {
+ IAGnssRil::AGnssRefLocation location;
+
+ if (agnssRilIface == nullptr) {
+ ALOGE("No AGPS RIL interface in agps_set_reference_location_cellid");
+ return;
+ }
+
+ switch (static_cast<IAGnssRil::AGnssRefLocationType>(type)) {
+ case IAGnssRil::AGnssRefLocationType::GSM_CELLID:
+ case IAGnssRil::AGnssRefLocationType::UMTS_CELLID:
+ location.type = static_cast<IAGnssRil::AGnssRefLocationType>(type);
+ location.cellID.mcc = mcc;
+ location.cellID.mnc = mnc;
+ location.cellID.lac = lac;
+ location.cellID.cid = cid;
+ break;
+ default:
+ ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).", __FUNCTION__, __LINE__);
+ return;
+ break;
+ }
+
+ agnssRilIface->setRefLocation(location);
+}
+
+static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
+ jint type, jstring setid_string) {
+ if (agnssRilIface == nullptr) {
+ ALOGE("no AGPS RIL interface in agps_set_id");
+ return;
+ }
+
+ const char *setid = env->GetStringUTFChars(setid_string, NULL);
+ agnssRilIface->setSetId((IAGnssRil::SetIDType)type, setid);
+ env->ReleaseStringUTFChars(setid_string, setid);
+}
+
+static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
+ jbyteArray nmeaArray, jint buffer_size) {
+ // this should only be called from within a call to reportNmea
+ jbyte* nmea = reinterpret_cast<jbyte *>(env->GetPrimitiveArrayCritical(nmeaArray, 0));
+ int length = GnssCallback::sNmeaStringLength;
+ if (length > buffer_size)
+ length = buffer_size;
+ memcpy(nmea, GnssCallback::sNmeaString, length);
+ env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
+ return (jint) length;
+}
+
+static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
+ jlong time, jlong timeReference, jint uncertainty) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->injectTime(time, timeReference, uncertainty);
+ if (!result || !result.getStatus().isOk()) {
+ ALOGE("%s: Gnss injectTime() failed", __func__);
+ }
+ }
+}
+
+static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
+ jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->injectLocation(latitude, longitude, accuracy);
+ if (!result || !result.getStatus().isOk()) {
+ ALOGE("%s: Gnss injectLocation() failed", __func__);
+ }
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_supports_xtra(
+ JNIEnv* /* env */, jobject /* obj */) {
+ return (gnssXtraIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
+ jbyteArray data, jint length) {
+ if (gnssXtraIface == nullptr) {
+ ALOGE("XTRA Interface not supported");
+ return;
+ }
+
+ jbyte* bytes = reinterpret_cast<jbyte *>(env->GetPrimitiveArrayCritical(data, 0));
+ gnssXtraIface->injectXtraData(std::string((const char*)bytes, length));
+ env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_open(
+ JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType) {
+ if (agnssIface == nullptr) {
+ ALOGE("no AGPS interface in agps_data_conn_open");
+ return;
+ }
+ if (apn == NULL) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ return;
+ }
+
+ const char *apnStr = env->GetStringUTFChars(apn, NULL);
+
+ auto result = agnssIface->dataConnOpen(apnStr, static_cast<IAGnss::ApnIpType>(apnIpType));
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("%s: Failed to set APN and its IP type", __func__);
+ }
+ env->ReleaseStringUTFChars(apn, apnStr);
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
+ jobject /* obj */) {
+ if (agnssIface == nullptr) {
+ ALOGE("%s: AGPS interface not supported", __func__);
+ return;
+ }
+
+ auto result = agnssIface->dataConnClosed();
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("%s: Failed to close AGnss data connection", __func__);
+ }
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
+ jobject /* obj */) {
+ if (agnssIface == nullptr) {
+ ALOGE("%s: AGPS interface not supported", __func__);
+ return;
+ }
+
+ auto result = agnssIface->dataConnFailed();
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("%s: Failed to notify unavailability of AGnss data connection", __func__);
+ }
+}
+
+static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
+ jint type, jstring hostname, jint port) {
+ if (agnssIface == nullptr) {
+ ALOGE("no AGPS interface in set_agps_server");
+ return;
+ }
+
+ const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
+ auto result = agnssIface->setServer(static_cast<IAGnssCallback::AGnssType>(type),
+ c_hostname,
+ port);
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("%s: Failed to set AGnss host name and port", __func__);
+ }
+
+ env->ReleaseStringUTFChars(hostname, c_hostname);
+}
+
+static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
+ jobject /* obj */, jint notifId, jint response) {
+ if (gnssNiIface == nullptr) {
+ ALOGE("no NI interface in send_ni_response");
+ return;
+ }
+
+ gnssNiIface->respond(notifId, static_cast<IGnssNiCallback::GnssUserResponseType>(response));
+}
+
+static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
+ jobject /* obj */) {
+ jstring result = NULL;
+ /*
+ * TODO(b/33089503) : Create a jobject to represent GnssDebug.
+ */
+ if (gnssDebugIface != nullptr) {
+ IGnssDebug::DebugData data;
+ gnssDebugIface->getDebugData([&data](const IGnssDebug::DebugData& debugData) {
+ data = debugData;
+ });
+
+ std::stringstream internalState;
+ if (data.position.valid) {
+ internalState << "Gnss Location Data:: LatitudeDegrees: " << data.position.latitudeDegrees
+ << ", LongitudeDegrees: " << data.position.longitudeDegrees
+ << ", altitudeMeters: " << data.position.altitudeMeters
+ << ", accuracyMeters: " << data.position.accuracyMeters
+ << ", ageSeconds: " << data.position.ageSeconds << std::endl;
+ }
+
+ if (data.time.valid) {
+ internalState << "Gnss Time Data:: timeEstimate: " << data.time.timeEstimate
+ << ", timeUncertaintyNs: " << data.time.timeUncertaintyNs << std::endl;
+ }
+
+ if (data.satelliteDataArray.size() != 0) {
+ internalState << "Satellite Data:: ";
+ }
+
+ for (size_t i = 0; i < data.satelliteDataArray.size(); i++) {
+ internalState << "svid: " << data.satelliteDataArray[i].svid
+ << ", constellation: "
+ << static_cast<uint32_t>(data.satelliteDataArray[i].constellation)
+ << ", ephemerisType: "
+ << static_cast<uint32_t>(data.satelliteDataArray[i].ephemerisType)
+ << ", ephemerisAgeSeconds: "
+ << data.satelliteDataArray[i].ephemerisAgeSeconds << std::endl;
+ }
+ result = env->NewStringUTF(internalState.str().c_str());
+ }
+ return result;
+}
+
+static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env,
+ jobject /* obj */,
+ jboolean connected,
+ jint type,
+ jboolean roaming,
+ jboolean available,
+ jstring extraInfo,
+ jstring apn) {
+ if (agnssRilIface != nullptr) {
+ auto result = agnssRilIface->updateNetworkState(connected,
+ static_cast<IAGnssRil::NetworkType>(type),
+ roaming);
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("updateNetworkState failed");
+ }
+
+ const char *c_apn = env->GetStringUTFChars(apn, NULL);
+ result = agnssRilIface->updateNetworkAvailability(available, c_apn);
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("updateNetworkAvailability failed");
+ }
+
+ env->ReleaseStringUTFChars(apn, c_apn);
+ } else {
+ ALOGE("AGnssRilInterface does not exist");
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_is_geofence_supported(
+ JNIEnv* /* env */, jobject /* obj */) {
+ return (gnssGeofencingIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
+ jobject /* obj */, jint geofenceId, jdouble latitude, jdouble longitude, jdouble radius,
+ jint last_transition, jint monitor_transition, jint notification_responsiveness,
+ jint unknown_timer) {
+ if (gnssGeofencingIface != nullptr) {
+ auto result = gnssGeofencingIface->addGeofence(
+ geofenceId, latitude, longitude, radius,
+ static_cast<IGnssGeofenceCallback::GeofenceTransition>(last_transition),
+ monitor_transition, notification_responsiveness, unknown_timer);
+ return boolToJbool(result.getStatus().isOk());
+ } else {
+ ALOGE("Geofence Interface not available");
+ }
+ return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
+ jobject /* obj */, jint geofenceId) {
+ if (gnssGeofencingIface != nullptr) {
+ auto result = gnssGeofencingIface->removeGeofence(geofenceId);
+ return boolToJbool(result.getStatus().isOk());
+ } else {
+ ALOGE("Geofence interface not available");
+ }
+ return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
+ jobject /* obj */, jint geofenceId) {
+ if (gnssGeofencingIface != nullptr) {
+ auto result = gnssGeofencingIface->pauseGeofence(geofenceId);
+ return boolToJbool(result.getStatus().isOk());
+ } else {
+ ALOGE("Geofence interface not available");
+ }
+ return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
+ jobject /* obj */, jint geofenceId, jint monitor_transition) {
+ if (gnssGeofencingIface != nullptr) {
+ auto result = gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition);
+ return boolToJbool(result.getStatus().isOk());
+ } else {
+ ALOGE("Geofence interface not available");
+ }
+ return JNI_FALSE;
+}
+
static jboolean android_location_GnssLocationProvider_is_measurement_supported(
- JNIEnv* env,
- jclass clazz) {
- if (sGpsMeasurementInterface != NULL) {
+ JNIEnv* env, jclass clazz) {
+ if (gnssMeasurementIface != nullptr) {
return JNI_TRUE;
}
+
return JNI_FALSE;
}
static jboolean android_location_GnssLocationProvider_start_measurement_collection(
JNIEnv* env,
jobject obj) {
- if (sGpsMeasurementInterface == NULL) {
- ALOGE("Measurement interface is not available.");
+ if (gnssMeasurementIface == nullptr) {
+ ALOGE("GNSS Measurement interface is not available.");
return JNI_FALSE;
}
- int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
- if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
- ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
+ sp<GnssMeasurementCallback> cbIface = new GnssMeasurementCallback();
+ IGnssMeasurement::GnssMeasurementStatus result = gnssMeasurementIface->setCallback(cbIface);
+ if (result != IGnssMeasurement::GnssMeasurementStatus::SUCCESS) {
+ ALOGE("An error has been found on GnssMeasurementInterface::init, status=%d",
+ static_cast<int32_t>(result));
return JNI_FALSE;
+ } else {
+ ALOGD("gnss measurement infc has been enabled");
}
return JNI_TRUE;
@@ -1464,104 +1464,19 @@
static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
JNIEnv* env,
jobject obj) {
- if (sGpsMeasurementInterface == NULL) {
+ if (gnssMeasurementIface == nullptr) {
ALOGE("Measurement interface not available");
return JNI_FALSE;
}
- sGpsMeasurementInterface->close();
- return JNI_TRUE;
+ auto result = gnssMeasurementIface->close();
+ return boolToJbool(result.getStatus().isOk());
}
-static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
- size_t dataLength = message->data_length;
- uint8_t* data = message->data;
- if (dataLength == 0 || data == NULL) {
- ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
- return NULL;
- }
- JavaObject object(env, "android/location/GnssNavigationMessage");
- SET(Svid, static_cast<int32_t>(message->prn));
- if (message->prn >=1 && message->prn <= 32) {
- SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
- // Legacy driver doesn't set the higher byte to constellation type
- // correctly. Set the higher byte to 'GPS'.
- SET(Type, static_cast<int32_t>(message->type | 0x0100));
- } else {
- ALOGD("Unknown constellation type with Svid = %d.", message->prn);
- SET(ConstellationType,
- static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
- SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
- }
- SET(MessageId, static_cast<int32_t>(message->message_id));
- SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
- object.callSetter("setData", data, dataLength);
- SET(Status, static_cast<int32_t>(message->status));
- return object.get();
-}
-
-static jobject translate_gnss_navigation_message(
- JNIEnv* env, GnssNavigationMessage* message) {
- size_t dataLength = message->data_length;
- uint8_t* data = message->data;
- if (dataLength == 0 || data == NULL) {
- ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
- return NULL;
- }
- JavaObject object(env, "android/location/GnssNavigationMessage");
- SET(Type, static_cast<int32_t>(message->type));
- SET(Svid, static_cast<int32_t>(message->svid));
- SET(MessageId, static_cast<int32_t>(message->message_id));
- SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
- object.callSetter("setData", data, dataLength);
- SET(Status, static_cast<int32_t>(message->status));
- return object.get();
-}
-
-static void navigation_message_callback(GpsNavigationMessage* message) {
- if (message == NULL) {
- ALOGE("Invalid Navigation Message provided to callback");
- return;
- }
- if (message->size != sizeof(GpsNavigationMessage)) {
- ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
- return;
- }
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jobject navigationMessage = translate_gps_navigation_message(env, message);
- env->CallVoidMethod(mCallbacksObj,
- method_reportNavigationMessages,
- navigationMessage);
- env->DeleteLocalRef(navigationMessage);
-}
-
-static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
- if (message == NULL) {
- ALOGE("Invalid Navigation Message provided to callback");
- return;
- }
- if (message->size != sizeof(GnssNavigationMessage)) {
- ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
- return;
- }
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jobject navigationMessage = translate_gnss_navigation_message(env, message);
- env->CallVoidMethod(mCallbacksObj,
- method_reportNavigationMessages,
- navigationMessage);
- env->DeleteLocalRef(navigationMessage);
-}
-
-GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
- sizeof(GpsNavigationMessageCallbacks),
- navigation_message_callback,
- gnss_navigation_message_callback,
-};
-
static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
JNIEnv* env,
jclass clazz) {
- if(sGpsNavigationMessageInterface != NULL) {
+ if (gnssNavigationMessageIface != nullptr) {
return JNI_TRUE;
}
return JNI_FALSE;
@@ -1570,14 +1485,18 @@
static jboolean android_location_GnssLocationProvider_start_navigation_message_collection(
JNIEnv* env,
jobject obj) {
- if (sGpsNavigationMessageInterface == NULL) {
+ if (gnssNavigationMessageIface == nullptr) {
ALOGE("Navigation Message interface is not available.");
return JNI_FALSE;
}
- int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks);
- if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) {
- ALOGE("An error has been found in %s: %d", __FUNCTION__, result);
+ sp<IGnssNavigationMessageCallback> gnssNavigationMessageCbIface =
+ new GnssNavigationMessageCallback();
+ IGnssNavigationMessage::GnssNavigationMessageStatus result =
+ gnssNavigationMessageIface->setCallback(gnssNavigationMessageCbIface);
+
+ if (result != IGnssNavigationMessage::GnssNavigationMessageStatus::SUCCESS) {
+ ALOGE("An error has been found in %s: %d", __FUNCTION__, static_cast<int32_t>(result));
return JNI_FALSE;
}
@@ -1587,127 +1506,255 @@
static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection(
JNIEnv* env,
jobject obj) {
- if (sGpsNavigationMessageInterface == NULL) {
+ if (gnssNavigationMessageIface == nullptr) {
ALOGE("Navigation Message interface is not available.");
return JNI_FALSE;
}
- sGpsNavigationMessageInterface->close();
- return JNI_TRUE;
+ auto result = gnssNavigationMessageIface->close();
+ return boolToJbool(result.getStatus().isOk());
}
-static void android_location_GnssLocationProvider_configuration_update(JNIEnv* env, jobject obj,
- jstring config_content)
-{
- if (!sGnssConfigurationInterface) {
- ALOGE("no GPS configuration interface in configuraiton_update");
- return;
+static jboolean android_location_GnssLocationProvider_set_emergency_supl_pdn(JNIEnv*,
+ jobject,
+ jint emergencySuplPdn) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
}
- const char *data = env->GetStringUTFChars(config_content, NULL);
- ALOGD("GPS configuration:\n %s", data);
- sGnssConfigurationInterface->configuration_update(
- data, env->GetStringUTFLength(config_content));
- env->ReleaseStringUTFChars(config_content, data);
+
+ auto result = gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_version(JNIEnv*,
+ jobject,
+ jint version) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+ auto result = gnssConfigurationIface->setSuplVersion(version);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_es(JNIEnv*,
+ jobject,
+ jint suplEs) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssConfigurationIface->setSuplEs(suplEs);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_mode(JNIEnv*,
+ jobject,
+ jint mode) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssConfigurationIface->setSuplMode(mode);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_gps_lock(JNIEnv*,
+ jobject,
+ jint gpsLock) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssConfigurationIface->setGpsLock(gpsLock);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_lpp_profile(JNIEnv*,
+ jobject,
+ jint lppProfile) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssConfigurationIface->setLppProfile(lppProfile);
+
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_gnss_pos_protocol_select(JNIEnv*,
+ jobject,
+ jint gnssPosProtocol) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
}
static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
- {"class_init_native", "()V", (void *)android_location_GnssLocationProvider_class_init_native},
- {"native_is_supported", "()Z", (void*)android_location_GnssLocationProvider_is_supported},
+ {"class_init_native", "()V", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_class_init_native)},
+ {"native_is_supported", "()Z", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_is_supported)},
{"native_is_agps_ril_supported", "()Z",
- (void*)android_location_GnssLocationProvider_is_agps_ril_supported},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_is_agps_ril_supported)},
{"native_is_gnss_configuration_supported", "()Z",
- (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported},
- {"native_init", "()Z", (void*)android_location_GnssLocationProvider_init},
- {"native_cleanup", "()V", (void*)android_location_GnssLocationProvider_cleanup},
+ reinterpret_cast<void *>(
+ android_location_gpsLocationProvider_is_gnss_configuration_supported)},
+ {"native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},
+ {"native_cleanup", "()V", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_cleanup)},
{"native_set_position_mode",
"(IIIII)Z",
- (void*)android_location_GnssLocationProvider_set_position_mode},
- {"native_start", "()Z", (void*)android_location_GnssLocationProvider_start},
- {"native_stop", "()Z", (void*)android_location_GnssLocationProvider_stop},
+ reinterpret_cast<void*>(android_location_GnssLocationProvider_set_position_mode)},
+ {"native_start", "()Z", reinterpret_cast<void*>(android_location_GnssLocationProvider_start)},
+ {"native_stop", "()Z", reinterpret_cast<void*>(android_location_GnssLocationProvider_stop)},
{"native_delete_aiding_data",
"(I)V",
- (void*)android_location_GnssLocationProvider_delete_aiding_data},
+ reinterpret_cast<void*>(android_location_GnssLocationProvider_delete_aiding_data)},
{"native_read_sv_status",
"([I[F[F[F)I",
- (void*)android_location_GnssLocationProvider_read_sv_status},
- {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
- {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_read_sv_status)},
+ {"native_read_nmea", "([BI)I", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_read_nmea)},
+ {"native_inject_time", "(JJI)V", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_inject_time)},
{"native_inject_location",
"(DDF)V",
- (void*)android_location_GnssLocationProvider_inject_location},
- {"native_supports_xtra", "()Z", (void*)android_location_GnssLocationProvider_supports_xtra},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_location)},
+ {"native_supports_xtra", "()Z", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_supports_xtra)},
{"native_inject_xtra_data",
"([BI)V",
- (void*)android_location_GnssLocationProvider_inject_xtra_data},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_xtra_data)},
{"native_agps_data_conn_open",
"(Ljava/lang/String;I)V",
- (void*)android_location_GnssLocationProvider_agps_data_conn_open},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_open)},
{"native_agps_data_conn_closed",
"()V",
- (void*)android_location_GnssLocationProvider_agps_data_conn_closed},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_closed)},
{"native_agps_data_conn_failed",
"()V",
- (void*)android_location_GnssLocationProvider_agps_data_conn_failed},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_failed)},
{"native_agps_set_id",
"(ILjava/lang/String;)V",
- (void*)android_location_GnssLocationProvider_agps_set_id},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_set_id)},
{"native_agps_set_ref_location_cellid",
"(IIIII)V",
- (void*)android_location_GnssLocationProvider_agps_set_reference_location_cellid},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_agps_set_reference_location_cellid)},
{"native_set_agps_server",
"(ILjava/lang/String;I)V",
- (void*)android_location_GnssLocationProvider_set_agps_server},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_agps_server)},
{"native_send_ni_response",
"(II)V",
- (void*)android_location_GnssLocationProvider_send_ni_response},
- {"native_agps_ni_message",
- "([BI)V",
- (void *)android_location_GnssLocationProvider_agps_send_ni_message},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_send_ni_response)},
{"native_get_internal_state",
"()Ljava/lang/String;",
- (void*)android_location_GnssLocationProvider_get_internal_state},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_get_internal_state)},
{"native_update_network_state",
"(ZIZZLjava/lang/String;Ljava/lang/String;)V",
- (void*)android_location_GnssLocationProvider_update_network_state },
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)},
{"native_is_geofence_supported",
"()Z",
- (void*) android_location_GnssLocationProvider_is_geofence_supported},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_is_geofence_supported)},
{"native_add_geofence",
"(IDDDIIII)Z",
- (void *)android_location_GnssLocationProvider_add_geofence},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_add_geofence)},
{"native_remove_geofence",
"(I)Z",
- (void *)android_location_GnssLocationProvider_remove_geofence},
- {"native_pause_geofence", "(I)Z", (void *)android_location_GnssLocationProvider_pause_geofence},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_remove_geofence)},
+ {"native_pause_geofence", "(I)Z", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_pause_geofence)},
{"native_resume_geofence",
"(II)Z",
- (void *)android_location_GnssLocationProvider_resume_geofence},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_resume_geofence)},
{"native_is_measurement_supported",
"()Z",
- (void*) android_location_GnssLocationProvider_is_measurement_supported},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_is_measurement_supported)},
{"native_start_measurement_collection",
"()Z",
- (void*) android_location_GnssLocationProvider_start_measurement_collection},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_start_measurement_collection)},
{"native_stop_measurement_collection",
"()Z",
- (void*) android_location_GnssLocationProvider_stop_measurement_collection},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_stop_measurement_collection)},
{"native_is_navigation_message_supported",
"()Z",
- (void*) android_location_GnssLocationProvider_is_navigation_message_supported},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_is_navigation_message_supported)},
{"native_start_navigation_message_collection",
"()Z",
- (void*) android_location_GnssLocationProvider_start_navigation_message_collection},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_start_navigation_message_collection)},
{"native_stop_navigation_message_collection",
"()Z",
- (void*) android_location_GnssLocationProvider_stop_navigation_message_collection},
- {"native_configuration_update",
- "(Ljava/lang/String;)V",
- (void*)android_location_GnssLocationProvider_configuration_update},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_stop_navigation_message_collection)},
+ {"native_set_supl_es",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_es)},
+ {"native_set_supl_version",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_version)},
+ {"native_set_supl_mode",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_mode)},
+ {"native_set_lpp_profile",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_lpp_profile)},
+ {"native_set_gnss_pos_protocol_select",
+ "(I)Z",
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_set_gnss_pos_protocol_select)},
+ {"native_set_gps_lock",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_gps_lock)},
+ {"native_set_emergency_supl_pdn",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_emergency_supl_pdn)},
};
-int register_android_server_location_GnssLocationProvider(JNIEnv* env)
-{
+int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
return jniRegisterNativeMethods(
env,
"com/android/server/location/GnssLocationProvider",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a2af40c..aafc432 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -17,6 +17,21 @@
package com.android.server.devicepolicy;
import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
+import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY;
+import static android.app.admin.DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED;
+import static android.app.admin.DevicePolicyManager.CODE_HAS_DEVICE_OWNER;
+import static android.app.admin.DevicePolicyManager.CODE_HAS_PAIRED;
+import static android.app.admin.DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED;
+import static android.app.admin.DevicePolicyManager.CODE_NONSYSTEM_USER_EXISTS;
+import static android.app.admin.DevicePolicyManager.CODE_NOT_SYSTEM_USER;
+import static android.app.admin.DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT;
+import static android.app.admin.DevicePolicyManager.CODE_OK;
+import static android.app.admin.DevicePolicyManager.CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER;
+import static android.app.admin.DevicePolicyManager.CODE_SYSTEM_USER;
+import static android.app.admin.DevicePolicyManager.CODE_USER_HAS_PROFILE_OWNER;
+import static android.app.admin.DevicePolicyManager.CODE_USER_NOT_RUNNING;
+import static android.app.admin.DevicePolicyManager.CODE_USER_SETUP_COMPLETED;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
@@ -310,21 +325,6 @@
private static final int PROFILE_KEYGUARD_FEATURES =
PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER | PROFILE_KEYGUARD_FEATURES_PROFILE_ONLY;
- private static final int CODE_OK = 0;
- private static final int CODE_HAS_DEVICE_OWNER = 1;
- private static final int CODE_USER_HAS_PROFILE_OWNER = 2;
- private static final int CODE_USER_NOT_RUNNING = 3;
- private static final int CODE_USER_SETUP_COMPLETED = 4;
- private static final int CODE_NONSYSTEM_USER_EXISTS = 5;
- private static final int CODE_ACCOUNTS_NOT_EMPTY = 6;
- private static final int CODE_NOT_SYSTEM_USER = 7;
- private static final int CODE_HAS_PAIRED = 8;
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({ CODE_OK, CODE_HAS_DEVICE_OWNER, CODE_USER_HAS_PROFILE_OWNER, CODE_USER_NOT_RUNNING,
- CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER })
- private @interface DeviceOwnerPreConditionCode {}
-
private static final int DEVICE_ADMIN_DEACTIVATE_TIMEOUT = 10000;
/**
@@ -3093,6 +3093,7 @@
// If admin is a device or profile owner tidy that up first.
if (isDeviceOwner(adminReceiver, userHandle)) {
clearDeviceOwnerLocked(getDeviceOwnerAdminLocked(), userHandle);
+ clearDeviceOwnerUserRestrictionLocked(UserHandle.of(userHandle));
}
if (isProfileOwner(adminReceiver, userHandle)) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver,
@@ -3108,6 +3109,15 @@
}
}
+ // It's temporary solution to clear DISALLOW_ADD_USER after CTS
+ // TODO: b/31952368 when the restriction is moved from system to the device owner,
+ // it can be removed.
+ private void clearDeviceOwnerUserRestrictionLocked(UserHandle userHandle) {
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER, userHandle)) {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false, userHandle);
+ }
+ }
+
/**
* Return if a given package has testOnly="true", in which case we'll relax certain rules
* for CTS.
@@ -6526,7 +6536,7 @@
enforceCanManageProfileAndDeviceOwners();
}
- final int code = checkSetDeviceOwnerPreConditionLocked(owner, userId, isAdb());
+ final int code = checkDeviceOwnerProvisioningPreConditionLocked(owner, userId, isAdb());
switch (code) {
case CODE_OK:
return;
@@ -6553,7 +6563,7 @@
throw new IllegalStateException("Not allowed to set the device owner because this "
+ "device has already paired");
default:
- throw new IllegalStateException("Unknown @DeviceOwnerPreConditionCode " + code);
+ throw new IllegalStateException("Unexpected @ProvisioningPreCondition " + code);
}
}
@@ -8761,79 +8771,42 @@
@Override
public boolean isProvisioningAllowed(String action) {
+ return checkProvisioningPreConditionSkipPermission(action) == CODE_OK;
+ }
+
+ @Override
+ public int checkProvisioningPreCondition(String action) {
+ enforceCanManageProfileAndDeviceOwners();
+ return checkProvisioningPreConditionSkipPermission(action);
+ }
+
+ private int checkProvisioningPreConditionSkipPermission(String action) {
if (!mHasFeature) {
- return false;
+ return CODE_DEVICE_ADMIN_NOT_SUPPORTED;
}
final int callingUserId = mInjector.userHandleGetCallingUserId();
- if (DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(action)) {
- if (!hasFeatureManagedUsers()) {
- return false;
+ if (action != null) {
+ switch (action) {
+ case DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE:
+ return checkManagedProfileProvisioningPreCondition(callingUserId);
+ case DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE:
+ return checkDeviceOwnerProvisioningPreCondition(callingUserId);
+ case DevicePolicyManager.ACTION_PROVISION_MANAGED_USER:
+ return checkManagedUserProvisioningPreCondition(callingUserId);
+ case DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE:
+ return checkManagedShareableDeviceProvisioningPreCondition(callingUserId);
}
- synchronized (this) {
- if (mOwners.hasDeviceOwner()) {
- // STOPSHIP Only allow creating a managed profile if allowed by the device
- // owner. http://b/31952368
- if (mInjector.userManagerIsSplitSystemUser()) {
- if (callingUserId == UserHandle.USER_SYSTEM) {
- // Managed-profiles cannot be setup on the system user.
- return false;
- }
- }
- }
- }
- if (getProfileOwner(callingUserId) != null) {
- // Managed user cannot have a managed profile.
- return false;
- }
- boolean canRemoveProfile
- = !mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER);
- final long ident = mInjector.binderClearCallingIdentity();
- try {
- if (!mUserManager.canAddMoreManagedProfiles(callingUserId, canRemoveProfile)) {
- return false;
- }
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
- return true;
- } else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE.equals(action)) {
- return isDeviceOwnerProvisioningAllowed(callingUserId);
- } else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_USER.equals(action)) {
- if (!hasFeatureManagedUsers()) {
- return false;
- }
- if (!mInjector.userManagerIsSplitSystemUser()) {
- // ACTION_PROVISION_MANAGED_USER only supported on split-user systems.
- return false;
- }
- if (callingUserId == UserHandle.USER_SYSTEM) {
- // System user cannot be a managed user.
- return false;
- }
- if (hasUserSetupCompleted(callingUserId)) {
- return false;
- }
- if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
- return false;
- }
- return true;
- } else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE.equals(action)) {
- if (!mInjector.userManagerIsSplitSystemUser()) {
- // ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE only supported on split-user systems.
- return false;
- }
- return isDeviceOwnerProvisioningAllowed(callingUserId);
}
throw new IllegalArgumentException("Unknown provisioning action " + action);
}
- /*
+ /**
* The device owner can only be set before the setup phase of the primary user has completed,
* except for adb command if no accounts or additional users are present on the device.
*/
- private synchronized @DeviceOwnerPreConditionCode int checkSetDeviceOwnerPreConditionLocked(
- @Nullable ComponentName owner, int deviceOwnerUserId, boolean isAdb) {
+ private int checkDeviceOwnerProvisioningPreConditionLocked(@Nullable ComponentName owner,
+ int deviceOwnerUserId, boolean isAdb) {
if (mOwners.hasDeviceOwner()) {
return CODE_HAS_DEVICE_OWNER;
}
@@ -8878,13 +8851,75 @@
}
}
- private boolean isDeviceOwnerProvisioningAllowed(int deviceOwnerUserId) {
+ private int checkDeviceOwnerProvisioningPreCondition(int deviceOwnerUserId) {
synchronized (this) {
- return CODE_OK == checkSetDeviceOwnerPreConditionLocked(
- /* owner unknown */ null, deviceOwnerUserId, /* isAdb */ false);
+ return checkDeviceOwnerProvisioningPreConditionLocked(/* owner unknown */ null,
+ deviceOwnerUserId, /* isAdb= */ false);
}
}
+ private int checkManagedProfileProvisioningPreCondition(int callingUserId) {
+ if (!hasFeatureManagedUsers()) {
+ return CODE_MANAGED_USERS_NOT_SUPPORTED;
+ }
+ synchronized (this) {
+ if (mOwners.hasDeviceOwner()) {
+ // STOPSHIP Only allow creating a managed profile if allowed by the device
+ // owner. http://b/31952368
+ if (mInjector.userManagerIsSplitSystemUser()) {
+ if (callingUserId == UserHandle.USER_SYSTEM) {
+ // Managed-profiles cannot be setup on the system user.
+ return CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER;
+ }
+ }
+ }
+ }
+ if (getProfileOwner(callingUserId) != null) {
+ // Managed user cannot have a managed profile.
+ return CODE_USER_HAS_PROFILE_OWNER;
+ }
+ boolean canRemoveProfile =
+ !mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER);
+ final long ident = mInjector.binderClearCallingIdentity();
+ try {
+ if (!mUserManager.canAddMoreManagedProfiles(callingUserId, canRemoveProfile)) {
+ return CODE_CANNOT_ADD_MANAGED_PROFILE;
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(ident);
+ }
+ return CODE_OK;
+ }
+
+ private int checkManagedUserProvisioningPreCondition(int callingUserId) {
+ if (!hasFeatureManagedUsers()) {
+ return CODE_MANAGED_USERS_NOT_SUPPORTED;
+ }
+ if (!mInjector.userManagerIsSplitSystemUser()) {
+ // ACTION_PROVISION_MANAGED_USER only supported on split-user systems.
+ return CODE_NOT_SYSTEM_USER_SPLIT;
+ }
+ if (callingUserId == UserHandle.USER_SYSTEM) {
+ // System user cannot be a managed user.
+ return CODE_SYSTEM_USER;
+ }
+ if (hasUserSetupCompleted(callingUserId)) {
+ return CODE_USER_SETUP_COMPLETED;
+ }
+ if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
+ return CODE_HAS_PAIRED;
+ }
+ return CODE_OK;
+ }
+
+ private int checkManagedShareableDeviceProvisioningPreCondition(int callingUserId) {
+ if (!mInjector.userManagerIsSplitSystemUser()) {
+ // ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE only supported on split-user systems.
+ return CODE_NOT_SYSTEM_USER_SPLIT;
+ }
+ return checkDeviceOwnerProvisioningPreCondition(callingUserId);
+ }
+
private boolean hasFeatureManagedUsers() {
try {
return mIPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0);
@@ -9831,9 +9866,8 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(admin);
synchronized (this) {
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ enforceDeviceOwnerOrManageUsers();
return isNetworkLoggingEnabledInternalLocked();
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1fc4378..02dc5fb 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -114,6 +114,7 @@
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
+import java.util.concurrent.CountDownLatch;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -1484,8 +1485,10 @@
@Override
public void run() {
Slog.i(TAG, "Making services ready");
+ traceBeginAndSlog("StartActivityManagerReadyPhase");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
+ traceEnd();
traceBeginAndSlog("PhaseActivityManagerReady");
traceBeginAndSlog("StartObservingNativeCrashes");
@@ -1523,6 +1526,11 @@
} catch (Throwable e) {
reportWtf("making Network Managment Service ready", e);
}
+ CountDownLatch networkPolicyInitReadySignal = null;
+ if (networkPolicyF != null) {
+ networkPolicyInitReadySignal = networkPolicyF
+ .networkScoreAndNetworkManagementServiceReady();
+ }
traceEnd();
traceBeginAndSlog("MakeNetworkStatsServiceReady");
try {
@@ -1531,13 +1539,6 @@
reportWtf("making Network Stats Service ready", e);
}
traceEnd();
- traceBeginAndSlog("MakeNetworkPolicyServiceReady");
- try {
- if (networkPolicyF != null) networkPolicyF.systemReady();
- } catch (Throwable e) {
- reportWtf("making Network Policy Service ready", e);
- }
- traceEnd();
traceBeginAndSlog("MakeConnectivityServiceReady");
try {
if (connectivityF != null) connectivityF.systemReady();
@@ -1545,6 +1546,15 @@
reportWtf("making Connectivity Service ready", e);
}
traceEnd();
+ traceBeginAndSlog("MakeNetworkPolicyServiceReady");
+ try {
+ if (networkPolicyF != null) {
+ networkPolicyF.systemReady(networkPolicyInitReadySignal);
+ }
+ } catch (Throwable e) {
+ reportWtf("making Network Policy Service ready", e);
+ }
+ traceEnd();
traceBeginAndSlog("StartWatchdog");
Watchdog.getInstance().start();
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index a8356dc..83001df 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -194,8 +194,10 @@
{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
- private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
+ private static final int ICMP6_ROUTER_SOLICITATION = 133;
private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
+ private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
+ private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
// NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 2;
@@ -805,6 +807,8 @@
// if it's multicast and we're dropping multicast:
// drop
// pass
+ // if it's ICMPv6 RS to any:
+ // drop
// if it's ICMPv6 NA to ff02::1:
// drop
@@ -829,10 +833,12 @@
// Add unsolicited multicast neighbor announcements filter
String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA";
- // If not neighbor announcements, skip unsolicited multicast NA filter
gen.addLoad8(Register.R0, ICMP6_TYPE_OFFSET);
+ // Drop all router solicitations (b/32833400)
+ gen.addJumpIfR0Equals(ICMP6_ROUTER_SOLICITATION, gen.DROP_LABEL);
+ // If not neighbor announcements, skip filter.
gen.addJumpIfR0NotEquals(ICMP6_NEIGHBOR_ANNOUNCEMENT, skipUnsolicitedMulticastNALabel);
- // If to ff02::1, drop
+ // If to ff02::1, drop.
// TODO: Drop only if they don't contain the address of on-link neighbours.
gen.addLoadImmediate(Register.R0, IPV6_DEST_ADDR_OFFSET);
gen.addJumpIfBytesNotEqual(Register.R0, IPV6_ALL_NODES_ADDRESS,
@@ -852,6 +858,7 @@
* <li>Pass all non-ICMPv6 IPv6 packets,
* <li>Pass all non-IPv4 and non-IPv6 packets,
* <li>Drop IPv6 ICMPv6 NAs to ff02::1.
+ * <li>Drop IPv6 ICMPv6 RSs.
* <li>Let execution continue off the end of the program for IPv6 ICMPv6 packets. This allows
* insertion of RA filters here, or if there aren't any, just passes the packets.
* </ul>
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationListenerServiceTest.java
new file mode 100644
index 0000000..b6166f6
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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 com.android.server.notification;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.NotificationChannel;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationRankingUpdate;
+import android.service.notification.SnoozeCriterion;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationListenerServiceTest {
+
+ private String[] mKeys = new String[] { "key", "key1", "key2", "key3"};
+
+ @Test
+ public void testRanking() throws Exception {
+ TestListenerService service = new TestListenerService();
+ service.applyUpdateLocked(generateUpdate());
+ for (int i = 0; i < mKeys.length; i++) {
+ String key = mKeys[i];
+ Ranking ranking = new Ranking();
+ service.getCurrentRanking().getRanking(key, ranking);
+ assertEquals(getVisibilityOverride(i), ranking.getVisibilityOverride());
+ assertEquals(getOverrideGroupKey(key), ranking.getOverrideGroupKey());
+ assertEquals(!isIntercepted(i), ranking.matchesInterruptionFilter());
+ assertEquals(getSuppressedVisualEffects(i), ranking.getSuppressedVisualEffects());
+ assertEquals(getImportance(i), ranking.getImportance());
+ assertEquals(getExplanation(key), ranking.getImportanceExplanation());
+ assertEquals(getChannel(key, i), ranking.getChannel());
+ assertEquals(getPeople(key, i), ranking.getAdditionalPeople());
+ assertEquals(getSnoozeCriteria(key, i), ranking.getSnoozeCriteria());
+ }
+ }
+
+ private NotificationRankingUpdate generateUpdate() {
+ List<String> interceptedKeys = new ArrayList<>();
+ Bundle visibilityOverrides = new Bundle();
+ Bundle overrideGroupKeys = new Bundle();
+ Bundle suppressedVisualEffects = new Bundle();
+ Bundle explanation = new Bundle();
+ Bundle overrideChannels = new Bundle();
+ Bundle overridePeople = new Bundle();
+ Bundle snoozeCriteria = new Bundle();
+ int[] importance = new int[mKeys.length];
+
+ for (int i = 0; i < mKeys.length; i++) {
+ String key = mKeys[i];
+ visibilityOverrides.putInt(key, getVisibilityOverride(i));
+ overrideGroupKeys.putString(key, getOverrideGroupKey(key));
+ if (isIntercepted(i)) {
+ interceptedKeys.add(key);
+ }
+ suppressedVisualEffects.putInt(key, getSuppressedVisualEffects(i));
+ importance[i] = getImportance(i);
+ explanation.putString(key, getExplanation(key));
+ overrideChannels.putParcelable(key, getChannel(key, i));
+ overridePeople.putStringArrayList(key, getPeople(key, i));
+ snoozeCriteria.putParcelableArrayList(key, getSnoozeCriteria(key, i));
+ }
+ NotificationRankingUpdate update = new NotificationRankingUpdate(mKeys,
+ interceptedKeys.toArray(new String[0]), visibilityOverrides,
+ suppressedVisualEffects, importance, explanation, overrideGroupKeys,
+ overrideChannels, overridePeople, snoozeCriteria);
+ return update;
+ }
+
+ private int getVisibilityOverride(int index) {
+ return index * 9;
+ }
+
+ private String getOverrideGroupKey(String key) {
+ return key + key;
+ }
+
+ private boolean isIntercepted(int index) {
+ return index % 2 == 0;
+ }
+
+ private int getSuppressedVisualEffects(int index) {
+ return index * 2;
+ }
+
+ private int getImportance(int index) {
+ return index;
+ }
+
+ private String getExplanation(String key) {
+ return key + "explain";
+ }
+
+ private NotificationChannel getChannel(String key, int index) {
+ return new NotificationChannel(key, key, getImportance(index));
+ }
+
+ private ArrayList<String> getPeople(String key, int index) {
+ ArrayList<String> people = new ArrayList<>();
+ for (int i = 0; i < index; i++) {
+ people.add(i + key);
+ }
+ return people;
+ }
+
+ private ArrayList<SnoozeCriterion> getSnoozeCriteria(String key, int index) {
+ ArrayList<SnoozeCriterion> snooze = new ArrayList<>();
+ for (int i = 0; i < index; i++) {
+ snooze.add(new SnoozeCriterion(key + i, getExplanation(key), key));
+ }
+ return snooze;
+ }
+
+ public static class TestListenerService extends NotificationListenerService {
+ private final IBinder binder = new LocalBinder();
+
+ public TestListenerService() {
+
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ super.onBind(intent);
+ return binder;
+ }
+
+ public class LocalBinder extends Binder {
+ TestListenerService getService() {
+ return TestListenerService.this;
+ }
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 3114f3f..796284d 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -43,12 +43,12 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
+import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
@@ -77,7 +77,6 @@
import android.net.INetworkStatsService;
import android.net.LinkProperties;
import android.net.NetworkInfo;
-import android.net.NetworkPolicyManager;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkPolicy;
import android.net.NetworkState;
@@ -141,6 +140,15 @@
/**
* Tests for {@link NetworkPolicyManagerService}.
+ *
+ * <p>Typical usage:
+ *
+ * <pre><code>
+ m -j32 FrameworksServicesTests && adb install -r -g \
+ ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && \
+ adb shell am instrument -e class "com.android.server.NetworkPolicyManagerServiceTest" -w \
+ "com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner"
+ * </code></pre>
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
@@ -247,7 +255,7 @@
return null;
}
}).when(mActivityManager).registerUidObserver(any(), anyInt(),
- ActivityManager.PROCESS_STATE_UNKNOWN, null);
+ eq(ActivityManager.PROCESS_STATE_UNKNOWN), isNull(String.class));
mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
mNetworkManager, mIpm, mTime, mPolicyDir, true);
@@ -282,7 +290,7 @@
expectCurrentTime();
// Prepare NPMS.
- mService.systemReady();
+ mService.systemReady(mService.networkScoreAndNetworkManagementServiceReady());
// catch INetworkManagementEventObserver during systemReady()
final ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
new file mode 100644
index 0000000..50911cb
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2012 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.android.server;
+
+import static android.net.NetworkScoreManager.CACHE_FILTER_NONE;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyListOf;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.Manifest.permission;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.net.INetworkScoreCache;
+import android.net.NetworkKey;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppManager;
+import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.ScoredNetwork;
+import android.net.WifiKey;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.R;
+import com.android.server.devicepolicy.MockUtils;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link NetworkScoreService}.
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class NetworkScoreServiceTest {
+ private static final ScoredNetwork SCORED_NETWORK =
+ new ScoredNetwork(new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00")),
+ null /* rssiCurve*/);
+ private static final NetworkScorerAppData PREV_SCORER = new NetworkScorerAppData(
+ "prevPackageName", 0, "prevScorerName", null /* configurationActivityClassName */,
+ "prevScoringServiceClass");
+ private static final NetworkScorerAppData NEW_SCORER = new NetworkScorerAppData(
+ "newPackageName", 1, "newScorerName", null /* configurationActivityClassName */,
+ "newScoringServiceClass");
+
+ @Mock private PackageManager mPackageManager;
+ @Mock private NetworkScorerAppManager mNetworkScorerAppManager;
+ @Mock private Context mContext;
+ @Mock private Resources mResources;
+ @Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2;
+ @Mock private IBinder mIBinder, mIBinder2;
+ @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;
+
+ private ContentResolver mContentResolver;
+ private NetworkScoreService mNetworkScoreService;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mNetworkScoreCache.asBinder()).thenReturn(mIBinder);
+ when(mNetworkScoreCache2.asBinder()).thenReturn(mIBinder2);
+ mContentResolver = InstrumentationRegistry.getContext().getContentResolver();
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getResources()).thenReturn(mResources);
+ mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager);
+ }
+
+ @Test
+ public void testSystemReady_networkScorerProvisioned() throws Exception {
+ Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 1);
+
+ mNetworkScoreService.systemReady();
+
+ verify(mNetworkScorerAppManager, never()).setActiveScorer(anyString());
+ }
+
+ @Test
+ public void testSystemReady_networkScorerNotProvisioned_defaultScorer() throws Exception {
+ Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 0);
+
+ when(mResources.getString(R.string.config_defaultNetworkScorerPackageName))
+ .thenReturn(NEW_SCORER.mPackageName);
+
+ mNetworkScoreService.systemReady();
+
+ verify(mNetworkScorerAppManager).setActiveScorer(NEW_SCORER.mPackageName);
+ assertEquals(1,
+ Settings.Global.getInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED));
+
+ }
+
+ @Test
+ public void testSystemReady_networkScorerNotProvisioned_noDefaultScorer() throws Exception {
+ Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 0);
+
+ when(mResources.getString(R.string.config_defaultNetworkScorerPackageName))
+ .thenReturn(null);
+
+ mNetworkScoreService.systemReady();
+
+ verify(mNetworkScorerAppManager, never()).setActiveScorer(anyString());
+ assertEquals(1,
+ Settings.Global.getInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED));
+ }
+
+ @Test
+ public void testSystemRunning() {
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
+
+ mNetworkScoreService.systemRunning();
+
+ verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
+ new ComponentName(NEW_SCORER.mPackageName, NEW_SCORER.mScoringServiceClassName))),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM));
+ }
+
+ @Test
+ public void testUpdateScores_notActiveScorer() {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+
+ try {
+ mNetworkScoreService.updateScores(new ScoredNetwork[0]);
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testUpdateScores_oneRegisteredCache() throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
+ mNetworkScoreCache, CACHE_FILTER_NONE);
+
+ mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
+
+ verify(mNetworkScoreCache).updateScores(mScoredNetworkCaptor.capture());
+
+ assertEquals(1, mScoredNetworkCaptor.getValue().size());
+ assertEquals(SCORED_NETWORK, mScoredNetworkCaptor.getValue().get(0));
+ }
+
+ @Test
+ public void testUpdateScores_twoRegisteredCaches() throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
+ mNetworkScoreCache, CACHE_FILTER_NONE);
+ mNetworkScoreService.registerNetworkScoreCache(
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache2, CACHE_FILTER_NONE);
+
+ // updateScores should update both caches
+ mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
+
+ verify(mNetworkScoreCache).updateScores(anyListOf(ScoredNetwork.class));
+ verify(mNetworkScoreCache2).updateScores(anyListOf(ScoredNetwork.class));
+
+ mNetworkScoreService.unregisterNetworkScoreCache(
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache2);
+
+ // updateScores should only update the first cache since the 2nd has been unregistered
+ mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
+
+ verify(mNetworkScoreCache, times(2)).updateScores(anyListOf(ScoredNetwork.class));
+
+ mNetworkScoreService.unregisterNetworkScoreCache(
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache);
+
+ // updateScores should not update any caches since they are both unregistered
+ mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
+
+ // The register and unregister calls grab the binder from the score cache.
+ verify(mNetworkScoreCache, atLeastOnce()).asBinder();
+ verify(mNetworkScoreCache2, atLeastOnce()).asBinder();
+ verifyNoMoreInteractions(mNetworkScoreCache, mNetworkScoreCache2);
+ }
+
+ @Test
+ public void testClearScores_notActiveScorer_noBroadcastNetworkPermission() {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+ when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+ try {
+ mNetworkScoreService.clearScores();
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testClearScores_activeScorer_noBroadcastNetworkPermission() {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+ when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+
+ mNetworkScoreService.clearScores();
+ }
+
+ @Test
+ public void testClearScores_activeScorer() throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+ mNetworkScoreService.clearScores();
+
+ verify(mNetworkScoreCache).clearScores();
+ }
+
+ @Test
+ public void testClearScores_notActiveScorer_hasBroadcastNetworkPermission()
+ throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+ when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+ mNetworkScoreService.clearScores();
+
+ verify(mNetworkScoreCache).clearScores();
+ }
+
+ @Test
+ public void testSetActiveScorer_noScoreNetworksPermission() {
+ doThrow(new SecurityException()).when(mContext)
+ .enforceCallingOrSelfPermission(eq(permission.SCORE_NETWORKS), anyString());
+
+ try {
+ mNetworkScoreService.setActiveScorer(null);
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testSetActiveScorer_failure() throws RemoteException {
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER);
+ when(mNetworkScorerAppManager.setActiveScorer(NEW_SCORER.mPackageName)).thenReturn(false);
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+
+ boolean success = mNetworkScoreService.setActiveScorer(NEW_SCORER.mPackageName);
+
+ assertFalse(success);
+ verify(mNetworkScoreCache).clearScores();
+ verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
+ new ComponentName(PREV_SCORER.mPackageName, PREV_SCORER.mScoringServiceClassName))),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM));
+ }
+
+ @Test
+ public void testSetActiveScorer_success() throws RemoteException {
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, NEW_SCORER);
+ when(mNetworkScorerAppManager.setActiveScorer(NEW_SCORER.mPackageName)).thenReturn(true);
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+
+ boolean success = mNetworkScoreService.setActiveScorer(NEW_SCORER.mPackageName);
+
+ assertTrue(success);
+ verify(mNetworkScoreCache).clearScores();
+ verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
+ new ComponentName(NEW_SCORER.mPackageName, NEW_SCORER.mScoringServiceClassName))),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM));
+ verify(mContext, times(2)).sendBroadcastAsUser(
+ MockUtils.checkIntentAction(NetworkScoreManager.ACTION_SCORER_CHANGED),
+ eq(UserHandle.SYSTEM));
+ }
+
+ @Test
+ public void testDisableScoring_notActiveScorer_noBroadcastNetworkPermission() {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+ when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+
+ try {
+ mNetworkScoreService.disableScoring();
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ }
+
+ @Test
+ public void testDisableScoring_activeScorer() throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, null);
+ when(mNetworkScorerAppManager.setActiveScorer(null)).thenReturn(true);
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+
+ mNetworkScoreService.disableScoring();
+
+ verify(mNetworkScoreCache).clearScores();
+ verify(mContext).sendBroadcastAsUser(
+ MockUtils.checkIntent(new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED)
+ .setPackage(PREV_SCORER.mPackageName)),
+ eq(UserHandle.SYSTEM));
+ verify(mContext, never()).bindServiceAsUser(any(Intent.class),
+ any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+ }
+
+ @Test
+ public void testDisableScoring_notActiveScorer_hasBroadcastNetworkPermission()
+ throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+ when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, null);
+ when(mNetworkScorerAppManager.setActiveScorer(null)).thenReturn(true);
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+
+ mNetworkScoreService.disableScoring();
+
+ verify(mNetworkScoreCache).clearScores();
+ verify(mContext).sendBroadcastAsUser(
+ MockUtils.checkIntent(new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED)
+ .setPackage(PREV_SCORER.mPackageName)),
+ eq(UserHandle.SYSTEM));
+ verify(mContext, never()).bindServiceAsUser(any(Intent.class),
+ any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+ }
+
+ @Test
+ public void testRegisterNetworkScoreCache_noBroadcastNetworkPermission() {
+ doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
+ eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
+
+ try {
+ mNetworkScoreService.registerNetworkScoreCache(
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE);
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testUnregisterNetworkScoreCache_noBroadcastNetworkPermission() {
+ doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
+ eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
+
+ try {
+ mNetworkScoreService.unregisterNetworkScoreCache(
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache);
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testDump_noDumpPermission() {
+ doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
+ eq(permission.DUMP), anyString());
+
+ try {
+ mNetworkScoreService.dump(
+ new FileDescriptor(), new PrintWriter(new StringWriter()), new String[0]);
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testDump_doesNotCrash() {
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
+ StringWriter stringWriter = new StringWriter();
+
+ mNetworkScoreService.dump(
+ new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
+
+ assertFalse(stringWriter.toString().isEmpty());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/GestureDescriptionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/GestureDescriptionTest.java
new file mode 100644
index 0000000..b876a5f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/GestureDescriptionTest.java
@@ -0,0 +1,420 @@
+/*
+ * 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 com.android.server.accessibility;
+
+import static android.accessibilityservice.GestureDescription.StrokeDescription.INVALID_STROKE_ID;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.everyItem;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import android.accessibilityservice.GestureDescription;
+import android.accessibilityservice.GestureDescription.GestureStep;
+import android.accessibilityservice.GestureDescription.MotionEventGenerator;
+import android.accessibilityservice.GestureDescription.StrokeDescription;
+import android.graphics.Path;
+import android.graphics.PointF;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Test;
+
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+
+/**
+ * Tests for GestureDescription
+ */
+public class GestureDescriptionTest {
+ @Test
+ public void testGestureShorterThanSampleRate_producesStartAndEnd() {
+ PointF click = new PointF(10, 20);
+ Path clickPath = new Path();
+ clickPath.moveTo(click.x, click.y);
+ StrokeDescription clickStroke = new StrokeDescription(clickPath, 0, 10);
+ GestureDescription.Builder clickBuilder = new GestureDescription.Builder();
+ clickBuilder.addStroke(clickStroke);
+ GestureDescription clickGesture = clickBuilder.build();
+
+ List<GestureStep> clickGestureSteps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(clickGesture, 100);
+
+ assertEquals(2, clickGestureSteps.size());
+ assertThat(clickGestureSteps.get(0), allOf(numTouchPointsIs(1), numStartsOfStroke(1),
+ numEndsOfStroke(0), hasPoint(click)));
+ assertThat(clickGestureSteps.get(1), allOf(numTouchPointsIs(1), numStartsOfStroke(0),
+ numEndsOfStroke(1), hasPoint(click)));
+ }
+
+ @Test
+ public void testSwipe_shouldContainEvenlySpacedPoints() {
+ int samplePeriod = 10;
+ int numSamples = 5;
+ float stepX = 2;
+ float stepY = 3;
+ PointF start = new PointF(10, 20);
+ PointF end = new PointF(10 + numSamples * stepX, 20 + numSamples * stepY);
+
+ GestureDescription swipe =
+ createSwipe(start.x, start.y, end.x, end.y, numSamples * samplePeriod);
+ List<GestureStep> swipeGestureSteps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(swipe, samplePeriod);
+ assertEquals(numSamples + 1, swipeGestureSteps.size());
+
+ assertThat(swipeGestureSteps.get(0), allOf(numTouchPointsIs(1), numStartsOfStroke(1),
+ numEndsOfStroke(0), hasPoint(start)));
+ assertThat(swipeGestureSteps.get(numSamples), allOf(numTouchPointsIs(1),
+ numStartsOfStroke(0), numEndsOfStroke(1), hasPoint(end)));
+
+ for (int i = 1; i < numSamples; ++i) {
+ PointF interpPoint = new PointF(start.x + stepX * i, start.y + stepY * i);
+ assertThat(swipeGestureSteps.get(i), allOf(numTouchPointsIs(1),
+ numStartsOfStroke(0), numEndsOfStroke(0), hasPoint(interpPoint)));
+ }
+ }
+
+ @Test
+ public void testSwipeWithNonIntegerValues_shouldRound() {
+ int strokeTime = 10;
+
+ GestureDescription swipe = createSwipe(10.1f, 20.6f, 11.9f, 22.1f, strokeTime);
+ List<GestureStep> swipeGestureSteps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(swipe, strokeTime);
+ assertEquals(2, swipeGestureSteps.size());
+ assertThat(swipeGestureSteps.get(0), hasPoint(new PointF(10, 21)));
+ assertThat(swipeGestureSteps.get(1), hasPoint(new PointF(12, 22)));
+ }
+
+ @Test
+ public void testPathsWithOverlappingTiming_produceCorrectSteps() {
+ // There are 4 paths
+ // 0: an L-shaped path that starts first
+ // 1: a swipe that starts in the middle of the L-shaped path and ends when the L ends
+ // 2: a swipe that starts at the same time as #1 but extends past the end of the L
+ // 3: a swipe that starts when #3 ends
+ PointF path0Start = new PointF(100, 150);
+ PointF path0Turn = new PointF(100, 200);
+ PointF path0End = new PointF(250, 200);
+ int path0StartTime = 0;
+ int path0EndTime = 100;
+ int path0Duration = path0EndTime - path0StartTime;
+ Path path0 = new Path();
+ path0.moveTo(path0Start.x, path0Start.y);
+ path0.lineTo(path0Turn.x, path0Turn.y);
+ path0.lineTo(path0End.x, path0End.y);
+ StrokeDescription path0Stroke = new StrokeDescription(path0, path0StartTime, path0Duration);
+
+ PointF path1Start = new PointF(300, 350);
+ PointF path1End = new PointF(300, 400);
+ int path1StartTime = 50;
+ int path1EndTime = path0EndTime;
+ StrokeDescription path1Stroke = createSwipeStroke(
+ path1Start.x, path1Start.y, path1End.x, path1End.y, path1StartTime, path1EndTime);
+
+ PointF path2Start = new PointF(400, 450);
+ PointF path2End = new PointF(400, 500);
+ int path2StartTime = 50;
+ int path2EndTime = 150;
+ StrokeDescription path2Stroke = createSwipeStroke(
+ path2Start.x, path2Start.y, path2End.x, path2End.y, path2StartTime, path2EndTime);
+
+ PointF path3Start = new PointF(500, 550);
+ PointF path3End = new PointF(500, 600);
+ int path3StartTime = path2EndTime;
+ int path3EndTime = 200;
+ StrokeDescription path3Stroke = createSwipeStroke(
+ path3Start.x, path3Start.y, path3End.x, path3End.y, path3StartTime, path3EndTime);
+
+ int deltaT = 12; // Force samples to happen on extra boundaries
+ GestureDescription.Builder builder = new GestureDescription.Builder();
+ builder.addStroke(path0Stroke);
+ builder.addStroke(path1Stroke);
+ builder.addStroke(path2Stroke);
+ builder.addStroke(path3Stroke);
+ List<GestureStep> steps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(builder.build(), deltaT);
+
+ long start = 0;
+ assertThat(steps.get(0), allOf(numStartsOfStroke(1), numEndsOfStroke(0), isAtTime(start),
+ numTouchPointsIs(1), hasPoint(path0Start)));
+ assertThat(steps.get(1), allOf(numTouchPointsIs(1), noStartsOrEnds(),
+ isAtTime(start + deltaT)));
+ assertThat(steps.get(2), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 2)));
+ assertThat(steps.get(3), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 3)));
+ assertThat(steps.get(4), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 4)));
+
+ assertThat(steps.get(5), allOf(numTouchPointsIs(3), numStartsOfStroke(2),
+ numEndsOfStroke(0), isAtTime(path1StartTime), hasPoint(path1Start),
+ hasPoint(path2Start)));
+
+ start = path1StartTime;
+ assertThat(steps.get(6), allOf(numTouchPointsIs(3), isAtTime(start + deltaT * 1)));
+ assertThat(steps.get(7), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 2)));
+ assertThat(steps.get(8), allOf(numTouchPointsIs(3), isAtTime(start + deltaT * 3)));
+ assertThat(steps.get(9), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 4)));
+
+ assertThat(steps.get(10), allOf(numTouchPointsIs(3), numStartsOfStroke(0),
+ numEndsOfStroke(2), isAtTime(path0EndTime), hasPoint(path0End),
+ hasPoint(path1End)));
+
+ start = path0EndTime;
+ assertThat(steps.get(11), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 1)));
+ assertThat(steps.get(12), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 2)));
+ assertThat(steps.get(13), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 3)));
+ assertThat(steps.get(14), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 4)));
+
+ assertThat(steps.get(15), allOf(numTouchPointsIs(2), numStartsOfStroke(1),
+ numEndsOfStroke(1), isAtTime(path2EndTime), hasPoint(path2End),
+ hasPoint(path3Start)));
+
+ start = path2EndTime;
+ assertThat(steps.get(16), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 1)));
+ assertThat(steps.get(17), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 2)));
+ assertThat(steps.get(18), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 3)));
+ assertThat(steps.get(19), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 4)));
+
+ assertThat(steps.get(20), allOf(numTouchPointsIs(1), numStartsOfStroke(0),
+ numEndsOfStroke(1), isAtTime(path3EndTime), hasPoint(path3End)));
+ }
+
+ @Test
+ public void testMaxTouchpoints_shouldHaveValidCoords() {
+ GestureDescription.Builder maxPointBuilder = new GestureDescription.Builder();
+ PointF baseStartPoint = new PointF(100, 100);
+ PointF baseEndPoint = new PointF(100, 200);
+ int xStep = 10;
+ int samplePeriod = 15;
+ int numSamples = 2;
+ int numPoints = GestureDescription.getMaxStrokeCount();
+ for (int i = 0; i < numPoints; i++) {
+ Path path = new Path();
+ path.moveTo(baseStartPoint.x + i * xStep, baseStartPoint.y);
+ path.lineTo(baseEndPoint.x + i * xStep, baseEndPoint.y);
+ maxPointBuilder.addStroke(new StrokeDescription(path, 0, samplePeriod * numSamples));
+ }
+
+ List<GestureStep> steps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(maxPointBuilder.build(), samplePeriod);
+ assertEquals(3, steps.size());
+
+ assertThat(steps.get(0), allOf(numTouchPointsIs(numPoints), numStartsOfStroke(numPoints),
+ numEndsOfStroke(0), isAtTime(0)));
+ assertThat(steps.get(1), allOf(numTouchPointsIs(numPoints), numStartsOfStroke(0),
+ numEndsOfStroke(0), isAtTime(samplePeriod)));
+ assertThat(steps.get(2), allOf(numTouchPointsIs(numPoints), numStartsOfStroke(0),
+ numEndsOfStroke(numPoints), isAtTime(samplePeriod * 2)));
+
+ PointF baseMidPoint = new PointF((baseStartPoint.x + baseEndPoint.x) / 2,
+ (baseStartPoint.y + baseEndPoint.y) / 2);
+ for (int i = 0; i < numPoints; i++) {
+ assertThat(steps.get(0),
+ hasPoint(new PointF(baseStartPoint.x + i * xStep, baseStartPoint.y)));
+ assertThat(steps.get(1),
+ hasPoint(new PointF(baseMidPoint.x + i * xStep, baseMidPoint.y)));
+ assertThat(steps.get(2),
+ hasPoint(new PointF(baseEndPoint.x + i * xStep, baseEndPoint.y)));
+ }
+ }
+
+ @Test
+ public void testGetGestureSteps_touchPointsHaveStrokeId() {
+ StrokeDescription swipeStroke = createSwipeStroke(10, 20, 30, 40, 0, 100);
+ GestureDescription swipe = new GestureDescription.Builder().addStroke(swipeStroke).build();
+ List<GestureStep> swipeGestureSteps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(swipe, 10);
+
+ assertThat(swipeGestureSteps, everyItem(hasStrokeId(swipeStroke.getId())));
+ }
+
+ @Test
+ public void testGetGestureSteps_continuedStroke_hasNoEndPoint() {
+ Path swipePath = new Path();
+ swipePath.moveTo(10, 20);
+ swipePath.lineTo(30, 40);
+ StrokeDescription stroke1 =
+ new StrokeDescription(swipePath, 0, 100, 0, true);
+ GestureDescription gesture = new GestureDescription.Builder().addStroke(stroke1).build();
+ List<GestureStep> steps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(gesture, 10);
+
+ assertThat(steps, everyItem(numEndsOfStroke(0)));
+ }
+
+ @Test
+ public void testGetGestureSteps_continuingStroke_hasNoStartPointAndHasContinuedId() {
+ Path swipePath = new Path();
+ swipePath.moveTo(10, 20);
+ swipePath.lineTo(30, 40);
+ StrokeDescription stroke1 =
+ new StrokeDescription(swipePath, 0, 100, INVALID_STROKE_ID, true);
+ StrokeDescription stroke2 =
+ new StrokeDescription(swipePath, 0, 100, stroke1.getId(), false);
+ GestureDescription gesture = new GestureDescription.Builder().addStroke(stroke2).build();
+ List<GestureStep> steps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(gesture, 10);
+
+ assertThat(steps, everyItem(
+ allOf(continuesStrokeId(stroke1.getId()), numStartsOfStroke(0))));
+ }
+
+ private GestureDescription createSwipe(
+ float startX, float startY, float endX, float endY, long duration) {
+ GestureDescription.Builder swipeBuilder = new GestureDescription.Builder();
+ swipeBuilder.addStroke(createSwipeStroke(startX, startY, endX, endY, 0, duration));
+ return swipeBuilder.build();
+ }
+
+ private StrokeDescription createSwipeStroke(
+ float startX, float startY, float endX, float endY, long startTime, long endTime) {
+ Path swipePath = new Path();
+ swipePath.moveTo(startX, startY);
+ swipePath.lineTo(endX, endY);
+ StrokeDescription swipeStroke =
+ new StrokeDescription(swipePath, startTime, endTime - startTime);
+ return swipeStroke;
+ }
+
+ Matcher<GestureStep> numTouchPointsIs(final int numTouchPoints) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ return gestureStep.numTouchPoints == numTouchPoints;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Has " + numTouchPoints + " touch point(s)");
+ }
+ };
+ }
+
+ Matcher<GestureStep> numStartsOfStroke(final int numStarts) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ int numStartsFound = 0;
+ for (int i = 0; i < gestureStep.numTouchPoints; i++) {
+ if (gestureStep.touchPoints[i].mIsStartOfPath) {
+ numStartsFound++;
+ }
+ }
+ return numStartsFound == numStarts;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Starts " + numStarts + " stroke(s)");
+ }
+ };
+ }
+
+ Matcher<GestureStep> numEndsOfStroke(final int numEnds) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ int numEndsFound = 0;
+ for (int i = 0; i < gestureStep.numTouchPoints; i++) {
+ if (gestureStep.touchPoints[i].mIsEndOfPath) {
+ numEndsFound++;
+ }
+ }
+ return numEndsFound == numEnds;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Ends " + numEnds + " stroke(s)");
+ }
+ };
+ }
+
+ Matcher<GestureStep> hasPoint(final PointF point) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ for (int i = 0; i < gestureStep.numTouchPoints; i++) {
+ if ((gestureStep.touchPoints[i].mX == point.x)
+ && (gestureStep.touchPoints[i].mY == point.y)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Has at least one point at " + point);
+ }
+ };
+ }
+
+ Matcher<GestureStep> hasStrokeId(final int strokeId) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ for (int i = 0; i < gestureStep.numTouchPoints; i++) {
+ if (gestureStep.touchPoints[i].mStrokeId == strokeId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Has at least one point with stroke id " + strokeId);
+ }
+ };
+ }
+
+ Matcher<GestureStep> continuesStrokeId(final int strokeId) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ for (int i = 0; i < gestureStep.numTouchPoints; i++) {
+ if (gestureStep.touchPoints[i].mContinuedStrokeId == strokeId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Continues stroke id " + strokeId);
+ }
+ };
+ }
+
+ Matcher<GestureStep> isAtTime(final long time) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ return gestureStep.timeSinceGestureStart == time;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Is at time " + time);
+ }
+ };
+ }
+
+ Matcher<GestureStep> noStartsOrEnds() {
+ return allOf(numStartsOfStroke(0), numEndsOfStroke(0));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
index d5305d9..73344e0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
@@ -16,9 +16,17 @@
package com.android.server.accessibility;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_UP;
+import static android.view.WindowManagerPolicy.FLAG_PASS_TO_USER;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.everyItem;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
@@ -29,7 +37,10 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
+import android.accessibilityservice.GestureDescription.GestureStep;
+import android.accessibilityservice.GestureDescription.TouchPoint;
import android.accessibilityservice.IAccessibilityServiceClient;
+import android.graphics.Point;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -40,11 +51,15 @@
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.view.WindowManagerPolicy;
+
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import android.view.accessibility.AccessibilityEvent;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -58,30 +73,59 @@
@RunWith(AndroidJUnit4.class)
public class MotionEventInjectorTest {
private static final String LOG_TAG = "MotionEventInjectorTest";
- private static final int CLICK_X = 100;
- private static final int CLICK_Y_START = 200;
- private static final int CLICK_Y_END = 201;
- private static final int CLICK_DURATION = 10;
- private static final int SEQUENCE = 50;
+ private static final Matcher<MotionEvent> IS_ACTION_DOWN =
+ new MotionEventActionMatcher(ACTION_DOWN);
+ private static final Matcher<MotionEvent> IS_ACTION_POINTER_DOWN =
+ new MotionEventActionMatcher(MotionEvent.ACTION_POINTER_DOWN);
+ private static final Matcher<MotionEvent> IS_ACTION_UP =
+ new MotionEventActionMatcher(ACTION_UP);
+ private static final Matcher<MotionEvent> IS_ACTION_POINTER_UP =
+ new MotionEventActionMatcher(MotionEvent.ACTION_POINTER_UP);
+ private static final Matcher<MotionEvent> IS_ACTION_CANCEL =
+ new MotionEventActionMatcher(MotionEvent.ACTION_CANCEL);
+ private static final Matcher<MotionEvent> IS_ACTION_MOVE =
+ new MotionEventActionMatcher(MotionEvent.ACTION_MOVE);
- private static final int SECOND_CLICK_X = 1000;
- private static final int SECOND_CLICK_Y = 2000;
- private static final int SECOND_SEQUENCE = 51;
+ private static final Point LINE_START = new Point(100, 200);
+ private static final Point LINE_END = new Point(100, 300);
+ private static final int LINE_DURATION = 100;
+ private static final int LINE_SEQUENCE = 50;
+
+ private static final Point CLICK_POINT = new Point(1000, 2000);
+ private static final int CLICK_DURATION = 10;
+ private static final int CLICK_SEQUENCE = 51;
private static final int MOTION_EVENT_SOURCE = InputDevice.SOURCE_TOUCHSCREEN;
private static final int OTHER_EVENT_SOURCE = InputDevice.SOURCE_MOUSE;
+ private static final Point CONTINUED_LINE_START = new Point(500, 300);
+ private static final Point CONTINUED_LINE_MID1 = new Point(500, 400);
+ private static final Point CONTINUED_LINE_MID2 = new Point(600, 300);
+ private static final Point CONTINUED_LINE_END = new Point(600, 400);
+ private static final int CONTINUED_LINE_STROKE_ID_1 = 100;
+ private static final int CONTINUED_LINE_STROKE_ID_2 = 101;
+ private static final int CONTINUED_LINE_INTERVAL = 100;
+ private static final int CONTINUED_LINE_SEQUENCE_1 = 52;
+ private static final int CONTINUED_LINE_SEQUENCE_2 = 53;
+
MotionEventInjector mMotionEventInjector;
IAccessibilityServiceClient mServiceInterface;
- List<MotionEvent> mClickList = new ArrayList<>();
- List<MotionEvent> mSecondClickList = new ArrayList<>();
+ List<GestureStep> mLineList = new ArrayList<>();
+ List<GestureStep> mClickList = new ArrayList<>();
+ List<GestureStep> mContinuedLineList1 = new ArrayList<>();
+ List<GestureStep> mContinuedLineList2 = new ArrayList<>();
+
+ MotionEvent mClickDownEvent;
+ MotionEvent mClickUpEvent;
+
ArgumentCaptor<MotionEvent> mCaptor1 = ArgumentCaptor.forClass(MotionEvent.class);
ArgumentCaptor<MotionEvent> mCaptor2 = ArgumentCaptor.forClass(MotionEvent.class);
MessageCapturingHandler mMessageCapturingHandler;
- MotionEventMatcher mClickEvent0Matcher;
- MotionEventMatcher mClickEvent1Matcher;
- MotionEventMatcher mClickEvent2Matcher;
- MotionEventMatcher mSecondClickEvent0Matcher;
+ Matcher<MotionEvent> mIsLineStart;
+ Matcher<MotionEvent> mIsLineMiddle;
+ Matcher<MotionEvent> mIsLineEnd;
+ Matcher<MotionEvent> mIsClickDown;
+ Matcher<MotionEvent> mIsClickUp;
@BeforeClass
public static void oneTimeInitialization() {
@@ -99,226 +143,191 @@
}
});
mMotionEventInjector = new MotionEventInjector(mMessageCapturingHandler);
- mClickList.add(
- MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, CLICK_X, CLICK_Y_START, 0));
- mClickList.add(MotionEvent.obtain(
- 0, CLICK_DURATION, MotionEvent.ACTION_MOVE, CLICK_X, CLICK_Y_END, 0));
- mClickList.add(MotionEvent.obtain(
- 0, CLICK_DURATION, MotionEvent.ACTION_UP, CLICK_X, CLICK_Y_END, 0));
- for (int i = 0; i < mClickList.size(); i++) {
- mClickList.get(i).setSource(MOTION_EVENT_SOURCE);
- }
-
- mClickEvent0Matcher = new MotionEventMatcher(mClickList.get(0));
- mClickEvent1Matcher = new MotionEventMatcher(mClickList.get(1));
- mClickEvent2Matcher = new MotionEventMatcher(mClickList.get(2));
-
- mSecondClickList.add(MotionEvent.obtain(
- 0, 0, MotionEvent.ACTION_DOWN, SECOND_CLICK_X, SECOND_CLICK_Y, 0));
- mSecondClickList.add(MotionEvent.obtain(
- 0, CLICK_DURATION, MotionEvent.ACTION_MOVE, SECOND_CLICK_X, CLICK_Y_END, 0));
- mSecondClickList.add(MotionEvent.obtain(
- 0, CLICK_DURATION, MotionEvent.ACTION_UP, SECOND_CLICK_X, CLICK_Y_END, 0));
- for (int i = 0; i < mSecondClickList.size(); i++) {
- mSecondClickList.get(i).setSource(MOTION_EVENT_SOURCE);
- }
-
- mSecondClickEvent0Matcher = new MotionEventMatcher(mSecondClickList.get(0));
-
mServiceInterface = mock(IAccessibilityServiceClient.class);
+
+ mLineList = createSimpleGestureFromPoints(0, 0, false, LINE_DURATION, LINE_START, LINE_END);
+ mClickList = createSimpleGestureFromPoints(
+ 0, 0, false, CLICK_DURATION, CLICK_POINT, CLICK_POINT);
+ mContinuedLineList1 = createSimpleGestureFromPoints(CONTINUED_LINE_STROKE_ID_1, 0, true,
+ CONTINUED_LINE_INTERVAL, CONTINUED_LINE_START, CONTINUED_LINE_MID1);
+ mContinuedLineList2 = createSimpleGestureFromPoints(CONTINUED_LINE_STROKE_ID_2,
+ CONTINUED_LINE_STROKE_ID_1, false, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_MID1,
+ CONTINUED_LINE_MID2, CONTINUED_LINE_END);
+
+ mClickDownEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, CLICK_POINT.x, CLICK_POINT.y, 0);
+ mClickDownEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ mClickUpEvent = MotionEvent.obtain(0, CLICK_DURATION, ACTION_UP, CLICK_POINT.x,
+ CLICK_POINT.y, 0);
+ mClickUpEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+
+ mIsLineStart = allOf(IS_ACTION_DOWN, isAtPoint(LINE_START), hasStandardInitialization(),
+ hasTimeFromDown(0));
+ mIsLineMiddle = allOf(IS_ACTION_MOVE, isAtPoint(LINE_END), hasStandardInitialization(),
+ hasTimeFromDown(LINE_DURATION));
+ mIsLineEnd = allOf(IS_ACTION_UP, isAtPoint(LINE_END), hasStandardInitialization(),
+ hasTimeFromDown(LINE_DURATION));
+ mIsClickDown = allOf(IS_ACTION_DOWN, isAtPoint(CLICK_POINT), hasStandardInitialization(),
+ hasTimeFromDown(0));
+ mIsClickUp = allOf(IS_ACTION_UP, isAtPoint(CLICK_POINT), hasStandardInitialization(),
+ hasTimeFromDown(CLICK_DURATION));
}
@Test
public void testInjectEvents_shouldEmergeInOrderWithCorrectTiming() throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
verifyNoMoreInteractions(next);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
- long gestureStart = mCaptor1.getValue().getDownTime();
- mClickEvent0Matcher.offsetTimesBy(gestureStart);
- mClickEvent1Matcher.offsetTimesBy(gestureStart);
- mClickEvent2Matcher.offsetTimesBy(gestureStart);
-
- verify(next).onMotionEvent(argThat(mClickEvent0Matcher), argThat(mClickEvent0Matcher),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(argThat(mIsLineStart), argThat(mIsLineStart),
+ eq(FLAG_PASS_TO_USER));
verifyNoMoreInteractions(next);
reset(next);
+ Matcher<MotionEvent> hasRightDownTime = hasDownTime(mCaptor1.getValue().getDownTime());
+
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(next).onMotionEvent(argThat(mClickEvent1Matcher), argThat(mClickEvent1Matcher),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(argThat(allOf(mIsLineMiddle, hasRightDownTime)),
+ argThat(allOf(mIsLineMiddle, hasRightDownTime)), eq(FLAG_PASS_TO_USER));
verifyNoMoreInteractions(next);
reset(next);
verifyZeroInteractions(mServiceInterface);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(next).onMotionEvent(argThat(mClickEvent2Matcher), argThat(mClickEvent2Matcher),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(argThat(allOf(mIsLineEnd, hasRightDownTime)),
+ argThat(allOf(mIsLineEnd, hasRightDownTime)), eq(FLAG_PASS_TO_USER));
verifyNoMoreInteractions(next);
- reset(next);
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, true);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
verifyNoMoreInteractions(mServiceInterface);
}
@Test
- public void testInjectEvents_eventWithManyPointers_shouldNotCrash() {
- int manyPointersCount = 20;
- MotionEvent.PointerCoords[] pointerCoords =
- new MotionEvent.PointerCoords[manyPointersCount];
- MotionEvent.PointerProperties[] pointerProperties =
- new MotionEvent.PointerProperties[manyPointersCount];
- for (int i = 0; i < manyPointersCount; i++) {
- pointerProperties[i] = new MotionEvent.PointerProperties();
- pointerProperties[i].id = i;
- pointerProperties[i].toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
- pointerCoords[i] = new MotionEvent.PointerCoords();
- pointerCoords[i].clear();
- pointerCoords[i].pressure = 1.0f;
- pointerCoords[i].size = 1.0f;
- pointerCoords[i].x = i;
- pointerCoords[i].y = i;
+ public void testInjectEvents_gestureWithTooManyPoints_shouldNotCrash() throws Exception {
+ int tooManyPointsCount = 20;
+ TouchPoint[] startTouchPoints = new TouchPoint[tooManyPointsCount];
+ TouchPoint[] endTouchPoints = new TouchPoint[tooManyPointsCount];
+ for (int i = 0; i < tooManyPointsCount; i++) {
+ startTouchPoints[i] = new TouchPoint();
+ startTouchPoints[i].mIsStartOfPath = true;
+ startTouchPoints[i].mX = i;
+ startTouchPoints[i].mY = i;
+ endTouchPoints[i] = new TouchPoint();
+ endTouchPoints[i].mIsEndOfPath = true;
+ endTouchPoints[i].mX = i;
+ endTouchPoints[i].mY = i;
}
- List<MotionEvent> events = new ArrayList<>();
- events.add(MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, manyPointersCount,
- pointerProperties, pointerCoords, 0, 0,
- 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0));
- events.add(MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, manyPointersCount,
- pointerProperties, pointerCoords, 0, 0,
- 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0));
- EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.injectEvents(events, mServiceInterface, SEQUENCE);
+ List<GestureStep> events = Arrays.asList(
+ new GestureStep(0, tooManyPointsCount, startTouchPoints),
+ new GestureStep(CLICK_DURATION, tooManyPointsCount, endTouchPoints));
+ attachMockNext(mMotionEventInjector);
+ injectEventsSync(events, mServiceInterface, CLICK_SEQUENCE);
mMessageCapturingHandler.sendAllMessages();
- verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- assertEquals(MotionEvent.ACTION_DOWN, mCaptor1.getAllValues().get(0).getActionMasked());
- assertEquals(MotionEvent.ACTION_UP, mCaptor1.getAllValues().get(1).getActionMasked());
+ verify(mServiceInterface).onPerformGestureResult(eq(CLICK_SEQUENCE), anyBoolean());
}
@Test
public void testRegularEvent_afterGestureComplete_shouldPassToNext() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendAllMessages(); // Send all motion events
reset(next);
- mMotionEventInjector.onMotionEvent(mSecondClickList.get(0), mClickList.get(0), 0);
- verify(next).onMotionEvent(argThat(mSecondClickEvent0Matcher),
- argThat(mClickEvent0Matcher), eq(0));
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
+ verify(next).onMotionEvent(argThat(mIsClickDown), argThat(mIsClickDown), eq(0));
}
@Test
public void testInjectEvents_withRealGestureUnderway_shouldCancelRealAndPassInjected() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0);
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked());
+ assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
+ assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
reset(next);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
- long gestureStart = mCaptor1.getValue().getDownTime();
- mSecondClickEvent0Matcher.offsetTimesBy(gestureStart);
-
- verify(next).onMotionEvent(argThat(mSecondClickEvent0Matcher),
- argThat(mSecondClickEvent0Matcher), eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(
+ argThat(mIsLineStart), argThat(mIsLineStart), eq(FLAG_PASS_TO_USER));
}
@Test
public void testInjectEvents_withRealMouseGestureUnderway_shouldContinueRealAndPassInjected() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- MotionEvent mouseEvent = MotionEvent.obtain(mClickList.get(0));
+ MotionEvent mouseEvent = MotionEvent.obtain(mClickDownEvent);
mouseEvent.setSource(InputDevice.SOURCE_MOUSE);
- MotionEventMatcher mouseEventMatcher = new MotionEventMatcher(mouseEvent);
+ MotionEventMatcher isMouseEvent = new MotionEventMatcher(mouseEvent);
mMotionEventInjector.onMotionEvent(mouseEvent, mouseEvent, 0);
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- assertTrue(mouseEventMatcher.matches(mCaptor1.getAllValues().get(0)));
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(1).getDownTime());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(1)));
+ assertThat(mCaptor1.getAllValues().get(0), isMouseEvent);
+ assertThat(mCaptor1.getAllValues().get(1), mIsLineStart);
}
@Test
public void testInjectEvents_withRealGestureFinished_shouldJustPassInjected() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0);
- mMotionEventInjector.onMotionEvent(mClickList.get(1), mClickList.get(1), 0);
- mMotionEventInjector.onMotionEvent(mClickList.get(2), mClickList.get(2), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
+ mMotionEventInjector.onMotionEvent(mClickUpEvent, mClickUpEvent, 0);
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
- verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
-
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertTrue(mClickEvent1Matcher.matches(mCaptor1.getAllValues().get(1)));
- assertTrue(mClickEvent2Matcher.matches(mCaptor1.getAllValues().get(2)));
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
+ assertThat(mCaptor1.getAllValues().get(1), mIsClickUp);
reset(next);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getValue().getDownTime());
- verify(next).onMotionEvent(argThat(mSecondClickEvent0Matcher),
- argThat(mSecondClickEvent0Matcher), eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(
+ argThat(mIsLineStart), argThat(mIsLineStart), eq(FLAG_PASS_TO_USER));
}
@Test
public void testOnMotionEvents_openInjectedGestureInProgress_shouldCancelAndNotifyAndPassReal()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
-
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- mMotionEventInjector.onMotionEvent(mSecondClickList.get(0), mSecondClickList.get(0), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- mClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(0).getDownTime());
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(2)));
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false);
+ assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+ assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
+ assertThat(mCaptor1.getAllValues().get(2), mIsClickDown);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
}
@Test
public void testOnMotionEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassReal()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mClickList.add(MotionEvent.obtain(2 * CLICK_DURATION, 2 * CLICK_DURATION,
- MotionEvent.ACTION_DOWN, CLICK_X, CLICK_Y_START, 0));
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ // Tack a click down to the end of the line
+ TouchPoint clickTouchPoint = new TouchPoint();
+ clickTouchPoint.mIsStartOfPath = true;
+ clickTouchPoint.mX = CLICK_POINT.x;
+ clickTouchPoint.mY = CLICK_POINT.y;
+ mLineList.add(new GestureStep(0, 1, new TouchPoint[] {clickTouchPoint}));
+
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
// Send 3 motion events, leaving the extra down in the queue
mMessageCapturingHandler.sendOneMessage();
mMessageCapturingHandler.sendOneMessage();
mMessageCapturingHandler.sendOneMessage();
- mMotionEventInjector.onMotionEvent(mSecondClickList.get(0), mClickList.get(0), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- long gestureStart = mCaptor1.getAllValues().get(0).getDownTime();
- mClickEvent0Matcher.offsetTimesBy(gestureStart);
- mClickEvent1Matcher.offsetTimesBy(gestureStart);
- mClickEvent2Matcher.offsetTimesBy(gestureStart);
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertTrue(mClickEvent1Matcher.matches(mCaptor1.getAllValues().get(1)));
- assertTrue(mClickEvent2Matcher.matches(mCaptor1.getAllValues().get(2)));
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(3)));
-
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false);
+ assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+ assertThat(mCaptor1.getAllValues().get(1), mIsLineMiddle);
+ assertThat(mCaptor1.getAllValues().get(2), mIsLineEnd);
+ assertThat(mCaptor1.getAllValues().get(3), mIsClickDown);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
assertFalse(mMessageCapturingHandler.hasMessages());
}
@@ -326,105 +335,327 @@
public void testInjectEvents_openInjectedGestureInProgress_shouldCancelAndNotifyAndPassNew()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SECOND_SEQUENCE);
- mMessageCapturingHandler.sendLastMessage(); // Process the second event injection
+ injectEventsSync(mClickList, mServiceInterface, CLICK_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(mServiceInterface, times(1)).onPerformGestureResult(SEQUENCE, false);
+ verify(mServiceInterface, times(1)).onPerformGestureResult(LINE_SEQUENCE, false);
verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- mClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(0).getDownTime());
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked());
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(2).getDownTime());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(2)));
+ assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+ assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
+ assertThat(mCaptor1.getAllValues().get(2), mIsClickDown);
}
@Test
public void testInjectEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassNew()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- MotionEvent newEvent = MotionEvent.obtain(2 * CLICK_DURATION, 2 * CLICK_DURATION,
- MotionEvent.ACTION_DOWN, CLICK_X, CLICK_Y_START, 0);
- newEvent.setSource(mClickList.get(0).getSource());
- mClickList.add(newEvent);
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ // Tack a click down to the end of the line
+ TouchPoint clickTouchPoint = new TouchPoint();
+ clickTouchPoint.mIsStartOfPath = true;
+ clickTouchPoint.mX = CLICK_POINT.x;
+ clickTouchPoint.mY = CLICK_POINT.y;
+ mLineList.add(new GestureStep(0, 1, new TouchPoint[] {clickTouchPoint}));
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
// Send 3 motion events, leaving newEvent in the queue
mMessageCapturingHandler.sendOneMessage();
mMessageCapturingHandler.sendOneMessage();
mMessageCapturingHandler.sendOneMessage();
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SECOND_SEQUENCE);
- mMessageCapturingHandler.sendLastMessage(); // Process the event injection
+ injectEventsSync(mClickList, mServiceInterface, CLICK_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- long gestureStart = mCaptor1.getAllValues().get(0).getDownTime();
- mClickEvent0Matcher.offsetTimesBy(gestureStart);
- mClickEvent1Matcher.offsetTimesBy(gestureStart);
- mClickEvent2Matcher.offsetTimesBy(gestureStart);
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertTrue(mClickEvent1Matcher.matches(mCaptor1.getAllValues().get(1)));
- assertTrue(mClickEvent2Matcher.matches(mCaptor1.getAllValues().get(2)));
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(3).getDownTime());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(3)));
+ assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+ assertThat(mCaptor1.getAllValues().get(1), mIsLineMiddle);
+ assertThat(mCaptor1.getAllValues().get(2), mIsLineEnd);
+ assertThat(mCaptor1.getAllValues().get(3), mIsClickDown);
+ }
+
+ @Test
+ public void testContinuedGesture_continuationArrivesAfterDispatched_gestureCompletes()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ injectEventsSync(mContinuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
+ verify(next, times(5)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ long downTime = events.get(0).getDownTime();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN,
+ hasEventTime(downTime)));
+ assertThat(events, everyItem(hasDownTime(downTime)));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
+ // Timing will restart when the gesture continues
+ long secondSequenceStart = events.get(2).getEventTime();
+ assertTrue(secondSequenceStart > events.get(1).getEventTime());
+ assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE));
+ assertThat(events.get(3), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_MOVE,
+ hasEventTime(secondSequenceStart + CONTINUED_LINE_INTERVAL)));
+ assertThat(events.get(4), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_UP,
+ hasEventTime(secondSequenceStart + CONTINUED_LINE_INTERVAL)));
+ }
+
+ @Test
+ public void testContinuedGesture_withTwoTouchPoints_gestureCompletes()
+ throws Exception {
+ // Run one point through the continued line backwards
+ int backLineId1 = 30;
+ int backLineId2 = 30;
+ List<GestureStep> continuedBackLineList1 = createSimpleGestureFromPoints(backLineId1, 0,
+ true, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_END, CONTINUED_LINE_MID2);
+ List<GestureStep> continuedBackLineList2 = createSimpleGestureFromPoints(backLineId2,
+ backLineId1, false, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_MID2,
+ CONTINUED_LINE_MID1, CONTINUED_LINE_START);
+ List<GestureStep> combinedLines1 = combineGestureSteps(
+ mContinuedLineList1, continuedBackLineList1);
+ List<GestureStep> combinedLines2 = combineGestureSteps(
+ mContinuedLineList2, continuedBackLineList2);
+
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(combinedLines1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ injectEventsSync(combinedLines2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
+ verify(next, times(7)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ long downTime = events.get(0).getDownTime();
+ assertThat(events.get(0), allOf(
+ anyOf(isAtPoint(CONTINUED_LINE_END), isAtPoint(CONTINUED_LINE_START)),
+ IS_ACTION_DOWN, hasEventTime(downTime)));
+ assertThat(events, everyItem(hasDownTime(downTime)));
+ assertThat(events.get(1), allOf(containsPoints(CONTINUED_LINE_START, CONTINUED_LINE_END),
+ IS_ACTION_POINTER_DOWN, hasEventTime(downTime)));
+ assertThat(events.get(2), allOf(containsPoints(CONTINUED_LINE_MID1, CONTINUED_LINE_MID2),
+ IS_ACTION_MOVE, hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
+ assertThat(events.get(3), allOf(containsPoints(CONTINUED_LINE_MID1, CONTINUED_LINE_MID2),
+ IS_ACTION_MOVE, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 2)));
+ assertThat(events.get(4), allOf(containsPoints(CONTINUED_LINE_START, CONTINUED_LINE_END),
+ IS_ACTION_MOVE, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ assertThat(events.get(5), allOf(containsPoints(CONTINUED_LINE_START, CONTINUED_LINE_END),
+ IS_ACTION_POINTER_UP, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ assertThat(events.get(6), allOf(
+ anyOf(isAtPoint(CONTINUED_LINE_END), isAtPoint(CONTINUED_LINE_START)),
+ IS_ACTION_UP, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ }
+
+
+ @Test
+ public void testContinuedGesture_continuationArrivesWhileDispatching_gestureCompletes()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendOneMessage(); // Send a motion event
+ injectEventsSync(mContinuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
+ verify(next, times(5)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ long downTime = events.get(0).getDownTime();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN,
+ hasEventTime(downTime)));
+ assertThat(events, everyItem(hasDownTime(downTime)));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
+ assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 2)));
+ assertThat(events.get(3), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ assertThat(events.get(4), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_UP,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ }
+
+ @Test
+ public void testContinuedGesture_twoContinuationsArriveWhileDispatching_gestureCompletes()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ // Continue line again
+ List<GestureStep> continuedLineList2 = createSimpleGestureFromPoints(
+ CONTINUED_LINE_STROKE_ID_2, CONTINUED_LINE_STROKE_ID_1, true,
+ CONTINUED_LINE_INTERVAL, CONTINUED_LINE_MID1,
+ CONTINUED_LINE_MID2, CONTINUED_LINE_END);
+ // Finish line by backtracking
+ int strokeId3 = CONTINUED_LINE_STROKE_ID_2 + 1;
+ int sequence3 = CONTINUED_LINE_SEQUENCE_2 + 1;
+ List<GestureStep> continuedLineList3 = createSimpleGestureFromPoints(strokeId3,
+ CONTINUED_LINE_STROKE_ID_2, false, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_END,
+ CONTINUED_LINE_MID2);
+
+ mMessageCapturingHandler.sendOneMessage(); // Send a motion event
+ injectEventsSync(continuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ injectEventsSync(continuedLineList3, mServiceInterface, sequence3);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
+ verify(mServiceInterface).onPerformGestureResult(sequence3, true);
+ verify(next, times(6)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ long downTime = events.get(0).getDownTime();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN,
+ hasEventTime(downTime)));
+ assertThat(events, everyItem(hasDownTime(downTime)));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
+ assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 2)));
+ assertThat(events.get(3), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ assertThat(events.get(4), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 4)));
+ assertThat(events.get(5), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_UP,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 4)));
+ }
+
+ @Test
+ public void testContinuedGesture_nonContinuingGestureArrivesDuringDispatch_gestureCanceled()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendOneMessage(); // Send a motion event
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, false);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
+ verify(next, times(5)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(1), IS_ACTION_CANCEL);
+ assertThat(events.get(2), allOf(isAtPoint(LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(3), allOf(isAtPoint(LINE_END), IS_ACTION_MOVE));
+ assertThat(events.get(4), allOf(isAtPoint(LINE_END), IS_ACTION_UP));
+ }
+
+ @Test
+ public void testContinuedGesture_nonContinuingGestureArrivesAfterDispatch_gestureCanceled()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
+ verify(next, times(6)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE));
+ assertThat(events.get(2), IS_ACTION_CANCEL);
+ assertThat(events.get(3), allOf(isAtPoint(LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(4), allOf(isAtPoint(LINE_END), IS_ACTION_MOVE));
+ assertThat(events.get(5), allOf(isAtPoint(LINE_END), IS_ACTION_UP));
+ }
+
+ @Test
+ public void testContinuedGesture_misMatchedContinuationArrives_bothGesturesCanceled()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ List<GestureStep> discontinuousGesture = mContinuedLineList2
+ .subList(1, mContinuedLineList2.size());
+ injectEventsSync(discontinuousGesture, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, false);
+ verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE));
+ assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_CANCEL));
+ }
+
+ @Test
+ public void testContinuedGesture_continuationArrivesFromOtherService_bothGesturesCanceled()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ IAccessibilityServiceClient otherService = mock(IAccessibilityServiceClient.class);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendOneMessage(); // Send a motion events
+ injectEventsSync(mContinuedLineList2, otherService, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, false);
+ verify(otherService).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, false);
+ verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(1), IS_ACTION_CANCEL);
+ }
+
+ @Test
+ public void testContinuedGesture_realGestureArrivesInBetween_getsCanceled()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
+
+ injectEventsSync(mContinuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, false);
+ verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE));
+ assertThat(events.get(2), IS_ACTION_CANCEL);
+ assertThat(events.get(3), allOf(isAtPoint(CLICK_POINT), IS_ACTION_DOWN));
}
@Test
public void testClearEvents_realGestureInProgress_shouldForgetAboutGesture() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
mMotionEventInjector.clearEvents(MOTION_EVENT_SOURCE);
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(1).getDownTime());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(1)));
+ assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
+ assertThat(mCaptor1.getAllValues().get(1), mIsLineStart);
}
@Test
public void testClearEventsOnOtherSource_realGestureInProgress_shouldNotForgetAboutGesture() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
mMotionEventInjector.clearEvents(OTHER_EVENT_SOURCE);
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SECOND_SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked());
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(2).getDownTime());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(2)));
+ assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
+ assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
+ assertThat(mCaptor1.getAllValues().get(2), mIsLineStart);
}
@Test
public void testOnDestroy_shouldCancelGestures() throws RemoteException {
mMotionEventInjector.onDestroy();
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false);
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
}
@Test
public void testInjectEvents_withNoNext_shouldCancel() throws RemoteException {
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false);
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
}
@Test
public void testOnMotionEvent_withNoNext_shouldNotCrash() {
- mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
}
@Test
@@ -455,6 +686,52 @@
mMotionEventInjector.onAccessibilityEvent(event);
}
+ private void injectEventsSync(List<GestureStep> gestureSteps,
+ IAccessibilityServiceClient serviceInterface, int sequence) {
+ mMotionEventInjector.injectEvents(gestureSteps, serviceInterface, sequence);
+ // Dispatch the message sent by the injector. Our simple handler doesn't guarantee stuff
+ // happens in order.
+ mMessageCapturingHandler.sendLastMessage();
+ }
+
+ private List<GestureStep> createSimpleGestureFromPoints(int strokeId, int continuedStrokeId,
+ boolean continued, long interval, Point... points) {
+ List<GestureStep> gesture = new ArrayList<>(points.length);
+ TouchPoint[] touchPoints = new TouchPoint[1];
+ touchPoints[0] = new TouchPoint();
+ for (int i = 0; i < points.length; i++) {
+ touchPoints[0].mX = points[i].x;
+ touchPoints[0].mY = points[i].y;
+ touchPoints[0].mIsStartOfPath = ((i == 0) && (continuedStrokeId <= 0));
+ touchPoints[0].mContinuedStrokeId = continuedStrokeId;
+ touchPoints[0].mStrokeId = strokeId;
+ touchPoints[0].mIsEndOfPath = ((i == points.length - 1) && !continued);
+ gesture.add(new GestureStep(interval * i, 1, touchPoints));
+ }
+ return gesture;
+ }
+
+ List<GestureStep> combineGestureSteps(List<GestureStep> list1, List<GestureStep> list2) {
+ assertEquals(list1.size(), list2.size());
+ List<GestureStep> gesture = new ArrayList<>(list1.size());
+ for (int i = 0; i < list1.size(); i++) {
+ int numPoints1 = list1.get(i).numTouchPoints;
+ int numPoints2 = list2.get(i).numTouchPoints;
+ TouchPoint[] touchPoints = new TouchPoint[numPoints1 + numPoints2];
+ for (int j = 0; j < numPoints1; j++) {
+ touchPoints[j] = new TouchPoint();
+ touchPoints[j].copyFrom(list1.get(i).touchPoints[j]);
+ }
+ for (int j = 0; j < numPoints2; j++) {
+ touchPoints[numPoints1 + j] = new TouchPoint();
+ touchPoints[numPoints1 + j].copyFrom(list2.get(i).touchPoints[j]);
+ }
+ gesture.add(new GestureStep(list1.get(i).timeSinceGestureStart,
+ numPoints1 + numPoints2, touchPoints));
+ }
+ return gesture;
+ }
+
private EventStreamTransformation attachMockNext(MotionEventInjector motionEventInjector) {
EventStreamTransformation next = mock(EventStreamTransformation.class);
motionEventInjector.setNext(next);
@@ -506,4 +783,126 @@
return false;
}
}
+
+ private static class MotionEventActionMatcher extends TypeSafeMatcher<MotionEvent> {
+ int mAction;
+
+ MotionEventActionMatcher(int action) {
+ super();
+ mAction = action;
+ }
+
+ @Override
+ protected boolean matchesSafely(MotionEvent motionEvent) {
+ return motionEvent.getActionMasked() == mAction;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Matching to action " + mAction);
+ }
+ }
+
+ private static TypeSafeMatcher<MotionEvent> isAtPoint(final Point point) {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ return ((event.getX() == point.x) && (event.getY() == point.y));
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Is at point " + point);
+ }
+ };
+ }
+
+ private static TypeSafeMatcher<MotionEvent> containsPoints(final Point... points) {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
+ for (int i = 0; i < points.length; i++) {
+ boolean havePoint = false;
+ for (int j = 0; j < points.length; j++) {
+ event.getPointerCoords(j, coords);
+ if ((points[i].x == coords.x) && (points[i].y == coords.y)) {
+ havePoint = true;
+ }
+ }
+ if (!havePoint) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Contains points " + points);
+ }
+ };
+ }
+
+ private static TypeSafeMatcher<MotionEvent> hasDownTime(final long downTime) {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ return event.getDownTime() == downTime;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Down time = " + downTime);
+ }
+ };
+ }
+
+ private static TypeSafeMatcher<MotionEvent> hasEventTime(final long eventTime) {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ return event.getEventTime() == eventTime;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Event time = " + eventTime);
+ }
+ };
+ }
+
+ private static TypeSafeMatcher<MotionEvent> hasTimeFromDown(final long timeFromDown) {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ return (event.getEventTime() - event.getDownTime()) == timeFromDown;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Time from down to event times = " + timeFromDown);
+ }
+ };
+ }
+
+ private static TypeSafeMatcher<MotionEvent> hasStandardInitialization() {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ return (0 == event.getActionIndex()) && (0 == event.getDeviceId())
+ && (0 == event.getEdgeFlags()) && (0 == event.getFlags())
+ && (0 == event.getMetaState()) && (0F == event.getOrientation())
+ && (0F == event.getTouchMajor()) && (0F == event.getTouchMinor())
+ && (1F == event.getXPrecision()) && (1F == event.getYPrecision())
+ && (1 == event.getPointerCount()) && (1F == event.getPressure())
+ && (InputDevice.SOURCE_TOUCHSCREEN == event.getSource());
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Has standard values for all parameters");
+ }
+ };
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 3ad40758..0c00886 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1993,7 +1993,7 @@
// UnfinishedVerificationException.
}
- public void testIsProvisioningAllowed_DeviceAdminFeatureOff() throws Exception {
+ public void setup_DeviceAdminFeatureOff() throws Exception {
when(mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN))
.thenReturn(false);
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
@@ -2005,7 +2005,10 @@
setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_DeviceAdminFeatureOff() throws Exception {
+ setup_DeviceAdminFeatureOff();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, false);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
@@ -2013,7 +2016,21 @@
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false);
}
- public void testIsProvisioningAllowed_ManagedProfileFeatureOff() throws Exception {
+ public void testCheckProvisioningPreCondition_DeviceAdminFeatureOff() throws Exception {
+ setup_DeviceAdminFeatureOff();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED);
+ }
+
+ public void setup_ManagedProfileFeatureOff() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(false);
initializeDpms();
@@ -2023,7 +2040,10 @@
setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_ManagedProfileFeatureOff() throws Exception {
+ setup_ManagedProfileFeatureOff();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
@@ -2039,7 +2059,33 @@
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false);
}
- public void testIsProvisioningAllowed_nonSplitUser_firstBoot_primaryUser() throws Exception {
+ public void testCheckProvisioningPreCondition_ManagedProfileFeatureOff() throws Exception {
+ setup_ManagedProfileFeatureOff();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED);
+
+ // Test again when split user is on
+ when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED);
+ }
+
+ public void setup_nonSplitUser_firstBoot_primaryUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(false);
@@ -2048,7 +2094,10 @@
setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_nonSplitUser_firstBoot_primaryUser() throws Exception {
+ setup_nonSplitUser_firstBoot_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
@@ -2057,8 +2106,22 @@
false /* because of non-split user */);
}
- public void testIsProvisioningAllowed_nonSplitUser_afterDeviceSetup_primaryUser()
+ public void testCheckProvisioningPreCondition_nonSplitUser_firstBoot_primaryUser()
throws Exception {
+ setup_nonSplitUser_firstBoot_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
+ }
+
+ public void setup_nonSplitUser_afterDeviceSetup_primaryUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(false);
@@ -2067,7 +2130,11 @@
setUserSetupCompleteForUser(true, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_nonSplitUser_afterDeviceSetup_primaryUser()
+ throws Exception {
+ setup_nonSplitUser_afterDeviceSetup_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
false/* because of completed device setup */);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
@@ -2077,7 +2144,22 @@
false/* because of non-split user */);
}
- public void testIsProvisioningAllowed_splitUser_firstBoot_systemUser() throws Exception {
+ public void testCheckProvisioningPreCondition_nonSplitUser_afterDeviceSetup_primaryUser()
+ throws Exception {
+ setup_nonSplitUser_afterDeviceSetup_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_USER_SETUP_COMPLETED);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
+ }
+
+ public void setup_splitUser_firstBoot_systemUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
@@ -2086,7 +2168,10 @@
setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_splitUser_firstBoot_systemUser() throws Exception {
+ setup_splitUser_firstBoot_systemUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
false /* because canAddMoreManagedProfiles returns false */);
@@ -2094,10 +2179,24 @@
true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
false/* because calling uid is system user */);
-
}
- public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_systemUser() throws Exception {
+ public void testCheckProvisioningPreCondition_splitUser_firstBoot_systemUser()
+ throws Exception {
+ setup_splitUser_firstBoot_systemUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_SYSTEM_USER);
+ }
+
+ public void setup_splitUser_afterDeviceSetup_systemUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
@@ -2106,7 +2205,10 @@
setUserSetupCompleteForUser(true, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_systemUser() throws Exception {
+ setup_splitUser_afterDeviceSetup_systemUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
true/* it's undefined behavior. Can be changed into false in the future */);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
@@ -2117,7 +2219,22 @@
false/* because calling uid is system user */);
}
- public void testIsProvisioningAllowed_splitUser_firstBoot_primaryUser() throws Exception {
+ public void testCheckProvisioningPreCondition_splitUser_afterDeviceSetup_systemUser()
+ throws Exception {
+ setup_splitUser_afterDeviceSetup_systemUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_SYSTEM_USER);
+ }
+
+ public void setup_splitUser_firstBoot_primaryUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
@@ -2126,17 +2243,33 @@
setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE);
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ }
+ public void testIsProvisioningAllowed_splitUser_firstBoot_primaryUser() throws Exception {
+ setup_splitUser_firstBoot_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, true);
-
}
- public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_primaryUser()
+ public void testCheckProvisioningPreCondition_splitUser_firstBoot_primaryUser()
throws Exception {
+ setup_splitUser_firstBoot_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_OK);
+ }
+
+ public void setup_splitUser_afterDeviceSetup_primaryUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
@@ -2145,7 +2278,11 @@
setUserSetupCompleteForUser(true, DpmMockContext.CALLER_USER_HANDLE);
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ }
+ public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_primaryUser()
+ throws Exception {
+ setup_splitUser_afterDeviceSetup_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
true/* it's undefined behavior. Can be changed into false in the future */);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
@@ -2155,8 +2292,22 @@
false/* because user setup completed */);
}
- public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_systemUser()
+ public void testCheckProvisioningPreCondition_splitUser_afterDeviceSetup_primaryUser()
throws Exception {
+ setup_splitUser_afterDeviceSetup_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_USER_SETUP_COMPLETED);
+ }
+
+ public void setup_provisionManagedProfileWithDeviceOwner_systemUser() throws Exception {
setDeviceOwner();
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
@@ -2167,13 +2318,24 @@
setUserSetupCompleteForUser(true, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_systemUser()
+ throws Exception {
+ setup_provisionManagedProfileWithDeviceOwner_systemUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
false /* can't provision managed profile on system user */);
}
- public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_primaryUser()
+ public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_systemUser()
throws Exception {
+ setup_provisionManagedProfileWithDeviceOwner_systemUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER);
+ }
+
+ private void setup_provisionManagedProfileWithDeviceOwner_primaryUser() throws Exception {
setDeviceOwner();
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
@@ -2184,12 +2346,23 @@
setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE);
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ }
+ public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_primaryUser()
+ throws Exception {
+ setup_provisionManagedProfileWithDeviceOwner_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
}
- public void testIsProvisioningAllowed_provisionManagedProfileCantRemoveUser_primaryUser()
+ public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_primaryUser()
throws Exception {
+ setup_provisionManagedProfileWithDeviceOwner_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_OK);
+ }
+
+ private void setup_provisionManagedProfileCantRemoveUser_primaryUser() throws Exception {
setDeviceOwner();
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
@@ -2198,16 +2371,37 @@
when(mContext.userManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER))
.thenReturn(true);
when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
- false /* we can't remove a managed profile*/)).thenReturn(false);
+ false /* we can't remove a managed profile */)).thenReturn(false);
when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
true)).thenReturn(true);
setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE);
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ }
+ public void testIsProvisioningAllowed_provisionManagedProfileCantRemoveUser_primaryUser()
+ throws Exception {
+ setup_provisionManagedProfileCantRemoveUser_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
}
+ public void testCheckProvisioningPreCondition_provisionManagedProfileCantRemoveUser_primaryUser()
+ throws Exception {
+ setup_provisionManagedProfileCantRemoveUser_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ }
+
+ public void testCheckProvisioningPreCondition_permission() {
+ // GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted
+ try {
+ dpm.checkProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE);
+ fail("Didn't throw SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
public void testForceUpdateUserSetupComplete_permission() {
// GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted
try {
@@ -2568,6 +2762,11 @@
dpm.isProvisioningAllowed(action));
}
+ private void assertCheckProvisioningPreCondition(String action, int provisioningCondition) {
+ assertEquals("checkProvisioningPreCondition(" + action + ") returning unexpected result",
+ provisioningCondition, dpm.checkProvisioningPreCondition(action));
+ }
+
/**
* Setup a managed profile with the specified admin and its uid.
* @param admin ComponentName that's visible to the test code, which doesn't have to exist.
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index 58db192..3806da6 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -82,6 +82,21 @@
return Mockito.argThat(m);
}
+ public static Intent checkIntent(final Intent intent) {
+ final Matcher<Intent> m = new BaseMatcher<Intent>() {
+ @Override
+ public boolean matches(Object item) {
+ if (item == null) return false;
+ return intent.filterEquals((Intent) item);
+ }
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(intent.toString());
+ }
+ };
+ return Mockito.argThat(m);
+ }
+
public static Bundle checkUserRestrictions(String... keys) {
final Bundle expected = DpmTestUtils.newRestrictions(Preconditions.checkNotNull(keys));
final Matcher<Bundle> m = new BaseMatcher<Bundle>() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 9f01773..99af9e8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -376,6 +376,7 @@
@Override
boolean injectIsActivityEnabledAndExported(ComponentName activity, @UserIdInt int userId) {
+ assertNotNull(activity);
return mEnabledActivityChecker.test(activity, userId);
}
@@ -416,6 +417,11 @@
// During tests, WTF is fatal.
fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th));
}
+
+ @Override
+ void verifyError() {
+ fail("Verify error");
+ }
}
/** ShortcutManager with injection override methods. */
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
index f773c15..5c552a2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
@@ -27,12 +27,16 @@
import android.util.ArraySet;
import com.android.internal.os.RoSystemProperties;
+import com.android.internal.util.ArrayUtils;
import com.android.server.SystemConfig;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.List;
+
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static junit.framework.Assert.assertTrue;
@@ -53,27 +57,34 @@
}
/**
- * <p>This test ensures that all signature|privileged permissions are granted to core apps like
- * systemui/settings. If CONTROL_PRIVAPP_PERMISSIONS is set, the test also verifies that
+ * <p>This test ensures that all signature|privileged permissions are granted to priv-apps.
+ * If CONTROL_PRIVAPP_PERMISSIONS_ENFORCE is set, the test also verifies that
* granted permissions are whitelisted in {@link SystemConfig}
*/
@Test
@SmallTest
@Presubmit
public void testPrivAppPermissions() throws PackageManager.NameNotFoundException {
- String[] testPackages = {"com.android.settings", "com.android.shell",
- "com.android.systemui"};
- for (String testPackage : testPackages) {
- testPackagePrivAppPermission(testPackage);
+ List<PackageInfo> installedPackages = mPackageManager
+ .getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES | GET_PERMISSIONS);
+ for (PackageInfo packageInfo : installedPackages) {
+ if (!packageInfo.applicationInfo.isPrivilegedApp()
+ || PackageManagerService.PLATFORM_PACKAGE_NAME.equals(packageInfo.packageName)) {
+ continue;
+ }
+ testPackagePrivAppPermission(packageInfo);
}
+
}
- private void testPackagePrivAppPermission(String testPackage)
+ private void testPackagePrivAppPermission(PackageInfo packageInfo)
throws PackageManager.NameNotFoundException {
- PackageInfo packageInfo = mPackageManager.getPackageInfo(testPackage,
- PackageManager.GET_PERMISSIONS);
+ String packageName = packageInfo.packageName;
ArraySet<String> privAppPermissions = SystemConfig.getInstance()
- .getPrivAppPermissions(testPackage);
+ .getPrivAppPermissions(packageName);
+ if (ArrayUtils.isEmpty(packageInfo.requestedPermissions)) {
+ return;
+ }
for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
String pName = packageInfo.requestedPermissions[i];
int protectionLevel;
@@ -89,15 +100,17 @@
if ((protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
boolean granted = (packageInfo.requestedPermissionsFlags[i]
& PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
- assertTrue("Permission " + pName + " should be granted to " + testPackage, granted);
// if privapp permissions are enforced, platform permissions must be whitelisted
// in SystemConfig
if (platformPermission && RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
assertTrue("Permission " + pName
- + " should be declared in the xml file for package "
- + testPackage,
+ + " should be declared in "
+ + "/etc/permissions/privapp-permissions-platform.xml "
+ + "or privapp-permissions-<device>.xml file for package "
+ + packageName,
privAppPermissions.contains(pName));
}
+ assertTrue("Permission " + pName + " should be granted to " + packageName, granted);
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
new file mode 100644
index 0000000..84bb4e8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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 com.android.server.pm;
+
+import android.content.pm.PackageParser;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import libcore.io.IoUtils;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class PackageParserTest {
+ private File mTmpDir;
+ private static final File FRAMEWORK = new File("/system/framework/framework-res.apk");
+
+ @Before
+ public void setUp() {
+ // Create a new temporary directory for each of our tests.
+ mTmpDir = IoUtils.createTemporaryDirectory("PackageParserTest");
+ }
+
+ @Test
+ public void testParse_noCache() throws Exception {
+ PackageParser pp = new CachePackageNameParser();
+ PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
+ false /* useCaches */);
+ assertNotNull(pkg);
+
+ pp.setCacheDir(mTmpDir);
+ pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
+ false /* useCaches */);
+ assertNotNull(pkg);
+
+ // Make sure that we always write out a cache entry for future reference,
+ // whether or not we're asked to use caches.
+ assertEquals(1, mTmpDir.list().length);
+ }
+
+ @Test
+ public void testParse_withCache() throws Exception {
+ PackageParser pp = new CachePackageNameParser();
+
+ pp.setCacheDir(mTmpDir);
+ // The first parse will write this package to the cache.
+ pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */);
+
+ // Now attempt to parse the package again, should return the
+ // cached result.
+ PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
+ true /* useCaches */);
+ assertEquals("cache_android", pkg.packageName);
+
+ // Try again, with useCaches == false, shouldn't return the parsed
+ // result.
+ pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */);
+ assertEquals("android", pkg.packageName);
+
+ // We haven't set a cache directory here : the parse should still succeed,
+ // just not using the cached results.
+ pp = new CachePackageNameParser();
+ pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */);
+ assertEquals("android", pkg.packageName);
+
+ pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */);
+ assertEquals("android", pkg.packageName);
+ }
+
+ /**
+ * A trivial subclass of package parser that only caches the package name, and throws away
+ * all other information.
+ */
+ public static class CachePackageNameParser extends PackageParser {
+ @Override
+ public byte[] toCacheEntry(Package pkg) {
+ return ("cache_" + pkg.packageName).getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ public Package fromCacheEntry(byte[] cacheEntry) {
+ return new Package(new String(cacheEntry, StandardCharsets.UTF_8));
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 74c1ca5..97bcaf0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -1292,7 +1292,43 @@
/* activity =*/ null, /* flags */ 0), getCallingUser());
});
- // TODO More tests: pinned but dynamic.
+ // Make sure floating shortcuts don't match with an activity.
+ // At this point, s1 is dynamic and pinned, so it still has a target activity.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertWith(mLauncherApps.getShortcuts(buildQuery(
+ /* time =*/ 0,
+ CALLING_PACKAGE_2,
+ /* activity =*/ new ComponentName(CALLING_PACKAGE_2,
+ ShortcutActivity2.class.getName()),
+ ShortcutQuery.FLAG_GET_PINNED),
+ getCallingUser()))
+ .haveIds("s3")
+ .areAllPinned()
+ .areAllDynamic()
+ .areAllWithActivity(new ComponentName(CALLING_PACKAGE_2,
+ ShortcutActivity2.class.getName()));
+ });
+
+ // Now remove as a dynamic, making it floating.
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ mManager.removeDynamicShortcuts(list("s3"));
+ assertWith(mManager.getPinnedShortcuts())
+ .selectFloating()
+ .areAllWithNoActivity();
+ });
+
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ // This shouldn't match now.
+ assertWith(mLauncherApps.getShortcuts(buildQuery(
+ /* time =*/ 0,
+ CALLING_PACKAGE_2,
+ /* activity =*/ new ComponentName(CALLING_PACKAGE_2,
+ ShortcutActivity2.class.getName()),
+ ShortcutQuery.FLAG_GET_PINNED),
+ getCallingUser()))
+ .isEmpty();
+ });
+
}
public void testGetShortcuts_shortcutKinds() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index d25923c..7486858 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -1052,7 +1052,7 @@
assertEquals(CALLING_PACKAGE_1, si.getPackage());
assertEquals("id", si.getId());
- assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
+ assertNull(si.getActivity()); // It's now floating, so no target activity.
assertEquals(null, si.getIcon());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
@@ -1116,7 +1116,7 @@
assertEquals(CALLING_PACKAGE_1, si.getPackage());
assertEquals("id", si.getId());
- assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
+ assertNull(si.getActivity()); // It's now floating, so no target activity.
assertEquals(null, si.getIcon());
assertEquals(10, si.getTitleResId());
assertEquals("r10", si.getTitleResName());
diff --git a/services/tests/servicestests/src/com/android/server/twilight/TwilightServiceTest.java b/services/tests/servicestests/src/com/android/server/twilight/TwilightServiceTest.java
new file mode 100644
index 0000000..751e4b5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/twilight/TwilightServiceTest.java
@@ -0,0 +1,71 @@
+package com.android.server.twilight;
+
+/*
+ * 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.
+ */
+
+import android.app.AlarmManager;
+import android.content.Context;
+import android.location.Location;
+import android.test.AndroidTestCase;
+
+public class TwilightServiceTest extends AndroidTestCase {
+
+ private TwilightService mTwilightService;
+ private Location mInitialLocation;
+
+ @Override
+ protected void setUp() throws Exception {
+ final Context context = getContext();
+ mTwilightService = new TwilightService(context);
+ mTwilightService.mAlarmManager =
+ (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+
+ mInitialLocation = createMockLocation(10.0, 10.0);
+ mTwilightService.onLocationChanged(mInitialLocation);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mTwilightService = null;
+ mInitialLocation = null;
+ }
+
+ public void testValidLocation_updatedLocation() {
+ final TwilightState priorState = mTwilightService.mLastTwilightState;
+ final Location validLocation = createMockLocation(35.0, 35.0);
+ mTwilightService.onLocationChanged(validLocation);
+ assertEquals(mTwilightService.mLastLocation, validLocation);
+ assertNotSame(priorState, mTwilightService.mLastTwilightState);
+ }
+
+ public void testInvalidLocation_ignoreLocationUpdate() {
+ final TwilightState priorState = mTwilightService.mLastTwilightState;
+ final Location invalidLocation = createMockLocation(0.0, 0.0);
+ mTwilightService.onLocationChanged(invalidLocation);
+ assertEquals(mTwilightService.mLastLocation, mInitialLocation);
+ assertEquals(priorState, mTwilightService.mLastTwilightState);
+ }
+
+ private Location createMockLocation(double latitude, double longitude) {
+ // There's no empty constructor, so we initialize with a string and quickly reset it.
+ final Location location = new Location("");
+ location.reset();
+ location.setLatitude(latitude);
+ location.setLongitude(longitude);
+ return location;
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 207939f..06837d3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -16,17 +16,12 @@
package com.android.server.wm;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import android.content.Context;
import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.IWindow;
-import android.view.WindowManager;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -49,7 +44,7 @@
@Test
public void testAddWindow_Order() throws Exception {
- final TestAppWindowToken token = new TestAppWindowToken();
+ final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
assertEquals(0, token.getWindowsCount());
@@ -59,11 +54,6 @@
final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, token, "baseWin");
final WindowState win4 = createWindow(null, TYPE_APPLICATION, token, "win4");
- token.addWindow(win1);
- token.addWindow(startingWin);
- token.addWindow(baseWin);
- token.addWindow(win4);
-
// Should not contain the windows that were added above.
assertEquals(4, token.getWindowsCount());
assertTrue(token.hasWindow(win1));
@@ -80,43 +70,17 @@
@Test
public void testFindMainWindow() throws Exception {
- final TestAppWindowToken token = new TestAppWindowToken();
+ final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
assertNull(token.findMainWindow());
final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, token, "window1");
final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11");
final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12");
- token.addWindow(window1);
assertEquals(window1, token.findMainWindow());
window1.mAnimatingExit = true;
assertEquals(window1, token.findMainWindow());
final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, token, "window2");
- token.addWindow(window2);
assertEquals(window2, token.findMainWindow());
}
-
- /* Used so we can gain access to some protected members of the {@link AppWindowToken} class */
- private class TestAppWindowToken extends AppWindowToken {
-
- TestAppWindowToken() {
- super(sWm, null, false, sWm.getDefaultDisplayContentLocked());
- }
-
- int getWindowsCount() {
- return mChildren.size();
- }
-
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
-
- WindowState getFirstChild() {
- return mChildren.getFirst();
- }
-
- WindowState getLastChild() {
- return mChildren.getLast();
- }
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 0801a88..162a1a9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -25,14 +25,7 @@
import java.util.ArrayList;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static org.junit.Assert.assertEquals;
/**
@@ -48,21 +41,8 @@
@Test
public void testForAllWindows() throws Exception {
- final DisplayContent dc = new DisplayContent(mDisplay, sWm, null, null);
- final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, dc, "wallpaper");
- final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, dc, "ime");
- final WindowState imeDialogWindow = createWindow(null, TYPE_INPUT_METHOD_DIALOG, dc,
- "ime dialog");
- final WindowState statusBarWindow = createWindow(null, TYPE_STATUS_BAR, dc, "status bar");
- final WindowState navBarWindow = createWindow(null, TYPE_NAVIGATION_BAR,
- statusBarWindow.mToken, "nav bar");
- final WindowState appWindow = createWindow(null, TYPE_BASE_APPLICATION, dc, "app");
- final WindowState negChildAppWindow = createWindow(appWindow, TYPE_APPLICATION_MEDIA,
- appWindow.mToken, "negative app child");
- final WindowState posChildAppWindow = createWindow(appWindow,
- TYPE_APPLICATION_ATTACHED_DIALOG, appWindow.mToken, "positive app child");
- final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION, dc,
- "exiting app");
+ final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
+ sDisplayContent, "exiting app");
final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
exitingAppToken.mIsExiting = true;
exitingAppToken.mTask.mStack.mExitingAppTokens.add(exitingAppToken);
@@ -70,30 +50,75 @@
final ArrayList<WindowState> windows = new ArrayList();
// Test forward traversal.
- dc.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
- assertEquals(wallpaperWindow, windows.get(0));
+ assertEquals(sWallpaperWindow, windows.get(0));
assertEquals(exitingAppWindow, windows.get(1));
- assertEquals(negChildAppWindow, windows.get(2));
- assertEquals(appWindow, windows.get(3));
- assertEquals(posChildAppWindow, windows.get(4));
- assertEquals(statusBarWindow, windows.get(5));
- assertEquals(navBarWindow, windows.get(6));
- assertEquals(imeWindow, windows.get(7));
- assertEquals(imeDialogWindow, windows.get(8));
+ assertEquals(sChildAppWindowBelow, windows.get(2));
+ assertEquals(sAppWindow, windows.get(3));
+ assertEquals(sChildAppWindowAbove, windows.get(4));
+ assertEquals(sDockedDividerWindow, windows.get(5));
+ assertEquals(sStatusBarWindow, windows.get(6));
+ assertEquals(sNavBarWindow, windows.get(7));
+ assertEquals(sImeWindow, windows.get(8));
+ assertEquals(sImeDialogWindow, windows.get(9));
// Test backward traversal.
windows.clear();
- dc.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
- assertEquals(wallpaperWindow, windows.get(8));
- assertEquals(exitingAppWindow, windows.get(7));
- assertEquals(negChildAppWindow, windows.get(6));
- assertEquals(appWindow, windows.get(5));
- assertEquals(posChildAppWindow, windows.get(4));
- assertEquals(statusBarWindow, windows.get(3));
- assertEquals(navBarWindow, windows.get(2));
- assertEquals(imeWindow, windows.get(1));
- assertEquals(imeDialogWindow, windows.get(0));
+ assertEquals(sWallpaperWindow, windows.get(9));
+ assertEquals(exitingAppWindow, windows.get(8));
+ assertEquals(sChildAppWindowBelow, windows.get(7));
+ assertEquals(sAppWindow, windows.get(6));
+ assertEquals(sChildAppWindowAbove, windows.get(5));
+ assertEquals(sDockedDividerWindow, windows.get(4));
+ assertEquals(sStatusBarWindow, windows.get(3));
+ assertEquals(sNavBarWindow, windows.get(2));
+ assertEquals(sImeWindow, windows.get(1));
+ assertEquals(sImeDialogWindow, windows.get(0));
+ }
+
+ @Test
+ public void testForAllWindows_WithImeTarget() throws Exception {
+ final WindowState imeAppTarget =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
+
+ sWm.mInputMethodTarget = imeAppTarget;
+
+ final ArrayList<WindowState> windows = new ArrayList();
+
+ // Test forward traversal.
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
+
+ assertEquals(sWallpaperWindow, windows.get(0));
+ assertEquals(sChildAppWindowBelow, windows.get(1));
+ assertEquals(sAppWindow, windows.get(2));
+ assertEquals(sChildAppWindowAbove, windows.get(3));
+ assertEquals(imeAppTarget, windows.get(4));
+ assertEquals(sImeWindow, windows.get(5));
+ assertEquals(sImeDialogWindow, windows.get(6));
+ assertEquals(sDockedDividerWindow, windows.get(7));
+ assertEquals(sStatusBarWindow, windows.get(8));
+ assertEquals(sNavBarWindow, windows.get(9));
+
+ // Test backward traversal.
+ windows.clear();
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
+
+ assertEquals(sWallpaperWindow, windows.get(9));
+ assertEquals(sChildAppWindowBelow, windows.get(8));
+ assertEquals(sAppWindow, windows.get(7));
+ assertEquals(sChildAppWindowAbove, windows.get(6));
+ assertEquals(imeAppTarget, windows.get(5));
+ assertEquals(sImeWindow, windows.get(4));
+ assertEquals(sImeDialogWindow, windows.get(3));
+ assertEquals(sDockedDividerWindow, windows.get(2));
+ assertEquals(sStatusBarWindow, windows.get(1));
+ assertEquals(sNavBarWindow, windows.get(0));
+
+ // Clean-up
+ sWm.mInputMethodTarget = null;
+ imeAppTarget.removeImmediately();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
new file mode 100644
index 0000000..1260a53
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
@@ -0,0 +1,455 @@
+/*
+ * 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 com.android.server.wm;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.graphics.Rect;
+import android.os.Binder;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
+import static com.android.server.wm.WindowManagerService.dipToPixel;
+import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
+import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for the {@link TaskPositioner} class.
+ *
+ * runtest frameworks-services -c com.android.server.wm.TaskPositionerTests
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TaskPositionerTests extends WindowTestsBase {
+
+ private final boolean DEBUGGING = false;
+ private final String TAG = "TaskPositionerTest";
+
+ private final static int MOUSE_DELTA_X = 5;
+ private final static int MOUSE_DELTA_Y = 5;
+
+ private int mMinVisibleWidth;
+ private int mMinVisibleHeight;
+ private TaskPositioner mPositioner;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ final Display display = sDisplayContent.getDisplay();
+ final DisplayMetrics dm = new DisplayMetrics();
+ display.getMetrics(dm);
+
+ // This should be the same calculation as the TaskPositioner uses.
+ mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
+ mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
+
+ mPositioner = new TaskPositioner(sWm);
+ mPositioner.register(display);
+ }
+
+ /**
+ * This tests that free resizing will allow to change the orientation as well
+ * as does some basic tests (e.g. dragging in Y only will keep X stable).
+ */
+ @Test
+ public void testBasicFreeWindowResizing() throws Exception {
+ final Rect r = new Rect(100, 220, 700, 520);
+ final int midY = (r.top + r.bottom) / 2;
+
+ // Start a drag resize starting upper left.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+ assertBoundsEquals(r, mPositioner.getWindowDragBounds());
+
+ // Drag to a good landscape size.
+ mPositioner.resizeDrag(0.0f, 0.0f);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a good portrait size.
+ mPositioner.resizeDrag(400.0f, 0.0f);
+ assertBoundsEquals(new Rect(400 + MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a too small size for the width.
+ mPositioner.resizeDrag(2000.0f, r.top);
+ assertBoundsEquals(
+ new Rect(r.right - mMinVisibleWidth, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a too small size for the height.
+ mPositioner.resizeDrag(r.left, 2000.0f);
+ assertBoundsEquals(
+ new Rect(r.left + MOUSE_DELTA_X, r.bottom - mMinVisibleHeight, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Start a drag resize left and see that only the left coord changes..
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
+
+ // Drag to the left.
+ mPositioner.resizeDrag(0.0f, midY);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the right.
+ mPositioner.resizeDrag(200.0f, midY);
+ assertBoundsEquals(new Rect(200 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the top
+ mPositioner.resizeDrag(r.left, 0.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the bottom
+ mPositioner.resizeDrag(r.left, 1000.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that by dragging any edge, the fixed / opposite edge(s) remains anchored.
+ */
+ @Test
+ public void testFreeWindowResizingTestAllEdges() throws Exception {
+ final Rect r = new Rect(100, 220, 700, 520);
+ final int midX = (r.left + r.right) / 2;
+ final int midY = (r.top + r.bottom) / 2;
+
+ // Drag upper left.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(0.0f, 0.0f);
+ assertTrue(r.left != mPositioner.getWindowDragBounds().left);
+ assertEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertTrue(r.top != mPositioner.getWindowDragBounds().top);
+ assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
+
+ // Drag upper.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(0.0f, 0.0f);
+ assertEquals(r.left, mPositioner.getWindowDragBounds().left);
+ assertEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertTrue(r.top != mPositioner.getWindowDragBounds().top);
+ assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
+
+ // Drag upper right.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(r.right + 100, 0.0f);
+ assertEquals(r.left, mPositioner.getWindowDragBounds().left);
+ assertTrue(r.right != mPositioner.getWindowDragBounds().right);
+ assertTrue(r.top != mPositioner.getWindowDragBounds().top);
+ assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
+
+ // Drag right.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, midY, r);
+ mPositioner.resizeDrag(r.right + 100, 0.0f);
+ assertEquals(r.left, mPositioner.getWindowDragBounds().left);
+ assertTrue(r.right != mPositioner.getWindowDragBounds().right);
+ assertEquals(r.top, mPositioner.getWindowDragBounds().top);
+ assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
+
+ // Drag bottom right.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/,
+ r.right + MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
+ assertEquals(r.left, mPositioner.getWindowDragBounds().left);
+ assertTrue(r.right != mPositioner.getWindowDragBounds().right);
+ assertEquals(r.top, mPositioner.getWindowDragBounds().top);
+ assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
+
+ // Drag bottom.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, midX, r.bottom + MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
+ assertEquals(r.left, mPositioner.getWindowDragBounds().left);
+ assertEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertEquals(r.top, mPositioner.getWindowDragBounds().top);
+ assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
+
+ // Drag bottom left.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(0.0f, r.bottom + 100);
+ assertTrue(r.left != mPositioner.getWindowDragBounds().left);
+ assertEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertEquals(r.top, mPositioner.getWindowDragBounds().top);
+ assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
+
+ // Drag left.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midX, r);
+ mPositioner.resizeDrag(0.0f, r.bottom + 100);
+ assertTrue(r.left != mPositioner.getWindowDragBounds().left);
+ assertEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertEquals(r.top, mPositioner.getWindowDragBounds().top);
+ assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
+ }
+
+ /**
+ * This tests that a constrained landscape window will keep the aspect and do the
+ * right things upon resizing when dragged from the top left corner.
+ */
+ @Test
+ public void testLandscapePreservedWindowResizingDragTopLeft() throws Exception {
+ final Rect r = new Rect(100, 220, 700, 520);
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+ assertBoundsEquals(r, mPositioner.getWindowDragBounds());
+
+ // Drag to a good landscape size.
+ mPositioner.resizeDrag(0.0f, 0.0f);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a good portrait size.
+ mPositioner.resizeDrag(400.0f, 0.0f);
+ int width = Math.round((float) (r.bottom - MOUSE_DELTA_Y) * MIN_ASPECT);
+ assertBoundsEquals(new Rect(r.right - width, MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a too small size for the width.
+ mPositioner.resizeDrag(2000.0f, r.top);
+ final int w = mMinVisibleWidth;
+ final int h = Math.round(w / MIN_ASPECT);
+ assertBoundsEquals(new Rect(r.right - w, r.bottom - h, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a too small size for the height.
+ mPositioner.resizeDrag(r.left, 2000.0f);
+ assertBoundsEquals(
+ new Rect(r.left + MOUSE_DELTA_X, r.bottom - mMinVisibleHeight, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that a constrained landscape window will keep the aspect and do the
+ * right things upon resizing when dragged from the left corner.
+ */
+ @Test
+ public void testLandscapePreservedWindowResizingDragLeft() throws Exception {
+ final Rect r = new Rect(100, 220, 700, 520);
+ final int midY = (r.top + r.bottom) / 2;
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
+
+ // Drag to the left.
+ mPositioner.resizeDrag(0.0f, midY);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the right.
+ mPositioner.resizeDrag(200.0f, midY);
+ assertBoundsEquals(new Rect(200 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag all the way to the right and see the height also shrinking.
+ mPositioner.resizeDrag(2000.0f, midY);
+ final int w = mMinVisibleWidth;
+ final int h = Math.round((float)w / MIN_ASPECT);
+ assertBoundsEquals(new Rect(r.right - w, r.top, r.right, r.top + h),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the top.
+ mPositioner.resizeDrag(r.left, 0.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the bottom.
+ mPositioner.resizeDrag(r.left, 1000.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that a constrained landscape window will keep the aspect and do the
+ * right things upon resizing when dragged from the top corner.
+ */
+ @Test
+ public void testLandscapePreservedWindowResizingDragTop() throws Exception {
+ final Rect r = new Rect(100, 220, 700, 520);
+ final int midX = (r.left + r.right) / 2;
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
+
+ // Drag to the left (no change).
+ mPositioner.resizeDrag(0.0f, r.top);
+ assertBoundsEquals(new Rect(r.left, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the right (no change).
+ mPositioner.resizeDrag(2000.0f, r.top);
+ assertBoundsEquals(new Rect(r.left , r.top + MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the top.
+ mPositioner.resizeDrag(300.0f, 0.0f);
+ int h = r.bottom - MOUSE_DELTA_Y;
+ int w = Math.max(r.right - r.left, Math.round(h * MIN_ASPECT));
+ assertBoundsEquals(new Rect(r.left, MOUSE_DELTA_Y, r.left + w, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the bottom.
+ mPositioner.resizeDrag(r.left, 1000.0f);
+ h = mMinVisibleHeight;
+ assertBoundsEquals(new Rect(r.left, r.bottom - h, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that a constrained portrait window will keep the aspect and do the
+ * right things upon resizing when dragged from the top left corner.
+ */
+ @Test
+ public void testPortraitPreservedWindowResizingDragTopLeft() throws Exception {
+ final Rect r = new Rect(330, 100, 630, 600);
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+ assertBoundsEquals(r, mPositioner.getWindowDragBounds());
+
+ // Drag to a good landscape size.
+ mPositioner.resizeDrag(0.0f, 0.0f);
+ int height = Math.round((float) (r.right - MOUSE_DELTA_X) * MIN_ASPECT);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.bottom - height, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a good portrait size.
+ mPositioner.resizeDrag(500.0f, 0.0f);
+ assertBoundsEquals(new Rect(500 + MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a too small size for the height and the the width shrinking.
+ mPositioner.resizeDrag(r.left + MOUSE_DELTA_X, 2000.0f);
+ final int w = Math.max(mMinVisibleWidth, Math.round(mMinVisibleHeight / MIN_ASPECT));
+ final int h = Math.max(mMinVisibleHeight, Math.round(w * MIN_ASPECT));
+ assertBoundsEquals(
+ new Rect(r.right - w, r.bottom - h, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that a constrained portrait window will keep the aspect and do the
+ * right things upon resizing when dragged from the left corner.
+ */
+ @Test
+ public void testPortraitPreservedWindowResizingDragLeft() throws Exception {
+ final Rect r = new Rect(330, 100, 630, 600);
+ final int midY = (r.top + r.bottom) / 2;
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
+
+ // Drag to the left.
+ mPositioner.resizeDrag(0.0f, midY);
+ int w = r.right - MOUSE_DELTA_X;
+ int h = Math.round(w * MIN_ASPECT);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.top + h),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the right.
+ mPositioner.resizeDrag(450.0f, midY);
+ assertBoundsEquals(new Rect(450 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag all the way to the right.
+ mPositioner.resizeDrag(2000.0f, midY);
+ w = mMinVisibleWidth;
+ h = Math.max(Math.round((float)w * MIN_ASPECT), r.height());
+ assertBoundsEquals(new Rect(r.right - w, r.top, r.right, r.top + h),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the top.
+ mPositioner.resizeDrag(r.left, 0.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the bottom.
+ mPositioner.resizeDrag(r.left, 1000.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that a constrained portrait window will keep the aspect and do the
+ * right things upon resizing when dragged from the top corner.
+ */
+ @Test
+ public void testPortraitPreservedWindowResizingDragTop() throws Exception {
+ final Rect r = new Rect(330, 100, 630, 600);
+ final int midX = (r.left + r.right) / 2;
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
+
+ // Drag to the left (no change).
+ mPositioner.resizeDrag(0.0f, r.top);
+ assertBoundsEquals(new Rect(r.left, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the right (no change).
+ mPositioner.resizeDrag(2000.0f, r.top);
+ assertBoundsEquals(new Rect(r.left , r.top + MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the top.
+ mPositioner.resizeDrag(300.0f, 0.0f);
+ int h = r.bottom - MOUSE_DELTA_Y;
+ int w = Math.min(r.width(), Math.round(h / MIN_ASPECT));
+ assertBoundsEquals(new Rect(r.left, MOUSE_DELTA_Y, r.left + w, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the bottom.
+ mPositioner.resizeDrag(r.left, 1000.0f);
+ h = Math.max(mMinVisibleHeight, Math.round(mMinVisibleWidth * MIN_ASPECT));
+ w = Math.round(h / MIN_ASPECT);
+ assertBoundsEquals(new Rect(r.left, r.bottom - h, r.left + w, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ private void assertBoundsEquals(Rect expected, Rect actual) {
+ if (DEBUGGING) {
+ if (!expected.equals(actual)) {
+ Log.e(TAG, "rect(" + actual.toString() + ") != isRect(" + actual.toString()
+ + ") " + Log.getStackTraceString(new Throwable()));
+ }
+ }
+ assertEquals(expected.left, actual.left);
+ assertEquals(expected.right, actual.right);
+ assertEquals(expected.top, actual.top);
+ assertEquals(expected.bottom, actual.bottom);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 36bd13a..a820eb1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -45,7 +45,6 @@
* runtest frameworks-services -c com.android.server.wm.UnknownVisibilityControllerTest
*/
@SmallTest
-@Presubmit
@RunWith(AndroidJUnit4.class)
public class UnknownAppVisibilityControllerTest {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java
index 5a035d6..c8650bf 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -25,14 +24,9 @@
import android.support.test.runner.AndroidJUnit4;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
/**
* Tests for the {@link WindowLayersController} class.
@@ -45,43 +39,6 @@
@RunWith(AndroidJUnit4.class)
public class WindowLayersControllerTests extends WindowTestsBase {
- private static boolean sOneTimeSetupDone = false;
- private static WindowLayersController sLayersController;
- private static DisplayContent sDisplayContent;
- private static WindowState sImeWindow;
- private static WindowState sImeDialogWindow;
- private static WindowState sStatusBarWindow;
- private static WindowState sDockedDividerWindow;
- private static WindowState sNavBarWindow;
- private static WindowState sAppWindow;
- private static WindowState sChildAppWindow;
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- if (sOneTimeSetupDone) {
- return;
- }
- sOneTimeSetupDone = true;
- sLayersController = new WindowLayersController(sWm);
- sDisplayContent =
- new DisplayContent(mDisplay, sWm, sLayersController, new WallpaperController(sWm));
- final WindowState wallpaperWindow =
- createWindow(null, TYPE_WALLPAPER, sDisplayContent, "wallpaperWindow");
- sImeWindow = createWindow(null, TYPE_INPUT_METHOD, sDisplayContent, "sImeWindow");
- sImeDialogWindow =
- createWindow(null, TYPE_INPUT_METHOD_DIALOG, sDisplayContent, "sImeDialogWindow");
- sStatusBarWindow = createWindow(null, TYPE_STATUS_BAR, sDisplayContent, "sStatusBarWindow");
- sNavBarWindow =
- createWindow(null, TYPE_NAVIGATION_BAR, sStatusBarWindow.mToken, "sNavBarWindow");
- sDockedDividerWindow =
- createWindow(null, TYPE_DOCK_DIVIDER, sDisplayContent, "sDockedDividerWindow");
- sAppWindow = createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "sAppWindow");
- sChildAppWindow = createWindow(sAppWindow,
- TYPE_APPLICATION_ATTACHED_DIALOG, sAppWindow.mToken, "sChildAppWindow");
- }
-
@Test
public void testAssignWindowLayers_ForImeWithNoTarget() throws Exception {
sWm.mInputMethodTarget = null;
@@ -90,7 +47,7 @@
// The Ime has an higher base layer than app windows and lower base layer than system
// windows, so it should be above app windows and below system windows if there isn't an IME
// target.
- assertWindowLayerGreaterThan(sImeWindow, sChildAppWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sChildAppWindowAbove);
assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
@@ -110,7 +67,63 @@
// Ime should be above all app windows and below system windows if it is targeting an app
// window.
assertWindowLayerGreaterThan(sImeWindow, imeAppTarget);
- assertWindowLayerGreaterThan(sImeWindow, sChildAppWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sChildAppWindowAbove);
+ assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
+ assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
+ assertWindowLayerGreaterThan(sStatusBarWindow, sImeWindow);
+
+ // And, IME dialogs should always have an higher layer than the IME.
+ assertWindowLayerGreaterThan(sImeDialogWindow, sImeWindow);
+ }
+
+ @Test
+ public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() throws Exception {
+ final WindowState imeAppTarget =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
+ final WindowState imeAppTargetChildAboveWindow = createWindow(imeAppTarget,
+ TYPE_APPLICATION_ATTACHED_DIALOG, imeAppTarget.mToken,
+ "imeAppTargetChildAboveWindow");
+ final WindowState imeAppTargetChildBelowWindow = createWindow(imeAppTarget,
+ TYPE_APPLICATION_MEDIA_OVERLAY, imeAppTarget.mToken,
+ "imeAppTargetChildBelowWindow");
+
+ sWm.mInputMethodTarget = imeAppTarget;
+ sLayersController.assignWindowLayers(sDisplayContent);
+
+ // Ime should be above all app windows except for child windows that are z-ordered above it
+ // and below system windows if it is targeting an app window.
+ assertWindowLayerGreaterThan(sImeWindow, imeAppTarget);
+ assertWindowLayerGreaterThan(imeAppTargetChildAboveWindow, sImeWindow);
+ assertWindowLayerGreaterThan(sImeWindow, imeAppTargetChildBelowWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sChildAppWindowAbove);
+ assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
+ assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
+ assertWindowLayerGreaterThan(sStatusBarWindow, sImeWindow);
+
+ // And, IME dialogs should always have an higher layer than the IME.
+ assertWindowLayerGreaterThan(sImeDialogWindow, sImeWindow);
+ }
+
+ @Test
+ public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() throws Exception {
+ final WindowState appBelowImeTarget =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "appBelowImeTarget");
+ final WindowState imeAppTarget =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
+ final WindowState appAboveImeTarget =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "appAboveImeTarget");
+
+ sWm.mInputMethodTarget = imeAppTarget;
+ sLayersController.assignWindowLayers(sDisplayContent);
+
+ // Ime should be above all app windows except for non-fullscreen app window above it and
+ // below system windows if it is targeting an app window.
+ assertWindowLayerGreaterThan(sImeWindow, imeAppTarget);
+ assertWindowLayerGreaterThan(sImeWindow, appBelowImeTarget);
+ assertWindowLayerGreaterThan(appAboveImeTarget, sImeWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sChildAppWindowAbove);
assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
@@ -131,7 +144,7 @@
// The IME target base layer is higher than all window except for the nav bar window, so the
// IME should be above all windows except for the nav bar.
assertWindowLayerGreaterThan(sImeWindow, imeSystemOverlayTarget);
- assertWindowLayerGreaterThan(sImeWindow, sChildAppWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sChildAppWindowAbove);
assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
assertWindowLayerGreaterThan(sImeWindow, sStatusBarWindow);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 50e5a22..df35b7e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -16,23 +16,18 @@
package com.android.server.wm;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import android.content.Context;
-import android.os.Binder;
import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.IWindow;
-import android.view.WindowManager;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -41,30 +36,19 @@
/**
* Tests for the {@link WindowState} class.
*
- * runtest frameworks-services -c com.android.server.wm.WindowStateTests
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.wm.WindowStateTests
*/
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public class WindowStateTests extends WindowTestsBase {
- private WindowToken mWindowToken;
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
- mWindowToken = new WindowToken(sWm, new Binder(), 0, false,
- sWm.getDefaultDisplayContentLocked());
- }
-
@Test
public void testIsParentWindowHidden() throws Exception {
- final WindowState parentWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
- final WindowState child1 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child1");
- final WindowState child2 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child2");
+ final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
+ final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
assertFalse(parentWindow.mHidden);
assertFalse(parentWindow.isParentWindowHidden());
@@ -79,14 +63,10 @@
@Test
public void testIsChildWindow() throws Exception {
- final WindowState parentWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
- final WindowState child1 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child1");
- final WindowState child2 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child2");
- final WindowState randomWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "randomWindow");
+ final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
+ final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
+ final WindowState randomWindow = createWindow(null, TYPE_APPLICATION, "randomWindow");
assertFalse(parentWindow.isChildWindow());
assertTrue(child1.isChildWindow());
@@ -96,13 +76,12 @@
@Test
public void testHasChild() throws Exception {
- final WindowState win1 = createWindow(null, TYPE_APPLICATION, mWindowToken, "win1");
- final WindowState win11 = createWindow(win1, FIRST_SUB_WINDOW, mWindowToken, "win11");
- final WindowState win12 = createWindow(win1, FIRST_SUB_WINDOW, mWindowToken, "win12");
- final WindowState win2 = createWindow(null, TYPE_APPLICATION, mWindowToken, "win2");
- final WindowState win21 = createWindow(win2, FIRST_SUB_WINDOW, mWindowToken, "win21");
- final WindowState randomWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "randomWindow");
+ final WindowState win1 = createWindow(null, TYPE_APPLICATION, "win1");
+ final WindowState win11 = createWindow(win1, FIRST_SUB_WINDOW, "win11");
+ final WindowState win12 = createWindow(win1, FIRST_SUB_WINDOW, "win12");
+ final WindowState win2 = createWindow(null, TYPE_APPLICATION, "win2");
+ final WindowState win21 = createWindow(win2, FIRST_SUB_WINDOW, "win21");
+ final WindowState randomWindow = createWindow(null, TYPE_APPLICATION, "randomWindow");
assertTrue(win1.hasChild(win11));
assertTrue(win1.hasChild(win12));
@@ -117,42 +96,10 @@
}
@Test
- public void testGetBottomChild() throws Exception {
- final WindowState parentWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
- assertNull(parentWindow.getBottomChild());
-
- final WindowState child1 =
- createWindow(parentWindow, TYPE_APPLICATION_PANEL, mWindowToken, "child1");
- assertEquals(child1, parentWindow.getBottomChild());
-
- final WindowState child2 =
- createWindow(parentWindow, TYPE_APPLICATION_PANEL, mWindowToken, "child2");
- // Since child1 and child2 are at the same layer, then child2 is expect to be added on top
- // on child1
- assertEquals(child1, parentWindow.getBottomChild());
-
- final WindowState child3 =
- createWindow(parentWindow, TYPE_APPLICATION_MEDIA_OVERLAY, mWindowToken, "child3");
- // Since child3 is a negative layer, we would expect it to be added below current children
- // with positive layers.
- assertEquals(child3, parentWindow.getBottomChild());
-
- final WindowState child4 =
- createWindow(parentWindow, TYPE_APPLICATION_MEDIA_OVERLAY, mWindowToken, "child4");
- // We would also expect additional negative layers to be added below existing negative
- // layers.
- assertEquals(child4, parentWindow.getBottomChild());
- }
-
- @Test
public void testGetParentWindow() throws Exception {
- final WindowState parentWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
- final WindowState child1 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child1");
- final WindowState child2 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child2");
+ final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
+ final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
assertNull(parentWindow.getParentWindow());
assertEquals(parentWindow, child1.getParentWindow());
@@ -161,22 +108,63 @@
@Test
public void testGetTopParentWindow() throws Exception {
- final WindowState root = createWindow(null, TYPE_APPLICATION, mWindowToken, "root");
- final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, mWindowToken, "child1");
- final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, mWindowToken, "child2");
+ final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
+ final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, "child1");
+ final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, "child2");
assertEquals(root, root.getTopParentWindow());
assertEquals(root, child1.getTopParentWindow());
assertEquals(child1, child2.getParentWindow());
assertEquals(root, child2.getTopParentWindow());
+
+ // Test case were child is detached from parent.
+ root.removeChild(child1);
+ assertEquals(child1, child1.getTopParentWindow());
+ assertEquals(child1, child2.getParentWindow());
}
@Test
public void testIsOnScreen_hiddenByPolicy() {
- final WindowState window = createWindow(null, TYPE_APPLICATION, mWindowToken, "window");
+ final WindowState window = createWindow(null, TYPE_APPLICATION, "window");
window.setHasSurface(true);
assertTrue(window.isOnScreen());
window.hideLw(false /* doAnimation */);
assertFalse(window.isOnScreen());
}
+
+ @Test
+ public void testCanBeImeTarget() throws Exception {
+ final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+ final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, "imeWindow");
+
+ // Setting FLAG_NOT_FOCUSABLE without FLAG_ALT_FOCUSABLE_IM prevents the window from being
+ // an IME target.
+ appWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+ imeWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+
+ // Make windows visible
+ appWindow.setHasSurface(true);
+ imeWindow.setHasSurface(true);
+
+ // Windows without flags (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) can't be IME targets
+ assertFalse(appWindow.canBeImeTarget());
+ assertFalse(imeWindow.canBeImeTarget());
+
+ // Add IME target flags
+ appWindow.mAttrs.flags |= (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
+ imeWindow.mAttrs.flags |= (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
+
+ // Visible app window with flags can be IME target while an IME window can never be an IME
+ // target regardless of its visibility or flags.
+ assertTrue(appWindow.canBeImeTarget());
+ assertFalse(imeWindow.canBeImeTarget());
+
+ // Make windows invisible
+ appWindow.hideLw(false /* doAnimation */);
+ imeWindow.hideLw(false /* doAnimation */);
+
+ // Invisible window can't be IME targets even if they have the right flags.
+ assertFalse(appWindow.canBeImeTarget());
+ assertFalse(imeWindow.canBeImeTarget());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 9681bd2..ab6968b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -22,7 +22,6 @@
import android.content.Context;
import android.os.IBinder;
import android.support.test.InstrumentationRegistry;
-import android.view.Display;
import android.view.IWindow;
import android.view.WindowManager;
@@ -31,6 +30,15 @@
import static android.content.res.Configuration.EMPTY;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static org.mockito.Mockito.mock;
/**
@@ -40,15 +48,49 @@
static WindowManagerService sWm = null;
private final IWindow mIWindow = new TestIWindow();
private final Session mMockSession = mock(Session.class);
- Display mDisplay;
private static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
private static int sNextTaskId = 0;
+ private static boolean sOneTimeSetupDone = false;
+ protected static DisplayContent sDisplayContent;
+ protected static WindowLayersController sLayersController;
+ protected static WindowState sWallpaperWindow;
+ protected static WindowState sImeWindow;
+ protected static WindowState sImeDialogWindow;
+ protected static WindowState sStatusBarWindow;
+ protected static WindowState sDockedDividerWindow;
+ protected static WindowState sNavBarWindow;
+ protected static WindowState sAppWindow;
+ protected static WindowState sChildAppWindowAbove;
+ protected static WindowState sChildAppWindowBelow;
+
@Before
public void setUp() throws Exception {
+ if (sOneTimeSetupDone) {
+ return;
+ }
+ sOneTimeSetupDone = true;
final Context context = InstrumentationRegistry.getTargetContext();
sWm = TestWindowManagerPolicy.getWindowManagerService(context);
- mDisplay = context.getDisplay();
+ sLayersController = new WindowLayersController(sWm);
+ sDisplayContent = new DisplayContent(context.getDisplay(), sWm, sLayersController,
+ new WallpaperController(sWm));
+
+ // Set-up some common windows.
+ sWallpaperWindow = createWindow(null, TYPE_WALLPAPER, sDisplayContent, "wallpaperWindow");
+ sImeWindow = createWindow(null, TYPE_INPUT_METHOD, sDisplayContent, "sImeWindow");
+ sImeDialogWindow =
+ createWindow(null, TYPE_INPUT_METHOD_DIALOG, sDisplayContent, "sImeDialogWindow");
+ sStatusBarWindow = createWindow(null, TYPE_STATUS_BAR, sDisplayContent, "sStatusBarWindow");
+ sNavBarWindow =
+ createWindow(null, TYPE_NAVIGATION_BAR, sStatusBarWindow.mToken, "sNavBarWindow");
+ sDockedDividerWindow =
+ createWindow(null, TYPE_DOCK_DIVIDER, sDisplayContent, "sDockedDividerWindow");
+ sAppWindow = createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "sAppWindow");
+ sChildAppWindowAbove = createWindow(sAppWindow,
+ TYPE_APPLICATION_ATTACHED_DIALOG, sAppWindow.mToken, "sChildAppWindowAbove");
+ sChildAppWindowBelow = createWindow(sAppWindow,
+ TYPE_APPLICATION_MEDIA_OVERLAY, sAppWindow.mToken, "sChildAppWindowBelow");
}
/** Asserts that the first entry is greater than the second entry. */
@@ -56,9 +98,9 @@
Assert.assertTrue("Excepted " + first + " to be greater than " + second, first > second);
}
- WindowToken createWindowToken(DisplayContent dc, int type) {
+ private WindowToken createWindowToken(DisplayContent dc, int type) {
if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
- return new WindowToken(sWm, mock(IBinder.class), type, false, dc);
+ return new TestWindowToken(type, dc);
}
final int stackId = sNextStackId++;
@@ -66,11 +108,17 @@
final TaskStack stack = sWm.mStackIdToStack.get(stackId);
final Task task = new Task(sNextTaskId++, stack, 0, sWm, null, EMPTY, false);
stack.addTask(task, true);
- final AppWindowToken token = new AppWindowToken(sWm, null, false, dc);
+ final TestAppWindowToken token = new TestAppWindowToken(dc);
task.addAppToken(0, token, 0, false);
return token;
}
+ WindowState createWindow(WindowState parent, int type, String name) {
+ return (parent == null)
+ ? createWindow(parent, type, sDisplayContent, name)
+ : createWindow(parent, type, parent.mToken, name);
+ }
+
WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) {
final WindowToken token = createWindowToken(dc, type);
return createWindow(parent, type, token, name);
@@ -87,4 +135,48 @@
token.addWindow(w);
return w;
}
+
+ /* Used so we can gain access to some protected members of the {@link WindowToken} class */
+ class TestWindowToken extends WindowToken {
+
+ TestWindowToken(int type, DisplayContent dc) {
+ this(type, dc, false /* persistOnEmpty */);
+ }
+
+ TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
+ super(sWm, mock(IBinder.class), type, persistOnEmpty, dc);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+ }
+
+ /* Used so we can gain access to some protected members of the {@link AppWindowToken} class */
+ class TestAppWindowToken extends AppWindowToken {
+
+ TestAppWindowToken(DisplayContent dc) {
+ super(sWm, null, false, dc);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+
+ WindowState getFirstChild() {
+ return mChildren.getFirst();
+ }
+
+ WindowState getLastChild() {
+ return mChildren.getLast();
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
index d6bfa17..0c053b9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -16,24 +16,19 @@
package com.android.server.wm;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import android.content.Context;
-import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.IWindow;
-import android.view.WindowManager;
-import static android.app.AppOpsManager.OP_NONE;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
@@ -51,7 +46,7 @@
@Test
public void testAddWindow() throws Exception {
- final TestWindowToken token = new TestWindowToken();
+ final TestWindowToken token = new TestWindowToken(0, sDisplayContent);
assertEquals(0, token.getWindowsCount());
@@ -80,15 +75,13 @@
@Test
public void testChildRemoval() throws Exception {
- final TestWindowToken token = new TestWindowToken();
- final DisplayContent dc = sWm.getDefaultDisplayContentLocked();
+ final DisplayContent dc = sDisplayContent;
+ final TestWindowToken token = new TestWindowToken(0, dc);
assertEquals(token, dc.getWindowToken(token.token));
final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
final WindowState window2 = createWindow(null, TYPE_APPLICATION, token, "window2");
- token.addWindow(window1);
- token.addWindow(window2);
window2.removeImmediately();
// The token should still be mapped in the display content since it still has a child.
@@ -102,17 +95,13 @@
@Test
public void testAdjustAnimLayer() throws Exception {
- final TestWindowToken token = new TestWindowToken();
+ final TestWindowToken token = new TestWindowToken(0, sDisplayContent);
final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11");
final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12");
final WindowState window2 = createWindow(null, TYPE_APPLICATION, token, "window2");
final WindowState window3 = createWindow(null, TYPE_APPLICATION, token, "window3");
- token.addWindow(window1);
- token.addWindow(window2);
- token.addWindow(window3);
-
final int adj = 50;
final int window2StartLayer = window2.mLayer = 100;
final int window3StartLayer = window3.mLayer = 200;
@@ -126,19 +115,39 @@
assertEquals(window3StartLayer + adj, highestLayer);
}
- /* Used so we can gain access to some protected members of the {@link WindowToken} class */
- private class TestWindowToken extends WindowToken {
+ /**
+ * Test that a window token isn't orphaned by the system when it is requested to be removed.
+ * Tokens should only be removed from the system when all their windows are gone.
+ */
+ @Test
+ public void testTokenRemovalProcess() throws Exception {
+ final TestWindowToken token =
+ new TestWindowToken(TYPE_TOAST, sDisplayContent, true /* persistOnEmpty */);
- TestWindowToken() {
- super(sWm, mock(IBinder.class), 0, false, sWm.getDefaultDisplayContentLocked());
- }
+ // Verify that the token is on the display
+ assertNotNull(sDisplayContent.getWindowToken(token.token));
- int getWindowsCount() {
- return mChildren.size();
- }
+ final WindowState window1 = createWindow(null, TYPE_TOAST, token, "window1");
+ final WindowState window2 = createWindow(null, TYPE_TOAST, token, "window2");
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
+ sDisplayContent.removeWindowToken(token.token);
+ // Verify that the token is no longer mapped on the display
+ assertNull(sDisplayContent.getWindowToken(token.token));
+ // Verify that the token is still attached to its parent
+ assertNotNull(token.getParent());
+ // Verify that the token windows are still around.
+ assertEquals(2, token.getWindowsCount());
+
+ window1.removeImmediately();
+ // Verify that the token is still attached to its parent
+ assertNotNull(token.getParent());
+ // Verify that the other token window is still around.
+ assertEquals(1, token.getWindowsCount());
+
+ window2.removeImmediately();
+ // Verify that the token is no-longer attached to its parent
+ assertNull(token.getParent());
+ // Verify that the token windows are no longer attached to it.
+ assertEquals(0, token.getWindowsCount());
}
}
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index 1fe5cb7..6e74deb 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -764,6 +764,12 @@
filter(mList, ShortcutInfo::isPinned));
}
+ public ShortcutListAsserter selectFloating() {
+ return new ShortcutListAsserter(this,
+ filter(mList, (si -> si.isPinned()
+ && !(si.isDynamic() || si.isDeclaredInManifest()))));
+ }
+
public ShortcutListAsserter selectByActivity(ComponentName activity) {
return new ShortcutListAsserter(this,
ShortcutManagerTestUtils.filterByActivity(mList, activity));
@@ -895,6 +901,11 @@
return this;
}
+ public ShortcutListAsserter areAllWithNoActivity() {
+ forAllShortcuts(s -> assertNull("id=" + s.getId(), s.getActivity()));
+ return this;
+ }
+
public ShortcutListAsserter forAllShortcuts(Consumer<ShortcutInfo> sa) {
boolean found = false;
for (int i = 0; i < mList.size(); i++) {
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index a012082..177759e 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -28,6 +28,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
@@ -453,6 +454,10 @@
* @param conferenceableConnections The set of connections this connection can conference with.
*/
public final void setConferenceableConnections(List<Connection> conferenceableConnections) {
+ if (Objects.equals(mConferenceableConnections, conferenceableConnections)) {
+ return;
+ }
+
clearConferenceableList();
for (Connection c : conferenceableConnections) {
// If statement checks for duplicates in input. It makes it N^2 but we're dealing with a
diff --git a/telecomm/java/android/telecom/DefaultDialerManager.java b/telecomm/java/android/telecom/DefaultDialerManager.java
index a5e8fe1..cd65232 100644
--- a/telecomm/java/android/telecom/DefaultDialerManager.java
+++ b/telecomm/java/android/telecom/DefaultDialerManager.java
@@ -118,7 +118,7 @@
String defaultPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
- final List<String> packageNames = getInstalledDialerApplications(context);
+ final List<String> packageNames = getInstalledDialerApplications(context, user);
// Verify that the default dialer has not been disabled or uninstalled.
if (packageNames.contains(defaultPackageName)) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index d7f96a9..e6354b7 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -73,6 +73,15 @@
KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
/**
+ * When checking if a given number is the voicemail number, if this flag is true
+ * then in addition to comparing the given number to the voicemail number, we also compare it
+ * to the mdn. If this flag is false, the given number is only compared to the voicemail number.
+ * By default this value is false.
+ */
+ public static final String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL =
+ "mdn_is_additional_voicemail_number_bool";
+
+ /**
* Flag indicating whether the Phone app should provide a "Dismiss" button on the SIM network
* unlock screen. The default value is true. If set to false, there will be *no way* to dismiss
* the SIM network unlock screen if you don't enter the correct unlock code. (One important
@@ -649,6 +658,24 @@
public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
/**
+ * Determines whether a maximum size limit for IMS conference calls is enforced on the device.
+ * When {@code true}, IMS conference calls will be limited to at most
+ * {@link #KEY_IMS_CONFERENCE_SIZE_LIMIT_INT} participants. When {@code false}, no attempt is made
+ * to limit the number of participants in a conference (the carrier will raise an error when an
+ * attempt is made to merge too many participants into a conference).
+ */
+ public static final String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL =
+ "is_ims_conference_size_enforced_bool";
+
+ /**
+ * Determines the maximum number of participants the carrier supports for a conference call.
+ * This number is exclusive of the current device. A conference between 3 devices, for example,
+ * would have a size limit of 2 participants.
+ * Enforced when {@link #KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL} is {@code true}.
+ */
+ public static final String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
+
+ /**
* Determines whether High Definition audio property is displayed in the dialer UI.
* If {@code false}, remove the HD audio property from the connection so that HD audio related
* UI is not displayed. If {@code true}, keep HD audio property as it is configured.
@@ -1103,6 +1130,14 @@
*/
public static final String KEY_CARRIER_WIFI_STRING_ARRAY = "carrier_wifi_string_array";
+ /**
+ * Time delay (in ms) after which we show the notification to switch the preferred
+ * network.
+ * @hide
+ */
+ public static final String KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT =
+ "network_notification_delay_int";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -1148,6 +1183,7 @@
sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false);
sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false);
+ sDefaults.putBoolean(KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL, false);
sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
sDefaults.putBoolean(KEY_PREFER_2G_BOOL, true);
sDefaults.putBoolean(KEY_SHOW_APN_SETTING_CDMA_BOOL, false);
@@ -1222,6 +1258,8 @@
sDefaults.putInt(KEY_CDMA_3WAYCALL_FLASH_DELAY_INT , 0);
sDefaults.putBoolean(KEY_SUPPORT_CONFERENCE_CALL_BOOL, true);
sDefaults.putBoolean(KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL, false);
+ sDefaults.putBoolean(KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL, false);
+ sDefaults.putInt(KEY_IMS_CONFERENCE_SIZE_LIMIT_INT, 5);
sDefaults.putBoolean(KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL, true);
sDefaults.putBoolean(KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, true);
sDefaults.putBoolean(KEY_HIDE_IMS_APN_BOOL, false);
@@ -1301,6 +1339,7 @@
sDefaults.putBoolean(KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL, false);
sDefaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, false);
sDefaults.putStringArray(KEY_CARRIER_WIFI_STRING_ARRAY, null);
+ sDefaults.putInt(KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT, -1);
}
/**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 152b868..6f51c6e 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -29,6 +29,7 @@
import android.location.CountryDetector;
import android.net.Uri;
import android.os.SystemProperties;
+import android.os.PersistableBundle;
import android.provider.Contacts;
import android.provider.ContactsContract;
import android.telecom.PhoneAccount;
@@ -2106,7 +2107,7 @@
* number provided by the RIL and SIM card. The caller must have
* the READ_PHONE_STATE credential.
*
- * @param context a non-null {@link Context}.
+ * @param context {@link Context}.
* @param subId the subscription id of the SIM.
* @param number the number to look up.
* @return true if the number is in the list of voicemail. False
@@ -2115,25 +2116,54 @@
* @hide
*/
public static boolean isVoiceMailNumber(Context context, int subId, String number) {
- String vmNumber;
+ String vmNumber, mdn;
try {
final TelephonyManager tm;
if (context == null) {
tm = TelephonyManager.getDefault();
+ if (DBG) log("isVoiceMailNumber: default tm");
} else {
tm = TelephonyManager.from(context);
+ if (DBG) log("isVoiceMailNumber: tm from context");
}
vmNumber = tm.getVoiceMailNumber(subId);
+ mdn = tm.getLine1Number(subId);
+ if (DBG) log("isVoiceMailNumber: mdn=" + mdn + ", vmNumber=" + vmNumber
+ + ", number=" + number);
} catch (SecurityException ex) {
+ if (DBG) log("isVoiceMailNumber: SecurityExcpetion caught");
return false;
}
// Strip the separators from the number before comparing it
// to the list.
number = extractNetworkPortionAlt(number);
+ if (TextUtils.isEmpty(number)) {
+ if (DBG) log("isVoiceMailNumber: number is empty after stripping");
+ return false;
+ }
- // compare tolerates null so we need to make sure that we
- // don't return true when both are null.
- return !TextUtils.isEmpty(number) && compare(number, vmNumber);
+ // check if the carrier considers MDN to be an additional voicemail number
+ boolean compareWithMdn = false;
+ if (context != null) {
+ CarrierConfigManager configManager = (CarrierConfigManager)
+ context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configManager != null) {
+ PersistableBundle b = configManager.getConfigForSubId(subId);
+ if (b != null) {
+ compareWithMdn = b.getBoolean(CarrierConfigManager.
+ KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL);
+ if (DBG) log("isVoiceMailNumber: compareWithMdn=" + compareWithMdn);
+ }
+ }
+ }
+
+ if (compareWithMdn) {
+ if (DBG) log("isVoiceMailNumber: treating mdn as additional vm number");
+ return compare(number, vmNumber) || compare(number, mdn);
+ } else {
+ if (DBG) log("isVoiceMailNumber: returning regular compare");
+ return compare(number, vmNumber);
+ }
}
/**
diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
index 39e83c6..0da27e1 100644
--- a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
+++ b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
@@ -43,7 +43,7 @@
oneway interface IImsVideoCallProvider {
void setCallback(IImsVideoCallCallback callback);
- void setCamera(String cameraId);
+ void setCamera(String cameraId, int uid);
void setPreviewSurface(in Surface surface);
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index d4104bd..20c303e 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -438,7 +438,7 @@
// check to see if these are recognized numbers, and use shortcuts if we can.
if (PhoneNumberUtils.isLocalEmergencyNumber(context, number)) {
cw.event = EVENT_EMERGENCY_NUMBER;
- } else if (PhoneNumberUtils.isVoiceMailNumber(subId, number)) {
+ } else if (PhoneNumberUtils.isVoiceMailNumber(context, subId, number)) {
cw.event = EVENT_VOICEMAIL_NUMBER;
} else {
cw.event = EVENT_NEW_QUERY;
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 6115656..fe37531 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -447,4 +447,16 @@
void sendStoredMultipartText(int subId, String callingPkg, in Uri messageUri,
String scAddress, in List<PendingIntent> sentIntents,
in List<PendingIntent> deliveryIntents);
+
+ /**
+ * Create an app-only incoming SMS request for the calling package.
+ *
+ * If an incoming text contains the token returned by this method the provided
+ * <code>PendingIntent</code> will be sent containing the SMS data.
+ *
+ * @param subId the SIM id.
+ * @param callingPkg the package name of the calling app.
+ * @param intent PendingIntent to be sent when an SMS is received containing the token.
+ */
+ String createAppSpecificSmsToken(int subId, String callingPkg, in PendingIntent intent);
}
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 68bde35..a317994 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -20,7 +20,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := core-oj core-libart core-junit framework
+LOCAL_JAVA_LIBRARIES := core-oj core-libart junit framework
LOCAL_STATIC_JAVA_LIBRARIES := junit-runner
LOCAL_MODULE:= android.test.runner
diff --git a/test-runner/src/android/test/mock/MockContentProvider.java b/test-runner/src/android/test/mock/MockContentProvider.java
index e443911..d5f3ce8 100644
--- a/test-runner/src/android/test/mock/MockContentProvider.java
+++ b/test-runner/src/android/test/mock/MockContentProvider.java
@@ -16,6 +16,7 @@
package android.test.mock;
+import android.annotation.Nullable;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@@ -97,11 +98,11 @@
}
@Override
- public Cursor query(String callingPackage, Uri url, String[] projection, String selection,
- String[] selectionArgs,
- String sortOrder, ICancellationSignal cancellationSignal) throws RemoteException {
- return MockContentProvider.this.query(url, projection, selection,
- selectionArgs, sortOrder);
+ public Cursor query(String callingPackage, Uri url, @Nullable String[] projection,
+ @Nullable Bundle queryArgs,
+ @Nullable ICancellationSignal cancellationSignal)
+ throws RemoteException {
+ return MockContentProvider.this.query(url, projection, queryArgs, null);
}
@Override
@@ -248,10 +249,12 @@
throw new UnsupportedOperationException("unimplemented mock method call");
}
+ @Override
public String[] getStreamTypes(Uri url, String mimeTypeFilter) {
throw new UnsupportedOperationException("unimplemented mock method call");
}
+ @Override
public AssetFileDescriptor openTypedAssetFile(Uri url, String mimeType, Bundle opts) {
throw new UnsupportedOperationException("unimplemented mock method call");
}
diff --git a/test-runner/src/android/test/mock/MockIContentProvider.java b/test-runner/src/android/test/mock/MockIContentProvider.java
index 09d45d1..112d7ee 100644
--- a/test-runner/src/android/test/mock/MockIContentProvider.java
+++ b/test-runner/src/android/test/mock/MockIContentProvider.java
@@ -16,6 +16,7 @@
package android.test.mock;
+import android.annotation.Nullable;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
@@ -41,45 +42,52 @@
* @hide - @hide because this exposes bulkQuery() and call(), which must also be hidden.
*/
public class MockIContentProvider implements IContentProvider {
+ @Override
public int bulkInsert(String callingPackage, Uri url, ContentValues[] initialValues) {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
@SuppressWarnings("unused")
public int delete(String callingPackage, Uri url, String selection, String[] selectionArgs)
throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public String getType(Uri url) {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
@SuppressWarnings("unused")
public Uri insert(String callingPackage, Uri url, ContentValues initialValues)
throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public ParcelFileDescriptor openFile(
String callingPackage, Uri url, String mode, ICancellationSignal signal,
IBinder callerToken) {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public AssetFileDescriptor openAssetFile(
String callingPackage, Uri uri, String mode, ICancellationSignal signal) {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public ContentProviderResult[] applyBatch(String callingPackage,
ArrayList<ContentProviderOperation> operations) {
throw new UnsupportedOperationException("unimplemented mock method");
}
- public Cursor query(String callingPackage, Uri url, String[] projection, String selection,
- String[] selectionArgs,
- String sortOrder, ICancellationSignal cancellationSignal) {
+ @Override
+ public Cursor query(String callingPackage, Uri url, @Nullable String[] projection,
+ @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -88,24 +96,29 @@
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public int update(String callingPackage, Uri url, ContentValues values, String selection,
String[] selectionArgs) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public Bundle call(String callingPackage, String method, String request, Bundle args)
throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public IBinder asBinder() {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public AssetFileDescriptor openTypedAssetFile(String callingPackage, Uri url, String mimeType,
Bundle opts, ICancellationSignal signal) throws RemoteException, FileNotFoundException {
throw new UnsupportedOperationException("unimplemented mock method");
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 3785cdc..b4f3d69 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -989,5 +989,15 @@
</intent-filter>
</activity>
+ <activity
+ android:name="PixelCopyWindow"
+ android:label="Readback/Window"
+ android:screenOrientation="fullSensor">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.hwui.TEST" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PixelCopyWindow.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PixelCopyWindow.java
new file mode 100644
index 0000000..a039fba
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PixelCopyWindow.java
@@ -0,0 +1,98 @@
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Paint.Style;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.view.PixelCopy;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class PixelCopyWindow extends Activity {
+
+ private Handler mHandler;
+ private ImageView mImage;
+ private TextView mText;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mHandler = new Handler();
+
+ LinearLayout layout = new LinearLayout(this);
+ TextView text = new TextView(this);
+ text.setText("Hello, World!");
+ Button btn = new Button(this);
+ btn.setText("Screenshot!");
+ btn.setOnClickListener((v) -> takeScreenshot());
+ mImage = new ImageView(this);
+ mText = new TextView(this);
+
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.addView(text);
+ layout.addView(btn);
+ layout.addView(mImage);
+ layout.addView(mText);
+ final float density = getResources().getDisplayMetrics().density;
+ layout.setBackground(new Drawable() {
+ Paint mPaint = new Paint();
+
+ @Override
+ public void draw(Canvas canvas) {
+ mPaint.setStyle(Style.STROKE);
+ mPaint.setStrokeWidth(4 * density);
+ mPaint.setColor(Color.BLUE);
+ final Rect bounds = getBounds();
+ canvas.drawRect(bounds, mPaint);
+ mPaint.setColor(Color.RED);
+ canvas.drawLine(bounds.centerX(), 0, bounds.centerX(), bounds.height(), mPaint);
+ mPaint.setColor(Color.GREEN);
+ canvas.drawLine(0, bounds.centerY(), bounds.width(), bounds.centerY(), mPaint);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+ });
+ setContentView(layout);
+ }
+
+ private void takeScreenshot() {
+ View decor = getWindow().getDecorView();
+ Rect srcRect = new Rect();
+ decor.getGlobalVisibleRect(srcRect);
+ final Bitmap bitmap = Bitmap.createBitmap(
+ (int) (srcRect.width() * .25), (int) (srcRect.height() * .25), Config.ARGB_8888);
+ PixelCopy.request(getWindow(), srcRect, bitmap, (result) -> {
+ if (result != PixelCopy.SUCCESS) {
+ mText.setText("Copy failed, result: " + result);
+ mImage.setImageBitmap(null);
+ } else {
+ mText.setText("");
+ mImage.setImageBitmap(bitmap);
+ }
+ }, mHandler);
+ }
+}
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 51adfe7..ff61754 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -661,9 +661,13 @@
// The IPv6 all nodes address ff02::1
private static final byte[] IPV6_ALL_NODES_ADDRESS =
{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+ private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
+ { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
+ private static final int ICMP6_ROUTER_SOLICITATION = 133;
private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
+ private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
private static final int ICMP6_RA_HEADER_LEN = 16;
@@ -798,6 +802,12 @@
put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
assertDrop(program, packet.array());
+ // Verify ICMPv6 RS to any is dropped
+ packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
+ assertDrop(program, packet.array());
+ put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
+ assertDrop(program, packet.array());
+
apfFilter.shutdown();
}
diff --git a/tools/aapt2/.clang-format b/tools/aapt2/.clang-format
index 545366a..71c5ef2 100644
--- a/tools/aapt2/.clang-format
+++ b/tools/aapt2/.clang-format
@@ -1,2 +1,3 @@
BasedOnStyle: Google
+ColumnLimit: 100
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index a3404e5..a2b216d 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -25,7 +25,7 @@
static const char* sMajorVersion = "2";
// Update minor version whenever a feature or flag is added.
-static const char* sMinorVersion = "3";
+static const char* sMinorVersion = "4";
int PrintVersion() {
std::cerr << "Android Asset Packaging Tool (aapt) " << sMajorVersion << "."
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 36a3494..4185937e6 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -216,6 +216,8 @@
manifest_action["supports-gl-texture"];
+ manifest_action["meta-data"] = meta_data_action;
+
// Application actions.
xml::XmlNodeAction& application_action = manifest_action["application"];
application_action.Action(OptionalNameIsJavaClassName);
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index e9bc64a..fc6970c 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -87,6 +87,23 @@
EXPECT_EQ(nullptr, Verify("<manifest package=\"@string/str\" />"));
}
+TEST_F(ManifestFixerTest, AllowMetaData) {
+ auto doc = Verify(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <meta-data />
+ <application>
+ <meta-data />
+ <activity android:name=".Hi"><meta-data /></activity>
+ <activity-alias android:name=".Ho"><meta-data /></activity-alias>
+ <receiver android:name=".OffToWork"><meta-data /></receiver>
+ <provider android:name=".We"><meta-data /></provider>
+ <service android:name=".Go"><meta-data /></service>
+ </application>
+ </manifest>)EOF");
+ ASSERT_NE(nullptr, doc);
+}
+
TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
ManifestFixerOptions options = {std::string("8"), std::string("22")};
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index ac411b1..8001033 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,5 +1,9 @@
# Android Asset Packaging Tool 2.0 (AAPT2) release notes
+## Version 2.4
+### `aapt2 link ...`
+- Supports `<meta-data>` tags in `<manifest>`.
+
## Version 2.3
### `aapt2`
- Support new `font` resource type.
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 9da65a6..35cf903 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -80,7 +80,7 @@
public BridgeTypedArray(Resources resources, BridgeContext context, int len,
boolean platformFile) {
- super(resources, null, null, 0);
+ super(resources);
mBridgeResources = resources;
mContext = context;
mPlatformFile = platformFile;
diff --git a/tools/layoutlib/bridge/src/android/view/SurfaceView.java b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
index 1e7dfbe..ebb2af4 100644
--- a/tools/layoutlib/bridge/src/android/view/SurfaceView.java
+++ b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.graphics.Region;
import android.util.AttributeSet;
/**
@@ -49,6 +50,19 @@
super(context, attrs, defStyleAttr, defStyleRes);
}
+ public boolean gatherTransparentRegion(Region region) {
+ return false;
+ }
+
+ public void setZOrderMediaOverlay(boolean isMediaOverlay) {
+ }
+
+ public void setZOrderOnTop(boolean onTop) {
+ }
+
+ public void setSecure(boolean isSecure) {
+ }
+
public SurfaceHolder getHolder() {
return mSurfaceHolder;
}
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
index ffce1a0..da1ab27 100644
--- a/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
@@ -19,6 +19,7 @@
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import android.graphics.Path;
import android.util.MathUtils;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
@@ -31,6 +32,7 @@
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
+import android.view.animation.PathInterpolator;
/**
* Delegate used to provide new implementation of a select few methods of {@link
@@ -93,6 +95,16 @@
return sManager.addNewDelegate(new OvershootInterpolator(tension));
}
+ @LayoutlibDelegate
+ /*package*/ static long createPathInterpolator(float[] x, float[] y) {
+ Path path = new Path();
+ path.moveTo(x[0], y[0]);
+ for (int i = 1; i < x.length; i++) {
+ path.lineTo(x[i], y[i]);
+ }
+ return sManager.addNewDelegate(new PathInterpolator(path));
+ }
+
private static class LutInterpolator extends BaseInterpolator {
private final float[] mValues;
private final int mSize;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
index 3471165..c827f17 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
@@ -97,8 +97,8 @@
}
@Override
- public Cursor query(String callingPackage, Uri arg0, String[] arg1, String arg2, String[] arg3,
- String arg4, ICancellationSignal arg5) throws RemoteException {
+ public Cursor query(String callingPackage, Uri arg0, String[] arg1,
+ Bundle arg3, ICancellationSignal arg4) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
diff --git a/tools/preload2/Android.mk b/tools/preload2/Android.mk
index 769db6b..d3ee1d3 100644
--- a/tools/preload2/Android.mk
+++ b/tools/preload2/Android.mk
@@ -17,6 +17,8 @@
LOCAL_MODULE:= preload2
include $(BUILD_HOST_JAVA_LIBRARY)
+# Copy to build artifacts
+$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE):$(LOCAL_MODULE).jar)
# Copy the preload-tool shell script to the host's bin directory.
include $(CLEAR_VARS)
diff --git a/tools/streaming_proto/main.cpp b/tools/streaming_proto/main.cpp
index 5435728..5b4ba04 100644
--- a/tools/streaming_proto/main.cpp
+++ b/tools/streaming_proto/main.cpp
@@ -94,7 +94,7 @@
* Figure out the name of the file we are generating.
*/
static string
-make_file_name(const FileDescriptorProto& file_descriptor)
+make_file_name(const FileDescriptorProto& file_descriptor, const string& class_name)
{
string const package = make_java_package(file_descriptor);
string result;
@@ -103,7 +103,7 @@
result += '/';
}
- result += make_outer_class_name(file_descriptor);
+ result += class_name;
result += ".java";
return result;
@@ -320,10 +320,16 @@
/**
* Write the contents of a file.
+ *
+ * If there are enums and generate_outer is false, invalid java code will be generated.
*/
static void
-write_file(stringstream& text, const FileDescriptorProto& file_descriptor)
+write_file(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor,
+ const string& filename, bool generate_outer,
+ const vector<EnumDescriptorProto>& enums, const vector<DescriptorProto>& messages)
{
+ stringstream text;
+
string const package_name = make_java_package(file_descriptor);
string const outer_class_name = make_outer_class_name(file_descriptor);
@@ -338,27 +344,92 @@
}
// This bit of policy is android api rules specific: Raw proto classes
- // must never be in the API, but they should all be available for testing.
+ // must never be in the API
text << "/** @hide */" << endl;
- text << "@android.annotation.TestApi" << endl;
+// text << "@android.annotation.TestApi" << endl;
- text << "public final class " << outer_class_name << " {" << endl;
- text << endl;
+ if (generate_outer) {
+ text << "public final class " << outer_class_name << " {" << endl;
+ text << endl;
+ }
- int N;
- const string indented = indent_more("");
+ size_t N;
+ const string indented = generate_outer ? indent_more("") : string();
+ N = enums.size();
+ for (size_t i=0; i<N; i++) {
+ write_enum(text, enums[i], indented);
+ }
+
+ N = messages.size();
+ for (size_t i=0; i<N; i++) {
+ write_message(text, messages[i], indented);
+ }
+
+ if (generate_outer) {
+ text << "}" << endl;
+ }
+
+ CodeGeneratorResponse::File* file_response = response->add_file();
+ file_response->set_name(filename);
+ file_response->set_content(text.str());
+}
+
+/**
+ * Write one file per class. Put all of the enums into the "outer" class.
+ */
+static void
+write_multiple_files(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor)
+{
+ // If there is anything to put in the outer class file, create one
+ if (file_descriptor.enum_type_size() > 0) {
+ vector<EnumDescriptorProto> enums;
+ int N = file_descriptor.enum_type_size();
+ for (int i=0; i<N; i++) {
+ enums.push_back(file_descriptor.enum_type(i));
+ }
+
+ vector<DescriptorProto> messages;
+
+ write_file(response, file_descriptor,
+ make_file_name(file_descriptor, make_outer_class_name(file_descriptor)),
+ true, enums, messages);
+ }
+
+ // For each of the message types, make a file
+ int N = file_descriptor.message_type_size();
+ for (int i=0; i<N; i++) {
+ vector<EnumDescriptorProto> enums;
+
+ vector<DescriptorProto> messages;
+ messages.push_back(file_descriptor.message_type(i));
+
+ write_file(response, file_descriptor,
+ make_file_name(file_descriptor, file_descriptor.message_type(i).name()),
+ false, enums, messages);
+ }
+}
+
+static void
+write_single_file(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor)
+{
+ int N;
+
+ vector<EnumDescriptorProto> enums;
N = file_descriptor.enum_type_size();
for (int i=0; i<N; i++) {
- write_enum(text, file_descriptor.enum_type(i), indented);
+ enums.push_back(file_descriptor.enum_type(i));
}
+ vector<DescriptorProto> messages;
N = file_descriptor.message_type_size();
for (int i=0; i<N; i++) {
- write_message(text, file_descriptor.message_type(i), indented);
+ messages.push_back(file_descriptor.message_type(i));
}
- text << "}" << endl;
+ write_file(response, file_descriptor,
+ make_file_name(file_descriptor, make_outer_class_name(file_descriptor)),
+ true, enums, messages);
}
/**
@@ -383,16 +454,11 @@
for (int i=0; i<N; i++) {
const FileDescriptorProto& file_descriptor = request.proto_file(i);
if (should_generate_for_file(request, file_descriptor.name())) {
- // Generate the text
- stringstream text;
- write_file(text, file_descriptor);
-
- // Put the text in the response
- CodeGeneratorResponse::File* file_response = response.add_file();
- file_response->set_name(make_file_name(file_descriptor));
- file_response->set_content(text.str());
-
- cerr << "writing file: " << file_response->name() << endl;
+ if (file_descriptor.options().java_multiple_files()) {
+ write_multiple_files(&response, file_descriptor);
+ } else {
+ write_single_file(&response, file_descriptor);
+ }
}
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 82d41e3..43e6246 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -98,10 +98,22 @@
*/
public static final int OSEN = 5;
+ /**
+ * IEEE 802.11r Fast BSS Transition with PSK authentication.
+ * @hide
+ */
+ public static final int FT_PSK = 6;
+
+ /**
+ * IEEE 802.11r Fast BSS Transition with EAP authentication.
+ * @hide
+ */
+ public static final int FT_EAP = 7;
+
public static final String varName = "key_mgmt";
public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X",
- "WPA2_PSK", "OSEN" };
+ "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" };
}
/**
@@ -734,50 +746,6 @@
@SystemApi
public int numAssociation;
- /**
- * @hide
- * Number of time user disabled WiFi while associated to this configuration with Low RSSI.
- */
- public int numUserTriggeredWifiDisableLowRSSI;
-
- /**
- * @hide
- * Number of time user disabled WiFi while associated to this configuration with Bad RSSI.
- */
- public int numUserTriggeredWifiDisableBadRSSI;
-
- /**
- * @hide
- * Number of time user disabled WiFi while associated to this configuration
- * and RSSI was not HIGH.
- */
- public int numUserTriggeredWifiDisableNotHighRSSI;
-
- /**
- * @hide
- * Number of ticks associated to this configuration with Low RSSI.
- */
- public int numTicksAtLowRSSI;
-
- /**
- * @hide
- * Number of ticks associated to this configuration with Bad RSSI.
- */
- public int numTicksAtBadRSSI;
-
- /**
- * @hide
- * Number of ticks associated to this configuration
- * and RSSI was not HIGH.
- */
- public int numTicksAtNotHighRSSI;
- /**
- * @hide
- * Number of time user (WifiManager) triggered association to this configuration.
- * TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps
- */
- public int numUserTriggeredJoinAttempts;
-
/** @hide
* Boost given to RSSI on a home network for the purpose of calculating the score
* This adds stickiness to home networks, as defined by:
@@ -1618,16 +1586,6 @@
sbuf.append('\n');
}
}
- sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI);
- sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI);
- sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI);
- sbuf.append('\n');
- sbuf.append("ticksLow: ").append(this.numTicksAtLowRSSI);
- sbuf.append(" ticksBad: ").append(this.numTicksAtBadRSSI);
- sbuf.append(" ticksNotHigh: ").append(this.numTicksAtNotHighRSSI);
- sbuf.append('\n');
- sbuf.append("triggeredJoin: ").append(this.numUserTriggeredJoinAttempts);
- sbuf.append('\n');
return sbuf.toString();
}
@@ -1934,13 +1892,6 @@
numScorerOverride = source.numScorerOverride;
numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
numAssociation = source.numAssociation;
- numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI;
- numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI;
- numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI;
- numTicksAtLowRSSI = source.numTicksAtLowRSSI;
- numTicksAtBadRSSI = source.numTicksAtBadRSSI;
- numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI;
- numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts;
userApproved = source.userApproved;
numNoInternetAccessReports = source.numNoInternetAccessReports;
noInternetAccessExpected = source.noInternetAccessExpected;
@@ -2006,13 +1957,6 @@
dest.writeInt(numScorerOverride);
dest.writeInt(numScorerOverrideAndSwitchedNetwork);
dest.writeInt(numAssociation);
- dest.writeInt(numUserTriggeredWifiDisableLowRSSI);
- dest.writeInt(numUserTriggeredWifiDisableBadRSSI);
- dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI);
- dest.writeInt(numTicksAtLowRSSI);
- dest.writeInt(numTicksAtBadRSSI);
- dest.writeInt(numTicksAtNotHighRSSI);
- dest.writeInt(numUserTriggeredJoinAttempts);
dest.writeInt(userApproved);
dest.writeInt(numNoInternetAccessReports);
dest.writeInt(noInternetAccessExpected ? 1 : 0);
@@ -2078,13 +2022,6 @@
config.numScorerOverride = in.readInt();
config.numScorerOverrideAndSwitchedNetwork = in.readInt();
config.numAssociation = in.readInt();
- config.numUserTriggeredWifiDisableLowRSSI = in.readInt();
- config.numUserTriggeredWifiDisableBadRSSI = in.readInt();
- config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt();
- config.numTicksAtLowRSSI = in.readInt();
- config.numTicksAtBadRSSI = in.readInt();
- config.numTicksAtNotHighRSSI = in.readInt();
- config.numUserTriggeredJoinAttempts = in.readInt();
config.userApproved = in.readInt();
config.numNoInternetAccessReports = in.readInt();
config.noInternetAccessExpected = in.readInt() != 0;
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index bf35445..0fe69a8 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -405,7 +405,7 @@
* single match session (corresponding to the same publish action on the
* peer) reported to the host (using the
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], byte[])}). The options are: only report the first match and ignore the rest
+ * byte[], List)}). The options are: only report the first match and ignore the rest
* {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single
* match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default).
*
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
index 95d128d..092aa34 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
@@ -70,8 +70,8 @@
/**
* Returns the maximum length of byte array that can be used to specify a Aware match filter.
* Restricts the parameters of the
- * {@link PublishConfig.Builder#setMatchFilter(java.util.List<byte[]>)} and
- * {@link SubscribeConfig.Builder#setMatchFilter(java.util.List<byte[]>)}.
+ * {@link PublishConfig.Builder#setMatchFilter(java.util.List)} and
+ * {@link SubscribeConfig.Builder#setMatchFilter(java.util.List)}.
*
* @return A positive integer, maximum legngth of byte array for Aware discovery match filter.
*/
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java b/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
index 451d8a5..2812ad4 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
@@ -140,7 +140,7 @@
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} event.
+ * byte[], java.util.List)} event.
* <p>
* Aware messages are not guaranteed delivery. Callbacks on
* {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
@@ -154,7 +154,7 @@
*
* @param peerHandle The peer's handle for the message. Must be a result of an
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} or
+ * byte[], java.util.List)} or
* {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
* byte[])} events.
* @param messageId An arbitrary integer used by the caller to identify the message. The same
@@ -187,7 +187,7 @@
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} event.
+ * byte[], java.util.List)} event.
* <p>
* Aware messages are not guaranteed delivery. Callbacks on
* {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
@@ -203,7 +203,7 @@
*
* @param peerHandle The peer's handle for the message. Must be a result of an
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} or
+ * byte[], java.util.List)} or
* {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
* byte[])} events.
* @param messageId An arbitrary integer used by the caller to identify the message. The same
@@ -220,7 +220,7 @@
/**
* Start a ranging operation with the specified peers. The peer IDs are obtained from an
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} or
+ * byte[], java.util.List)} or
* {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
* byte[])} operation - can
* only range devices which are part of an ongoing discovery session.
@@ -266,7 +266,7 @@
*
* @param peerHandle The peer's handle obtained through
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} or
+ * byte[], java.util.List)} or
* {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
* byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
* from only that peer. A RESPONDER may specified a null - indicating that
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
new file mode 100644
index 0000000..5f949747
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.net.wifi;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import android.os.Parcel;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiConfiguration}.
+ */
+public class WifiConfigurationTest {
+
+ @Before
+ public void setUp() {
+ }
+
+ /**
+ * Check that parcel marshalling/unmarshalling works
+ *
+ * Create and populate a WifiConfiguration.
+ * Marshall and unmashall it, and expect to recover a copy of the original.
+ * Marshall the resulting object, and expect the bytes to match the
+ * first marshall result.
+ */
+ @Test
+ public void testWifiConfigurationParcel() {
+ String cookie = "C O.o |<IE";
+ WifiConfiguration config = new WifiConfiguration();
+ config.setPasspointManagementObjectTree(cookie);
+ Parcel parcelW = Parcel.obtain();
+ config.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ WifiConfiguration reconfig = WifiConfiguration.CREATOR.createFromParcel(parcelR);
+
+ // lacking a useful config.equals, check one field near the end.
+ assertEquals(cookie, reconfig.getMoTree());
+
+ Parcel parcelWW = Parcel.obtain();
+ reconfig.writeToParcel(parcelWW, 0);
+ byte[] rebytes = parcelWW.marshall();
+ parcelWW.recycle();
+
+ assertArrayEquals(bytes, rebytes);
+ }
+}