Merge "Fix: Cursor can be at an invalid offset in EditText."
diff --git a/Android.mk b/Android.mk
index 769a555..40da134 100644
--- a/Android.mk
+++ b/Android.mk
@@ -90,6 +90,7 @@
core/java/android/app/IWallpaperManager.aidl \
core/java/android/app/IWallpaperManagerCallback.aidl \
core/java/android/app/admin/IDevicePolicyManager.aidl \
+ core/java/android/app/trust/IStrongAuthTracker.aidl \
core/java/android/app/trust/ITrustManager.aidl \
core/java/android/app/trust/ITrustListener.aidl \
core/java/android/app/backup/IBackupManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 3e1f5a5..e9c5727 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21,6 +21,7 @@
field public static final deprecated java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
field public static final java.lang.String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
+ field public static final java.lang.String BIND_CONDITION_PROVIDER_SERVICE = "android.permission.BIND_CONDITION_PROVIDER_SERVICE";
field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
field public static final java.lang.String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_SERVICE";
@@ -240,8 +241,10 @@
field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
+ field public static final int activityHeight = 16844019; // 0x10104f3
field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
+ field public static final int activityWidth = 16844018; // 0x10104f2
field public static final int addPrintersActivity = 16843750; // 0x10103e6
field public static final int addStatesFromChildren = 16842992; // 0x10100f0
field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -8881,6 +8884,7 @@
field public int configChanges;
field public int documentLaunchMode;
field public int flags;
+ field public android.content.pm.ActivityInfo.InitialLayout initialLayout;
field public int launchMode;
field public int maxRecents;
field public java.lang.String parentActivityName;
@@ -8894,6 +8898,15 @@
field public int uiOptions;
}
+ public static final class ActivityInfo.InitialLayout {
+ ctor public ActivityInfo.InitialLayout(int, float, int, float, int);
+ field public final int gravity;
+ field public final int height;
+ field public final float heightFraction;
+ field public final int width;
+ field public final float widthFraction;
+ }
+
public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
ctor public ApplicationInfo();
ctor public ApplicationInfo(android.content.pm.ApplicationInfo);
@@ -18102,7 +18115,7 @@
method public boolean importFile(int, java.lang.String);
method public boolean importFile(int, android.os.ParcelFileDescriptor);
method public boolean open(android.hardware.usb.UsbDeviceConnection);
- method public boolean sendObject(int, android.os.ParcelFileDescriptor);
+ method public boolean sendObject(int, int, android.os.ParcelFileDescriptor);
method public android.mtp.MtpObjectInfo sendObjectInfo(android.mtp.MtpObjectInfo);
}
@@ -18136,7 +18149,7 @@
method public final int getThumbPixWidth();
}
- public class MtpObjectInfo.Builder {
+ public static class MtpObjectInfo.Builder {
ctor public MtpObjectInfo.Builder();
ctor public MtpObjectInfo.Builder(android.mtp.MtpObjectInfo);
method public android.mtp.MtpObjectInfo build();
@@ -28731,6 +28744,49 @@
package android.service.notification {
+ public class Condition implements android.os.Parcelable {
+ ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
+ method public android.service.notification.Condition copy();
+ method public int describeContents();
+ method public static boolean isValidId(android.net.Uri, java.lang.String);
+ method public static android.net.Uri.Builder newId(android.content.Context);
+ method public static java.lang.String relevanceToString(int);
+ method public static java.lang.String stateToString(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.notification.Condition> CREATOR;
+ field public static final int FLAG_RELEVANT_ALWAYS = 2; // 0x2
+ field public static final int FLAG_RELEVANT_NOW = 1; // 0x1
+ field public static final java.lang.String SCHEME = "condition";
+ field public static final int STATE_ERROR = 3; // 0x3
+ field public static final int STATE_FALSE = 0; // 0x0
+ field public static final int STATE_TRUE = 1; // 0x1
+ field public static final int STATE_UNKNOWN = 2; // 0x2
+ field public final int flags;
+ field public final int icon;
+ field public final android.net.Uri id;
+ field public final java.lang.String line1;
+ field public final java.lang.String line2;
+ field public final int state;
+ field public final java.lang.String summary;
+ }
+
+ public abstract class ConditionProviderService extends android.app.Service {
+ ctor public ConditionProviderService();
+ method public final void notifyCondition(android.service.notification.Condition);
+ method public final void notifyConditions(android.service.notification.Condition...);
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public abstract void onConnected();
+ method public abstract void onRequestConditions(int);
+ method public abstract void onSubscribe(android.net.Uri);
+ method public abstract void onUnsubscribe(android.net.Uri);
+ field public static final java.lang.String EXTRA_CONDITION_ID = "android.content.automatic.conditionId";
+ field public static final java.lang.String EXTRA_RULE_NAME = "android.content.automatic.ruleName";
+ field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
+ field public static final java.lang.String META_DATA_DEFAULT_CONDITION_ID = "android.service.zen.automatic.defaultConditionId";
+ field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
+ }
+
public abstract class NotificationListenerService extends android.app.Service {
ctor public NotificationListenerService();
method public final void cancelAllNotifications();
@@ -30623,6 +30679,7 @@
field public static final java.lang.String KEY_AUTO_RETRY_ENABLED_BOOL = "auto_retry_enabled_bool";
field public static final java.lang.String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool";
field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
+ field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
@@ -32512,7 +32569,7 @@
method public static int getLayoutDirectionFromLocale(java.util.Locale);
method public static int getOffsetAfter(java.lang.CharSequence, int);
method public static int getOffsetBefore(java.lang.CharSequence, int);
- method public static java.lang.CharSequence getReverse(java.lang.CharSequence, int, int);
+ method public static deprecated java.lang.CharSequence getReverse(java.lang.CharSequence, int, int);
method public static int getTrimmedLength(java.lang.CharSequence);
method public static java.lang.String htmlEncode(java.lang.String);
method public static int indexOf(java.lang.CharSequence, char);
@@ -34141,6 +34198,15 @@
field public static final int RTL = 1; // 0x1
}
+ public final class LocaleList {
+ ctor public LocaleList();
+ ctor public LocaleList(java.util.Locale[]);
+ method public java.util.Locale get(int);
+ method public java.util.Locale getPrimary();
+ method public boolean isEmpty();
+ method public int size();
+ }
+
public final class Log {
method public static int d(java.lang.String, java.lang.String);
method public static int d(java.lang.String, java.lang.String, java.lang.Throwable);
diff --git a/api/system-current.txt b/api/system-current.txt
index 984d395..e234970 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -333,8 +333,10 @@
field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
+ field public static final int activityHeight = 16844019; // 0x10104f3
field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
+ field public static final int activityWidth = 16844018; // 0x10104f2
field public static final int addPrintersActivity = 16843750; // 0x10103e6
field public static final int addStatesFromChildren = 16842992; // 0x10100f0
field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -9139,6 +9141,7 @@
field public int configChanges;
field public int documentLaunchMode;
field public int flags;
+ field public android.content.pm.ActivityInfo.InitialLayout initialLayout;
field public int launchMode;
field public int maxRecents;
field public java.lang.String parentActivityName;
@@ -9152,6 +9155,15 @@
field public int uiOptions;
}
+ public static final class ActivityInfo.InitialLayout {
+ ctor public ActivityInfo.InitialLayout(int, float, int, float, int);
+ field public final int gravity;
+ field public final int height;
+ field public final float heightFraction;
+ field public final int width;
+ field public final float widthFraction;
+ }
+
public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
ctor public ApplicationInfo();
ctor public ApplicationInfo(android.content.pm.ApplicationInfo);
@@ -19615,7 +19627,7 @@
method public boolean importFile(int, java.lang.String);
method public boolean importFile(int, android.os.ParcelFileDescriptor);
method public boolean open(android.hardware.usb.UsbDeviceConnection);
- method public boolean sendObject(int, android.os.ParcelFileDescriptor);
+ method public boolean sendObject(int, int, android.os.ParcelFileDescriptor);
method public android.mtp.MtpObjectInfo sendObjectInfo(android.mtp.MtpObjectInfo);
}
@@ -19649,7 +19661,7 @@
method public final int getThumbPixWidth();
}
- public class MtpObjectInfo.Builder {
+ public static class MtpObjectInfo.Builder {
ctor public MtpObjectInfo.Builder();
ctor public MtpObjectInfo.Builder(android.mtp.MtpObjectInfo);
method public android.mtp.MtpObjectInfo build();
@@ -30856,6 +30868,11 @@
method public abstract void onRequestConditions(int);
method public abstract void onSubscribe(android.net.Uri);
method public abstract void onUnsubscribe(android.net.Uri);
+ field public static final java.lang.String EXTRA_CONDITION_ID = "android.content.automatic.conditionId";
+ field public static final java.lang.String EXTRA_RULE_NAME = "android.content.automatic.ruleName";
+ field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
+ field public static final java.lang.String META_DATA_DEFAULT_CONDITION_ID = "android.service.zen.automatic.defaultConditionId";
+ field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
}
@@ -32893,6 +32910,7 @@
field public static final java.lang.String KEY_AUTO_RETRY_ENABLED_BOOL = "auto_retry_enabled_bool";
field public static final java.lang.String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool";
field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
+ field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
@@ -34845,7 +34863,7 @@
method public static int getLayoutDirectionFromLocale(java.util.Locale);
method public static int getOffsetAfter(java.lang.CharSequence, int);
method public static int getOffsetBefore(java.lang.CharSequence, int);
- method public static java.lang.CharSequence getReverse(java.lang.CharSequence, int, int);
+ method public static deprecated java.lang.CharSequence getReverse(java.lang.CharSequence, int, int);
method public static int getTrimmedLength(java.lang.CharSequence);
method public static java.lang.String htmlEncode(java.lang.String);
method public static int indexOf(java.lang.CharSequence, char);
@@ -36474,6 +36492,15 @@
field public static final int RTL = 1; // 0x1
}
+ public final class LocaleList {
+ ctor public LocaleList();
+ ctor public LocaleList(java.util.Locale[]);
+ method public java.util.Locale get(int);
+ method public java.util.Locale getPrimary();
+ method public boolean isEmpty();
+ method public int size();
+ }
+
public final class Log {
method public static int d(java.lang.String, java.lang.String);
method public static int d(java.lang.String, java.lang.String, java.lang.Throwable);
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 2ee586f..7c8842c 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -27,6 +27,8 @@
LOCAL_MODULE:= bootanimation
+LOCAL_INIT_RC := bootanim.rc
+
ifdef TARGET_32_BIT_SURFACEFLINGER
LOCAL_32_BIT_ONLY := true
endif
diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc
new file mode 100644
index 0000000..ee0d0b8
--- /dev/null
+++ b/cmds/bootanimation/bootanim.rc
@@ -0,0 +1,6 @@
+service bootanim /system/bin/bootanimation
+ class core
+ user graphics
+ group graphics audio
+ disabled
+ oneshot
diff --git a/cmds/dpm/src/com/android/commands/dpm/Dpm.java b/cmds/dpm/src/com/android/commands/dpm/Dpm.java
index f9b3419..471fa3b 100644
--- a/cmds/dpm/src/com/android/commands/dpm/Dpm.java
+++ b/cmds/dpm/src/com/android/commands/dpm/Dpm.java
@@ -107,7 +107,7 @@
private void runSetDeviceOwner() throws RemoteException {
ComponentName component = parseComponentName(nextArgRequired());
- mDevicePolicyManager.setActiveAdmin(component, true /*refreshing*/, UserHandle.USER_OWNER);
+ mDevicePolicyManager.setActiveAdmin(component, true /*refreshing*/, UserHandle.USER_SYSTEM);
String packageName = component.getPackageName();
try {
@@ -117,7 +117,7 @@
}
} catch (Exception e) {
// Need to remove the admin that we just added.
- mDevicePolicyManager.removeActiveAdmin(component, UserHandle.USER_OWNER);
+ mDevicePolicyManager.removeActiveAdmin(component, UserHandle.USER_SYSTEM);
throw e;
}
System.out.println("Success: Device owner set to package " + packageName);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index f66a4c7..3f0a444 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -51,6 +51,7 @@
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.net.Uri;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IUserManager;
@@ -987,6 +988,7 @@
case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
+ case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
}
return "Unknown link state: " + state;
}
@@ -1094,6 +1096,7 @@
}
}
+ userId = translateUserId(userId, "runInstall");
if (userId == UserHandle.USER_ALL) {
userId = UserHandle.USER_SYSTEM;
installFlags |= PackageManager.INSTALL_ALL_USERS;
@@ -1164,6 +1167,16 @@
}
}
+ /**
+ * @param userId The user id to be translated.
+ * @param logContext Optional human readable text to provide some context in error log.
+ * @return Translated concrete user id. This will include USER_ALL.
+ */
+ private int translateUserId(int userId, String logContext) {
+ return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, true, true, logContext, "pm command");
+ }
+
private int runInstallCreate() throws RemoteException {
int userId = UserHandle.USER_ALL;
String installerPackageName = null;
@@ -1220,6 +1233,7 @@
}
}
+ userId = translateUserId(userId, "runInstallCreate");
if (userId == UserHandle.USER_ALL) {
userId = UserHandle.USER_SYSTEM;
params.installFlags |= PackageManager.INSTALL_ALL_USERS;
@@ -1551,6 +1565,7 @@
return 1;
}
+ userId = translateUserId(userId, "runUninstall");
if (userId == UserHandle.USER_ALL) {
userId = UserHandle.USER_SYSTEM;
flags |= PackageManager.DELETE_ALL_USERS;
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 c551482..cb39e37 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
@@ -61,7 +61,7 @@
IBinder token = new Binder();
try {
ContentProviderHolder holder = activityManager.getContentProviderExternal(
- providerName, UserHandle.USER_OWNER, token);
+ providerName, UserHandle.USER_SYSTEM, token);
if (holder == null) {
throw new IllegalStateException("Could not find provider: " + providerName);
}
diff --git a/core/java/android/animation/AnimationHandler.java b/core/java/android/animation/AnimationHandler.java
new file mode 100644
index 0000000..7778c35
--- /dev/null
+++ b/core/java/android/animation/AnimationHandler.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation;
+
+import android.os.SystemClock;
+import android.util.ArrayMap;
+import android.view.Choreographer;
+
+import java.util.ArrayList;
+
+/**
+ * This custom, static handler handles the timing pulse that is shared by all active
+ * ValueAnimators. This approach ensures that the setting of animation values will happen on the
+ * same thread that animations start on, and that all animations will share the same times for
+ * calculating their values, which makes synchronizing animations possible.
+ *
+ * The handler uses the Choreographer by default for doing periodic callbacks. A custom
+ * AnimationFrameCallbackProvider can be set on the handler to provide timing pulse that
+ * may be independent of UI frame update. This could be useful in testing.
+ *
+ * @hide
+ */
+public class AnimationHandler {
+ /**
+ * Internal per-thread collections used to avoid set collisions as animations start and end
+ * while being processed.
+ * @hide
+ */
+ private final ArrayMap<AnimationFrameCallback, Long> mDelayedCallbackStartTime =
+ new ArrayMap<>();
+ private final ArrayList<AnimationFrameCallback> mAnimationCallbacks =
+ new ArrayList<>();
+ private final ArrayList<AnimationFrameCallback> mCommitCallbacks =
+ new ArrayList<>();
+ private AnimationFrameCallbackProvider mProvider;
+
+ private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
+ @Override
+ public void doFrame(long frameTimeNanos) {
+ doAnimationFrame(getProvider().getFrameTime());
+ if (mAnimationCallbacks.size() > 0) {
+ getProvider().postFrameCallback(this);
+ }
+ }
+ };
+
+ public final static ThreadLocal<AnimationHandler> sAnimatorHandler = new ThreadLocal<>();
+ private boolean mListDirty = false;
+
+ public static AnimationHandler getInstance() {
+ if (sAnimatorHandler.get() == null) {
+ sAnimatorHandler.set(new AnimationHandler());
+ }
+ return sAnimatorHandler.get();
+ }
+
+ /**
+ * By default, the Choreographer is used to provide timing for frame callbacks. A custom
+ * provider can be used here to provide different timing pulse.
+ */
+ public void setProvider(AnimationFrameCallbackProvider provider) {
+ if (provider == null) {
+ mProvider = new MyFrameCallbackProvider();
+ } else {
+ mProvider = provider;
+ }
+ }
+
+ private AnimationFrameCallbackProvider getProvider() {
+ if (mProvider == null) {
+ mProvider = new MyFrameCallbackProvider();
+ }
+ return mProvider;
+ }
+
+ /**
+ * Register to get a callback on the next frame after the delay.
+ */
+ public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
+ if (mAnimationCallbacks.size() == 0) {
+ getProvider().postFrameCallback(mFrameCallback);
+ }
+ if (!mAnimationCallbacks.contains(callback)) {
+ mAnimationCallbacks.add(callback);
+ }
+
+ if (delay > 0) {
+ mDelayedCallbackStartTime.put(callback, (SystemClock.uptimeMillis() + delay));
+ }
+ }
+
+ /**
+ * Register to get a one shot callback for frame commit timing. Frame commit timing is the
+ * time *after* traversals are done, as opposed to the animation frame timing, which is
+ * before any traversals. This timing can be used to adjust the start time of an animation
+ * when expensive traversals create big delta between the animation frame timing and the time
+ * that animation is first shown on screen.
+ *
+ * Note this should only be called when the animation has already registered to receive
+ * animation frame callbacks. This callback will be guaranteed to happen *after* the next
+ * animation frame callback.
+ */
+ public void addOneShotCommitCallback(final AnimationFrameCallback callback) {
+ if (!mCommitCallbacks.contains(callback)) {
+ mCommitCallbacks.add(callback);
+ }
+ }
+
+ /**
+ * Removes the given callback from the list, so it will no longer be called for frame related
+ * timing.
+ */
+ public void removeCallback(AnimationFrameCallback callback) {
+ mCommitCallbacks.remove(callback);
+ mDelayedCallbackStartTime.remove(callback);
+ int id = mAnimationCallbacks.indexOf(callback);
+ if (id >= 0) {
+ mAnimationCallbacks.set(id, null);
+ mListDirty = true;
+ }
+ }
+
+ private void doAnimationFrame(long frameTime) {
+ int size = mAnimationCallbacks.size();
+ long currentTime = SystemClock.uptimeMillis();
+ for (int i = 0; i < size; i++) {
+ final AnimationFrameCallback callback = mAnimationCallbacks.get(i);
+ if (callback == null) {
+ continue;
+ }
+ if (isCallbackDue(callback, currentTime)) {
+ callback.doAnimationFrame(frameTime);
+ if (mCommitCallbacks.contains(callback)) {
+ getProvider().postCommitCallback(new Runnable() {
+ @Override
+ public void run() {
+ commitAnimationFrame(callback, getProvider().getFrameTime());
+ }
+ });
+ }
+ }
+ }
+ cleanUpList();
+ }
+
+ private void commitAnimationFrame(AnimationFrameCallback callback, long frameTime) {
+ if (!mDelayedCallbackStartTime.containsKey(callback) &&
+ mCommitCallbacks.contains(callback)) {
+ callback.commitAnimationFrame(frameTime);
+ mCommitCallbacks.remove(callback);
+ }
+ }
+
+ /**
+ * Remove the callbacks from mDelayedCallbackStartTime once they have passed the initial delay
+ * so that they can start getting frame callbacks.
+ *
+ * @return true if they have passed the initial delay or have no delay, false otherwise.
+ */
+ private boolean isCallbackDue(AnimationFrameCallback callback, long currentTime) {
+ Long startTime = mDelayedCallbackStartTime.get(callback);
+ if (startTime == null) {
+ return true;
+ }
+ if (startTime < currentTime) {
+ mDelayedCallbackStartTime.remove(callback);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return the number of callbacks that have registered for frame callbacks.
+ */
+ public static int getAnimationCount() {
+ AnimationHandler handler = sAnimatorHandler.get();
+ if (handler == null) {
+ return 0;
+ }
+ return handler.getCallbackSize();
+ }
+
+ public static void setFrameDelay(long delay) {
+ getInstance().getProvider().setFrameDelay(delay);
+ }
+
+ public static long getFrameDelay() {
+ return getInstance().getProvider().getFrameDelay();
+ }
+
+ void autoCancelBasedOn(ObjectAnimator objectAnimator) {
+ for (int i = mAnimationCallbacks.size() - 1; i >= 0; i--) {
+ AnimationFrameCallback cb = mAnimationCallbacks.get(i);
+ if (cb == null) {
+ continue;
+ }
+ if (objectAnimator.shouldAutoCancel(cb)) {
+ ((Animator) mAnimationCallbacks.get(i)).cancel();
+ }
+ }
+ }
+
+ private void cleanUpList() {
+ if (mListDirty) {
+ for (int i = mAnimationCallbacks.size() - 1; i >= 0; i--) {
+ if (mAnimationCallbacks.get(i) == null) {
+ mAnimationCallbacks.remove(i);
+ }
+ }
+ mListDirty = false;
+ }
+ }
+
+ private int getCallbackSize() {
+ int count = 0;
+ int size = mAnimationCallbacks.size();
+ for (int i = size - 1; i >= 0; i--) {
+ if (mAnimationCallbacks.get(i) != null) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Default provider of timing pulse that uses Choreographer for frame callbacks.
+ */
+ private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider {
+
+ final Choreographer mChoreographer = Choreographer.getInstance();
+
+ @Override
+ public void postFrameCallback(Choreographer.FrameCallback callback) {
+ mChoreographer.postFrameCallback(callback);
+ }
+
+ @Override
+ public void postCommitCallback(Runnable runnable) {
+ mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, runnable, null);
+ }
+
+ @Override
+ public long getFrameTime() {
+ return mChoreographer.getFrameTime();
+ }
+
+ @Override
+ public long getFrameDelay() {
+ return Choreographer.getFrameDelay();
+ }
+
+ @Override
+ public void setFrameDelay(long delay) {
+ Choreographer.setFrameDelay(delay);
+ }
+ }
+
+ /**
+ * Callbacks that receives notifications for animation timing and frame commit timing.
+ */
+ interface AnimationFrameCallback {
+ /**
+ * Run animation based on the frame time.
+ * @param frameTime The frame start time, in the {@link SystemClock#uptimeMillis()} time
+ * base.
+ */
+ void doAnimationFrame(long frameTime);
+
+ /**
+ * This notifies the callback of frame commit time. Frame commit time is the time after
+ * traversals happen, as opposed to the normal animation frame time that is before
+ * traversals. This is used to compensate expensive traversals that happen as the
+ * animation starts. When traversals take a long time to complete, the rendering of the
+ * initial frame will be delayed (by a long time). But since the startTime of the
+ * animation is set before the traversal, by the time of next frame, a lot of time would
+ * have passed since startTime was set, the animation will consequently skip a few frames
+ * to respect the new frameTime. By having the commit time, we can adjust the start time to
+ * when the first frame was drawn (after any expensive traversals) so that no frames
+ * will be skipped.
+ *
+ * @param frameTime The frame time after traversals happen, if any, in the
+ * {@link SystemClock#uptimeMillis()} time base.
+ */
+ void commitAnimationFrame(long frameTime);
+ }
+
+ /**
+ * The intention for having this interface is to increase the testability of ValueAnimator.
+ * Specifically, we can have a custom implementation of the interface below and provide
+ * timing pulse without using Choreographer. That way we could use any arbitrary interval for
+ * our timing pulse in the tests.
+ *
+ * @hide
+ */
+ public interface AnimationFrameCallbackProvider {
+ void postFrameCallback(Choreographer.FrameCallback callback);
+ void postCommitCallback(Runnable runnable);
+ long getFrameTime();
+ long getFrameDelay();
+ void setFrameDelay(long delay);
+ }
+}
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index f9333739..26c886e 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -25,6 +25,7 @@
import android.util.Property;
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
/**
* This subclass of {@link ValueAnimator} provides support for animating properties on target objects.
@@ -809,37 +810,7 @@
@Override
public void start() {
- // See if any of the current active/pending animators need to be canceled
- AnimationHandler handler = sAnimationHandler.get();
- if (handler != null) {
- int numAnims = handler.mAnimations.size();
- for (int i = numAnims - 1; i >= 0; i--) {
- if (handler.mAnimations.get(i) instanceof ObjectAnimator) {
- ObjectAnimator anim = (ObjectAnimator) handler.mAnimations.get(i);
- if (anim.mAutoCancel && hasSameTargetAndProperties(anim)) {
- anim.cancel();
- }
- }
- }
- numAnims = handler.mPendingAnimations.size();
- for (int i = numAnims - 1; i >= 0; i--) {
- if (handler.mPendingAnimations.get(i) instanceof ObjectAnimator) {
- ObjectAnimator anim = (ObjectAnimator) handler.mPendingAnimations.get(i);
- if (anim.mAutoCancel && hasSameTargetAndProperties(anim)) {
- anim.cancel();
- }
- }
- }
- numAnims = handler.mDelayedAnims.size();
- for (int i = numAnims - 1; i >= 0; i--) {
- if (handler.mDelayedAnims.get(i) instanceof ObjectAnimator) {
- ObjectAnimator anim = (ObjectAnimator) handler.mDelayedAnims.get(i);
- if (anim.mAutoCancel && hasSameTargetAndProperties(anim)) {
- anim.cancel();
- }
- }
- }
- }
+ AnimationHandler.getInstance().autoCancelBasedOn(this);
if (DBG) {
Log.d(LOG_TAG, "Anim target, duration: " + getTarget() + ", " + getDuration());
for (int i = 0; i < mValues.length; ++i) {
@@ -852,6 +823,20 @@
super.start();
}
+ boolean shouldAutoCancel(AnimationHandler.AnimationFrameCallback anim) {
+ if (anim == null) {
+ return false;
+ }
+
+ if (anim instanceof ObjectAnimator) {
+ ObjectAnimator objAnim = (ObjectAnimator) anim;
+ if (objAnim.mAutoCancel && hasSameTargetAndProperties(objAnim)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* This function is called immediately before processing the first animation
* frame of an animation. If there is a nonzero <code>startDelay</code>, the
diff --git a/core/java/android/animation/TimeAnimator.java b/core/java/android/animation/TimeAnimator.java
index 1ba68df..113a21f 100644
--- a/core/java/android/animation/TimeAnimator.java
+++ b/core/java/android/animation/TimeAnimator.java
@@ -37,7 +37,7 @@
}
@Override
- boolean animationFrame(long currentTime) {
+ boolean animateBasedOnTime(long currentTime) {
if (mListener != null) {
long totalTime = currentTime - mStartTime;
long deltaTime = (mPreviousTime < 0) ? 0 : (currentTime - mPreviousTime);
@@ -52,7 +52,7 @@
long currentTime = AnimationUtils.currentAnimationTimeMillis();
mStartTime = Math.max(mStartTime, currentTime - playTime);
mStartTimeCommitted = true; // do not allow start time to be compensated for jank
- animationFrame(currentTime);
+ animateBasedOnTime(currentTime);
}
/**
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 35a8816..da9a8c8 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -21,7 +21,6 @@
import android.os.Trace;
import android.util.AndroidRuntimeException;
import android.util.Log;
-import android.view.Choreographer;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
@@ -64,7 +63,7 @@
* </div>
*/
@SuppressWarnings("unchecked")
-public class ValueAnimator extends Animator {
+public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
private static final String TAG = "ValueAnimator";
private static final boolean DEBUG = false;
@@ -74,14 +73,6 @@
private static float sDurationScale = 1.0f;
/**
- * Values used with internal variable mPlayingState to indicate the current state of an
- * animation.
- */
- static final int STOPPED = 0; // Not yet playing
- static final int RUNNING = 1; // Playing normally
- static final int SEEKED = 2; // Seeked to some time value
-
- /**
* Internal variables
* NOTE: This object implements the clone() method, making a deep copy of any referenced
* objects. As other non-trivial fields are added to this class, make sure to add logic
@@ -130,15 +121,6 @@
*/
private boolean mResumed = false;
-
- // The static sAnimationHandler processes the internal timing loop on which all animations
- // are based
- /**
- * @hide
- */
- protected static ThreadLocal<AnimationHandler> sAnimationHandler =
- new ThreadLocal<AnimationHandler>();
-
// The time interpolator to be used if none is set on the animation
private static final TimeInterpolator sDefaultInterpolator =
new AccelerateDecelerateInterpolator();
@@ -170,25 +152,9 @@
private float mCurrentFraction = 0f;
/**
- * Tracks whether a startDelay'd animation has begun playing through the startDelay.
+ * Tracks the time (in milliseconds) when the last frame arrived.
*/
- private boolean mStartedDelay = false;
-
- /**
- * Tracks the time at which the animation began playing through its startDelay. This is
- * different from the mStartTime variable, which is used to track when the animation became
- * active (which is when the startDelay expired and the animation was added to the active
- * animations list).
- */
- private long mDelayStartTime;
-
- /**
- * Flag that represents the current state of the animation. Used to figure out when to start
- * an animation (if state == STOPPED). Also used to end an animation that
- * has been cancel()'d or end()'d since the last animation frame. Possible values are
- * STOPPED, RUNNING, SEEKED.
- */
- int mPlayingState = STOPPED;
+ private long mLastFrameTime = 0;
/**
* Additional playing state to indicate whether an animator has been start()'d. There is
@@ -219,16 +185,21 @@
*/
boolean mInitialized = false;
+ /**
+ * Flag that tracks whether animation has been requested to end.
+ */
+ private boolean mAnimationEndRequested = false;
+
//
// Backing variables
//
// How long the animation should last in ms
- private long mDuration = (long)(300 * sDurationScale);
private long mUnscaledDuration = 300;
+ private long mDuration = (long)(mUnscaledDuration * sDurationScale);
// The amount of time in ms to delay starting the animation after start() is called
- private long mStartDelay = 0;
+ long mStartDelay = 0;
private long mUnscaledStartDelay = 0;
// The number of times the animation will repeat. The default is 0, which means the animation
@@ -285,7 +256,6 @@
*/
public static final int INFINITE = -1;
-
/**
* @hide
*/
@@ -539,7 +509,6 @@
}
}
-
/**
* Sets the length of the animation. The default duration is 300 milliseconds.
*
@@ -644,9 +613,8 @@
long currentTime = AnimationUtils.currentAnimationTimeMillis();
mStartTime = currentTime - seekTime;
mStartTimeCommitted = true; // do not allow start time to be compensated for jank
- if (mPlayingState != RUNNING) {
+ if (!mRunning) {
mSeekFraction = fraction;
- mPlayingState = SEEKED;
}
if (mPlayingBackwards) {
fraction = 1f - fraction;
@@ -662,168 +630,13 @@
* @return The current position in time of the animation.
*/
public long getCurrentPlayTime() {
- if (!mInitialized || mPlayingState == STOPPED) {
+ if (!mInitialized || !mStarted) {
return 0;
}
return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
}
/**
- * This custom, static handler handles the timing pulse that is shared by
- * all active animations. This approach ensures that the setting of animation
- * values will happen on the UI thread and that all animations will share
- * the same times for calculating their values, which makes synchronizing
- * animations possible.
- *
- * The handler uses the Choreographer for executing periodic callbacks.
- *
- * @hide
- */
- @SuppressWarnings("unchecked")
- protected static class AnimationHandler {
- // The per-thread list of all active animations
- /** @hide */
- protected final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>();
-
- // Used in doAnimationFrame() to avoid concurrent modifications of mAnimations
- private final ArrayList<ValueAnimator> mTmpAnimations = new ArrayList<ValueAnimator>();
-
- // The per-thread set of animations to be started on the next animation frame
- /** @hide */
- protected final ArrayList<ValueAnimator> mPendingAnimations = new ArrayList<ValueAnimator>();
-
- /**
- * Internal per-thread collections used to avoid set collisions as animations start and end
- * while being processed.
- * @hide
- */
- protected final ArrayList<ValueAnimator> mDelayedAnims = new ArrayList<ValueAnimator>();
- private final ArrayList<ValueAnimator> mEndingAnims = new ArrayList<ValueAnimator>();
- private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>();
-
- private final Choreographer mChoreographer;
- private boolean mAnimationScheduled;
- private long mLastFrameTime;
-
- private AnimationHandler() {
- mChoreographer = Choreographer.getInstance();
- }
-
- /**
- * Start animating on the next frame.
- */
- public void start() {
- scheduleAnimation();
- }
-
- void doAnimationFrame(long frameTime) {
- mLastFrameTime = frameTime;
-
- // mPendingAnimations holds any animations that have requested to be started
- // We're going to clear mPendingAnimations, but starting animation may
- // cause more to be added to the pending list (for example, if one animation
- // starting triggers another starting). So we loop until mPendingAnimations
- // is empty.
- while (mPendingAnimations.size() > 0) {
- ArrayList<ValueAnimator> pendingCopy =
- (ArrayList<ValueAnimator>) mPendingAnimations.clone();
- mPendingAnimations.clear();
- int count = pendingCopy.size();
- for (int i = 0; i < count; ++i) {
- ValueAnimator anim = pendingCopy.get(i);
- // If the animation has a startDelay, place it on the delayed list
- if (anim.mStartDelay == 0) {
- anim.startAnimation(this);
- } else {
- mDelayedAnims.add(anim);
- }
- }
- }
-
- // Next, process animations currently sitting on the delayed queue, adding
- // them to the active animations if they are ready
- int numDelayedAnims = mDelayedAnims.size();
- for (int i = 0; i < numDelayedAnims; ++i) {
- ValueAnimator anim = mDelayedAnims.get(i);
- if (anim.delayedAnimationFrame(frameTime)) {
- mReadyAnims.add(anim);
- }
- }
- int numReadyAnims = mReadyAnims.size();
- if (numReadyAnims > 0) {
- for (int i = 0; i < numReadyAnims; ++i) {
- ValueAnimator anim = mReadyAnims.get(i);
- anim.startAnimation(this);
- anim.mRunning = true;
- mDelayedAnims.remove(anim);
- }
- mReadyAnims.clear();
- }
-
- // Now process all active animations. The return value from animationFrame()
- // tells the handler whether it should now be ended
- int numAnims = mAnimations.size();
- for (int i = 0; i < numAnims; ++i) {
- mTmpAnimations.add(mAnimations.get(i));
- }
- for (int i = 0; i < numAnims; ++i) {
- ValueAnimator anim = mTmpAnimations.get(i);
- if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) {
- mEndingAnims.add(anim);
- }
- }
- mTmpAnimations.clear();
- if (mEndingAnims.size() > 0) {
- for (int i = 0; i < mEndingAnims.size(); ++i) {
- mEndingAnims.get(i).endAnimation(this);
- }
- mEndingAnims.clear();
- }
-
- // Schedule final commit for the frame.
- mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, mCommit, null);
-
- // If there are still active or delayed animations, schedule a future call to
- // onAnimate to process the next frame of the animations.
- if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) {
- scheduleAnimation();
- }
- }
-
- void commitAnimationFrame(long frameTime) {
- final long adjustment = frameTime - mLastFrameTime;
- final int numAnims = mAnimations.size();
- for (int i = 0; i < numAnims; ++i) {
- mAnimations.get(i).commitAnimationFrame(adjustment);
- }
- }
-
- private void scheduleAnimation() {
- if (!mAnimationScheduled) {
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimate, null);
- mAnimationScheduled = true;
- }
- }
-
- // Called by the Choreographer.
- final Runnable mAnimate = new Runnable() {
- @Override
- public void run() {
- mAnimationScheduled = false;
- doAnimationFrame(mChoreographer.getFrameTime());
- }
- };
-
- // Called by the Choreographer.
- final Runnable mCommit = new Runnable() {
- @Override
- public void run() {
- commitAnimationFrame(mChoreographer.getFrameTime());
- }
- };
- }
-
- /**
* The amount of time, in milliseconds, to delay starting the animation after
* {@link #start()} is called.
*
@@ -859,7 +672,7 @@
* @return the requested time between frames, in milliseconds
*/
public static long getFrameDelay() {
- return Choreographer.getFrameDelay();
+ return AnimationHandler.getInstance().getFrameDelay();
}
/**
@@ -875,7 +688,7 @@
* @param frameDelay the requested time between frames, in milliseconds
*/
public static void setFrameDelay(long frameDelay) {
- Choreographer.setFrameDelay(frameDelay);
+ AnimationHandler.getInstance().setFrameDelay(frameDelay);
}
/**
@@ -1104,24 +917,13 @@
mPlayingBackwards = (mCurrentIteration % 2) != 0;
}
}
- int prevPlayingState = mPlayingState;
- mPlayingState = STOPPED;
mStarted = true;
- mStartedDelay = false;
mPaused = false;
+ mRunning = false;
+ mAnimationEndRequested = false;
updateScaledDuration(); // in case the scale factor has changed since creation time
- AnimationHandler animationHandler = getOrCreateAnimationHandler();
- animationHandler.mPendingAnimations.add(this);
- if (mStartDelay == 0) {
- // This sets the initial value of the animation, prior to actually starting it running
- if (prevPlayingState != SEEKED) {
- setCurrentPlayTime(0);
- }
- mPlayingState = STOPPED;
- mRunning = true;
- notifyStartListeners();
- }
- animationHandler.start();
+ AnimationHandler animationHandler = AnimationHandler.getInstance();
+ animationHandler.addAnimationFrameCallback(this, mStartDelay);
}
@Override
@@ -1131,41 +933,48 @@
@Override
public void cancel() {
+ if (Looper.myLooper() == null) {
+ throw new AndroidRuntimeException("Animators may only be run on Looper threads");
+ }
+
+ // If end has already been requested, through a previous end() or cancel() call, no-op
+ // until animation starts again.
+ if (mAnimationEndRequested) {
+ return;
+ }
+
// Only cancel if the animation is actually running or has been started and is about
// to run
- AnimationHandler handler = getOrCreateAnimationHandler();
- if (mPlayingState != STOPPED
- || handler.mPendingAnimations.contains(this)
- || handler.mDelayedAnims.contains(this)) {
- // Only notify listeners if the animator has actually started
- if ((mStarted || mRunning) && mListeners != null) {
- if (!mRunning) {
- // If it's not yet running, then start listeners weren't called. Call them now.
- notifyStartListeners();
- }
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- for (AnimatorListener listener : tmpListeners) {
- listener.onAnimationCancel(this);
- }
+ // Only notify listeners if the animator has actually started
+ if ((mStarted || mRunning) && mListeners != null) {
+ if (!mRunning) {
+ // If it's not yet running, then start listeners weren't called. Call them now.
+ notifyStartListeners();
}
- endAnimation(handler);
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ for (AnimatorListener listener : tmpListeners) {
+ listener.onAnimationCancel(this);
+ }
}
+ endAnimation();
+
}
@Override
public void end() {
- AnimationHandler handler = getOrCreateAnimationHandler();
- if (!handler.mAnimations.contains(this) && !handler.mPendingAnimations.contains(this)) {
+ if (Looper.myLooper() == null) {
+ throw new AndroidRuntimeException("Animators may only be run on Looper threads");
+ }
+ if (!mRunning) {
// Special case if the animation has not yet started; get it ready for ending
- mStartedDelay = false;
- startAnimation(handler);
+ startAnimation();
mStarted = true;
} else if (!mInitialized) {
initAnimation();
}
animateValue(mPlayingBackwards ? 0f : 1f);
- endAnimation(handler);
+ endAnimation();
}
@Override
@@ -1188,7 +997,7 @@
@Override
public boolean isRunning() {
- return (mPlayingState == RUNNING || mRunning);
+ return mRunning;
}
@Override
@@ -1206,7 +1015,7 @@
@Override
public void reverse() {
mPlayingBackwards = !mPlayingBackwards;
- if (mPlayingState == RUNNING) {
+ if (mRunning) {
long currentTime = AnimationUtils.currentAnimationTimeMillis();
long currentPlayTime = currentTime - mStartTime;
long timeLeft = mDuration - currentPlayTime;
@@ -1231,13 +1040,15 @@
/**
* Called internally to end an animation by removing it from the animations list. Must be
* called on the UI thread.
- * @hide
*/
- protected void endAnimation(AnimationHandler handler) {
- handler.mAnimations.remove(this);
- handler.mPendingAnimations.remove(this);
- handler.mDelayedAnims.remove(this);
- mPlayingState = STOPPED;
+ private void endAnimation() {
+ if (mAnimationEndRequested) {
+ return;
+ }
+ AnimationHandler handler = AnimationHandler.getInstance();
+ handler.removeCallback(this);
+
+ mAnimationEndRequested = true;
mPaused = false;
if ((mStarted || mRunning) && mListeners != null) {
if (!mRunning) {
@@ -1267,16 +1078,14 @@
* Called internally to start an animation by adding it to the active animations list. Must be
* called on the UI thread.
*/
- private void startAnimation(AnimationHandler handler) {
+ private void startAnimation() {
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, getNameForTrace(),
System.identityHashCode(this));
}
initAnimation();
- handler.mAnimations.add(this);
- if (mStartDelay > 0 && mListeners != null) {
- // Listeners were already notified in start() if startDelay is 0; this is
- // just for delayed animations
+ mRunning = true;
+ if (mListeners != null) {
notifyStartListeners();
}
}
@@ -1288,53 +1097,16 @@
return "animator";
}
-
- /**
- * Internal function called to process an animation frame on an animation that is currently
- * sleeping through its <code>startDelay</code> phase. The return value indicates whether it
- * should be woken up and put on the active animations queue.
- *
- * @param currentTime The current animation time, used to calculate whether the animation
- * has exceeded its <code>startDelay</code> and should be started.
- * @return True if the animation's <code>startDelay</code> has been exceeded and the animation
- * should be added to the set of active animations.
- */
- private boolean delayedAnimationFrame(long currentTime) {
- if (!mStartedDelay) {
- mStartedDelay = true;
- mDelayStartTime = currentTime;
- }
- if (mPaused) {
- if (mPauseTime < 0) {
- mPauseTime = currentTime;
- }
- return false;
- } else if (mResumed) {
- mResumed = false;
- if (mPauseTime > 0) {
- // Offset by the duration that the animation was paused
- mDelayStartTime += (currentTime - mPauseTime);
- }
- }
- long deltaTime = currentTime - mDelayStartTime;
- if (deltaTime > mStartDelay) {
- // startDelay ended - start the anim and record the mStartTime appropriately
- mStartTime = mDelayStartTime + mStartDelay;
- mStartTimeCommitted = true; // do not allow start time to be compensated for jank
- mPlayingState = RUNNING;
- return true;
- }
- return false;
- }
-
/**
* Applies an adjustment to the animation to compensate for jank between when
* the animation first ran and when the frame was drawn.
+ * @hide
*/
- void commitAnimationFrame(long adjustment) {
+ public void commitAnimationFrame(long frameTime) {
if (!mStartTimeCommitted) {
mStartTimeCommitted = true;
- if (mPlayingState == RUNNING && adjustment > 0) {
+ long adjustment = frameTime - mLastFrameTime;
+ if (adjustment > 0) {
mStartTime += adjustment;
if (DEBUG) {
Log.d(TAG, "Adjusted start time by " + adjustment + " ms: " + toString());
@@ -1353,13 +1125,11 @@
*
* @param currentTime The current time, as tracked by the static timing handler
* @return true if the animation's duration, including any repetitions due to
- * <code>repeatCount</code>, has been exceeded and the animation should be ended.
+ * <code>repeatCount</code> has been exceeded and the animation should be ended.
*/
- boolean animationFrame(long currentTime) {
+ boolean animateBasedOnTime(long currentTime) {
boolean done = false;
- switch (mPlayingState) {
- case RUNNING:
- case SEEKED:
+ if (mRunning) {
float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
if (mDuration == 0 && mRepeatCount != INFINITE) {
// Skip to the end
@@ -1394,9 +1164,7 @@
fraction = 1f - fraction;
}
animateValue(fraction);
- break;
}
-
return done;
}
@@ -1405,10 +1173,15 @@
*
* @param frameTime The frame time.
* @return true if the animation has ended.
+ * @hide
*/
- final boolean doAnimationFrame(long frameTime) {
- if (mPlayingState == STOPPED) {
- mPlayingState = RUNNING;
+ public final void doAnimationFrame(long frameTime) {
+ mLastFrameTime = frameTime;
+ AnimationHandler handler = AnimationHandler.getInstance();
+ if (!mRunning) {
+ // First frame
+ handler.addOneShotCommitCallback(this);
+ startAnimation();
if (mSeekFraction < 0) {
mStartTime = frameTime;
} else {
@@ -1422,7 +1195,7 @@
if (mPauseTime < 0) {
mPauseTime = frameTime;
}
- return false;
+ return;
} else if (mResumed) {
mResumed = false;
if (mPauseTime > 0) {
@@ -1430,13 +1203,18 @@
mStartTime += (frameTime - mPauseTime);
mStartTimeCommitted = false; // allow start time to be compensated for jank
}
+ handler.addOneShotCommitCallback(this);
}
// The frame time might be before the start time during the first frame of
// an animation. The "current time" must always be on or after the start
// time to avoid animating frames at negative time intervals. In practice, this
// is very rare and only happens when seeking backwards.
final long currentTime = Math.max(frameTime, mStartTime);
- return animationFrame(currentTime);
+ boolean finished = animateBasedOnTime(currentTime);
+
+ if (finished) {
+ endAnimation();
+ }
}
/**
@@ -1488,8 +1266,6 @@
anim.mReversing = false;
anim.mCurrentIteration = 0;
anim.mInitialized = false;
- anim.mPlayingState = STOPPED;
- anim.mStartedDelay = false;
anim.mStarted = false;
anim.mRunning = false;
anim.mPaused = false;
@@ -1497,9 +1273,10 @@
anim.mStartListenersCalled = false;
anim.mStartTime = 0;
anim.mStartTimeCommitted = false;
+ anim.mAnimationEndRequested = false;
anim.mPauseTime = 0;
+ anim.mLastFrameTime = 0;
anim.mCurrentFraction = 0;
- anim.mDelayStartTime = 0;
PropertyValuesHolder[] oldValues = mValues;
if (oldValues != null) {
@@ -1540,32 +1317,7 @@
* @hide
*/
public static int getCurrentAnimationsCount() {
- AnimationHandler handler = sAnimationHandler.get();
- return handler != null ? handler.mAnimations.size() : 0;
- }
-
- /**
- * Clear all animations on this thread, without canceling or ending them.
- * This should be used with caution.
- *
- * @hide
- */
- public static void clearAllAnimations() {
- AnimationHandler handler = sAnimationHandler.get();
- if (handler != null) {
- handler.mAnimations.clear();
- handler.mPendingAnimations.clear();
- handler.mDelayedAnims.clear();
- }
- }
-
- private static AnimationHandler getOrCreateAnimationHandler() {
- AnimationHandler handler = sAnimationHandler.get();
- if (handler == null) {
- handler = new AnimationHandler();
- sAnimationHandler.set(handler);
- }
- return handler;
+ return AnimationHandler.getAnimationCount();
}
@Override
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index fe79629..412e3cd 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1727,7 +1727,8 @@
String[] libDirs, int displayId, Configuration overrideConfiguration,
LoadedApk pkgInfo) {
return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
- displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo());
+ displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(),
+ pkgInfo.getClassLoader());
}
final Handler getHandler() {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 235f294..fca5567 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1838,7 +1838,7 @@
resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
- overrideConfiguration, compatInfo);
+ overrideConfiguration, compatInfo, packageInfo.getClassLoader());
}
}
mResources = resources;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 2117597..1605b3e 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -157,7 +157,8 @@
*/
Resources getTopLevelResources(String resDir, String[] splitResDirs,
String[] overlayDirs, String[] libDirs, int displayId,
- Configuration overrideConfiguration, CompatibilityInfo compatInfo) {
+ Configuration overrideConfiguration, CompatibilityInfo compatInfo,
+ ClassLoader classLoader) {
final float scale = compatInfo.applicationScale;
Configuration overrideConfigCopy = (overrideConfiguration != null)
? new Configuration(overrideConfiguration) : null;
@@ -237,7 +238,7 @@
} else {
config = getConfiguration();
}
- r = new Resources(assets, dm, config, compatInfo);
+ r = new Resources(assets, dm, config, compatInfo, classLoader);
if (DEBUG) Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
+ r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale);
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 7718a36..9ea2ba2 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -401,7 +401,19 @@
activeSet.add(canonicalJournalPath);
if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) {
Log.v(TAG_XML_PARSER, "...automatically generated "
- + canonicalJournalPath + ". Ignore if nonexistant.");
+ + canonicalJournalPath + ". Ignore if nonexistent.");
+ }
+ }
+
+ // Special case for sharedpref files (not dirs) also add ".xml" suffix file.
+ if ("sharedpref".equals(domainFromXml) && !canonicalFile.isDirectory() &&
+ !canonicalFile.getCanonicalPath().endsWith(".xml")) {
+ final String canonicalXmlPath =
+ canonicalFile.getCanonicalPath() + ".xml";
+ activeSet.add(canonicalXmlPath);
+ if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) {
+ Log.v(TAG_XML_PARSER, "...automatically generated "
+ + canonicalXmlPath + ". Ignore if nonexistent.");
}
}
}
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java
index 7a80936..30c11ef 100644
--- a/core/java/android/app/backup/WallpaperBackupHelper.java
+++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -56,11 +56,12 @@
// This path must match what the WallpaperManagerService uses
// TODO: Will need to change if backing up non-primary user's wallpaper
+ // http://b/22388012
public static final String WALLPAPER_IMAGE =
- new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+ new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
"wallpaper").getAbsolutePath();
public static final String WALLPAPER_INFO =
- new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+ new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
"wallpaper_info.xml").getAbsolutePath();
// Use old keys to keep legacy data compatibility and avoid writing two wallpapers
public static final String WALLPAPER_IMAGE_KEY =
@@ -71,8 +72,9 @@
// will be saved to this file from the restore stream, then renamed to the proper
// location if it's deemed suitable.
// TODO: Will need to change if backing up non-primary user's wallpaper
+ // http://b/22388012
private static final String STAGE_FILE =
- new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+ new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
"wallpaper-tmp").getAbsolutePath();
Context mContext;
diff --git a/core/java/android/app/trust/IStrongAuthTracker.aidl b/core/java/android/app/trust/IStrongAuthTracker.aidl
new file mode 100644
index 0000000..36c71bf
--- /dev/null
+++ b/core/java/android/app/trust/IStrongAuthTracker.aidl
@@ -0,0 +1,26 @@
+/*
+**
+** Copyright 2015, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package android.app.trust;
+
+/**
+ * Private API to be notified about strong auth changes
+ *
+ * {@hide}
+ */
+oneway interface IStrongAuthTracker {
+ void onStrongAuthRequiredChanged(int strongAuthRequired, int userId);
+}
\ No newline at end of file
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index 32951d9..2dea545 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -26,11 +26,9 @@
interface ITrustManager {
void reportUnlockAttempt(boolean successful, int userId);
void reportEnabledTrustAgentsChanged(int userId);
- void reportRequireCredentialEntry(int userId);
void registerTrustListener(in ITrustListener trustListener);
void unregisterTrustListener(in ITrustListener trustListener);
void reportKeyguardShowingChanged();
boolean isDeviceLocked(int userId);
boolean isDeviceSecure(int userId);
- boolean hasUserAuthenticatedSinceBoot(int userId);
}
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 8cab565..aff69f0 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -16,13 +16,19 @@
package android.app.trust;
+import android.annotation.IntDef;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseIntArray;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* See {@link com.android.server.trust.TrustManagerService}
@@ -73,21 +79,6 @@
}
/**
- * Reports that trust is disabled until credentials have been entered for user {@param userId}.
- *
- * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
- *
- * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
- */
- public void reportRequireCredentialEntry(int userId) {
- try {
- mService.reportRequireCredentialEntry(userId);
- } catch (RemoteException e) {
- onError(e);
- }
- }
-
- /**
* Reports that the visibility of the keyguard has changed.
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
@@ -147,23 +138,6 @@
}
}
- /**
- * Checks whether the specified user has been authenticated since the last boot.
- *
- * @param userId the user id of the user to check for
- * @return true if the user has authenticated since boot, false otherwise
- *
- * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
- */
- public boolean hasUserAuthenticatedSinceBoot(int userId) {
- try {
- return mService.hasUserAuthenticatedSinceBoot(userId);
- } catch (RemoteException e) {
- onError(e);
- return false;
- }
- }
-
private void onError(Exception e) {
Log.e(TAG, "Error while calling TrustManagerService", e);
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 1f3ff51..2d825fa 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -64,9 +64,7 @@
* <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
* adapter, when running on JELLY_BEAN_MR1 and below, call the
* static {@link #getDefaultAdapter} method; when running on JELLY_BEAN_MR2 and
- * higher, retrieve it through
- * {@link android.content.Context#getSystemService} with
- * {@link android.content.Context#BLUETOOTH_SERVICE}.
+ * higher, call {@link BluetoothManager#getAdapter}.
* Fundamentally, this is your starting point for all
* Bluetooth actions. Once you have the local adapter, you can get a set of
* {@link BluetoothDevice} objects representing all paired devices with
diff --git a/core/java/android/content/RestrictionEntry.java b/core/java/android/content/RestrictionEntry.java
index ab049ec..0473475 100644
--- a/core/java/android/content/RestrictionEntry.java
+++ b/core/java/android/content/RestrictionEntry.java
@@ -456,7 +456,7 @@
if (o == this) return true;
if (!(o instanceof RestrictionEntry)) return false;
final RestrictionEntry other = (RestrictionEntry) o;
- if (mType != other.mType || mKey.equals(other.mKey)) {
+ if (mType != other.mType || !mKey.equals(other.mKey)) {
return false;
}
if (mCurrentValues == null && other.mCurrentValues == null
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index 1fac06e..a7744e7 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -677,7 +677,8 @@
* <table>
* <tr><th>RestrictionEntry</th><th>Bundle</th></tr>
* <tr><td>{@link RestrictionEntry#TYPE_BOOLEAN}</td><td>{@link Bundle#putBoolean}</td></tr>
- * <tr><td>{@link RestrictionEntry#TYPE_CHOICE}, {@link RestrictionEntry#TYPE_CHOICE}</td>
+ * <tr><td>{@link RestrictionEntry#TYPE_CHOICE},
+ * {@link RestrictionEntry#TYPE_MULTI_SELECT}</td>
* <td>{@link Bundle#putStringArray}</td></tr>
* <tr><td>{@link RestrictionEntry#TYPE_INTEGER}</td><td>{@link Bundle#putInt}</td></tr>
* <tr><td>{@link RestrictionEntry#TYPE_STRING}</td><td>{@link Bundle#putString}</td></tr>
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 43cc63b..a59f429 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -273,10 +273,10 @@
public static final int FLAG_RESUME_WHILE_PAUSING = 0x4000;
/**
* @hide Bit in {@link #flags}: If set, this component will only be seen
- * by the primary user. Only works with broadcast receivers. Set from the
- * android.R.attr#primaryUserOnly attribute.
+ * by the system user. Only works with broadcast receivers. Set from the
+ * android.R.attr#systemUserOnly attribute.
*/
- public static final int FLAG_PRIMARY_USER_ONLY = 0x20000000;
+ public static final int FLAG_SYSTEM_USER_ONLY = 0x20000000;
/**
* Bit in {@link #flags}: If set, a single instance of the receiver will
* run for all users on the device. Set from the
@@ -698,6 +698,8 @@
*/
public int lockTaskLaunchMode;
+ public InitialLayout initialLayout;
+
public ActivityInfo() {
}
@@ -717,6 +719,7 @@
maxRecents = orig.maxRecents;
resizeable = orig.resizeable;
lockTaskLaunchMode = orig.lockTaskLaunchMode;
+ initialLayout = orig.initialLayout;
}
/**
@@ -763,9 +766,14 @@
}
pw.println(prefix + "resizeable=" + resizeable + " lockTaskLaunchMode="
+ lockTaskLaunchModeToString(lockTaskLaunchMode));
+ if (initialLayout != null) {
+ pw.println(prefix + "initialLayout=" + initialLayout.width + "|"
+ + initialLayout.widthFraction + ", " + initialLayout.height + "|"
+ + initialLayout.heightFraction + ", " + initialLayout.gravity);
+ }
super.dumpBack(pw, prefix);
}
-
+
public String toString() {
return "ActivityInfo{"
+ Integer.toHexString(System.identityHashCode(this))
@@ -793,6 +801,16 @@
dest.writeInt(maxRecents);
dest.writeInt(resizeable ? 1 : 0);
dest.writeInt(lockTaskLaunchMode);
+ if (initialLayout != null) {
+ dest.writeInt(1);
+ dest.writeInt(initialLayout.width);
+ dest.writeFloat(initialLayout.widthFraction);
+ dest.writeInt(initialLayout.height);
+ dest.writeFloat(initialLayout.heightFraction);
+ dest.writeInt(initialLayout.gravity);
+ } else {
+ dest.writeInt(0);
+ }
}
public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -822,5 +840,33 @@
maxRecents = source.readInt();
resizeable = (source.readInt() == 1);
lockTaskLaunchMode = source.readInt();
+ if (source.readInt() == 1) {
+ initialLayout = new InitialLayout(source);
+ }
+ }
+
+ public static final class InitialLayout {
+ public InitialLayout(int width, float widthFraction, int height, float heightFraction,
+ int gravity) {
+ this.width = width;
+ this.widthFraction = widthFraction;
+ this.height = height;
+ this.heightFraction = heightFraction;
+ this.gravity = gravity;
+ }
+
+ InitialLayout(Parcel source) {
+ width = source.readInt();
+ widthFraction = source.readFloat();
+ height = source.readInt();
+ heightFraction = source.readFloat();
+ gravity = source.readInt();
+ }
+
+ public final int width;
+ public final float widthFraction;
+ public final int height;
+ public final float heightFraction;
+ public final int gravity;
}
}
diff --git a/core/java/android/content/pm/AppsQueryHelper.java b/core/java/android/content/pm/AppsQueryHelper.java
new file mode 100644
index 0000000..56b3173
--- /dev/null
+++ b/core/java/android/content/pm/AppsQueryHelper.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.content.pm;
+
+import android.Manifest;
+import android.app.AppGlobals;
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helper class for querying installed applications using multiple criteria.
+ *
+ * @hide
+ */
+public class AppsQueryHelper {
+
+ /**
+ * Return apps without launcher icon
+ */
+ public static int GET_NON_LAUNCHABLE_APPS = 1;
+
+ /**
+ * Return apps with {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission
+ */
+ public static int GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM = 1 << 1;
+
+ private final Context mContext;
+ private List<ApplicationInfo> mAllApps;
+
+ public AppsQueryHelper(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Return a List of all packages that satisfy a specified criteria.
+ * @param flags search flags. Use any combination of {@link #GET_NON_LAUNCHABLE_APPS},
+ * {@link #GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM}
+ * @param systemAppsOnly if true, only system apps will be returned
+ * @param user user, whose apps are queried
+ */
+ public List<String> queryApps(int flags, boolean systemAppsOnly, UserHandle user) {
+ boolean nonLaunchableApps = (flags & GET_NON_LAUNCHABLE_APPS) > 0;
+ boolean interactAcrossUsers = (flags & GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM) > 0;
+ if (mAllApps == null) {
+ mAllApps = getAllApps(user.getIdentifier());
+ }
+
+ List<String> result = new ArrayList<>();
+ if (flags == 0) {
+ final int allAppsSize = mAllApps.size();
+ for (int i = 0; i < allAppsSize; i++) {
+ final ApplicationInfo appInfo = mAllApps.get(i);
+ if (systemAppsOnly && !appInfo.isSystemApp()) {
+ continue;
+ }
+ result.add(appInfo.packageName);
+ }
+ return result;
+ }
+
+ if (nonLaunchableApps) {
+ Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
+ final List<ResolveInfo> resolveInfos = queryIntentActivitiesAsUser(intent,
+ user.getIdentifier());
+
+ ArraySet<String> appsWithLaunchers = new ArraySet<>();
+ final int resolveInfosSize = resolveInfos.size();
+ for (int i = 0; i < resolveInfosSize; i++) {
+ appsWithLaunchers.add(resolveInfos.get(i).activityInfo.packageName);
+ }
+ final int allAppsSize = mAllApps.size();
+ for (int i = 0; i < allAppsSize; i++) {
+ final ApplicationInfo appInfo = mAllApps.get(i);
+ if (systemAppsOnly && !appInfo.isSystemApp()) {
+ continue;
+ }
+ final String packageName = appInfo.packageName;
+ if (!appsWithLaunchers.contains(packageName)) {
+ result.add(packageName);
+ }
+ }
+ }
+
+ if (interactAcrossUsers) {
+ final List<PackageInfo> packagesHoldingPermissions = getPackagesHoldingPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS, user.getIdentifier());
+ final int packagesHoldingPermissionsSize = packagesHoldingPermissions.size();
+ for (int i = 0; i < packagesHoldingPermissionsSize; i++) {
+ PackageInfo packageInfo = packagesHoldingPermissions.get(i);
+ if (systemAppsOnly && !packageInfo.applicationInfo.isSystemApp()) {
+ continue;
+ }
+ if (!result.contains(packageInfo.packageName)) {
+ result.add(packageInfo.packageName);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ @VisibleForTesting
+ @SuppressWarnings("unchecked")
+ protected List<ApplicationInfo> getAllApps(int userId) {
+ try {
+ return AppGlobals.getPackageManager().getInstalledApplications(
+ PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_DISABLED_COMPONENTS, userId).getList();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Package manager has died", e);
+ }
+ }
+
+ @VisibleForTesting
+ protected List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int userId) {
+ return mContext.getPackageManager()
+ .queryIntentActivitiesAsUser(intent, PackageManager.GET_DISABLED_COMPONENTS
+ | PackageManager.GET_UNINSTALLED_PACKAGES, userId);
+ }
+
+ @VisibleForTesting
+ @SuppressWarnings("unchecked")
+ protected List<PackageInfo> getPackagesHoldingPermission(String perm, int userId) {
+ try {
+ return AppGlobals.getPackageManager().getPackagesHoldingPermissions(new String[]{perm},
+ 0, userId).getList();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Package manager has died", e);
+ }
+ }
+}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ed7a2a3..968f9b2 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -50,6 +50,7 @@
import android.util.Pair;
import android.util.Slog;
import android.util.TypedValue;
+import android.view.Gravity;
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
@@ -3137,8 +3138,8 @@
a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
}
- if (sa.getBoolean(R.styleable.AndroidManifestActivity_primaryUserOnly, false)) {
- a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
+ a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
}
if (!receiver) {
@@ -3260,10 +3261,12 @@
owner.preferredActivityFilters.add(intent);
}
} else if (parser.getName().equals("meta-data")) {
- if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
+ if ((a.metaData = parseMetaData(res, parser, attrs, a.metaData,
outError)) == null) {
return null;
}
+ } else if (!receiver && parser.getName().equals("initial-layout")) {
+ parseInitialLayout(res, attrs, a);
} else {
if (!RIGID_PARSER) {
Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
@@ -3296,6 +3299,43 @@
return a;
}
+ private void parseInitialLayout(Resources res, AttributeSet attrs, Activity a) {
+ TypedArray sw = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.AndroidManifestInitialLayout);
+ int width = -1;
+ float widthFraction = -1f;
+ int height = -1;
+ float heightFraction = -1f;
+ final int widthType = sw.getType(
+ com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth);
+ if (widthType == TypedValue.TYPE_FRACTION) {
+ widthFraction = sw.getFraction(
+ com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth,
+ 1, 1, -1);
+ } else if (widthType == TypedValue.TYPE_DIMENSION) {
+ width = sw.getDimensionPixelSize(
+ com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth,
+ -1);
+ }
+ final int heightType = sw.getType(
+ com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight);
+ if (heightType == TypedValue.TYPE_FRACTION) {
+ heightFraction = sw.getFraction(
+ com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight,
+ 1, 1, -1);
+ } else if (heightType == TypedValue.TYPE_DIMENSION) {
+ height = sw.getDimensionPixelSize(
+ com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight,
+ -1);
+ }
+ int gravity = sw.getInt(
+ com.android.internal.R.styleable.AndroidManifestInitialLayout_gravity,
+ Gravity.CENTER);
+ sw.recycle();
+ a.info.initialLayout = new ActivityInfo.InitialLayout(width, widthFraction,
+ height, heightFraction, gravity);
+ }
+
private Activity parseActivityAlias(Package owner, Resources res,
XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
throws XmlPullParserException, IOException {
@@ -3375,6 +3415,7 @@
info.uiOptions = target.info.uiOptions;
info.parentActivityName = target.info.parentActivityName;
info.maxRecents = target.info.maxRecents;
+ info.initialLayout = target.info.initialLayout;
Activity a = new Activity(mParseActivityAliasArgs, info);
if (outError[0] != null) {
@@ -4702,7 +4743,7 @@
private static boolean copyNeeded(int flags, Package p,
PackageUserState state, Bundle metaData, int userId) {
- if (userId != UserHandle.USER_OWNER) {
+ if (userId != UserHandle.USER_SYSTEM) {
// We always need to copy for other users, since we need
// to fix up the uid.
return true;
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index b293e2a..b3f03c3 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -213,7 +213,7 @@
@Override
public void onReceive(Context context, Intent intent) {
// External apps can't coexist with multi-user, so scan owner
- handlePackageEvent(intent, UserHandle.USER_OWNER);
+ handlePackageEvent(intent, UserHandle.USER_SYSTEM);
}
};
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index cbd2f78..2aae1de 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -129,6 +129,15 @@
}
/**
+ * Returns true if the user is a split system user.
+ * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
+ * the method always returns false.
+ */
+ public boolean isSystemOnly() {
+ return id == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
+ }
+
+ /**
* @return true if this user can be switched to.
**/
public boolean supportsSwitchTo() {
@@ -145,6 +154,18 @@
return (!hideSystemUser || id != UserHandle.USER_SYSTEM) && supportsSwitchTo();
}
+ /* @hide */
+ public boolean canHaveProfile() {
+ if (isManagedProfile() || isGuest() || isRestricted()) {
+ return false;
+ }
+ if (UserManager.isSplitSystemUser()) {
+ return id != UserHandle.USER_SYSTEM;
+ } else {
+ return id == UserHandle.USER_SYSTEM;
+ }
+ }
+
public UserInfo() {
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ae92108..e29bd2c 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -20,6 +20,7 @@
import android.annotation.ColorInt;
import android.annotation.StyleRes;
import android.annotation.StyleableRes;
+import android.graphics.drawable.DrawableInflater;
import android.icu.text.PluralRules;
import com.android.internal.util.GrowingArrayUtils;
import com.android.internal.util.XmlUtils;
@@ -142,6 +143,9 @@
private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
new ConfigurationBoundResourceCache<>(this);
+ /** Used to inflate drawable objects from XML. */
+ private DrawableInflater mDrawableInflater;
+
private TypedValue mTmpValue = new TypedValue();
private boolean mPreloading;
@@ -150,6 +154,7 @@
private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4];
final AssetManager mAssets;
+ final ClassLoader mClassLoader;
final DisplayMetrics mMetrics = new DisplayMetrics();
private final Configuration mConfiguration = new Configuration();
@@ -204,6 +209,17 @@
}
/**
+ * @return the inflater used to create drawable objects
+ * @hide Pending API finalization.
+ */
+ public final DrawableInflater getDrawableInflater() {
+ if (mDrawableInflater == null) {
+ mDrawableInflater = new DrawableInflater(this, mClassLoader);
+ }
+ return mDrawableInflater;
+ }
+
+ /**
* Used by AnimatorInflater.
*
* @hide
@@ -245,7 +261,7 @@
* selecting/computing resource values (optional).
*/
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
- this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
+ this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
}
/**
@@ -257,11 +273,15 @@
* @param config Desired device configuration to consider when
* selecting/computing resource values (optional).
* @param compatInfo this resource's compatibility info. Must not be null.
+ * @param classLoader class loader for the package used to load custom
+ * resource classes, may be {@code null} to use system
+ * class loader
* @hide
*/
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config,
- CompatibilityInfo compatInfo) {
+ CompatibilityInfo compatInfo, @Nullable ClassLoader classLoader) {
mAssets = assets;
+ mClassLoader = classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
mMetrics.setToDefaults();
if (compatInfo != null) {
mCompatibilityInfo = compatInfo;
@@ -2803,6 +2823,7 @@
private Resources() {
mAssets = AssetManager.getSystem();
+ mClassLoader = ClassLoader.getSystemClassLoader();
// NOTE: Intentionally leaving this uninitialized (all values set
// to zero), so that anyone who tries to do something that requires
// metrics will get a very wrong value.
diff --git a/core/java/android/hardware/ICameraServiceProxy.aidl b/core/java/android/hardware/ICameraServiceProxy.aidl
index 0bb24bc..0e654d5 100644
--- a/core/java/android/hardware/ICameraServiceProxy.aidl
+++ b/core/java/android/hardware/ICameraServiceProxy.aidl
@@ -19,6 +19,8 @@
/**
* Binder interface for the camera service proxy running in system_server.
*
+ * Keep in sync with frameworks/av/include/camera/ICameraServiceProxy.h
+ *
* @hide
*/
interface ICameraServiceProxy
@@ -27,4 +29,9 @@
* Ping the service proxy to update the valid users for the camera service.
*/
oneway void pingForUserUpdate();
+
+ /**
+ * Update the status of a camera device
+ */
+ oneway void notifyCameraState(String cameraId, int newCameraState);
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 5583920..a2ef078 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1003,13 +1003,13 @@
/**
* <p>The orientation of the camera relative to the sensor
* coordinate system.</p>
- * <p>The four coefficients that describe the quarternion
+ * <p>The four coefficients that describe the quaternion
* rotation from the Android sensor coordinate system to a
* camera-aligned coordinate system where the X-axis is
* aligned with the long side of the image sensor, the Y-axis
* is aligned with the short side of the image sensor, and
* the Z-axis is aligned with the optical axis of the sensor.</p>
- * <p>To convert from the quarternion coefficients <code>(x,y,z,w)</code>
+ * <p>To convert from the quaternion coefficients <code>(x,y,z,w)</code>
* to the axis of rotation <code>(a_x, a_y, a_z)</code> and rotation
* amount <code>theta</code>, the following formulas can be used:</p>
* <pre><code> theta = 2 * acos(w)
@@ -1018,7 +1018,7 @@
* a_z = z / sin(theta/2)
* </code></pre>
* <p>To create a 3x3 rotation matrix that applies the rotation
- * defined by this quarternion, the following matrix can be
+ * defined by this quaternion, the following matrix can be
* used:</p>
* <pre><code>R = [ 1 - 2y^2 - 2z^2, 2xy - 2zw, 2xz + 2yw,
* 2xy + 2zw, 1 - 2x^2 - 2z^2, 2yz - 2xw,
@@ -1030,7 +1030,7 @@
* <p>where <code>p</code> is in the device sensor coordinate system, and
* <code>p'</code> is in the camera-oriented coordinate system.</p>
* <p><b>Units</b>:
- * Quarternion coefficients</p>
+ * Quaternion coefficients</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*/
@PublicKey
@@ -1052,13 +1052,13 @@
* user's perspective) will report <code>(0.03, 0, 0)</code>.</p>
* <p>To transform a pixel coordinates between two cameras
* facing the same direction, first the source camera
- * android.lens.radialDistortion must be corrected for. Then
- * the source camera android.lens.intrinsicCalibration needs
+ * {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion} must be corrected for. Then
+ * the source camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs
* to be applied, followed by the {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}
* of the source camera, the translation of the source camera
* relative to the destination camera, the
* {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the destination camera, and
- * finally the inverse of android.lens.intrinsicCalibration
+ * finally the inverse of {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}
* of the destination camera. This obtains a
* radial-distortion-free coordinate in the destination
* camera pixel coordinates.</p>
@@ -1069,7 +1069,9 @@
* <p><b>Units</b>: Meters</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
* @see CameraCharacteristics#LENS_POSE_ROTATION
+ * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
*/
@PublicKey
public static final Key<float[]> LENS_POSE_TRANSLATION =
@@ -1115,7 +1117,7 @@
* where <code>(0,0)</code> is the top-left of the
* preCorrectionActiveArraySize rectangle. Once the pose and
* intrinsic calibration transforms have been applied to a
- * world point, then the android.lens.radialDistortion
+ * world point, then the {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}
* transform needs to be applied, and the result adjusted to
* be in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
* system (where <code>(0, 0)</code> is the top-left of the
@@ -1130,6 +1132,7 @@
*
* @see CameraCharacteristics#LENS_POSE_ROTATION
* @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@@ -1156,7 +1159,7 @@
* </code></pre>
* <p>The pixel coordinates are defined in a normalized
* coordinate system related to the
- * android.lens.intrinsicCalibration calibration fields.
+ * {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} calibration fields.
* Both <code>[x_i, y_i]</code> and <code>[x_c, y_c]</code> have <code>(0,0)</code> at the
* lens optical center <code>[c_x, c_y]</code>. The maximum magnitudes
* of both x and y coordinates are normalized to be 1 at the
@@ -1169,6 +1172,8 @@
* <p><b>Units</b>:
* Unitless coefficients.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
*/
@PublicKey
public static final Key<float[]> LENS_RADIAL_DISTORTION =
@@ -2262,7 +2267,7 @@
* {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
* <p>The currently supported fields that correct for geometric distortion are:</p>
* <ol>
- * <li>android.lens.radialDistortion.</li>
+ * <li>{@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}.</li>
* </ol>
* <p>If all of the geometric distortion fields are no-ops, this rectangle will be the same
* as the post-distortion-corrected rectangle given in
@@ -2275,6 +2280,7 @@
* <p><b>Units</b>: Pixel coordinates on the image sensor</p>
* <p>This key is available on all devices.</p>
*
+ * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
* @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 4a71aa0..20b0be1 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -480,8 +480,11 @@
* the configurations in the tables below are also guaranteed for creating a reprocessable
* capture session if the camera device supports YUV reprocessing or PRIVATE reprocessing.
* However, not all output targets used to create a reprocessable session may be used in a
- * {@link CaptureRequest} simultaneously. The guaranteed output targets that can be included
- * in a {@link CaptureRequest} simultaneously are listed in the tables under
+ * {@link CaptureRequest} simultaneously. For devices that support only 1 output target in a
+ * reprocess {@link CaptureRequest}, submitting a reprocess {@link CaptureRequest} with multiple
+ * output targets will result in a {@link CaptureFailure}. For devices that support multiple
+ * output targets in a reprocess {@link CaptureRequest}, the guaranteed output targets that can
+ * be included in a {@link CaptureRequest} simultaneously are listed in the tables under
* {@link #createCaptureSession createCaptureSession}. For example, with a FULL-capability
* ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL} {@code == }
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) device that supports PRIVATE
@@ -532,8 +535,6 @@
* <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code RECORD}</td> <td></td><td id="rb"></td> <td>High-resolution ZSL in-app video processing with regular preview.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>Maximum-resolution ZSL in-app processing with regular preview.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>Maximum-resolution two-input ZSL in-app processing.</td> </tr>
- * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code RECORD}</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD}</td> <td>High-resolution ZSL in-app video processing and video snapshot with regular preview.</td> </tr>
- * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Maximum-resolution two-input ZSL in-app processing with regular preview.</td> </tr>
* <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>ZSL still capture and in-app processing.</td> </tr>
* </table><br>
* </p>
@@ -711,7 +712,9 @@
* provide input images to camera device via {@link android.media.ImageWriter#queueInputImage}.
* The application must use the capture result of one of those output images to create a
* reprocess capture request so that the camera device can use the information to achieve
- * optimal reprocess image quality.
+ * optimal reprocess image quality. For camera devices that support only 1 output
+ * {@link Surface}, submitting a reprocess {@link CaptureRequest} with multiple
+ * output targets will result in a {@link CaptureFailure}.
*
* @param inputResult The capture result of the output image or one of the output images used
* to generate the reprocess input image for this capture request.
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index c580083..35a1d96 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -647,8 +647,8 @@
* {@link android.hardware.camera2.CaptureResult }:<ul>
* <li>{@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}</li>
* <li>{@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}</li>
- * <li>android.lens.intrinsicCalibration</li>
- * <li>android.lens.radialDistortion</li>
+ * <li>{@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}</li>
+ * <li>{@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}</li>
* </ul>
* </li>
* <li>The {@link CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE android.depth.depthIsExclusive} entry is listed by this device.</li>
@@ -667,8 +667,10 @@
*
* @see CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE
* @see CameraCharacteristics#LENS_FACING
+ * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
* @see CameraCharacteristics#LENS_POSE_ROTATION
* @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d5511c1..46eddb3 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2602,13 +2602,13 @@
/**
* <p>The orientation of the camera relative to the sensor
* coordinate system.</p>
- * <p>The four coefficients that describe the quarternion
+ * <p>The four coefficients that describe the quaternion
* rotation from the Android sensor coordinate system to a
* camera-aligned coordinate system where the X-axis is
* aligned with the long side of the image sensor, the Y-axis
* is aligned with the short side of the image sensor, and
* the Z-axis is aligned with the optical axis of the sensor.</p>
- * <p>To convert from the quarternion coefficients <code>(x,y,z,w)</code>
+ * <p>To convert from the quaternion coefficients <code>(x,y,z,w)</code>
* to the axis of rotation <code>(a_x, a_y, a_z)</code> and rotation
* amount <code>theta</code>, the following formulas can be used:</p>
* <pre><code> theta = 2 * acos(w)
@@ -2617,7 +2617,7 @@
* a_z = z / sin(theta/2)
* </code></pre>
* <p>To create a 3x3 rotation matrix that applies the rotation
- * defined by this quarternion, the following matrix can be
+ * defined by this quaternion, the following matrix can be
* used:</p>
* <pre><code>R = [ 1 - 2y^2 - 2z^2, 2xy - 2zw, 2xz + 2yw,
* 2xy + 2zw, 1 - 2x^2 - 2z^2, 2yz - 2xw,
@@ -2629,7 +2629,7 @@
* <p>where <code>p</code> is in the device sensor coordinate system, and
* <code>p'</code> is in the camera-oriented coordinate system.</p>
* <p><b>Units</b>:
- * Quarternion coefficients</p>
+ * Quaternion coefficients</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*/
@PublicKey
@@ -2651,13 +2651,13 @@
* user's perspective) will report <code>(0.03, 0, 0)</code>.</p>
* <p>To transform a pixel coordinates between two cameras
* facing the same direction, first the source camera
- * android.lens.radialDistortion must be corrected for. Then
- * the source camera android.lens.intrinsicCalibration needs
+ * {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion} must be corrected for. Then
+ * the source camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs
* to be applied, followed by the {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}
* of the source camera, the translation of the source camera
* relative to the destination camera, the
* {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the destination camera, and
- * finally the inverse of android.lens.intrinsicCalibration
+ * finally the inverse of {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}
* of the destination camera. This obtains a
* radial-distortion-free coordinate in the destination
* camera pixel coordinates.</p>
@@ -2668,7 +2668,9 @@
* <p><b>Units</b>: Meters</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
* @see CameraCharacteristics#LENS_POSE_ROTATION
+ * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
*/
@PublicKey
public static final Key<float[]> LENS_POSE_TRANSLATION =
@@ -2714,7 +2716,7 @@
* where <code>(0,0)</code> is the top-left of the
* preCorrectionActiveArraySize rectangle. Once the pose and
* intrinsic calibration transforms have been applied to a
- * world point, then the android.lens.radialDistortion
+ * world point, then the {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}
* transform needs to be applied, and the result adjusted to
* be in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
* system (where <code>(0, 0)</code> is the top-left of the
@@ -2729,6 +2731,7 @@
*
* @see CameraCharacteristics#LENS_POSE_ROTATION
* @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@@ -2755,7 +2758,7 @@
* </code></pre>
* <p>The pixel coordinates are defined in a normalized
* coordinate system related to the
- * android.lens.intrinsicCalibration calibration fields.
+ * {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} calibration fields.
* Both <code>[x_i, y_i]</code> and <code>[x_c, y_c]</code> have <code>(0,0)</code> at the
* lens optical center <code>[c_x, c_y]</code>. The maximum magnitudes
* of both x and y coordinates are normalized to be 1 at the
@@ -2768,6 +2771,8 @@
* <p><b>Units</b>:
* Unitless coefficients.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
*/
@PublicKey
public static final Key<float[]> LENS_RADIAL_DISTORTION =
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index e786707..fddfbde 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -338,6 +338,8 @@
} else {
sizedSurfaces.add(new Pair<>(output, s));
}
+ // Lock down the size before configuration
+ setSurfaceDimens(output, s.getWidth(), s.getHeight());
} catch (BufferQueueAbandonedException e) {
Log.e(TAG, "Surface bufferqueue is abandoned, cannot configure as output: ", e);
return BAD_VALUE;
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 7aa9787..a04cdce 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -19,7 +19,9 @@
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.utils.HashCodeHelpers;
+import android.hardware.camera2.utils.SurfaceUtils;
import android.util.Log;
+import android.util.Size;
import android.view.Surface;
import android.os.Parcel;
import android.os.Parcelable;
@@ -66,9 +68,7 @@
*
*/
public OutputConfiguration(Surface surface) {
- checkNotNull(surface, "Surface must not be null");
- mSurface = surface;
- mRotation = ROTATION_0;
+ this(surface, ROTATION_0);
}
/**
@@ -94,6 +94,9 @@
checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
mSurface = surface;
mRotation = rotation;
+ mConfiguredSize = SurfaceUtils.getSurfaceSize(surface);
+ mConfiguredFormat = SurfaceUtils.getSurfaceFormat(surface);
+ mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(surface);
}
/**
@@ -106,6 +109,9 @@
checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
mSurface = surface;
mRotation = rotation;
+ mConfiguredSize = SurfaceUtils.getSurfaceSize(mSurface);
+ mConfiguredFormat = SurfaceUtils.getSurfaceFormat(mSurface);
+ mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(mSurface);
}
/**
@@ -163,8 +169,9 @@
/**
* Check if this {@link OutputConfiguration} is equal to another {@link OutputConfiguration}.
*
- * <p>Two output configurations are only equal if and only if the underlying surface and
- * all other configuration parameters are equal. </p>
+ * <p>Two output configurations are only equal if and only if the underlying surfaces, surface
+ * properties (width, height, format, dataspace) when the output configurations are created,
+ * and all other configuration parameters are equal. </p>
*
* @return {@code true} if the objects were equal, {@code false} otherwise
*/
@@ -176,7 +183,11 @@
return true;
} else if (obj instanceof OutputConfiguration) {
final OutputConfiguration other = (OutputConfiguration) obj;
- return (mSurface == other.mSurface && mRotation == other.mRotation);
+ return mSurface == other.mSurface &&
+ mRotation == other.mRotation &&
+ mConfiguredSize.equals(other.mConfiguredSize) &&
+ mConfiguredFormat == other.mConfiguredFormat &&
+ mConfiguredDataspace == other.mConfiguredDataspace;
}
return false;
}
@@ -192,4 +203,9 @@
private static final String TAG = "OutputConfiguration";
private final Surface mSurface;
private final int mRotation;
+
+ // The size, format, and dataspace of the surface when OutputConfiguration is created.
+ private final Size mConfiguredSize;
+ private final int mConfiguredFormat;
+ private final int mConfiguredDataspace;
}
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index e71e49f..b8d6960 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -1290,7 +1290,7 @@
for (StreamConfiguration config : configurations) {
int fmt = config.getFormat();
if (fmt == format && config.isOutput() == output) {
- if (output) {
+ if (output && mListHighResolution) {
// Filter slow high-res output formats; include for
// highRes, remove for !highRes
long duration = 0;
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 061fad9..7cff11b 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -395,7 +395,7 @@
* Request authentication of a crypto object. This call warms up the fingerprint hardware
* and starts scanning for a fingerprint. It terminates when
* {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
- * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at
+ * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
* which point the object is no longer valid. The operation can be canceled by using the
* provided cancel object.
*
diff --git a/core/java/android/hardware/location/ActivityRecognitionHardware.java b/core/java/android/hardware/location/ActivityRecognitionHardware.java
index 5d3953a..8acd1ff 100644
--- a/core/java/android/hardware/location/ActivityRecognitionHardware.java
+++ b/core/java/android/hardware/location/ActivityRecognitionHardware.java
@@ -30,20 +30,34 @@
* @hide
*/
public class ActivityRecognitionHardware extends IActivityRecognitionHardware.Stub {
- private static final String TAG = "ActivityRecognitionHardware";
+ private static final String TAG = "ActivityRecognitionHW";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+ private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+ + HARDWARE_PERMISSION + "' not granted to access ActivityRecognitionHardware";
+
private static final int INVALID_ACTIVITY_TYPE = -1;
private static final int NATIVE_SUCCESS_RESULT = 0;
+ private static final int EVENT_TYPE_DISABLED = 0;
+ private static final int EVENT_TYPE_ENABLED = 1;
- private static ActivityRecognitionHardware sSingletonInstance = null;
+ /**
+ * Contains the number of supported Event Types.
+ *
+ * NOTE: increment this counter every time a new EVENT_TYPE_ is added to
+ * com.android.location.provider.ActivityRecognitionProvider
+ */
+ private static final int EVENT_TYPE_COUNT = 3;
+
+ private static ActivityRecognitionHardware sSingletonInstance;
private static final Object sSingletonInstanceLock = new Object();
private final Context mContext;
+ private final int mSupportedActivitiesCount;
private final String[] mSupportedActivities;
-
- private final RemoteCallbackList<IActivityRecognitionHardwareSink> mSinks =
- new RemoteCallbackList<IActivityRecognitionHardwareSink>();
+ private final int[][] mSupportedActivitiesEnabledEvents;
+ private final SinkList mSinks = new SinkList();
private static class Event {
public int activity;
@@ -56,6 +70,8 @@
mContext = context;
mSupportedActivities = fetchSupportedActivities();
+ mSupportedActivitiesCount = mSupportedActivities.length;
+ mSupportedActivitiesEnabledEvents = new int[mSupportedActivitiesCount][EVENT_TYPE_COUNT];
}
public static ActivityRecognitionHardware getInstance(Context context) {
@@ -107,7 +123,11 @@
}
int result = nativeEnableActivityEvent(activityType, eventType, reportLatencyNs);
- return result == NATIVE_SUCCESS_RESULT;
+ if (result == NATIVE_SUCCESS_RESULT) {
+ mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_ENABLED;
+ return true;
+ }
+ return false;
}
@Override
@@ -120,7 +140,11 @@
}
int result = nativeDisableActivityEvent(activityType, eventType);
- return result == NATIVE_SUCCESS_RESULT;
+ if (result == NATIVE_SUCCESS_RESULT) {
+ mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED;
+ return true;
+ }
+ return false;
}
@Override
@@ -135,7 +159,7 @@
*/
private void onActivityChanged(Event[] events) {
if (events == null || events.length == 0) {
- Log.d(TAG, "No events to broadcast for onActivityChanged.");
+ if (DEBUG) Log.d(TAG, "No events to broadcast for onActivityChanged.");
return;
}
@@ -161,7 +185,6 @@
}
}
mSinks.finishBroadcast();
-
}
private String getActivityName(int activityType) {
@@ -193,10 +216,7 @@
}
private void checkPermissions() {
- String message = String.format(
- "Permission '%s' not granted to access ActivityRecognitionHardware",
- HARDWARE_PERMISSION);
- mContext.enforceCallingPermission(HARDWARE_PERMISSION, message);
+ mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
}
private String[] fetchSupportedActivities() {
@@ -208,6 +228,39 @@
return new String[0];
}
+ private class SinkList extends RemoteCallbackList<IActivityRecognitionHardwareSink> {
+ @Override
+ public void onCallbackDied(IActivityRecognitionHardwareSink callback) {
+ int callbackCount = mSinks.getRegisteredCallbackCount();
+ if (DEBUG) Log.d(TAG, "RegisteredCallbackCount: " + callbackCount);
+ if (callbackCount != 0) {
+ return;
+ }
+ // currently there is only one client for this, so if all its sinks have died, we clean
+ // up after them, this ensures that the AR HAL is not out of sink
+ for (int activity = 0; activity < mSupportedActivitiesCount; ++activity) {
+ for (int event = 0; event < EVENT_TYPE_COUNT; ++event) {
+ disableActivityEventIfEnabled(activity, event);
+ }
+ }
+ }
+
+ private void disableActivityEventIfEnabled(int activityType, int eventType) {
+ if (mSupportedActivitiesEnabledEvents[activityType][eventType] != EVENT_TYPE_ENABLED) {
+ return;
+ }
+
+ int result = nativeDisableActivityEvent(activityType, eventType);
+ mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED;
+ String message = String.format(
+ "DisableActivityEvent: activityType=%d, eventType=%d, result=%d",
+ activityType,
+ eventType,
+ result);
+ Log.e(TAG, message);
+ }
+ }
+
// native bindings
static { nativeClassInit(); }
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 3b3ee52..a23a6cb 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -70,6 +70,8 @@
* <li> {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the
* MIDI function is enabled
* </ul>
+ * If the sticky intent has not been found, that indicates USB is disconnected,
+ * USB is not configued, MTP function is enabled, and all the other functions are disabled.
*
* {@hide}
*/
@@ -592,7 +594,7 @@
/** @hide */
public static String addFunction(String functions, String function) {
- if ("none".equals(functions)) {
+ if (USB_FUNCTION_NONE.equals(functions)) {
return function;
}
if (!containsFunction(functions, function)) {
@@ -613,7 +615,7 @@
}
}
if (split.length == 1 && split[0] == null) {
- return "none";
+ return USB_FUNCTION_NONE;
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < split.length; i++) {
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index a6d477f..3bd12c0 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -351,8 +351,12 @@
public void maybeMarkCapabilitiesRestricted() {
// If all the capabilities are typically provided by restricted networks, conclude that this
// network is restricted.
- if ((mNetworkCapabilities & ~(DEFAULT_CAPABILITIES | RESTRICTED_CAPABILITIES)) == 0)
+ if ((mNetworkCapabilities & ~(DEFAULT_CAPABILITIES | RESTRICTED_CAPABILITIES)) == 0 &&
+ // Must have at least some restricted capabilities, otherwise a request for an
+ // internet-less network will get marked restricted.
+ (mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0) {
removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+ }
}
/**
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index 29daf35..ec76b8a 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -94,8 +94,9 @@
PackageManager pm = context.getPackageManager();
// Only apps installed under the primary user of the device can be scorers.
+ // TODO: http://b/23422763
List<ResolveInfo> receivers =
- pm.queryBroadcastReceivers(SCORE_INTENT, 0 /* flags */, UserHandle.USER_OWNER);
+ pm.queryBroadcastReceivers(SCORE_INTENT, 0 /* flags */, UserHandle.USER_SYSTEM);
for (ResolveInfo receiver : receivers) {
// This field is a misnomer, see android.content.pm.ResolveInfo#activityInfo
final ActivityInfo receiverInfo = receiver.activityInfo;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 80169a9..4ad9d6d 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -169,7 +169,7 @@
/**
* Current version of checkin data format.
*/
- static final String CHECKIN_VERSION = "14";
+ static final String CHECKIN_VERSION = "15";
/**
* Old version, we hit 9 and ran out of room, need to remove.
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 364c0eb..aeb5d45 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -43,7 +43,7 @@
UserInfo getPrimaryUser();
List<UserInfo> getUsers(boolean excludeDying);
List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
- boolean canAddMoreManagedProfiles();
+ boolean canAddMoreManagedProfiles(int userId);
UserInfo getProfileParent(int userHandle);
UserInfo getUserInfo(int userHandle);
long getUserCreationTime(int userHandle);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index aea5123..849f5de 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1024,9 +1024,9 @@
* @return true if more managed profiles can be added, false if limit has been reached.
* @hide
*/
- public boolean canAddMoreManagedProfiles() {
+ public boolean canAddMoreManagedProfiles(int userId) {
try {
- return mService.canAddMoreManagedProfiles();
+ return mService.canAddMoreManagedProfiles(userId);
} catch (RemoteException re) {
Log.w(TAG, "Could not check if we can add more managed profiles", re);
return false;
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index ef54d84..6888594 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -341,6 +341,7 @@
}
String description = null;
+ String derivedFsUuid = fsUuid;
long mtpReserveSize = 0;
long maxFileSize = 0;
int mtpStorageId = StorageVolume.STORAGE_ID_INVALID;
@@ -351,6 +352,7 @@
final VolumeInfo privateVol = storage.findPrivateForEmulated(this);
if (privateVol != null) {
description = storage.getBestVolumeDescription(privateVol);
+ derivedFsUuid = privateVol.fsUuid;
}
if (isPrimary()) {
@@ -393,7 +395,7 @@
return new StorageVolume(id, mtpStorageId, userPath, description, isPrimary(), removable,
emulated, mtpReserveSize, allowMassStorage, maxFileSize, new UserHandle(userId),
- fsUuid, envState);
+ derivedFsUuid, envState);
}
public static int buildStableMtpStorageId(String fsUuid) {
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 80bdbf1..2c7bf65 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -16,7 +16,6 @@
package android.service.notification;
-import android.annotation.SystemApi;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
@@ -26,10 +25,7 @@
/**
* Condition information from condition providers.
- *
- * @hide
*/
-@SystemApi
public class Condition implements Parcelable {
public static final String SCHEME = "condition";
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index 03ee726..2a8fb2c 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -17,9 +17,9 @@
package android.service.notification;
import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
import android.app.INotificationManager;
import android.app.Service;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -33,7 +33,10 @@
* A service that provides conditions about boolean state.
* <p>To extend this class, you must declare the service in your manifest file with
* the {@link android.Manifest.permission#BIND_CONDITION_PROVIDER_SERVICE} permission
- * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. If you want users to be
+ * able to create and update conditions for this service to monitor, include the
+ * {@link #META_DATA_RULE_TYPE}, {@link #META_DATA_DEFAULT_CONDITION_ID}, and
+ * {@link #META_DATA_CONFIGURATION_ACTIVITY} tags. For example:</p>
* <pre>
* <service android:name=".MyConditionProvider"
* android:label="@string/service_name"
@@ -41,11 +44,21 @@
* <intent-filter>
* <action android:name="android.service.notification.ConditionProviderService" />
* </intent-filter>
+ * <meta-data
+ * android:name="android.service.zen.automatic.ruleType"
+ * android:value="@string/my_condition_rule">
+ * </meta-data>
+ * <meta-data
+ * android:name="android.service.zen.automatic.defaultConditionId"
+ * android:value="condition://com.my.package/mycondition">
+ * </meta-data>
+ * <meta-data
+ * android:name="android.service.zen.automatic.configurationActivity"
+ * android:value="com.my.package/.MyConditionConfigurationActivity">
+ * </meta-data>
* </service></pre>
*
- * @hide
*/
-@SystemApi
public abstract class ConditionProviderService extends Service {
private final String TAG = ConditionProviderService.class.getSimpleName()
+ "[" + getClass().getSimpleName() + "]";
@@ -62,9 +75,63 @@
public static final String SERVICE_INTERFACE
= "android.service.notification.ConditionProviderService";
+ /**
+ * The name of the {@code meta-data} tag containing a localized name of the type of zen rules
+ * provided by this service.
+ */
+ public static final String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
+
+ /**
+ * The name of the {@code meta-data} tag containing a default Condition {@link Uri} that can
+ * be parsed by this service.
+ */
+ public static final String META_DATA_DEFAULT_CONDITION_ID =
+ "android.service.zen.automatic.defaultConditionId";
+
+ /**
+ * The name of the {@code meta-data} tag containing the {@link ComponentName} of an activity
+ * that allows users to configure the conditions provided by this service.
+ */
+ public static final String META_DATA_CONFIGURATION_ACTIVITY =
+ "android.service.zen.automatic.configurationActivity";
+
+ /**
+ * A condition {@link Uri} extra passed to {@link #META_DATA_CONFIGURATION_ACTIVITY}. If the
+ * condition Uri is modified by that activity, it must be included in the result Intent extras
+ * in order to be persisted.
+ */
+ public static final String EXTRA_CONDITION_ID = "android.content.automatic.conditionId";
+
+ /**
+ * A String rule name extra passed to {@link #META_DATA_CONFIGURATION_ACTIVITY}. This extra is
+ * informative only, and will be ignored if included in the result Intent extras.
+ */
+ public static final String EXTRA_RULE_NAME = "android.content.automatic.ruleName";
+
+ /**
+ * Called when this service is connected.
+ */
abstract public void onConnected();
+
+ /**
+ * Called when the system wants to know the state of Conditions managed by this provider.
+ *
+ * Implementations should evaluate the state of all subscribed conditions, and provide updates
+ * by calling {@link #notifyCondition(Condition)} or {@link #notifyConditions(Condition...)}.
+ * @param relevance
+ */
abstract public void onRequestConditions(int relevance);
+
+ /**
+ * Called by the system when there is a new {@link Condition} to be managed by this provider.
+ * @param conditionId the Uri describing the criteria of the condition.
+ */
abstract public void onSubscribe(Uri conditionId);
+
+ /**
+ * Called by the system when a {@link Condition} has been deleted.
+ * @param conditionId the Uri describing the criteria of the deleted condition.
+ */
abstract public void onUnsubscribe(Uri conditionId);
private final INotificationManager getNotificationInterface() {
@@ -75,11 +142,19 @@
return mNoMan;
}
+ /**
+ * Informs the notification manager that the state of a Condition has changed.
+ * @param condition the condition that has changed.
+ */
public final void notifyCondition(Condition condition) {
if (condition == null) return;
notifyConditions(new Condition[]{ condition });
}
+ /**
+ * Informs the notification manager that the state of one or more Conditions has changed.
+ * @param conditions the changed conditions.
+ */
public final void notifyConditions(Condition... conditions) {
if (!isBound() || conditions == null) return;
try {
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index db19f7a..6310570 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -118,7 +118,7 @@
public boolean allowEvents = DEFAULT_ALLOW_EVENTS;
public int allowCallsFrom = DEFAULT_SOURCE;
public int allowMessagesFrom = DEFAULT_SOURCE;
- public int user = UserHandle.USER_OWNER;
+ public int user = UserHandle.USER_SYSTEM;
public ZenRule manualRule;
public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>();
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 4d8a7d0..49cb8e2 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -462,7 +462,7 @@
/**
* Returns the length that the specified CharSequence would have if
- * spaces and control characters were trimmed from the start and end,
+ * spaces and ASCII control characters were trimmed from the start and end,
* as by {@link String#trim}.
*/
public static int getTrimmedLength(CharSequence s) {
@@ -505,7 +505,13 @@
return false;
}
- // XXX currently this only reverses chars, not spans
+ /*
+ * @deprecated
+ * Do not use. This function only reverses individual {@code char}s and not their associated
+ * spans. It doesn't support surrogate pairs (that correspond to non-BMP code points),
+ * combining sequences or conjuncts either.
+ */
+ @Deprecated
public static CharSequence getReverse(CharSequence source,
int start, int end) {
return new Reverser(source, start, end);
@@ -1470,8 +1476,9 @@
*/
public static boolean isDigitsOnly(CharSequence str) {
final int len = str.length();
- for (int i = 0; i < len; i++) {
- if (!Character.isDigit(str.charAt(i))) {
+ for (int cp, i = 0; i < len; i += Character.charCount(cp)) {
+ cp = Character.codePointAt(str, i);
+ if (!Character.isDigit(cp)) {
return false;
}
}
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index a53da09..9f5dfa6 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -98,7 +98,8 @@
/** {@hide} */
public static BytesResult formatBytes(Resources res, long sizeBytes, int flags) {
- float result = sizeBytes;
+ final boolean isNegative = (sizeBytes < 0);
+ float result = isNegative ? -sizeBytes : sizeBytes;
int suffix = com.android.internal.R.string.byteShort;
long mult = 1;
if (result > 900) {
@@ -154,9 +155,13 @@
roundFormat = "%.2f";
}
}
+
+ if (isNegative) {
+ result = -result;
+ }
final String roundedString = String.format(roundFormat, result);
- // Note this might overflow if result >= Long.MAX_VALUE / 100, but that's like 80PB so
+ // Note this might overflow if abs(result) >= Long.MAX_VALUE / 100, but that's like 80PB so
// it's okay (for now)...
final long roundedBytes =
(flags & FLAG_CALCULATE_ROUNDED) == 0 ? 0
diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java
new file mode 100644
index 0000000..017735a
--- /dev/null
+++ b/core/java/android/util/LocaleList.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.annotation.Nullable;
+
+import java.util.HashSet;
+import java.util.Locale;
+
+// TODO: We don't except too many LocaleLists to exist at the same time, and
+// we need access to the data at native level, so we should pass the data
+// down to the native level, create a mapt of every list seen there, take a
+// pointer back, and just keep that pointed in the Java-level object, so
+// things could be copied very quickly.
+
+/**
+ * LocaleList is an immutable list of Locales, typically used to keep an
+ * ordered user preferences for locales.
+ */
+public final class LocaleList {
+ private final Locale[] mList;
+ private static final Locale[] sEmptyList = new Locale[0];
+
+ public Locale get(int location) {
+ return location < mList.length ? mList[location] : null;
+ }
+
+ public Locale getPrimary() {
+ return mList.length == 0 ? null : get(0);
+ }
+
+ public boolean isEmpty() {
+ return mList.length == 0;
+ }
+
+ public int size() {
+ return mList.length;
+ }
+
+ public LocaleList() {
+ mList = sEmptyList;
+ }
+
+ /**
+ * @throws NullPointerException if any of the input locales is <code>null</code>.
+ * @throws IllegalArgumentException if any of the input locales repeat.
+ */
+ public LocaleList(@Nullable Locale[] list) {
+ if (list == null || list.length == 0) {
+ mList = sEmptyList;
+ } else {
+ final Locale[] localeList = new Locale[list.length];
+ final HashSet<Locale> seenLocales = new HashSet<Locale>();
+ for (int i = 0; i < list.length; ++i) {
+ final Locale l = list[i];
+ if (l == null) {
+ throw new NullPointerException();
+ } else if (seenLocales.contains(l)) {
+ throw new IllegalArgumentException();
+ } else {
+ seenLocales.add(l);
+ localeList[i] = (Locale) l.clone();
+ }
+ }
+ mList = localeList;
+ }
+ }
+}
diff --git a/core/java/android/view/AppTransitionAnimationSpec.aidl b/core/java/android/view/AppTransitionAnimationSpec.aidl
new file mode 100644
index 0000000..8388347
--- /dev/null
+++ b/core/java/android/view/AppTransitionAnimationSpec.aidl
@@ -0,0 +1,20 @@
+/*
+** Copyright 2015, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.view;
+
+/** @hide */
+parcelable AppTransitionAnimationSpec;
diff --git a/core/java/android/view/AppTransitionAnimationSpec.java b/core/java/android/view/AppTransitionAnimationSpec.java
new file mode 100644
index 0000000..c6e1989
--- /dev/null
+++ b/core/java/android/view/AppTransitionAnimationSpec.java
@@ -0,0 +1,61 @@
+package android.view;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Holds information about how the next app transition animation should be executed.
+ *
+ * This class is intended to be used with IWindowManager.overridePendingAppTransition* methods when
+ * simple arguments are not enough to describe the animation.
+ *
+ * @hide
+ */
+public class AppTransitionAnimationSpec implements Parcelable {
+ public final int taskId;
+ public final Bitmap bitmap;
+ public final Rect rect;
+
+ public AppTransitionAnimationSpec(int taskId, Bitmap bitmap, Rect rect) {
+ this.taskId = taskId;
+ this.bitmap = bitmap;
+ this.rect = rect;
+ }
+
+ public AppTransitionAnimationSpec(Parcel in) {
+ taskId = in.readInt();
+ bitmap = in.readParcelable(null);
+ rect = in.readParcelable(null);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(taskId);
+ dest.writeParcelable(bitmap, 0 /* flags */);
+ dest.writeParcelable(rect, 0 /* flags */);
+
+ }
+
+ public static final Parcelable.Creator<AppTransitionAnimationSpec> CREATOR
+ = new Parcelable.Creator<AppTransitionAnimationSpec>() {
+ public AppTransitionAnimationSpec createFromParcel(Parcel in) {
+ return new AppTransitionAnimationSpec(in);
+ }
+
+ public AppTransitionAnimationSpec[] newArray(int size) {
+ return new AppTransitionAnimationSpec[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return "{taskId: " + taskId + ", bitmap: " + bitmap + ", rect: " + rect + "}";
+ }
+}
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index ce50091..ea0873d 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -19,12 +19,13 @@
import android.annotation.StyleRes;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
/**
- * A ContextWrapper that allows you to modify the theme from what is in the
- * wrapped context.
+ * A context wrapper that allows you to modify or replace the theme of the
+ * wrapped context.
*/
public class ContextThemeWrapper extends ContextWrapper {
private int mThemeResource;
@@ -33,15 +34,42 @@
private Configuration mOverrideConfiguration;
private Resources mResources;
+ /**
+ * Creates a new context wrapper with no theme and no base context.
+ * <p>
+ * <stong>Note:</strong> A base context <strong>must</strong> be attached
+ * using {@link #attachBaseContext(Context)} before calling any other
+ * method on the newly constructed context wrapper.
+ */
public ContextThemeWrapper() {
super(null);
}
+ /**
+ * Creates a new context wrapper with the specified theme.
+ * <p>
+ * The specified theme will be applied on top of the base context's theme.
+ * Any attributes not explicitly defined in the theme identified by
+ * <var>themeResId</var> will retain their original values.
+ *
+ * @param base the base context
+ * @param themeResId the resource ID of the theme to be applied on top of
+ * the base context's theme
+ */
public ContextThemeWrapper(Context base, @StyleRes int themeResId) {
super(base);
mThemeResource = themeResId;
}
+ /**
+ * Creates a new context wrapper with the specified theme.
+ * <p>
+ * Unlike {@link #ContextThemeWrapper(Context, int)}, the theme passed to
+ * this constructor will completely replace the base context's theme.
+ *
+ * @param base the base context
+ * @param theme the theme against which resources should be inflated
+ */
public ContextThemeWrapper(Context base, Resources.Theme theme) {
super(base);
mTheme = theme;
@@ -60,11 +88,12 @@
* information.
*
* <p>This method can only be called once, and must be called before any
- * calls to {@link #getResources()} are made.
+ * calls to {@link #getResources()} or {@link #getAssets()} are made.
*/
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
if (mResources != null) {
- throw new IllegalStateException("getResources() has already been called");
+ throw new IllegalStateException(
+ "getResources() or getAssets() has already been called");
}
if (mOverrideConfiguration != null) {
throw new IllegalStateException("Override configuration has already been set");
@@ -73,20 +102,25 @@
}
@Override
- public Resources getResources() {
- if (mResources != null) {
- return mResources;
- }
- if (mOverrideConfiguration == null) {
- mResources = super.getResources();
- return mResources;
- } else {
- Context resc = createConfigurationContext(mOverrideConfiguration);
- mResources = resc.getResources();
- return mResources;
- }
+ public AssetManager getAssets() {
+ // Ensure we're returning assets with the correct configuration.
+ return getResources().getAssets();
}
-
+
+ @Override
+ public Resources getResources() {
+ if (mResources == null) {
+ if (mOverrideConfiguration == null) {
+ mResources = super.getResources();
+ } else {
+ final Context resContext = createConfigurationContext(mOverrideConfiguration);
+ mResources = resContext.getResources();
+ }
+ }
+
+ return mResources;
+ }
+
@Override
public void setTheme(int resid) {
if (mThemeResource != resid) {
@@ -94,14 +128,15 @@
initializeTheme();
}
}
-
+
/** @hide */
@Override
public int getThemeResId() {
return mThemeResource;
}
- @Override public Resources.Theme getTheme() {
+ @Override
+ public Resources.Theme getTheme() {
if (mTheme != null) {
return mTheme;
}
@@ -113,7 +148,8 @@
return mTheme;
}
- @Override public Object getSystemService(String name) {
+ @Override
+ public Object getSystemService(String name) {
if (LAYOUT_INFLATER_SERVICE.equals(name)) {
if (mInflater == null) {
mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
@@ -122,27 +158,27 @@
}
return getBaseContext().getSystemService(name);
}
-
+
/**
* Called by {@link #setTheme} and {@link #getTheme} to apply a theme
- * resource to the current Theme object. Can override to change the
- * default (simple) behavior. This method will not be called in multiple
+ * resource to the current Theme object. May be overridden to change the
+ * default (simple) behavior. This method will not be called in multiple
* threads simultaneously.
*
- * @param theme The Theme object being modified.
- * @param resid The theme style resource being applied to <var>theme</var>.
- * @param first Set to true if this is the first time a style is being
- * applied to <var>theme</var>.
+ * @param theme the theme being modified
+ * @param resId the style resource being applied to <var>theme</var>
+ * @param first {@code true} if this is the first time a style is being
+ * applied to <var>theme</var>
*/
- protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
- theme.applyStyle(resid, true);
+ protected void onApplyThemeResource(Resources.Theme theme, int resId, boolean first) {
+ theme.applyStyle(resId, true);
}
private void initializeTheme() {
final boolean first = mTheme == null;
if (first) {
mTheme = getResources().newTheme();
- Resources.Theme theme = getBaseContext().getTheme();
+ final Resources.Theme theme = getBaseContext().getTheme();
if (theme != null) {
mTheme.setTo(theme);
}
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 05fa45f..080ed9a 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -20,12 +20,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
-import android.graphics.NinePatch;
import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Picture;
-import android.graphics.Rect;
-import android.graphics.RectF;
import android.util.Pools.SynchronizedPool;
/**
@@ -206,44 +201,17 @@
* Draws the specified layer onto this canvas.
*
* @param layer The layer to composite on this canvas
- * @param x The left coordinate of the layer
- * @param y The top coordinate of the layer
- * @param paint The paint used to draw the layer
*/
- void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
- layer.setLayerPaint(paint);
- nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle(), x, y);
+ void drawHardwareLayer(HardwareLayer layer) {
+ nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle());
}
- private static native void nDrawLayer(long renderer, long layer, float x, float y);
+ private static native void nDrawLayer(long renderer, long layer);
///////////////////////////////////////////////////////////////////////////
// Drawing
///////////////////////////////////////////////////////////////////////////
- // TODO: move to Canvas.java
- @Override
- public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
- Bitmap bitmap = patch.getBitmap();
- throwIfCannotDraw(bitmap);
- final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
- nDrawPatch(mNativeCanvasWrapper, bitmap, patch.mNativeChunk,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint);
- }
-
- // TODO: move to Canvas.java
- @Override
- public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
- Bitmap bitmap = patch.getBitmap();
- throwIfCannotDraw(bitmap);
- final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
- nDrawPatch(mNativeCanvasWrapper, bitmap, patch.mNativeChunk,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint);
- }
-
- private static native void nDrawPatch(long renderer, Bitmap bitmap, long chunk,
- float left, float top, float right, float bottom, long paint);
-
public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 65ae8a6..692ca7b 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -150,8 +150,4 @@
private static native void nSetSurfaceTexture(long layerUpdater,
SurfaceTexture surface, boolean isAlreadyAttached);
private static native void nUpdateSurfaceTexture(long layerUpdater);
- private static native void nUpdateRenderLayer(long layerUpdater, long displayList,
- int left, int top, int right, int bottom);
-
- private static native int nGetTexName(long layerUpdater);
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0a4b982..f86adfe 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -39,6 +39,7 @@
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.IInputFilter;
+import android.view.AppTransitionAnimationSpec;
import android.view.WindowContentFrameStats;
/**
@@ -127,6 +128,16 @@
void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
boolean scaleUp);
+ /**
+ * Overrides animation for app transition that exits from an application to a multi-window
+ * environment and allows specifying transition animation parameters for each window.
+ *
+ * @param specs Array of transition animation descriptions for entering windows.
+ *
+ * @hide
+ */
+ void overridePendingAppTransitionMultiThumb(in AppTransitionAnimationSpec[] specs,
+ IRemoteCallback startedCallback, boolean scaleUp);
void overridePendingAppTransitionInPlace(String packageName, int anim);
void executeAppTransition();
void setAppStartingWindow(IBinder token, String pkg, int theme,
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index cdc196e..6b60be9 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -23,6 +23,7 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
@@ -294,6 +295,22 @@
public void buildLayer() {
}
+ @Override
+ public void setForeground(Drawable foreground) {
+ if (foreground != null) {
+ throw new UnsupportedOperationException(
+ "TextureView doesn't support displaying a foreground drawable");
+ }
+ }
+
+ @Override
+ public void setBackgroundDrawable(Drawable background) {
+ if (background != null) {
+ throw new UnsupportedOperationException(
+ "TextureView doesn't support displaying a background drawable");
+ }
+ }
+
/**
* Subclasses of TextureView cannot do their own rendering
* with the {@link Canvas} object.
@@ -302,11 +319,25 @@
*/
@Override
public final void draw(Canvas canvas) {
- // NOTE: Maintain this carefully (see View.java)
+ // NOTE: Maintain this carefully (see View#draw)
mPrivateFlags = (mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
- applyUpdate();
- applyTransformMatrix();
+ /* Simplify drawing to guarantee the layer is the only thing drawn - so e.g. no background,
+ scrolling, or fading edges. This guarantees all drawing is in the layer, so drawing
+ properties (alpha, layer paint) affect all of the content of a TextureView. */
+
+ if (canvas.isHardwareAccelerated()) {
+ DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
+
+ HardwareLayer layer = getHardwareLayer();
+ if (layer != null) {
+ applyUpdate();
+ applyTransformMatrix();
+
+ mLayer.setLayerPaint(mLayerPaint); // ensure layer paint is up to date
+ displayListCanvas.drawHardwareLayer(layer);
+ }
+ }
}
/**
@@ -342,12 +373,7 @@
invalidate(true);
}
- @Override
HardwareLayer getHardwareLayer() {
- // NOTE: Maintain these two lines very carefully (see View.java)
- mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
- mPrivateFlags &= ~PFLAG_DIRTY_MASK;
-
if (mLayer == null) {
if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
return null;
@@ -385,9 +411,6 @@
mSurface.setDefaultBufferSize(getWidth(), getHeight());
}
- applyUpdate();
- applyTransformMatrix();
-
return mLayer;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a492518..16d9bf3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -576,6 +576,53 @@
* often used as a convenience to store data related to views in the views
* themselves rather than by putting them in a separate structure.
* </p>
+ * <p>
+ * Tags may be specified with character sequence values in layout XML as either
+ * a single tag using the {@link android.R.styleable#View_tag android:tag}
+ * attribute or multiple tags using the {@code <tag>} child element:
+ * <pre>
+ * <View ...
+ * android:tag="@string/mytag_value" />
+ * <View ...>
+ * <tag android:id="@+id/mytag"
+ * android:value="@string/mytag_value" />
+ * </View>
+ * </pre>
+ * </p>
+ * <p>
+ * Tags may also be specified with arbitrary objects from code using
+ * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
+ * </p>
+ *
+ * <a name="Themes"></a>
+ * <h3>Themes</h3>
+ * <p>
+ * By default, Views are created using the theme of the Context object supplied
+ * to their constructor; however, a different theme may be specified by using
+ * the {@link android.R.styleable#View_theme android:theme} attribute in layout
+ * XML or by passing a {@link ContextThemeWrapper} to the constructor from
+ * code.
+ * </p>
+ * <p>
+ * When the {@link android.R.styleable#View_theme android:theme} attribute is
+ * used in XML, the specified theme is applied on top of the inflation
+ * context's theme (see {@link LayoutInflater}) and used for the view itself as
+ * well as any child elements.
+ * </p>
+ * <p>
+ * In the following example, both views will be created using the Material dark
+ * color scheme; however, because an overlay theme is used which only defines a
+ * subset of attributes, the value of
+ * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
+ * the inflation context's theme (e.g. the Activity theme) will be preserved.
+ * <pre>
+ * <LinearLayout
+ * ...
+ * android:theme="@android:theme/ThemeOverlay.Material.Dark">
+ * <View ...>
+ * </LinearLayout>
+ * </pre>
+ * </p>
*
* <a name="Properties"></a>
* <h3>Properties</h3>
@@ -699,6 +746,7 @@
* @attr ref android.R.styleable#View_translationY
* @attr ref android.R.styleable#View_translationZ
* @attr ref android.R.styleable#View_visibility
+ * @attr ref android.R.styleable#View_theme
*
* @see android.view.ViewGroup
*/
@@ -753,6 +801,11 @@
private static boolean sIgnoreMeasureCache = false;
/**
+ * Ignore an optimization that skips unnecessary EXACTLY layout passes.
+ */
+ private static boolean sAlwaysRemeasureExactly = false;
+
+ /**
* This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
* calling setFlags.
*/
@@ -3817,6 +3870,11 @@
// specifically apps that use some popular open source libraries.
sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
+ // Old versions of the platform would give different results from
+ // LinearLayout measurement passes using EXACTLY and non-EXACTLY
+ // modes, so we always need to run an additional EXACTLY pass.
+ sAlwaysRemeasureExactly = targetSdkVersion <= M;
+
sCompatibilityDone = true;
}
}
@@ -15002,16 +15060,6 @@
}
/**
- * If this View draws with a HardwareLayer, returns it.
- * Otherwise returns null
- *
- * TODO: Only TextureView uses this, can we eliminate it?
- */
- HardwareLayer getHardwareLayer() {
- return null;
- }
-
- /**
* Destroys all hardware rendering resources. This method is invoked
* when the system needs to reclaim resources. Upon execution of this
* method, you should free any OpenGL resources created by the view.
@@ -15161,10 +15209,7 @@
canvas.setHighContrastText(mAttachInfo.mHighContrastText);
try {
- final HardwareLayer layer = getHardwareLayer();
- if (layer != null && layer.isValid()) {
- canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
- } else if (layerType == LAYER_TYPE_SOFTWARE) {
+ if (layerType == LAYER_TYPE_SOFTWARE) {
buildDrawingCache(true);
Bitmap cache = getDrawingCache(true);
if (cache != null) {
@@ -18785,17 +18830,27 @@
long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
- if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
- widthMeasureSpec != mOldWidthMeasureSpec ||
- heightMeasureSpec != mOldHeightMeasureSpec) {
+ final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
+ // Optimize layout by avoiding an extra EXACTLY pass when the view is
+ // already measured as the correct size. In API 23 and below, this
+ // extra pass is required to make LinearLayout re-distribute weight.
+ final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
+ || heightMeasureSpec != mOldHeightMeasureSpec;
+ final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
+ && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
+ final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
+ && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
+ final boolean needsLayout = specChanged
+ && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
+
+ if (forceLayout || needsLayout) {
// first clears the measured dimension flag
mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
resolveRtlPropertiesIfNeeded();
- int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
- mMeasureCache.indexOfKey(key);
+ int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
if (cacheIndex < 0 || sIgnoreMeasureCache) {
// measure ourselves, this should set the measured dimension flag back
onMeasure(widthMeasureSpec, heightMeasureSpec);
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 7b4640b..a6d9932 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -120,6 +120,13 @@
}
/**
+ * An interface to be notified about hardware keyboard status.
+ */
+ public interface OnHardKeyboardStatusChangeListener {
+ public void onHardKeyboardStatusChange(boolean available);
+ }
+
+ /**
* Request that the window manager call
* {@link DisplayManagerInternal#performTraversalInTransactionFromWindowManager}
* within a surface transaction at a later time.
@@ -231,4 +238,29 @@
* @param listener The listener to register.
*/
public abstract void registerAppTransitionListener(AppTransitionListener listener);
+
+ /**
+ * Retrieves a height of input method window.
+ */
+ public abstract int getInputMethodWindowVisibleHeight();
+
+ /**
+ * Saves last input method window for transition.
+ *
+ * Note that it is assumed that this method is called only by InputMethodManagerService.
+ */
+ public abstract void saveLastInputMethodWindowForTransition();
+
+ /**
+ * Returns true when the hardware keyboard is available.
+ */
+ public abstract boolean isHardKeyboardAvailable();
+
+ /**
+ * Sets the callback listener for hardware keyboard status changes.
+ *
+ * @param listener The listener to set.
+ */
+ public abstract void setOnHardKeyboardStatusChangeListener(
+ OnHardKeyboardStatusChangeListener listener);
}
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 6962711..0cc1b25 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -612,7 +612,7 @@
View listItem = view;
try {
View v;
- while (!(v = (View) listItem.getParent()).equals(this)) {
+ while ((v = (View) listItem.getParent()) != null && !v.equals(this)) {
listItem = v;
}
} catch (ClassCastException e) {
@@ -620,11 +620,13 @@
return INVALID_POSITION;
}
- // Search the children for the list item
- final int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- if (getChildAt(i).equals(listItem)) {
- return mFirstPosition + i;
+ if (listItem != null) {
+ // Search the children for the list item
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ if (getChildAt(i).equals(listItem)) {
+ return mFirstPosition + i;
+ }
}
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 150b407..fddc40f 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -107,6 +107,7 @@
import android.widget.TextView.Drawables;
import android.widget.TextView.OnEditorActionListener;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
import com.android.internal.util.Preconditions;
@@ -2632,7 +2633,8 @@
}
}
- private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener {
+ @VisibleForTesting
+ public class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener {
private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
private static final int ADD_TO_DICTIONARY = -1;
private static final int DELETE_TEXT = -2;
@@ -2798,6 +2800,11 @@
return suggestionSpans;
}
+ @VisibleForTesting
+ public ViewGroup getContentViewForTesting() {
+ return mContentView;
+ }
+
@Override
public void show() {
if (!(mTextView.getText() instanceof Editable)) return;
@@ -5103,6 +5110,11 @@
return 0 <= start && start <= end && end <= text.length();
}
+ @VisibleForTesting
+ public SuggestionsPopupWindow getSuggestionsPopupWindowForTesting() {
+ return mSuggestionsPopupWindow;
+ }
+
/**
* An InputFilter that monitors text input to maintain undo history. It does not modify the
* text being typed (and hence always returns null from the filter() method).
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 20fe61d..b53af0c 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -72,6 +72,8 @@
*/
@RemoteView
public class ImageView extends View {
+ private static final String LOG_TAG = "ImageView";
+
// settable by the client
private Uri mUri;
private int mResource = 0;
@@ -87,7 +89,7 @@
private boolean mHasColorFilter = false;
private Xfermode mXfermode;
private int mAlpha = 255;
- private int mViewAlphaScale = 256;
+ private final int mViewAlphaScale = 256;
private boolean mColorMod = false;
private Drawable mDrawable = null;
@@ -105,8 +107,8 @@
private Matrix mDrawMatrix = null;
// Avoid allocations...
- private RectF mTempSrc = new RectF();
- private RectF mTempDst = new RectF();
+ private final RectF mTempSrc = new RectF();
+ private final RectF mTempDst = new RectF();
private boolean mCropToPadding;
@@ -116,6 +118,9 @@
// AdjustViewBounds behavior will be in compatibility mode for older apps.
private boolean mAdjustViewBoundsCompat = false;
+ /** Whether to pass Resources when creating the source from a stream. */
+ private boolean mUseCorrectStreamDensity;
+
private static final ScaleType[] sScaleTypeArray = {
ScaleType.MATRIX,
ScaleType.FIT_XY,
@@ -147,30 +152,21 @@
initImageView();
final TypedArray a = context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.ImageView, defStyleAttr, defStyleRes);
+ attrs, R.styleable.ImageView, defStyleAttr, defStyleRes);
- Drawable d = a.getDrawable(com.android.internal.R.styleable.ImageView_src);
+ final Drawable d = a.getDrawable(R.styleable.ImageView_src);
if (d != null) {
setImageDrawable(d);
}
- mBaselineAlignBottom = a.getBoolean(
- com.android.internal.R.styleable.ImageView_baselineAlignBottom, false);
+ mBaselineAlignBottom = a.getBoolean(R.styleable.ImageView_baselineAlignBottom, false);
+ mBaseline = a.getDimensionPixelSize(R.styleable.ImageView_baseline, -1);
- mBaseline = a.getDimensionPixelSize(
- com.android.internal.R.styleable.ImageView_baseline, -1);
+ setAdjustViewBounds(a.getBoolean(R.styleable.ImageView_adjustViewBounds, false));
+ setMaxWidth(a.getDimensionPixelSize(R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
+ setMaxHeight(a.getDimensionPixelSize(R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));
- setAdjustViewBounds(
- a.getBoolean(com.android.internal.R.styleable.ImageView_adjustViewBounds,
- false));
-
- setMaxWidth(a.getDimensionPixelSize(
- com.android.internal.R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
-
- setMaxHeight(a.getDimensionPixelSize(
- com.android.internal.R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));
-
- final int index = a.getInt(com.android.internal.R.styleable.ImageView_scaleType, -1);
+ final int index = a.getInt(R.styleable.ImageView_scaleType, -1);
if (index >= 0) {
setScaleType(sScaleTypeArray[index]);
}
@@ -193,24 +189,26 @@
applyImageTint();
- final int alpha = a.getInt(com.android.internal.R.styleable.ImageView_drawableAlpha, 255);
+ final int alpha = a.getInt(R.styleable.ImageView_drawableAlpha, 255);
if (alpha != 255) {
- setAlpha(alpha);
+ setImageAlpha(alpha);
}
mCropToPadding = a.getBoolean(
- com.android.internal.R.styleable.ImageView_cropToPadding, false);
-
+ R.styleable.ImageView_cropToPadding, false);
+
a.recycle();
//need inflate syntax/reader for matrix
}
private void initImageView() {
- mMatrix = new Matrix();
- mScaleType = ScaleType.FIT_CENTER;
- mAdjustViewBoundsCompat = mContext.getApplicationInfo().targetSdkVersion <=
- Build.VERSION_CODES.JELLY_BEAN_MR1;
+ mMatrix = new Matrix();
+ mScaleType = ScaleType.FIT_CENTER;
+
+ final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+ mAdjustViewBoundsCompat = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
+ mUseCorrectStreamDensity = targetSdkVersion > Build.VERSION_CODES.M;
}
@Override
@@ -258,7 +256,8 @@
@Override
public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
super.onPopulateAccessibilityEventInternal(event);
- CharSequence contentDescription = getContentDescription();
+
+ final CharSequence contentDescription = getContentDescription();
if (!TextUtils.isEmpty(contentDescription)) {
event.getText().add(contentDescription);
}
@@ -269,7 +268,7 @@
* to preserve the aspect ratio of its drawable
*
* @return whether to adjust the bounds of this view
- * to presrve the original aspect ratio of the drawable
+ * to preserve the original aspect ratio of the drawable
*
* @see #setAdjustViewBounds(boolean)
*
@@ -291,7 +290,7 @@
*
* @param adjustViewBounds Whether to adjust the bounds of this view
* to preserve the original aspect ratio of the drawable.
- *
+ *
* @see #getAdjustViewBounds()
*
* @attr ref android.R.styleable#ImageView_adjustViewBounds
@@ -323,14 +322,14 @@
* of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
* adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
* layout params to WRAP_CONTENT.
- *
+ *
* <p>
* Note that this view could be still smaller than 100 x 100 using this approach if the original
* image is small. To set an image to a fixed size, specify that size in the layout params and
* then use {@link #setScaleType(android.widget.ImageView.ScaleType)} to determine how to fit
* the image within the bounds.
* </p>
- *
+ *
* @param maxWidth maximum width for this view
*
* @see #getMaxWidth()
@@ -361,14 +360,14 @@
* maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
* adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
* layout params to WRAP_CONTENT.
- *
+ *
* <p>
* Note that this view could be still smaller than 100 x 100 using this approach if the original
* image is small. To set an image to a fixed size, specify that size in the layout params and
* then use {@link #setScaleType(android.widget.ImageView.ScaleType)} to determine how to fit
* the image within the bounds.
* </p>
- *
+ *
* @param maxHeight maximum height for this view
*
* @see #getMaxHeight()
@@ -436,9 +435,7 @@
*/
@android.view.RemotableViewMethod
public void setImageURI(@Nullable Uri uri) {
- if (mResource != 0 ||
- (mUri != uri &&
- (uri == null || mUri == null || !uri.equals(mUri)))) {
+ if (mResource != 0 || (mUri != uri && (uri == null || mUri == null || !uri.equals(mUri)))) {
updateDrawable(null);
mResource = 0;
mUri = uri;
@@ -457,7 +454,7 @@
/**
* Sets a drawable as the content of this ImageView.
- *
+ *
* @param drawable the Drawable to set, or {@code null} to clear the
* content
*/
@@ -577,7 +574,7 @@
/**
* Sets a Bitmap as the content of this ImageView.
- *
+ *
* @param bm The bitmap to set
*/
@android.view.RemotableViewMethod
@@ -609,7 +606,7 @@
}
/**
- * Sets the image level, when it is constructed from a
+ * Sets the image level, when it is constructed from a
* {@link android.graphics.drawable.LevelListDrawable}.
*
* @param level The new level for the image.
@@ -675,7 +672,7 @@
* From XML, use this syntax: <code>android:scaleType="centerInside"</code>.
*/
CENTER_INSIDE (7);
-
+
ScaleType(int ni) {
nativeInt = ni;
}
@@ -685,9 +682,9 @@
/**
* Controls how the image should be resized or moved to match the size
* of this ImageView.
- *
+ *
* @param scaleType The desired scaling mode.
- *
+ *
* @attr ref android.R.styleable#ImageView_scaleType
*/
public void setScaleType(ScaleType scaleType) {
@@ -698,13 +695,13 @@
if (mScaleType != scaleType) {
mScaleType = scaleType;
- setWillNotCacheDrawing(mScaleType == ScaleType.CENTER);
+ setWillNotCacheDrawing(mScaleType == ScaleType.CENTER);
requestLayout();
invalidate();
}
}
-
+
/**
* Return the current scale type in use by this ImageView.
*
@@ -734,7 +731,7 @@
* Adds a transformation {@link Matrix} that is applied
* to the view's drawable when it is drawn. Allows custom scaling,
* translation, and perspective distortion.
- *
+ *
* @param matrix the transformation parameters in matrix form
*/
public void setImageMatrix(Matrix matrix) {
@@ -787,8 +784,8 @@
return;
}
- Resources rsrc = getResources();
- if (rsrc == null) {
+ final Resources res = getResources();
+ if (res == null) {
return;
}
@@ -798,12 +795,12 @@
try {
d = mContext.getDrawable(mResource);
} catch (Exception e) {
- Log.w("ImageView", "Unable to find resource: " + mResource, e);
+ Log.w(LOG_TAG, "Unable to find resource: " + mResource, e);
// Don't try again.
mUri = null;
}
} else if (mUri != null) {
- String scheme = mUri.getScheme();
+ final String scheme = mUri.getScheme();
if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
try {
// Load drawable through Resources, to get the source density information
@@ -811,31 +808,32 @@
mContext.getContentResolver().getResourceId(mUri);
d = r.r.getDrawable(r.id, mContext.getTheme());
} catch (Exception e) {
- Log.w("ImageView", "Unable to open content: " + mUri, e);
+ Log.w(LOG_TAG, "Unable to open content: " + mUri, e);
}
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
|| ContentResolver.SCHEME_FILE.equals(scheme)) {
InputStream stream = null;
try {
stream = mContext.getContentResolver().openInputStream(mUri);
- d = Drawable.createFromStream(stream, null);
+ d = Drawable.createFromResourceStream(
+ mUseCorrectStreamDensity ? res : null, null, stream, null);
} catch (Exception e) {
- Log.w("ImageView", "Unable to open content: " + mUri, e);
+ Log.w(LOG_TAG, "Unable to open content: " + mUri, e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
- Log.w("ImageView", "Unable to close content: " + mUri, e);
+ Log.w(LOG_TAG, "Unable to close content: " + mUri, e);
}
}
}
- } else {
+ } else {
d = Drawable.createFromPath(mUri.toString());
}
-
+
if (d == null) {
- System.out.println("resolveUri failed on bad bitmap uri: " + mUri);
+ Log.w(LOG_TAG, "resolveUri failed on bad bitmap uri: " + mUri);
// Don't try again.
mUri = null;
}
@@ -890,7 +888,7 @@
}
private void resizeFromDrawable() {
- Drawable d = mDrawable;
+ final Drawable d = mDrawable;
if (d != null) {
int w = d.getIntrinsicWidth();
if (w < 0) w = mDrawableWidth;
@@ -923,23 +921,23 @@
private static Matrix.ScaleToFit scaleTypeToScaleToFit(ScaleType st) {
// ScaleToFit enum to their corresponding Matrix.ScaleToFit values
return sS2FArray[st.nativeInt - 1];
- }
+ }
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
resolveUri();
int w;
int h;
-
+
// Desired aspect ratio of the view's contents (not including padding)
float desiredAspect = 0.0f;
-
+
// We are allowed to change the view's width
boolean resizeWidth = false;
-
+
// We are allowed to change the view's height
boolean resizeHeight = false;
-
+
final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
@@ -959,15 +957,15 @@
if (mAdjustViewBounds) {
resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
-
+
desiredAspect = (float) w / (float) h;
}
}
-
- int pleft = mPaddingLeft;
- int pright = mPaddingRight;
- int ptop = mPaddingTop;
- int pbottom = mPaddingBottom;
+
+ final int pleft = mPaddingLeft;
+ final int pright = mPaddingRight;
+ final int ptop = mPaddingTop;
+ final int pbottom = mPaddingBottom;
int widthSize;
int heightSize;
@@ -975,7 +973,7 @@
if (resizeWidth || resizeHeight) {
/* If we get here, it means we want to resize to match the
drawables aspect ratio, and we have the freedom to change at
- least one dimension.
+ least one dimension.
*/
// Get the max possible width given our constraints
@@ -986,13 +984,13 @@
if (desiredAspect != 0.0f) {
// See what our actual aspect ratio is
- float actualAspect = (float)(widthSize - pleft - pright) /
+ final float actualAspect = (float)(widthSize - pleft - pright) /
(heightSize - ptop - pbottom);
-
+
if (Math.abs(actualAspect - desiredAspect) > 0.0000001) {
-
+
boolean done = false;
-
+
// Try adjusting width to be proportional to height
if (resizeWidth) {
int newWidth = (int)(desiredAspect * (heightSize - ptop - pbottom)) +
@@ -1006,9 +1004,9 @@
if (newWidth <= widthSize) {
widthSize = newWidth;
done = true;
- }
+ }
}
-
+
// Try adjusting height to be proportional to width
if (!done && resizeHeight) {
int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) +
@@ -1033,7 +1031,7 @@
*/
w += pleft + pright;
h += ptop + pbottom;
-
+
w = Math.max(w, getSuggestedMinimumWidth());
h = Math.max(h, getSuggestedMinimumHeight());
@@ -1047,8 +1045,8 @@
private int resolveAdjustedSize(int desiredSize, int maxSize,
int measureSpec) {
int result = desiredSize;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
+ final int specMode = MeasureSpec.getMode(measureSpec);
+ final int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
/* Parent says we can be as big as we want. Just don't be larger
@@ -1057,8 +1055,8 @@
result = Math.min(desiredSize, maxSize);
break;
case MeasureSpec.AT_MOST:
- // Parent says we can be as big as we want, up to specSize.
- // Don't be larger than specSize, and don't be larger than
+ // Parent says we can be as big as we want, up to specSize.
+ // Don't be larger than specSize, and don't be larger than
// the max size imposed on ourselves.
result = Math.min(Math.min(desiredSize, specSize), maxSize);
break;
@@ -1072,7 +1070,7 @@
@Override
protected boolean setFrame(int l, int t, int r, int b) {
- boolean changed = super.setFrame(l, t, r, b);
+ final boolean changed = super.setFrame(l, t, r, b);
mHaveFrame = true;
configureBounds();
return changed;
@@ -1083,14 +1081,14 @@
return;
}
- int dwidth = mDrawableWidth;
- int dheight = mDrawableHeight;
+ final int dwidth = mDrawableWidth;
+ final int dheight = mDrawableHeight;
- int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
- int vheight = getHeight() - mPaddingTop - mPaddingBottom;
+ final int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
+ final int vheight = getHeight() - mPaddingTop - mPaddingBottom;
- boolean fits = (dwidth < 0 || vwidth == dwidth) &&
- (dheight < 0 || vheight == dheight);
+ final boolean fits = (dwidth < 0 || vwidth == dwidth)
+ && (dheight < 0 || vheight == dheight);
if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
/* If the drawable has no intrinsic size, or we're told to
@@ -1125,7 +1123,7 @@
float dx = 0, dy = 0;
if (dwidth * vheight > vwidth * dheight) {
- scale = (float) vheight / (float) dheight;
+ scale = (float) vheight / (float) dheight;
dx = (vwidth - dwidth * scale) * 0.5f;
} else {
scale = (float) vwidth / (float) dwidth;
@@ -1139,14 +1137,14 @@
float scale;
float dx;
float dy;
-
+
if (dwidth <= vwidth && dheight <= vheight) {
scale = 1.0f;
} else {
scale = Math.min((float) vwidth / (float) dwidth,
(float) vheight / (float) dheight);
}
-
+
dx = Math.round((vwidth - dwidth * scale) * 0.5f);
dy = Math.round((vheight - dheight * scale) * 0.5f);
@@ -1156,7 +1154,7 @@
// Generate the required transform.
mTempSrc.set(0, 0, dwidth, dheight);
mTempDst.set(0, 0, vwidth, vheight);
-
+
mDrawMatrix = mMatrix;
mDrawMatrix.setRectToRect(mTempSrc, mTempDst, scaleTypeToScaleToFit(mScaleType));
}
@@ -1166,7 +1164,8 @@
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
- Drawable d = mDrawable;
+
+ final Drawable d = mDrawable;
if (d != null && d.isStateful()) {
d.setState(getDrawableState());
}
@@ -1213,9 +1212,9 @@
if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
mDrawable.draw(canvas);
} else {
- int saveCount = canvas.getSaveCount();
+ final int saveCount = canvas.getSaveCount();
canvas.save();
-
+
if (mCropToPadding) {
final int scrollX = mScrollX;
final int scrollY = mScrollY;
@@ -1223,7 +1222,7 @@
scrollX + mRight - mLeft - mPaddingRight,
scrollY + mBottom - mTop - mPaddingBottom);
}
-
+
canvas.translate(mPaddingLeft, mPaddingTop);
if (mDrawMatrix != null) {
@@ -1258,7 +1257,7 @@
*
* @param baseline The baseline to use, or -1 if none is to be provided.
*
- * @see #setBaseline(int)
+ * @see #setBaseline(int)
* @attr ref android.R.styleable#ImageView_baseline
*/
public void setBaseline(int baseline) {
@@ -1295,11 +1294,11 @@
/**
* Set a tinting option for the image.
- *
+ *
* @param color Color tint to apply.
* @param mode How to apply the color. The standard mode is
* {@link PorterDuff.Mode#SRC_ATOP}
- *
+ *
* @attr ref android.R.styleable#ImageView_tint
*/
public final void setColorFilter(int color, PorterDuff.Mode mode) {
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index b5e08ca..ad939be 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -25,6 +25,7 @@
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@@ -99,6 +100,13 @@
public static final int SHOW_DIVIDER_END = 4;
/**
+ * Compatibility check. Old versions of the platform would give different
+ * results from measurement passes using EXACTLY and non-EXACTLY modes,
+ * even when the resulting size was the same.
+ */
+ private final boolean mAllowInconsistentMeasurement;
+
+ /**
* Whether the children of this layout are baseline aligned. Only applicable
* if {@link #mOrientation} is horizontal.
*/
@@ -231,6 +239,9 @@
mShowDividers = a.getInt(R.styleable.LinearLayout_showDividers, SHOW_DIVIDER_NONE);
mDividerPadding = a.getDimensionPixelSize(R.styleable.LinearLayout_dividerPadding, 0);
+ final int version = context.getApplicationInfo().targetSdkVersion;
+ mAllowInconsistentMeasurement = version <= Build.VERSION_CODES.M;
+
a.recycle();
}
@@ -699,6 +710,7 @@
final boolean useLargestChild = mUseLargestChild;
int largestChildHeight = Integer.MIN_VALUE;
+ int consumedExcessSpace = 0;
// See how tall everyone is. Also remember max width.
for (int i = 0; i < count; ++i) {
@@ -718,26 +730,25 @@
mTotalLength += mDividerHeight;
}
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
totalWeight += lp.weight;
-
- if (heightMode == MeasureSpec.EXACTLY && lp.height == 0 && lp.weight > 0) {
- // Optimization: don't bother measuring children who are going to use
- // leftover space. These views will get measured again down below if
- // there is any leftover space.
+
+ final boolean useExcessSpace = lp.height == 0 && lp.weight > 0;
+ if (heightMode == MeasureSpec.EXACTLY && useExcessSpace) {
+ // Optimization: don't bother measuring children who are only
+ // laid out using excess space. These views will get measured
+ // later if we have space to distribute.
final int totalLength = mTotalLength;
mTotalLength = Math.max(totalLength, totalLength + lp.topMargin + lp.bottomMargin);
skippedMeasure = true;
} else {
- int oldHeight = Integer.MIN_VALUE;
-
- if (lp.height == 0 && lp.weight > 0) {
- // heightMode is either UNSPECIFIED or AT_MOST, and this
- // child wanted to stretch to fill available space.
- // Translate that to WRAP_CONTENT so that it does not end up
- // with a height of 0
- oldHeight = 0;
+ if (useExcessSpace) {
+ // The heightMode is either UNSPECIFIED or AT_MOST, and
+ // this child is only laid out using excess space. Measure
+ // using WRAP_CONTENT so that we can find out the view's
+ // optimal height. We'll restore the original height of 0
+ // after measurement.
lp.height = LayoutParams.WRAP_CONTENT;
}
@@ -745,15 +756,19 @@
// previous children have given a weight, then we allow it to
// use all available space (and we will shrink things later
// if needed).
- measureChildBeforeLayout(
- child, i, widthMeasureSpec, 0, heightMeasureSpec,
- totalWeight == 0 ? mTotalLength : 0);
-
- if (oldHeight != Integer.MIN_VALUE) {
- lp.height = oldHeight;
- }
+ final int usedHeight = totalWeight == 0 ? mTotalLength : 0;
+ measureChildBeforeLayout(child, i, widthMeasureSpec, 0,
+ heightMeasureSpec, usedHeight);
final int childHeight = child.getMeasuredHeight();
+ if (useExcessSpace) {
+ // Restore the original height and record how much space
+ // we've allocated to excess-only children so that we can
+ // match the behavior of EXACTLY measurement.
+ lp.height = 0;
+ consumedExcessSpace += childHeight;
+ }
+
final int totalLength = mTotalLength;
mTotalLength = Math.max(totalLength, totalLength + childHeight + lp.topMargin +
lp.bottomMargin + getNextLocationOffset(child));
@@ -857,52 +872,42 @@
// Either expand children with weight to take up available space or
// shrink them if they extend beyond our current bounds. If we skipped
// measurement on any children, we need to measure them now.
- int delta = heightSize - mTotalLength;
+ final int delta = heightSize - mTotalLength
+ + (mAllowInconsistentMeasurement ? 0 : consumedExcessSpace);
if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
- float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
+ final float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
mTotalLength = 0;
for (int i = 0; i < count; ++i) {
final View child = getVirtualChildAt(i);
-
- if (child.getVisibility() == View.GONE) {
+ if (child == null || child.getVisibility() == View.GONE) {
continue;
}
-
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
-
- float childExtra = lp.weight;
+
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ final float childExtra = lp.weight;
if (childExtra > 0) {
- // Child said it could absorb extra space -- give him his share
- int share = (int) (childExtra * delta / weightSum);
- weightSum -= childExtra;
- delta -= share;
-
- final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
- mPaddingLeft + mPaddingRight +
- lp.leftMargin + lp.rightMargin, lp.width);
-
- // TODO: Use a field like lp.isMeasured to figure out if this
- // child has been previously measured
- if ((lp.height != 0) || (heightMode != MeasureSpec.EXACTLY)) {
- // child was measured once already above...
- // base new measurement on stored values
- int childHeight = child.getMeasuredHeight() + share;
- if (childHeight < 0) {
- childHeight = 0;
- }
-
- child.measure(childWidthMeasureSpec,
- MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
+ final int share = (int) (childExtra * delta / weightSum);
+ final int childHeight;
+ if (lp.height == 0 && (!mAllowInconsistentMeasurement
+ || heightMode == MeasureSpec.EXACTLY)) {
+ // This child needs to be laid out from scratch using
+ // only its share of excess space.
+ childHeight = share;
} else {
- // child was skipped in the loop above.
- // Measure for this first time here
- child.measure(childWidthMeasureSpec,
- MeasureSpec.makeMeasureSpec(share > 0 ? share : 0,
- MeasureSpec.EXACTLY));
+ // This child had some intrinsic height to which we
+ // need to add its share of excess space.
+ childHeight = child.getMeasuredHeight() + share;
}
+ final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ Math.max(0, childHeight), MeasureSpec.EXACTLY);
+ final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+ mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin,
+ lp.width);
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+
// Child may now not fit in vertical dimension.
childState = combineMeasuredStates(childState, child.getMeasuredState()
& (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
@@ -1043,6 +1048,7 @@
final boolean isExactly = widthMode == MeasureSpec.EXACTLY;
int largestChildWidth = Integer.MIN_VALUE;
+ int usedExcessSpace = 0;
// See how wide everyone is. Also remember max height.
for (int i = 0; i < count; ++i) {
@@ -1062,15 +1068,15 @@
mTotalLength += mDividerWidth;
}
- final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
- child.getLayoutParams();
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
totalWeight += lp.weight;
-
- if (widthMode == MeasureSpec.EXACTLY && lp.width == 0 && lp.weight > 0) {
- // Optimization: don't bother measuring children who are going to use
- // leftover space. These views will get measured again down below if
- // there is any leftover space.
+
+ final boolean useExcessSpace = lp.width == 0 && lp.weight > 0;
+ if (widthMode == MeasureSpec.EXACTLY && useExcessSpace) {
+ // Optimization: don't bother measuring children who are only
+ // laid out using excess space. These views will get measured
+ // later if we have space to distribute.
if (isExactly) {
mTotalLength += lp.leftMargin + lp.rightMargin;
} else {
@@ -1094,14 +1100,12 @@
skippedMeasure = true;
}
} else {
- int oldWidth = Integer.MIN_VALUE;
-
- if (lp.width == 0 && lp.weight > 0) {
- // widthMode is either UNSPECIFIED or AT_MOST, and this
- // child
- // wanted to stretch to fill available space. Translate that to
- // WRAP_CONTENT so that it does not end up with a width of 0
- oldWidth = 0;
+ if (useExcessSpace) {
+ // The widthMode is either UNSPECIFIED or AT_MOST, and
+ // this child is only laid out using excess space. Measure
+ // using WRAP_CONTENT so that we can find out the view's
+ // optimal width. We'll restore the original width of 0
+ // after measurement.
lp.width = LayoutParams.WRAP_CONTENT;
}
@@ -1109,22 +1113,26 @@
// previous children have given a weight, then we allow it to
// use all available space (and we will shrink things later
// if needed).
- measureChildBeforeLayout(child, i, widthMeasureSpec,
- totalWeight == 0 ? mTotalLength : 0,
+ final int usedWidth = totalWeight == 0 ? mTotalLength : 0;
+ measureChildBeforeLayout(child, i, widthMeasureSpec, usedWidth,
heightMeasureSpec, 0);
- if (oldWidth != Integer.MIN_VALUE) {
- lp.width = oldWidth;
+ final int childWidth = child.getMeasuredWidth();
+ if (useExcessSpace) {
+ // Restore the original width and record how much space
+ // we've allocated to excess-only children so that we can
+ // match the behavior of EXACTLY measurement.
+ lp.width = 0;
+ usedExcessSpace += childWidth;
}
- final int childWidth = child.getMeasuredWidth();
if (isExactly) {
- mTotalLength += childWidth + lp.leftMargin + lp.rightMargin +
- getNextLocationOffset(child);
+ mTotalLength += childWidth + lp.leftMargin + lp.rightMargin
+ + getNextLocationOffset(child);
} else {
final int totalLength = mTotalLength;
- mTotalLength = Math.max(totalLength, totalLength + childWidth + lp.leftMargin +
- lp.rightMargin + getNextLocationOffset(child));
+ mTotalLength = Math.max(totalLength, totalLength + childWidth + lp.leftMargin
+ + lp.rightMargin + getNextLocationOffset(child));
}
if (useLargestChild) {
@@ -1242,9 +1250,10 @@
// Either expand children with weight to take up available space or
// shrink them if they extend beyond our current bounds. If we skipped
// measurement on any children, we need to measure them now.
- int delta = widthSize - mTotalLength;
+ final int delta = widthSize - mTotalLength
+ + (mAllowInconsistentMeasurement ? 0 : usedExcessSpace);
if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
- float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
+ final float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1;
@@ -1254,45 +1263,32 @@
for (int i = 0; i < count; ++i) {
final View child = getVirtualChildAt(i);
-
if (child == null || child.getVisibility() == View.GONE) {
continue;
}
-
- final LinearLayout.LayoutParams lp =
- (LinearLayout.LayoutParams) child.getLayoutParams();
- float childExtra = lp.weight;
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ final float childExtra = lp.weight;
if (childExtra > 0) {
- // Child said it could absorb extra space -- give him his share
- int share = (int) (childExtra * delta / weightSum);
- weightSum -= childExtra;
- delta -= share;
+ final int share = (int) (childExtra * delta / weightSum);
+ final int childWidth;
+ if (lp.width == 0 && (!mAllowInconsistentMeasurement
+ || widthMode == MeasureSpec.EXACTLY)) {
+ // This child needs to be laid out from scratch using
+ // only its share of excess space.
+ childWidth = share;
+ } else {
+ // This child had some intrinsic width to which we
+ // need to add its share of excess space.
+ childWidth = child.getMeasuredWidth() + share;
+ }
- final int childHeightMeasureSpec = getChildMeasureSpec(
- heightMeasureSpec,
+ final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
+ Math.max(0, childWidth), MeasureSpec.EXACTLY);
+ final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin,
lp.height);
-
- // TODO: Use a field like lp.isMeasured to figure out if this
- // child has been previously measured
- if ((lp.width != 0) || (widthMode != MeasureSpec.EXACTLY)) {
- // child was measured once already above ... base new measurement
- // on stored values
- int childWidth = child.getMeasuredWidth() + share;
- if (childWidth < 0) {
- childWidth = 0;
- }
-
- child.measure(
- MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
- childHeightMeasureSpec);
- } else {
- // child was skipped in the loop above. Measure for this first time here
- child.measure(MeasureSpec.makeMeasureSpec(
- share > 0 ? share : 0, MeasureSpec.EXACTLY),
- childHeightMeasureSpec);
- }
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
// Child may now not fit in horizontal dimension.
childState = combineMeasuredStates(childState,
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index abcd614..df01fc1 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1226,6 +1226,12 @@
private int mLeft, mTop, mRight, mBottom;
+ /**
+ * Whether this view had any relative rules modified following the most
+ * recent resolution of layout direction.
+ */
+ private boolean mNeedsLayoutResolution;
+
private boolean mRulesChanged = false;
private boolean mIsRtlCompatibilityMode = false;
@@ -1374,47 +1380,69 @@
}
/**
- * Adds a layout rule to be interpreted by the RelativeLayout. This
- * method should only be used for constraints that don't refer to another sibling
- * (e.g., CENTER_IN_PARENT) or take a boolean value ({@link RelativeLayout#TRUE}
- * for true or 0 for false). To specify a verb that takes a subject, use
- * {@link #addRule(int, int)} instead.
+ * Adds a layout rule to be interpreted by the RelativeLayout.
+ * <p>
+ * This method should only be used for verbs that don't refer to a
+ * sibling (ex. {@link #ALIGN_RIGHT}) or take a boolean
+ * value ({@link #TRUE} for true or 0 for false). To
+ * specify a verb that takes a subject, use {@link #addRule(int, int)}.
+ * <p>
+ * If the rule is relative to the layout direction (ex.
+ * {@link #ALIGN_PARENT_START}), then the layout direction must be
+ * resolved using {@link #resolveLayoutDirection(int)} before calling
+ * {@link #getRule(int)} an absolute rule (ex.
+ * {@link #ALIGN_PARENT_LEFT}.
*
- * @param verb One of the verbs defined by
- * {@link android.widget.RelativeLayout RelativeLayout}, such as
- * ALIGN_WITH_PARENT_LEFT.
+ * @param verb a layout verb, such as {@link #ALIGN_PARENT_LEFT}
* @see #addRule(int, int)
+ * @see #removeRule(int)
* @see #getRule(int)
*/
public void addRule(int verb) {
- mRules[verb] = TRUE;
- mInitialRules[verb] = TRUE;
- mRulesChanged = true;
+ addRule(verb, TRUE);
}
/**
- * Adds a layout rule to be interpreted by the RelativeLayout. Use this for
- * verbs that take a target, such as a sibling (ALIGN_RIGHT) or a boolean
- * value (VISIBLE).
+ * Adds a layout rule to be interpreted by the RelativeLayout.
+ * <p>
+ * Use this for verbs that refer to a sibling (ex.
+ * {@link #ALIGN_RIGHT}) or take a boolean value (ex.
+ * {@link #CENTER_IN_PARENT}).
+ * <p>
+ * If the rule is relative to the layout direction (ex.
+ * {@link #START_OF}), then the layout direction must be resolved using
+ * {@link #resolveLayoutDirection(int)} before calling
+ * {@link #getRule(int)} with an absolute rule (ex. {@link #LEFT_OF}.
*
- * @param verb One of the verbs defined by
- * {@link android.widget.RelativeLayout RelativeLayout}, such as
- * ALIGN_WITH_PARENT_LEFT.
- * @param anchor The id of another view to use as an anchor,
- * or a boolean value (represented as {@link RelativeLayout#TRUE}
- * for true or 0 for false). For verbs that don't refer to another sibling
- * (for example, ALIGN_WITH_PARENT_BOTTOM) just use -1.
+ * @param verb a layout verb, such as {@link #ALIGN_RIGHT}
+ * @param subject the ID of another view to use as an anchor, or a
+ * boolean value (represented as {@link #TRUE} for true
+ * or 0 for false)
* @see #addRule(int)
+ * @see #removeRule(int)
* @see #getRule(int)
*/
- public void addRule(int verb, int anchor) {
- mRules[verb] = anchor;
- mInitialRules[verb] = anchor;
+ public void addRule(int verb, int subject) {
+ // If we're removing a relative rule, we'll need to force layout
+ // resolution the next time it's requested.
+ if (!mNeedsLayoutResolution && isRelativeRule(verb)
+ && mInitialRules[verb] != 0 && subject == 0) {
+ mNeedsLayoutResolution = true;
+ }
+
+ mRules[verb] = subject;
+ mInitialRules[verb] = subject;
mRulesChanged = true;
}
/**
* Removes a layout rule to be interpreted by the RelativeLayout.
+ * <p>
+ * If the rule is relative to the layout direction (ex.
+ * {@link #START_OF}, {@link #ALIGN_PARENT_START}, etc.) then the
+ * layout direction must be resolved using
+ * {@link #resolveLayoutDirection(int)} before before calling
+ * {@link #getRule(int)} with an absolute rule (ex. {@link #LEFT_OF}.
*
* @param verb One of the verbs defined by
* {@link android.widget.RelativeLayout RelativeLayout}, such as
@@ -1424,9 +1452,7 @@
* @see #getRule(int)
*/
public void removeRule(int verb) {
- mRules[verb] = 0;
- mInitialRules[verb] = 0;
- mRulesChanged = true;
+ addRule(verb, 0);
}
/**
@@ -1451,6 +1477,12 @@
mInitialRules[ALIGN_PARENT_START] != 0 || mInitialRules[ALIGN_PARENT_END] != 0);
}
+ private boolean isRelativeRule(int rule) {
+ return rule == START_OF || rule == END_OF
+ || rule == ALIGN_START || rule == ALIGN_END
+ || rule == ALIGN_PARENT_START || rule == ALIGN_PARENT_END;
+ }
+
// The way we are resolving rules depends on the layout direction and if we are pre JB MR1
// or not.
//
@@ -1578,7 +1610,9 @@
mRules[ALIGN_PARENT_END] = 0;
}
}
+
mRulesChanged = false;
+ mNeedsLayoutResolution = false;
}
/**
@@ -1596,13 +1630,7 @@
* @hide
*/
public int[] getRules(int layoutDirection) {
- if (hasRelativeRules() &&
- (mRulesChanged || layoutDirection != getLayoutDirection())) {
- resolveRules(layoutDirection);
- if (layoutDirection != getLayoutDirection()) {
- setLayoutDirection(layoutDirection);
- }
- }
+ resolveLayoutDirection(layoutDirection);
return mRules;
}
@@ -1618,16 +1646,30 @@
return mRules;
}
+ /**
+ * This will be called by {@link android.view.View#requestLayout()} to
+ * resolve layout parameters that are relative to the layout direction.
+ * <p>
+ * After this method is called, any rules using layout-relative verbs
+ * (ex. {@link #START_OF}) previously added via {@link #addRule(int)}
+ * may only be accessed via their resolved absolute verbs (ex.
+ * {@link #LEFT_OF}).
+ */
@Override
public void resolveLayoutDirection(int layoutDirection) {
- final boolean isLayoutRtl = isLayoutRtl();
- if (hasRelativeRules() && layoutDirection != getLayoutDirection()) {
+ if (shouldResolveLayoutDirection(layoutDirection)) {
resolveRules(layoutDirection);
}
- // This will set the layout direction
+
+ // This will set the layout direction.
super.resolveLayoutDirection(layoutDirection);
}
+ private boolean shouldResolveLayoutDirection(int layoutDirection) {
+ return (mNeedsLayoutResolution || hasRelativeRules())
+ && (mRulesChanged || layoutDirection != getLayoutDirection());
+ }
+
/** @hide */
@Override
protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 088adbb..ad2b4a7 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -816,7 +816,15 @@
mSearchButton.setVisibility(visCollapsed);
updateSubmitButton(hasText);
mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE);
- mCollapsedIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE);
+
+ final int iconVisibility;
+ if (mCollapsedIcon.getDrawable() == null || mIconifiedByDefault) {
+ iconVisibility = GONE;
+ } else {
+ iconVisibility = VISIBLE;
+ }
+ mCollapsedIcon.setVisibility(iconVisibility);
+
updateCloseButton();
updateVoiceButton(!hasText);
updateSubmitArea();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ce66eeb..7a64377 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -139,6 +139,7 @@
import android.view.textservice.TextServicesManager;
import android.widget.RemoteViews.RemoteView;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastMath;
import com.android.internal.widget.EditableInputConnection;
@@ -1695,6 +1696,15 @@
throw new UnsupportedOperationException("not implemented");
}
+
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public final Editor getEditorForTesting() {
+ return mEditor;
+ }
+
/**
* Associate an {@link android.content.UndoManager} with this TextView. Once
* done, all edit operations on the TextView will result in appropriate
@@ -8755,12 +8765,9 @@
public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
super.onPopulateAccessibilityEventInternal(event);
- final boolean isPassword = hasPasswordTransformationMethod();
- if (!isPassword || shouldSpeakPasswordsForAccessibility()) {
- final CharSequence text = getTextForAccessibility();
- if (!TextUtils.isEmpty(text)) {
- event.getText().add(text);
- }
+ final CharSequence text = getTextForAccessibility();
+ if (!TextUtils.isEmpty(text)) {
+ event.getText().add(text);
}
}
@@ -8911,10 +8918,7 @@
final boolean isPassword = hasPasswordTransformationMethod();
info.setPassword(isPassword);
-
- if (!isPassword || shouldSpeakPasswordsForAccessibility()) {
- info.setText(getTextForAccessibility());
- }
+ info.setText(getTextForAccessibility());
if (mBufferType == BufferType.EDITABLE) {
info.setEditable(true);
@@ -9146,18 +9150,30 @@
}
/**
- * Gets the text reported for accessibility purposes.
+ * Returns the text that should be exposed to accessibility services.
+ * <p>
+ * This approximates what is displayed visually. If the user has specified
+ * that accessibility services should speak passwords, this method will
+ * bypass any password transformation method and return unobscured text.
*
- * @return The accessibility text.
- *
- * @hide
+ * @return the text that should be exposed to accessibility services, may
+ * be {@code null} if no text is set
*/
- public CharSequence getTextForAccessibility() {
- CharSequence text = getText();
- if (TextUtils.isEmpty(text)) {
- text = getHint();
+ @Nullable
+ private CharSequence getTextForAccessibility() {
+ // If the text is empty, we must be showing the hint text.
+ if (TextUtils.isEmpty(mText)) {
+ return mHint;
}
- return text;
+
+ // Check whether we need to bypass the transformation
+ // method and expose unobscured text.
+ if (hasPasswordTransformationMethod() && shouldSpeakPasswordsForAccessibility()) {
+ return mText;
+ }
+
+ // Otherwise, speak whatever text is being displayed.
+ return mTransformed;
}
void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText,
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index d9faece..5fc8c7a 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -220,7 +220,7 @@
result.putExtras(replExtras);
}
}
- if (aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER)
+ if (aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_PARENT)
|| aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE)) {
result = Intent.createChooser(result,
getIntent().getCharSequenceExtra(Intent.EXTRA_TITLE));
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 39b66aa..dbec740 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -45,8 +45,8 @@
public static String TAG = "IntentForwarderActivity";
- public static String FORWARD_INTENT_TO_USER_OWNER
- = "com.android.internal.app.ForwardIntentToUserOwner";
+ public static String FORWARD_INTENT_TO_PARENT
+ = "com.android.internal.app.ForwardIntentToParent";
public static String FORWARD_INTENT_TO_MANAGED_PROFILE
= "com.android.internal.app.ForwardIntentToManagedProfile";
@@ -60,9 +60,9 @@
final int targetUserId;
final int userMessageId;
- if (className.equals(FORWARD_INTENT_TO_USER_OWNER)) {
+ if (className.equals(FORWARD_INTENT_TO_PARENT)) {
userMessageId = com.android.internal.R.string.forward_intent_to_owner;
- targetUserId = UserHandle.USER_OWNER;
+ targetUserId = getProfileParent();
} else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
userMessageId = com.android.internal.R.string.forward_intent_to_work;
targetUserId = getManagedProfile();
@@ -72,7 +72,7 @@
targetUserId = UserHandle.USER_NULL;
}
if (targetUserId == UserHandle.USER_NULL) {
- // This covers the case where there is no managed profile.
+ // This covers the case where there is no parent / managed profile.
finish();
return;
}
@@ -168,7 +168,7 @@
*/
private int getManagedProfile() {
UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
- List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.USER_OWNER);
+ List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.myUserId());
for (UserInfo userInfo : relatedUsers) {
if (userInfo.isManagedProfile()) return userInfo.id;
}
@@ -176,4 +176,19 @@
+ " has been called, but there is no managed profile");
return UserHandle.USER_NULL;
}
+
+ /**
+ * Returns the userId of the profile parent or UserHandle.USER_NULL if there is
+ * no parent.
+ */
+ private int getProfileParent() {
+ UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
+ UserInfo parent = userManager.getProfileParent(UserHandle.myUserId());
+ if (parent == null) {
+ Slog.wtf(TAG, FORWARD_INTENT_TO_PARENT
+ + " has been called, but there is no parent");
+ return UserHandle.USER_NULL;
+ }
+ return parent.id;
+ }
}
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index c1b184e..9d12803 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -23,6 +23,7 @@
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.view.ActionMode;
+import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -467,6 +468,9 @@
public boolean onKeyShortcut(int keyCode, KeyEvent event) {
Menu menu = mDecorToolbar.getMenu();
if (menu != null) {
+ final KeyCharacterMap kmap = KeyCharacterMap.load(
+ event != null ? event.getDeviceId() : KeyCharacterMap.VIRTUAL_KEYBOARD);
+ menu.setQwertyMode(kmap.getKeyboardType() != KeyCharacterMap.NUMERIC);
menu.performShortcut(keyCode, event, 0);
}
// This action bar always returns true for handling keyboard shortcuts.
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6c7e298..4ff7869 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -25,7 +25,6 @@
import android.net.NetworkStats;
import android.net.wifi.WifiActivityEnergyInfo;
import android.net.wifi.WifiManager;
-import android.os.BadParcelableException;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Build;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index ea2b30f..55e23b1 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -20,6 +20,7 @@
import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.HOME_STACK_ID;
+import static android.app.ActivityManager.INVALID_STACK_ID;
import static android.view.View.MeasureSpec.AT_MOST;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.getMode;
@@ -2028,18 +2029,22 @@
}
// Save the accessibility focused view ID.
- final ViewRootImpl viewRootImpl = mContentParent.getViewRootImpl();
- final View accessFocusHost = viewRootImpl.getAccessibilityFocusedHost();
- if (accessFocusHost != null && accessFocusHost.getId() != View.NO_ID) {
- outState.putInt(ACCESSIBILITY_FOCUSED_ID_TAG, accessFocusHost.getId());
+ if (mDecor != null) {
+ final ViewRootImpl viewRootImpl = mDecor.getViewRootImpl();
+ if (viewRootImpl != null) {
+ final View accessFocusHost = viewRootImpl.getAccessibilityFocusedHost();
+ if (accessFocusHost != null && accessFocusHost.getId() != View.NO_ID) {
+ outState.putInt(ACCESSIBILITY_FOCUSED_ID_TAG, accessFocusHost.getId());
- // If we have a focused virtual node ID, save that too.
- final AccessibilityNodeInfo accessFocusedNode =
- viewRootImpl.getAccessibilityFocusedVirtualView();
- if (accessFocusedNode != null) {
- final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
- accessFocusedNode.getSourceNodeId());
- outState.putInt(ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, virtualNodeId);
+ // If we have a focused virtual node ID, save that too.
+ final AccessibilityNodeInfo accessFocusedNode =
+ viewRootImpl.getAccessibilityFocusedVirtualView();
+ if (accessFocusedNode != null) {
+ final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
+ accessFocusedNode.getSourceNodeId());
+ outState.putInt(ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, virtualNodeId);
+ }
+ }
}
}
@@ -2112,8 +2117,8 @@
}
private void tryRestoreAccessibilityFocus(int hostViewId, int virtualViewId) {
- if (hostViewId != View.NO_ID) {
- final View needsAccessFocus = mContentParent.findViewById(hostViewId);
+ if (hostViewId != View.NO_ID && mDecor != null) {
+ final View needsAccessFocus = mDecor.findViewById(hostViewId);
if (needsAccessFocus != null) {
if (!tryFocusingVirtualView(needsAccessFocus, virtualViewId)
&& !needsAccessFocus.requestAccessibilityFocus()) {
@@ -5246,7 +5251,7 @@
* @return Returns the workspace stack id which contains this window.
**/
private int getWorkspaceId() {
- int workspaceId = FULLSCREEN_WORKSPACE_STACK_ID;
+ int workspaceId = INVALID_STACK_ID;
WindowControllerCallback callback = getWindowControllerCallback();
if (callback != null) {
try {
@@ -5255,6 +5260,9 @@
Log.e(TAG, "Failed to get the workspace ID of a PhoneWindow.");
}
}
+ if (workspaceId == INVALID_STACK_ID) {
+ return FULLSCREEN_WORKSPACE_STACK_ID;
+ }
return workspaceId;
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index c1645c3..ab3ec98 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -46,6 +46,8 @@
void cancelPreloadRecentApps();
void showScreenPinningRequest();
+ void showKeyboardShortcutsMenu();
+
/**
* Notifies the status bar that an app transition is pending to delay applying some flags with
* visual impact until {@link #appTransitionReady} is called.
@@ -69,5 +71,10 @@
void showAssistDisclosure();
void startAssist(in Bundle args);
+
+ /**
+ * Notifies the status bar that a camera launch gesture has been detected.
+ */
+ void onCameraLaunchGestureDetected();
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 7db2cc9f..6c957be 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -68,6 +68,8 @@
void preloadRecentApps();
void cancelPreloadRecentApps();
+ void showKeyboardShortcutsMenu();
+
/**
* Notifies the status bar that an app transition is pending to delay applying some flags with
* visual impact until {@link #appTransitionReady} is called.
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 229407e..6816646 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -29,6 +29,7 @@
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
+import java.util.Iterator;
import java.util.HashMap;
import java.util.Vector;
@@ -1864,6 +1865,20 @@
}
/**
+ * Removes a message from the deferred messages queue.
+ */
+ protected final void removeDeferredMessages(int what) {
+ SmHandler smh = mSmHandler;
+ if (smh == null) return;
+
+ Iterator<Message> iterator = smh.mDeferredMessages.iterator();
+ while (iterator.hasNext()) {
+ Message msg = iterator.next();
+ if (msg.what == what) iterator.remove();
+ }
+ }
+
+ /**
* Validate that the message was sent by
* {@link StateMachine#quit} or {@link StateMachine#quitNow}.
* */
diff --git a/core/java/com/android/internal/widget/ExploreByTouchHelper.java b/core/java/com/android/internal/widget/ExploreByTouchHelper.java
index f5637dd..50ad547 100644
--- a/core/java/com/android/internal/widget/ExploreByTouchHelper.java
+++ b/core/java/com/android/internal/widget/ExploreByTouchHelper.java
@@ -307,6 +307,10 @@
private AccessibilityEvent createEventForHost(int eventType) {
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
mView.onInitializeAccessibilityEvent(event);
+
+ // Allow the client to populate the event.
+ onPopulateEventForHost(event);
+
return event;
}
@@ -369,6 +373,10 @@
private AccessibilityNodeInfo createNodeForHost() {
final AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain(mView);
mView.onInitializeAccessibilityNodeInfo(node);
+ final int realNodeCount = node.getChildCount();
+
+ // Allow the client to populate the host node.
+ onPopulateNodeForHost(node);
// Add the virtual descendants.
if (mTempArray == null) {
@@ -378,6 +386,9 @@
}
final IntArray virtualViewIds = mTempArray;
getVisibleVirtualViews(virtualViewIds);
+ if (realNodeCount > 0 && virtualViewIds.size() > 0) {
+ throw new RuntimeException("Views cannot have both real and virtual children");
+ }
final int N = virtualViewIds.size();
for (int i = 0; i < N; i++) {
@@ -692,6 +703,18 @@
int virtualViewId, AccessibilityEvent event);
/**
+ * Populates an {@link AccessibilityEvent} with information about the host
+ * view.
+ * <p>
+ * The default implementation is a no-op.
+ *
+ * @param event the event to populate with information about the host view
+ */
+ protected void onPopulateEventForHost(AccessibilityEvent event) {
+ // Default implementation is no-op.
+ }
+
+ /**
* Populates an {@link AccessibilityNodeInfo} with information
* about the specified item.
* <p>
@@ -750,6 +773,18 @@
int virtualViewId, AccessibilityNodeInfo node);
/**
+ * Populates an {@link AccessibilityNodeInfo} with information about the
+ * host view.
+ * <p>
+ * The default implementation is a no-op.
+ *
+ * @param node the node to populate with information about the host view
+ */
+ protected void onPopulateNodeForHost(AccessibilityNodeInfo node) {
+ // Default implementation is no-op.
+ }
+
+ /**
* Performs the specified accessibility action on the item associated
* with the virtual view identifier. See
* {@link AccessibilityNodeInfo#performAction(int, Bundle)} for
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index dfb7c50..4e4552d 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -16,6 +16,7 @@
package com.android.internal.widget;
+import android.app.trust.IStrongAuthTracker;
import com.android.internal.widget.VerifyCredentialResponse;
/** {@hide} */
@@ -35,4 +36,7 @@
boolean checkVoldPassword(int userId);
boolean havePattern(int userId);
boolean havePassword(int userId);
+ void registerStrongAuthTracker(in IStrongAuthTracker tracker);
+ void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
+ void requireStrongAuth(int strongAuthReason, int userId);
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index ca184d1..0579ce7d 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -16,19 +16,19 @@
package com.android.internal.widget;
-import android.Manifest;
+import android.annotation.IntDef;
import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
import android.app.admin.DevicePolicyManager;
+import android.app.trust.IStrongAuthTracker;
import android.app.trust.TrustManager;
-import android.bluetooth.BluetoothClass;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.AsyncTask;
+import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -39,9 +39,12 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseIntArray;
import com.google.android.collect.Lists;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -229,7 +232,7 @@
public void reportFailedPasswordAttempt(int userId) {
getDevicePolicyManager().reportFailedPasswordAttempt(userId);
getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
- getTrustManager().reportRequireCredentialEntry(userId);
+ requireCredentialEntry(userId);
}
public void reportSuccessfulPasswordAttempt(int userId) {
@@ -1168,10 +1171,32 @@
}
/**
- * @see android.app.trust.TrustManager#reportRequireCredentialEntry(int)
+ * Disable trust until credentials have been entered for user {@param userId}.
+ *
+ * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ *
+ * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
*/
public void requireCredentialEntry(int userId) {
- getTrustManager().reportRequireCredentialEntry(userId);
+ requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
+ }
+
+ /**
+ * Requests strong authentication for user {@param userId}.
+ *
+ * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ *
+ * @param strongAuthReason a combination of {@link StrongAuthTracker.StrongAuthFlags} indicating
+ * the reason for and the strength of the requested authentication.
+ * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
+ */
+ public void requireStrongAuth(@StrongAuthTracker.StrongAuthFlags int strongAuthReason,
+ int userId) {
+ try {
+ getLockSettings().requireStrongAuth(strongAuthReason, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error while requesting strong auth: " + e);
+ }
}
private void onAfterChangingPassword(int userHandle) {
@@ -1209,4 +1234,153 @@
throw new IllegalStateException("should not be called from the main thread.");
}
}
+
+ public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
+ try {
+ getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Could not register StrongAuthTracker");
+ }
+ }
+
+ public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
+ try {
+ getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.mStub);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not unregister StrongAuthTracker", e);
+ }
+ }
+
+ /**
+ * Tracks the global strong authentication state.
+ */
+ public static class StrongAuthTracker {
+
+ @IntDef(flag = true,
+ value = { STRONG_AUTH_NOT_REQUIRED,
+ STRONG_AUTH_REQUIRED_AFTER_BOOT,
+ STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
+ SOME_AUTH_REQUIRED_AFTER_USER_REQUEST})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StrongAuthFlags {}
+
+ /**
+ * Strong authentication is not required.
+ */
+ public static final int STRONG_AUTH_NOT_REQUIRED = 0x0;
+
+ /**
+ * Strong authentication is required because the user has not authenticated since boot.
+ */
+ public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;
+
+ /**
+ * Strong authentication is required because a device admin has requested it.
+ */
+ public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;
+
+ /**
+ * Some authentication is required because the user has temporarily disabled trust.
+ */
+ public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
+
+ /**
+ * Strong authentication is required because the user has been locked out after too many
+ * attempts.
+ */
+ public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
+
+ public static final int DEFAULT = STRONG_AUTH_REQUIRED_AFTER_BOOT;
+ private static final int ALLOWING_FINGERPRINT = SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
+
+ final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
+
+ private final H mHandler;
+
+ public StrongAuthTracker() {
+ this(Looper.myLooper());
+ }
+
+ /**
+ * @param looper the looper on whose thread calls to {@link #onStrongAuthRequiredChanged}
+ * will be scheduled.
+ */
+ public StrongAuthTracker(Looper looper) {
+ mHandler = new H(looper);
+ }
+
+ /**
+ * Returns {@link #STRONG_AUTH_NOT_REQUIRED} if strong authentication is not required,
+ * otherwise returns a combination of {@link StrongAuthFlags} indicating why strong
+ * authentication is required.
+ *
+ * @param userId the user for whom the state is queried.
+ */
+ public @StrongAuthFlags int getStrongAuthForUser(int userId) {
+ return mStrongAuthRequiredForUser.get(userId, DEFAULT);
+ }
+
+ /**
+ * @return true if unlocking with trust alone is allowed for {@param userId} by the current
+ * strong authentication requirements.
+ */
+ public boolean isTrustAllowedForUser(int userId) {
+ return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
+ }
+
+ /**
+ * @return true if unlocking with fingerprint alone is allowed for {@param userId} by the
+ * current strong authentication requirements.
+ */
+ public boolean isFingerprintAllowedForUser(int userId) {
+ return (getStrongAuthForUser(userId) & ~ALLOWING_FINGERPRINT) == 0;
+ }
+
+ /**
+ * Called when the strong authentication requirements for {@param userId} changed.
+ */
+ public void onStrongAuthRequiredChanged(int userId) {
+ }
+
+ void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
+ int userId) {
+
+ int oldValue = getStrongAuthForUser(userId);
+ if (strongAuthFlags != oldValue) {
+ if (strongAuthFlags == DEFAULT) {
+ mStrongAuthRequiredForUser.delete(userId);
+ } else {
+ mStrongAuthRequiredForUser.put(userId, strongAuthFlags);
+ }
+ onStrongAuthRequiredChanged(userId);
+ }
+ }
+
+
+ final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
+ @Override
+ public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
+ int userId) {
+ mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED,
+ strongAuthFlags, userId).sendToTarget();
+ }
+ };
+
+ private class H extends Handler {
+ static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1;
+
+ public H(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED:
+ handleStrongAuthRequiredChanged(msg.arg1, msg.arg2);
+ break;
+ }
+ }
+ };
+ }
}
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
index 05711b5..372d934 100644
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -20,6 +20,7 @@
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.view.ViewGroup;
@@ -63,18 +64,31 @@
private final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20;
// The height of a window which has not in DIP.
private final int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
-
private PhoneWindow mOwner = null;
- boolean mWindowHasShadow = false;
- boolean mShowDecor = false;
+ private boolean mWindowHasShadow = false;
+ private boolean mShowDecor = false;
+
+ // True if the window is being dragged.
+ private boolean mDragging = false;
+
+ // The bounds of the window and the absolute mouse pointer coordinates from before we started to
+ // drag the window. They will be used to determine the next window position.
+ private final Rect mWindowOriginalBounds = new Rect();
+ private float mStartDragX;
+ private float mStartDragY;
+ // True when the left mouse button got released while dragging.
+ private boolean mLeftMouseButtonReleased;
+
+ // Avoiding re-creation of Rect's by keeping a temporary window drag bound.
+ private final Rect mWindowDragBounds = new Rect();
// The current focus state of the window for updating the window elevation.
- boolean mWindowHasFocus = true;
+ private boolean mWindowHasFocus = true;
// Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
// size calculation takes the shadow size into account. We set the elevation currently
// to max until the first layout command has been executed.
- boolean mAllowUpdateElevation = false;
+ private boolean mAllowUpdateElevation = false;
public NonClientDecorView(Context context) {
super(context);
@@ -103,6 +117,66 @@
findViewById(R.id.close_window).setOnClickListener(this);
}
+ @Override
+ public boolean onTouchEvent(MotionEvent e) {
+ // Note: There are no mixed events. When a new device gets used (e.g. 1. Mouse, 2. touch)
+ // the old input device events get cancelled first. So no need to remember the kind of
+ // input device we are listening to.
+ switch (e.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ if (!mShowDecor) {
+ // When there is no decor we should not react to anything.
+ return false;
+ }
+ // A drag action is started if we aren't dragging already and the starting event is
+ // either a left mouse button or any other input device.
+ if (!mDragging &&
+ (e.getToolType(e.getActionIndex()) != MotionEvent.TOOL_TYPE_MOUSE ||
+ (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0)) {
+ mDragging = true;
+ mWindowOriginalBounds.set(getActivityBounds());
+ mLeftMouseButtonReleased = false;
+ mStartDragX = e.getRawX();
+ mStartDragY = e.getRawY();
+ }
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ if (mDragging && !mLeftMouseButtonReleased) {
+ if (e.getToolType(e.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE &&
+ (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) == 0) {
+ // There is no separate mouse button up call and if the user mixes mouse
+ // button drag actions, we stop dragging once he releases the button.
+ mLeftMouseButtonReleased = true;
+ break;
+ }
+ mWindowDragBounds.set(mWindowOriginalBounds);
+ mWindowDragBounds.offset(Math.round(e.getRawX() - mStartDragX),
+ Math.round(e.getRawY() - mStartDragY));
+ setActivityBounds(mWindowDragBounds);
+ }
+ break;
+
+ case MotionEvent.ACTION_UP:
+ if (mDragging) {
+ // Since the window is already where it should be we don't have to do anything
+ // special at this time.
+ mDragging = false;
+ return true;
+ }
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ if (mDragging) {
+ mDragging = false;
+ setActivityBounds(mWindowOriginalBounds);
+ return true;
+ }
+ break;
+ }
+ return mDragging;
+ }
+
/**
* The phone window configuration has changed and the decor needs to be updated.
* @param showDecor True if the decor should be shown.
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index b7eda4a..75da27e 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -114,7 +114,6 @@
android/graphics/MinikinUtils.cpp \
android/graphics/Movie.cpp \
android/graphics/NinePatch.cpp \
- android/graphics/NinePatchImpl.cpp \
android/graphics/NinePatchPeeker.cpp \
android/graphics/Paint.cpp \
android/graphics/PaintImpl.cpp \
diff --git a/core/jni/android/graphics/AvoidXfermode.h b/core/jni/android/graphics/AvoidXfermode.h
index 318d7be..8b7fb71 100644
--- a/core/jni/android/graphics/AvoidXfermode.h
+++ b/core/jni/android/graphics/AvoidXfermode.h
@@ -40,7 +40,7 @@
Tolerance near 255: draw on any colors even remotely similar to the op-color
*/
static AvoidXfermode* Create(SkColor opColor, U8CPU tolerance, Mode mode) {
- return SkNEW_ARGS(AvoidXfermode, (opColor, tolerance, mode));
+ return new AvoidXfermode(opColor, tolerance, mode);
}
// overrides from SkXfermode
diff --git a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
index e537942..ae99f0b 100644
--- a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
+++ b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
@@ -32,6 +32,7 @@
#include "HarfBuzzNGFaceSkia.h"
+#include <stdlib.h>
#include <cutils/log.h>
#include <SkPaint.h>
#include <SkPath.h>
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index e69f64e..1c28262 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -29,12 +29,11 @@
#include "SkRegion.h"
#include "GraphicsJNI.h"
+#include "utils/NinePatch.h"
+
#include "JNIHelp.h"
#include "core_jni_helpers.h"
-extern void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, const SkBitmap& bitmap,
- const android::Res_png_9patch& chunk, const SkPaint* paint, SkRegion** outRegion);
-
using namespace android;
/**
@@ -88,72 +87,6 @@
}
}
- static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds, const SkBitmap& bitmap,
- Res_png_9patch* chunk, const SkPaint* paint, jint destDensity, jint srcDensity) {
- if (destDensity == srcDensity || destDensity == 0 || srcDensity == 0) {
- ALOGV("Drawing unscaled 9-patch: (%g,%g)-(%g,%g)",
- SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
- SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom));
- NinePatch_Draw(canvas, bounds, bitmap, *chunk, paint, NULL);
- } else {
- canvas->save();
-
- SkScalar scale = destDensity / (float)srcDensity;
- canvas->translate(bounds.fLeft, bounds.fTop);
- canvas->scale(scale, scale);
-
- bounds.fRight = (bounds.fRight-bounds.fLeft) / scale;
- bounds.fBottom = (bounds.fBottom-bounds.fTop) / scale;
- bounds.fLeft = bounds.fTop = 0;
-
- ALOGV("Drawing scaled 9-patch: (%g,%g)-(%g,%g) srcDensity=%d destDensity=%d",
- SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
- SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom),
- srcDensity, destDensity);
-
- NinePatch_Draw(canvas, bounds, bitmap, *chunk, paint, NULL);
-
- canvas->restore();
- }
- }
-
- static void drawF(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRectF,
- jobject jbitmap, jlong chunkHandle, jlong paintHandle,
- jint destDensity, jint srcDensity) {
- SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->asSkCanvas();
- Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
- const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- SkASSERT(canvas);
- SkASSERT(boundsRectF);
- SkASSERT(chunk);
- // paint is optional
-
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
- SkRect bounds;
- GraphicsJNI::jrectf_to_rect(env, boundsRectF, &bounds);
-
- draw(env, canvas, bounds, bitmap, chunk, paint, destDensity, srcDensity);
- }
-
- static void drawI(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRect,
- jobject jbitmap, jlong chunkHandle, jlong paintHandle,
- jint destDensity, jint srcDensity) {
- SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->asSkCanvas();
- Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
- const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- SkASSERT(canvas);
- SkASSERT(boundsRect);
- SkASSERT(chunk);
- // paint is optional
-
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
- SkRect bounds;
- GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
- draw(env, canvas, bounds, bitmap, chunk, paint, destDensity, srcDensity);
- }
-
static jlong getTransparentRegion(JNIEnv* env, jobject, jobject jbitmap,
jlong chunkHandle, jobject boundsRect) {
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
@@ -166,7 +99,7 @@
GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
SkRegion* region = NULL;
- NinePatch_Draw(NULL, bounds, bitmap, *chunk, NULL, ®ion);
+ NinePatch::Draw(NULL, bounds, bitmap, *chunk, NULL, ®ion);
return reinterpret_cast<jlong>(region);
}
@@ -180,10 +113,6 @@
{ "validateNinePatchChunk", "([B)J",
(void*) SkNinePatchGlue::validateNinePatchChunk },
{ "nativeFinalize", "(J)V", (void*) SkNinePatchGlue::finalize },
- { "nativeDraw", "(JLandroid/graphics/RectF;Landroid/graphics/Bitmap;JJII)V",
- (void*) SkNinePatchGlue::drawF },
- { "nativeDraw", "(JLandroid/graphics/Rect;Landroid/graphics/Bitmap;JJII)V",
- (void*) SkNinePatchGlue::drawI },
{ "nativeGetTransparentRegion", "(Landroid/graphics/Bitmap;JLandroid/graphics/Rect;)J",
(void*) SkNinePatchGlue::getTransparentRegion }
};
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index c66cdfe..988d13a 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -112,15 +112,15 @@
}
static jlong init(JNIEnv* env, jobject clazz) {
- SK_COMPILE_ASSERT(1 << 0 == SkPaint::kAntiAlias_Flag, paint_flags_mismatch);
- SK_COMPILE_ASSERT(1 << 2 == SkPaint::kDither_Flag, paint_flags_mismatch);
- SK_COMPILE_ASSERT(1 << 3 == SkPaint::kUnderlineText_Flag, paint_flags_mismatch);
- SK_COMPILE_ASSERT(1 << 4 == SkPaint::kStrikeThruText_Flag, paint_flags_mismatch);
- SK_COMPILE_ASSERT(1 << 5 == SkPaint::kFakeBoldText_Flag, paint_flags_mismatch);
- SK_COMPILE_ASSERT(1 << 6 == SkPaint::kLinearText_Flag, paint_flags_mismatch);
- SK_COMPILE_ASSERT(1 << 7 == SkPaint::kSubpixelText_Flag, paint_flags_mismatch);
- SK_COMPILE_ASSERT(1 << 8 == SkPaint::kDevKernText_Flag, paint_flags_mismatch);
- SK_COMPILE_ASSERT(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, paint_flags_mismatch);
+ static_assert(1 << 0 == SkPaint::kAntiAlias_Flag, "paint_flags_mismatch");
+ static_assert(1 << 2 == SkPaint::kDither_Flag, "paint_flags_mismatch");
+ static_assert(1 << 3 == SkPaint::kUnderlineText_Flag, "paint_flags_mismatch");
+ static_assert(1 << 4 == SkPaint::kStrikeThruText_Flag, "paint_flags_mismatch");
+ static_assert(1 << 5 == SkPaint::kFakeBoldText_Flag, "paint_flags_mismatch");
+ static_assert(1 << 6 == SkPaint::kLinearText_Flag, "paint_flags_mismatch");
+ static_assert(1 << 7 == SkPaint::kSubpixelText_Flag, "paint_flags_mismatch");
+ static_assert(1 << 8 == SkPaint::kDevKernText_Flag, "paint_flags_mismatch");
+ static_assert(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, "paint_flags_mismatch");
Paint* obj = new Paint();
defaultSettingsForAndroid(obj);
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index f7b5dc2..dbd7c89 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -519,6 +519,9 @@
int register_android_graphics_Path(JNIEnv* env) {
return RegisterMethodsOrDie(env, "android/graphics/Path", methods, NELEM(methods));
+
+ static_assert(0 == SkPath::kCW_Direction, "direction_mismatch");
+ static_assert(1 == SkPath::kCCW_Direction, "direction_mismatch");
}
}
diff --git a/core/jni/android/graphics/PorterDuff.cpp b/core/jni/android/graphics/PorterDuff.cpp
index d65864d..fed90a5 100644
--- a/core/jni/android/graphics/PorterDuff.cpp
+++ b/core/jni/android/graphics/PorterDuff.cpp
@@ -33,29 +33,29 @@
static jlong CreateXfermode(JNIEnv* env, jobject, jint modeHandle) {
// validate that the Java enum values match our expectations
- SK_COMPILE_ASSERT(0 == SkXfermode::kClear_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(1 == SkXfermode::kSrc_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(2 == SkXfermode::kDst_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(3 == SkXfermode::kSrcOver_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(4 == SkXfermode::kDstOver_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(5 == SkXfermode::kSrcIn_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(6 == SkXfermode::kDstIn_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(7 == SkXfermode::kSrcOut_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(8 == SkXfermode::kDstOut_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(9 == SkXfermode::kSrcATop_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(10 == SkXfermode::kDstATop_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(11 == SkXfermode::kXor_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(16 == SkXfermode::kDarken_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(17 == SkXfermode::kLighten_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(13 == SkXfermode::kModulate_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(14 == SkXfermode::kScreen_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(12 == SkXfermode::kPlus_Mode, xfermode_mismatch);
- SK_COMPILE_ASSERT(15 == SkXfermode::kOverlay_Mode, xfermode_mismatch);
-
+ static_assert(0 == SkXfermode::kClear_Mode, "xfermode_mismatch");
+ static_assert(1 == SkXfermode::kSrc_Mode, "xfermode_mismatch");
+ static_assert(2 == SkXfermode::kDst_Mode, "xfermode_mismatch");
+ static_assert(3 == SkXfermode::kSrcOver_Mode, "xfermode_mismatch");
+ static_assert(4 == SkXfermode::kDstOver_Mode, "xfermode_mismatch");
+ static_assert(5 == SkXfermode::kSrcIn_Mode, "xfermode_mismatch");
+ static_assert(6 == SkXfermode::kDstIn_Mode, "xfermode_mismatch");
+ static_assert(7 == SkXfermode::kSrcOut_Mode, "xfermode_mismatch");
+ static_assert(8 == SkXfermode::kDstOut_Mode, "xfermode_mismatch");
+ static_assert(9 == SkXfermode::kSrcATop_Mode, "xfermode_mismatch");
+ static_assert(10 == SkXfermode::kDstATop_Mode, "xfermode_mismatch");
+ static_assert(11 == SkXfermode::kXor_Mode, "xfermode_mismatch");
+ static_assert(16 == SkXfermode::kDarken_Mode, "xfermode_mismatch");
+ static_assert(17 == SkXfermode::kLighten_Mode, "xfermode_mismatch");
+ static_assert(13 == SkXfermode::kModulate_Mode, "xfermode_mismatch");
+ static_assert(14 == SkXfermode::kScreen_Mode, "xfermode_mismatch");
+ static_assert(12 == SkXfermode::kPlus_Mode, "xfermode_mismatch");
+ static_assert(15 == SkXfermode::kOverlay_Mode, "xfermode_mismatch");
+
SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
return reinterpret_cast<jlong>(SkXfermode::Create(mode));
}
-
+
};
static JNINativeMethod methods[] = {
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 43825ad..5ddf235 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -18,7 +18,10 @@
#include "GraphicsJNI.h"
#include "core_jni_helpers.h"
+#include <androidfw/ResourceTypes.h>
#include <Canvas.h>
+
+#include "Bitmap.h"
#include "SkDrawFilter.h"
#include "SkGraphics.h"
#include "Paint.h"
@@ -330,6 +333,39 @@
indices, indexCount, *paint);
}
+static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
+ jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
+ jlong paintHandle, jint dstDensity, jint srcDensity) {
+
+ Canvas* canvas = get_canvas(canvasHandle);
+ Bitmap* bitmap = reinterpret_cast<Bitmap*>(bitmapHandle);
+ SkBitmap skiaBitmap;
+ bitmap->getSkBitmap(&skiaBitmap);
+ const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle);
+ const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+
+ if (CC_LIKELY(dstDensity == srcDensity || dstDensity == 0 || srcDensity == 0)) {
+ canvas->drawNinePatch(skiaBitmap, *chunk, left, top, right, bottom, paint);
+ } else {
+ canvas->save(SkCanvas::kMatrixClip_SaveFlag);
+
+ SkScalar scale = dstDensity / (float)srcDensity;
+ canvas->translate(left, top);
+ canvas->scale(scale, scale);
+
+ Paint filteredPaint;
+ if (paint) {
+ filteredPaint = *paint;
+ }
+ filteredPaint.setFilterQuality(kLow_SkFilterQuality);
+
+ canvas->drawNinePatch(skiaBitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale,
+ &filteredPaint);
+
+ canvas->restore();
+ }
+}
+
static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap,
jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
jint screenDensity, jint bitmapDensity) {
@@ -751,6 +787,7 @@
{"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
{"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
{"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
+ {"native_drawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
{"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
{"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
{"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
diff --git a/core/jni/android_media_AudioErrors.h b/core/jni/android_media_AudioErrors.h
index 4907830..c17a020 100644
--- a/core/jni/android_media_AudioErrors.h
+++ b/core/jni/android_media_AudioErrors.h
@@ -32,6 +32,7 @@
AUDIO_JAVA_PERMISSION_DENIED = -4,
AUDIO_JAVA_NO_INIT = -5,
AUDIO_JAVA_DEAD_OBJECT = -6,
+ AUDIO_JAVA_WOULD_BLOCK = -7,
};
static inline jint nativeToJavaStatus(status_t status) {
@@ -46,6 +47,8 @@
return AUDIO_JAVA_PERMISSION_DENIED;
case NO_INIT:
return AUDIO_JAVA_NO_INIT;
+ case WOULD_BLOCK:
+ return AUDIO_JAVA_WOULD_BLOCK;
case DEAD_OBJECT:
return AUDIO_JAVA_DEAD_OBJECT;
default:
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index 2953db4..460c1a1 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -22,8 +22,6 @@
#include <android_runtime/AndroidRuntime.h>
-#include <androidfw/ResourceTypes.h>
-
#include <cutils/properties.h>
#include <SkBitmap.h>
@@ -42,18 +40,14 @@
using namespace uirenderer;
-static struct {
- jmethodID set;
-} gRectClassInfo;
-
// ----------------------------------------------------------------------------
// Setup
// ----------------------------------------------------------------------------
static void android_view_DisplayListCanvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jboolean reorderEnable) {
- DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
- renderer->insertReorderBarrier(reorderEnable);
+ jlong canvasPtr, jboolean reorderEnable) {
+ DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+ canvas->insertReorderBarrier(reorderEnable);
}
// ----------------------------------------------------------------------------
@@ -61,10 +55,10 @@
// ----------------------------------------------------------------------------
static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong functorPtr) {
- DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
+ jlong canvasPtr, jlong functorPtr) {
+ DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
Functor* functor = reinterpret_cast<Functor*>(functorPtr);
- renderer->callDrawGLFunction(functor);
+ canvas->callDrawGLFunction(functor);
}
// ----------------------------------------------------------------------------
@@ -83,21 +77,10 @@
// Drawing
// ----------------------------------------------------------------------------
-static void android_view_DisplayListCanvas_drawPatch(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jobject jbitmap, jlong patchPtr,
- float left, float top, float right, float bottom, jlong paintPtr) {
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
- DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
- Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr);
- Paint* paint = reinterpret_cast<Paint*>(paintPtr);
- renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
-}
-
static void android_view_DisplayListCanvas_drawRoundRectProps(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
+ jlong canvasPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) {
- DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
+ DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
CanvasPropertyPrimitive* leftProp = reinterpret_cast<CanvasPropertyPrimitive*>(leftPropPtr);
CanvasPropertyPrimitive* topProp = reinterpret_cast<CanvasPropertyPrimitive*>(topPropPtr);
CanvasPropertyPrimitive* rightProp = reinterpret_cast<CanvasPropertyPrimitive*>(rightPropPtr);
@@ -105,17 +88,17 @@
CanvasPropertyPrimitive* rxProp = reinterpret_cast<CanvasPropertyPrimitive*>(rxPropPtr);
CanvasPropertyPrimitive* ryProp = reinterpret_cast<CanvasPropertyPrimitive*>(ryPropPtr);
CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
- renderer->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp);
+ canvas->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp);
}
static void android_view_DisplayListCanvas_drawCircleProps(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
- DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
+ jlong canvasPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
+ DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
- renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
+ canvas->drawCircle(xProp, yProp, radiusProp, paintProp);
}
// ----------------------------------------------------------------------------
@@ -123,9 +106,9 @@
// ----------------------------------------------------------------------------
static jlong android_view_DisplayListCanvas_finishRecording(JNIEnv* env,
- jobject clazz, jlong rendererPtr) {
- DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
- return reinterpret_cast<jlong>(renderer->finishRecording());
+ jobject clazz, jlong canvasPtr) {
+ DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+ return reinterpret_cast<jlong>(canvas->finishRecording());
}
static jlong android_view_DisplayListCanvas_createDisplayListCanvas(JNIEnv* env, jobject clazz,
@@ -134,17 +117,17 @@
}
static void android_view_DisplayListCanvas_resetDisplayListCanvas(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jint width, jint height) {
- DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
- renderer->reset(width, height);
+ jlong canvasPtr, jint width, jint height) {
+ DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+ canvas->reset(width, height);
}
static void android_view_DisplayListCanvas_drawRenderNode(JNIEnv* env,
- jobject clazz, jlong rendererPtr, jlong renderNodePtr) {
- DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
+ jobject clazz, jlong canvasPtr, jlong renderNodePtr) {
+ DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderer->drawRenderNode(renderNode);
+ canvas->drawRenderNode(renderNode);
}
// ----------------------------------------------------------------------------
@@ -152,10 +135,10 @@
// ----------------------------------------------------------------------------
static void android_view_DisplayListCanvas_drawLayer(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
- DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
+ jlong canvasPtr, jlong layerPtr) {
+ DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
- renderer->drawLayer(layer, x, y);
+ canvas->drawLayer(layer);
}
// ----------------------------------------------------------------------------
@@ -196,8 +179,6 @@
{ "nCallDrawGLFunction", "(JJ)V", (void*) android_view_DisplayListCanvas_callDrawGLFunction },
- { "nDrawPatch", "(JLandroid/graphics/Bitmap;JFFFFJ)V", (void*) android_view_DisplayListCanvas_drawPatch },
-
{ "nDrawRoundRect", "(JJJJJJJJ)V", (void*) android_view_DisplayListCanvas_drawRoundRectProps },
{ "nDrawCircle", "(JJJJJ)V", (void*) android_view_DisplayListCanvas_drawCircleProps },
@@ -207,7 +188,7 @@
{ "nCreateDisplayListCanvas", "(II)J", (void*) android_view_DisplayListCanvas_createDisplayListCanvas },
{ "nResetDisplayListCanvas", "(JII)V", (void*) android_view_DisplayListCanvas_resetDisplayListCanvas },
- { "nDrawLayer", "(JJFF)V", (void*) android_view_DisplayListCanvas_drawLayer },
+ { "nDrawLayer", "(JJ)V", (void*) android_view_DisplayListCanvas_drawLayer },
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_DisplayListCanvas_getMaxTextureWidth },
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_DisplayListCanvas_getMaxTextureHeight },
@@ -219,9 +200,6 @@
};
int register_android_view_DisplayListCanvas(JNIEnv* env) {
- jclass clazz = FindClassOrDie(env, "android/graphics/Rect");
- gRectClassInfo.set = GetMethodIDOrDie(env, clazz, "set", "(IIII)V");
-
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index aa79d70..17d2a5e 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -158,7 +158,7 @@
sp<GraphicBuffer> buffer(wrapper->buffer);
- Rect rect;
+ Rect rect(Rect::EMPTY_RECT);
if (dirtyRect) {
rect.left = GET_INT(dirtyRect, gRectClassInfo.left);
rect.top = GET_INT(dirtyRect, gRectClassInfo.top);
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 9e49afb..36ba892 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -79,12 +79,6 @@
layer->updateTexImage();
}
-static jint android_view_HardwareLayer_getTexName(JNIEnv* env, jobject clazz,
- jlong layerUpdaterPtr) {
- DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
- return layer->backingLayer()->getTextureId();
-}
-
// ----------------------------------------------------------------------------
// JNI Glue
// ----------------------------------------------------------------------------
@@ -98,8 +92,6 @@
{ "nSetSurfaceTexture", "(JLandroid/graphics/SurfaceTexture;Z)V",
(void*) android_view_HardwareLayer_setSurfaceTexture },
{ "nUpdateSurfaceTexture", "(J)V", (void*) android_view_HardwareLayer_updateSurfaceTexture },
-
- { "nGetTexName", "(J)I", (void*) android_view_HardwareLayer_getTexName },
};
int register_android_view_HardwareLayer(JNIEnv* env) {
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index abd2409..4a311d31 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -292,7 +292,7 @@
return 0;
}
- Rect dirtyRect;
+ Rect dirtyRect(Rect::EMPTY_RECT);
Rect* dirtyRectPtr = NULL;
if (dirtyRectObj) {
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 7e05793..beb83b1 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -142,7 +142,7 @@
ANativeWindow_Buffer buffer;
- Rect rect;
+ Rect rect(Rect::EMPTY_RECT);
if (dirtyRect) {
rect.left = GET_INT(dirtyRect, gRectClassInfo.left);
rect.top = GET_INT(dirtyRect, gRectClassInfo.top);
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 4c920dc..414cbb4 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -358,8 +358,8 @@
return;
}
jsize count = env->GetArrayLength(fdsToClose);
- jint *ar = env->GetIntArrayElements(fdsToClose, 0);
- if (!ar) {
+ ScopedIntArrayRO ar(env, fdsToClose);
+ if (ar.get() == NULL) {
ALOGE("Bad fd array");
RuntimeAbort(env);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d591f8b..b0621e9 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -786,6 +786,46 @@
android:protectionLevel="normal"
android:permissionFlags="hidden"/>
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.WRITE_SMS"
+ android:protectionLevel="normal"
+ android:permissionFlags="hidden"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
+ android:protectionLevel="normal"
+ android:permissionFlags="hidden"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
+ android:protectionLevel="normal"
+ android:permissionFlags="hidden"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
+ android:protectionLevel="normal"
+ android:permissionFlags="hidden"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.MANAGE_ACCOUNTS"
+ android:protectionLevel="normal"
+ android:permissionFlags="hidden"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.USE_CREDENTIALS"
+ android:protectionLevel="normal"
+ android:permissionFlags="hidden"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.SUBSCRIBED_FEEDS_READ"
+ android:protectionLevel="normal"
+ android:permissionFlags="hidden"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE"
+ android:protectionLevel="normal"
+ android:permissionFlags="hidden"/>
+
<!-- ====================================================================== -->
<!-- INSTALL PERMISSIONS -->
<!-- ====================================================================== -->
@@ -2527,10 +2567,11 @@
<permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
android:protectionLevel="signature" />
- <!-- @SystemApi Must be required by a {@link
+ <!-- Must be required by a {@link
android.service.notification.ConditionProviderService},
to ensure that only the system can bind to it.
- @hide -->
+ <p>Protection level: signature
+ -->
<permission android:name="android.permission.BIND_CONDITION_PROVIDER_SERVICE"
android:protectionLevel="signature" />
@@ -2658,7 +2699,7 @@
android:exported="true"
>
</activity>
- <activity-alias android:name="com.android.internal.app.ForwardIntentToUserOwner"
+ <activity-alias android:name="com.android.internal.app.ForwardIntentToParent"
android:targetActivity="com.android.internal.app.IntentForwarderActivity"
android:exported="true"
android:label="@string/user_owner_label">
@@ -2764,7 +2805,7 @@
</activity>
<receiver android:name="com.android.server.BootReceiver"
- android:primaryUserOnly="true">
+ android:systemUserOnly="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
diff --git a/core/res/res/drawable-hdpi/sim_dark_blue.9.png b/core/res/res/drawable-hdpi/sim_dark_blue.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_dark_green.9.png b/core/res/res/drawable-hdpi/sim_dark_green.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_dark_orange.9.png b/core/res/res/drawable-hdpi/sim_dark_orange.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_dark_purple.9.png b/core/res/res/drawable-hdpi/sim_dark_purple.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_blue.9.png b/core/res/res/drawable-hdpi/sim_light_blue.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_green.9.png b/core/res/res/drawable-hdpi/sim_light_green.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_orange.9.png b/core/res/res/drawable-hdpi/sim_light_orange.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_purple.9.png b/core/res/res/drawable-hdpi/sim_light_purple.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_blue.9.png b/core/res/res/drawable-mdpi/sim_dark_blue.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_green.9.png b/core/res/res/drawable-mdpi/sim_dark_green.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_orange.9.png b/core/res/res/drawable-mdpi/sim_dark_orange.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_purple.9.png b/core/res/res/drawable-mdpi/sim_dark_purple.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_blue.9.png b/core/res/res/drawable-mdpi/sim_light_blue.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_green.9.png b/core/res/res/drawable-mdpi/sim_light_green.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_orange.9.png b/core/res/res/drawable-mdpi/sim_light_orange.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_purple.9.png b/core/res/res/drawable-mdpi/sim_light_purple.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png b/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png b/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png b/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_gmail.png b/core/res/res/drawable-xxhdpi/stat_notify_gmail.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_more.png b/core/res/res/drawable-xxhdpi/stat_notify_more.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync.png b/core/res/res/drawable-xxhdpi/stat_notify_sync.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png b/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png b/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png b/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png b/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png b/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_throttled.png b/core/res/res/drawable-xxhdpi/stat_sys_throttled.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_warning.png b/core/res/res/drawable-xxhdpi/stat_sys_warning.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable/edit_text_material.xml b/core/res/res/drawable/edit_text_material.xml
index 38ac567..901b3dc 100644
--- a/core/res/res/drawable/edit_text_material.xml
+++ b/core/res/res/drawable/edit_text_material.xml
@@ -22,8 +22,7 @@
<selector>
<item android:state_enabled="false">
<nine-patch android:src="@drawable/textfield_default_mtrl_alpha"
- android:tint="?attr/colorControlNormal"
- android:alpha="?attr/disabledAlpha" />
+ android:tint="?attr/colorControlNormal" />
</item>
<item android:state_pressed="false" android:state_focused="false">
<nine-patch android:src="@drawable/textfield_default_mtrl_alpha"
diff --git a/core/res/res/drawable/scrollbar_handle_material.xml b/core/res/res/drawable/scrollbar_handle_material.xml
index 56fecec..33efbba 100644
--- a/core/res/res/drawable/scrollbar_handle_material.xml
+++ b/core/res/res/drawable/scrollbar_handle_material.xml
@@ -17,6 +17,9 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:tint="?attr/colorControlNormal"
android:shape="rectangle">
- <solid android:color="#84ffffff" />
- <size android:width="4dp" />
+ <solid
+ android:color="#84ffffff" />
+ <size
+ android:width="4dp"
+ android:height="4dp" />
</shape>
diff --git a/core/res/res/layout/non_client_decor_dark.xml b/core/res/res/layout/non_client_decor_dark.xml
index d1e2974..112f4b7 100644
--- a/core/res/res/layout/non_client_decor_dark.xml
+++ b/core/res/res/layout/non_client_decor_dark.xml
@@ -26,7 +26,9 @@
android:layout_width="match_parent"
android:layout_gravity="end"
android:layout_height="wrap_content"
- android:background="@drawable/non_client_decor_title" >
+ android:background="@drawable/non_client_decor_title"
+ android:focusable="false"
+ android:descendantFocusability="blocksDescendants" >
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
@@ -40,7 +42,7 @@
android:layout_gravity="center_vertical|end"
android:contentDescription="@string/maximize_button_text"
android:background="@drawable/decor_maximize_button_dark" />
- <Button
+ <Button
android:id="@+id/close_window"
android:layout_width="32dp"
android:layout_height="32dp"
diff --git a/core/res/res/layout/non_client_decor_light.xml b/core/res/res/layout/non_client_decor_light.xml
index f7c3fcd..5dd79c7 100644
--- a/core/res/res/layout/non_client_decor_light.xml
+++ b/core/res/res/layout/non_client_decor_light.xml
@@ -26,7 +26,9 @@
android:layout_width="match_parent"
android:layout_gravity="end"
android:layout_height="wrap_content"
- android:background="@drawable/non_client_decor_title" >
+ android:background="@drawable/non_client_decor_title"
+ android:focusable="false"
+ android:descendantFocusability="blocksDescendants" >
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
@@ -40,7 +42,7 @@
android:layout_gravity="center_vertical|end"
android:contentDescription="@string/maximize_button_text"
android:background="@drawable/decor_maximize_button_light" />
- <Button
+ <Button
android:id="@+id/close_window"
android:layout_width="32dp"
android:layout_height="32dp"
diff --git a/core/res/res/values-af-watch/strings.xml b/core/res/res/values-af-watch/strings.xml
index c81848a..9dc98a1 100644
--- a/core/res/res/values-af-watch/strings.xml
+++ b/core/res/res/values-af-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Program <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am-watch/strings.xml b/core/res/res/values-am-watch/strings.xml
index 95188b6..ebe6ae0 100644
--- a/core/res/res/values-am-watch/strings.xml
+++ b/core/res/res/values-am-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g> መተግበሪያ ከ<xliff:g id="NUMBER_1">%2$d</xliff:g>።"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar-watch/strings.xml b/core/res/res/values-ar-watch/strings.xml
index 8cbb0a5..374b665 100644
--- a/core/res/res/values-ar-watch/strings.xml
+++ b/core/res/res/values-ar-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"التطبيق <xliff:g id="NUMBER_0">%1$d</xliff:g> من <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-az-rAZ-watch/strings.xml b/core/res/res/values-az-rAZ-watch/strings.xml
index 7e4a762..cdc6a3d 100644
--- a/core/res/res/values-az-rAZ-watch/strings.xml
+++ b/core/res/res/values-az-rAZ-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Tətbiq <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bg-watch/strings.xml b/core/res/res/values-bg-watch/strings.xml
index 1f1d921..a31f8d8 100644
--- a/core/res/res/values-bg-watch/strings.xml
+++ b/core/res/res/values-bg-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Прилож. <xliff:g id="NUMBER_0">%1$d</xliff:g> от <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bn-rBD-watch/strings.xml b/core/res/res/values-bn-rBD-watch/strings.xml
index b934841..4ce6091 100644
--- a/core/res/res/values-bn-rBD-watch/strings.xml
+++ b/core/res/res/values-bn-rBD-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g>টির মধ্যে <xliff:g id="NUMBER_0">%1$d</xliff:g>টি অ্যাপ্লিকেশান"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca-watch/strings.xml b/core/res/res/values-ca-watch/strings.xml
index b44703e..8f626e5 100644
--- a/core/res/res/values-ca-watch/strings.xml
+++ b/core/res/res/values-ca-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicació <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-cs-watch/strings.xml b/core/res/res/values-cs-watch/strings.xml
index 89c9dee..34f8864 100644
--- a/core/res/res/values-cs-watch/strings.xml
+++ b/core/res/res/values-cs-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da-watch/strings.xml b/core/res/res/values-da-watch/strings.xml
index f1daf30..efc4cf2 100644
--- a/core/res/res/values-da-watch/strings.xml
+++ b/core/res/res/values-da-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-de-watch/strings.xml b/core/res/res/values-de-watch/strings.xml
index 52a21ba..99b3336 100644
--- a/core/res/res/values-de-watch/strings.xml
+++ b/core/res/res/values-de-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> von <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el-watch/strings.xml b/core/res/res/values-el-watch/strings.xml
index 81a7451..c159d6f 100644
--- a/core/res/res/values-el-watch/strings.xml
+++ b/core/res/res/values-el-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Εφαρμογή <xliff:g id="NUMBER_0">%1$d</xliff:g> από <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rAU-watch/strings.xml b/core/res/res/values-en-rAU-watch/strings.xml
index 6734cd3..6102d4e4 100644
--- a/core/res/res/values-en-rAU-watch/strings.xml
+++ b/core/res/res/values-en-rAU-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rGB-watch/strings.xml b/core/res/res/values-en-rGB-watch/strings.xml
index 6734cd3..6102d4e4 100644
--- a/core/res/res/values-en-rGB-watch/strings.xml
+++ b/core/res/res/values-en-rGB-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rIN-watch/strings.xml b/core/res/res/values-en-rIN-watch/strings.xml
index 6734cd3..6102d4e4 100644
--- a/core/res/res/values-en-rIN-watch/strings.xml
+++ b/core/res/res/values-en-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es-rUS-watch/strings.xml b/core/res/res/values-es-rUS-watch/strings.xml
index 763b24d..76664ef 100644
--- a/core/res/res/values-es-rUS-watch/strings.xml
+++ b/core/res/res/values-es-rUS-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es-watch/strings.xml b/core/res/res/values-es-watch/strings.xml
index d9ea0fe..002bfce 100644
--- a/core/res/res/values-es-watch/strings.xml
+++ b/core/res/res/values-es-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-et-rEE-watch/strings.xml b/core/res/res/values-et-rEE-watch/strings.xml
index 0adb487..a1d29a8 100644
--- a/core/res/res/values-et-rEE-watch/strings.xml
+++ b/core/res/res/values-et-rEE-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Rakendus <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-eu-rES-watch/strings.xml b/core/res/res/values-eu-rES-watch/strings.xml
index 9c13ef9..aa67602 100644
--- a/core/res/res/values-eu-rES-watch/strings.xml
+++ b/core/res/res/values-eu-rES-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> aplikaz."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa-watch/strings.xml b/core/res/res/values-fa-watch/strings.xml
index a33d7ec..243ccad 100644
--- a/core/res/res/values-fa-watch/strings.xml
+++ b/core/res/res/values-fa-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"برنامه <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi-watch/strings.xml b/core/res/res/values-fi-watch/strings.xml
index 89782a5..abe5ebb 100644
--- a/core/res/res/values-fi-watch/strings.xml
+++ b/core/res/res/values-fi-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Sovellus <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr-rCA-watch/strings.xml b/core/res/res/values-fr-rCA-watch/strings.xml
index ea9c1c2..197b18a 100644
--- a/core/res/res/values-fr-rCA-watch/strings.xml
+++ b/core/res/res/values-fr-rCA-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Appli <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr-watch/strings.xml b/core/res/res/values-fr-watch/strings.xml
index 7e616cd..b853188 100644
--- a/core/res/res/values-fr-watch/strings.xml
+++ b/core/res/res/values-fr-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Appli <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 2510e03..50adefa 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -519,7 +519,7 @@
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Définir le proxy global du mobile"</string>
<string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Indiquer le proxy global à utiliser pour l\'appareil lorsque la règle est activée. Seul le propriétaire de l\'appareil peut définir le proxy global."</string>
<string name="policylab_expirePassword" msgid="5610055012328825874">"Config. expir. mot passe verr. écran"</string>
- <string name="policydesc_expirePassword" msgid="5367525762204416046">"Modifier la fréquence de modification du mot de passe, du code d\'accès ou du motif de verrouillage de l\'écran"</string>
+ <string name="policydesc_expirePassword" msgid="5367525762204416046">"Modifier la fréquence de modification du mot de passe, du code d\'accès ou du schéma de verrouillage de l\'écran"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Définir chiffrement du stockage"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Exiger le chiffrement des données d\'application stockées"</string>
<string name="policylab_disableCamera" msgid="6395301023152297826">"Désactiver les appareils photo"</string>
diff --git a/core/res/res/values-gl-rES-watch/strings.xml b/core/res/res/values-gl-rES-watch/strings.xml
index d9ea0fe..002bfce 100644
--- a/core/res/res/values-gl-rES-watch/strings.xml
+++ b/core/res/res/values-gl-rES-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gu-rIN-watch/strings.xml b/core/res/res/values-gu-rIN-watch/strings.xml
index 3e50335..f607966 100644
--- a/core/res/res/values-gu-rIN-watch/strings.xml
+++ b/core/res/res/values-gu-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> માંથી <xliff:g id="NUMBER_0">%1$d</xliff:g> એપ્લિકેશન."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi-watch/strings.xml b/core/res/res/values-hi-watch/strings.xml
index 148dab4..ead4d60 100644
--- a/core/res/res/values-hi-watch/strings.xml
+++ b/core/res/res/values-hi-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> में से <xliff:g id="NUMBER_0">%1$d</xliff:g> ऐप."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr-watch/strings.xml b/core/res/res/values-hr-watch/strings.xml
index 4b88ac7..7e65f07 100644
--- a/core/res/res/values-hr-watch/strings.xml
+++ b/core/res/res/values-hr-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikacija <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu-watch/strings.xml b/core/res/res/values-hu-watch/strings.xml
index 9f2e97f..aa72468 100644
--- a/core/res/res/values-hu-watch/strings.xml
+++ b/core/res/res/values-hu-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>. alkalmazás"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hy-rAM-watch/strings.xml b/core/res/res/values-hy-rAM-watch/strings.xml
index 265268e..28617cb 100644
--- a/core/res/res/values-hy-rAM-watch/strings.xml
+++ b/core/res/res/values-hy-rAM-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Հավելված <xliff:g id="NUMBER_0">%1$d</xliff:g>՝ <xliff:g id="NUMBER_1">%2$d</xliff:g>-ից:"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in-watch/strings.xml b/core/res/res/values-in-watch/strings.xml
index 947a7f1..b0b22e7 100644
--- a/core/res/res/values-in-watch/strings.xml
+++ b/core/res/res/values-in-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikasi <xliff:g id="NUMBER_0">%1$d</xliff:g> dari <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-is-rIS-watch/strings.xml b/core/res/res/values-is-rIS-watch/strings.xml
index cb6da5c..ab82c1c 100644
--- a/core/res/res/values-is-rIS-watch/strings.xml
+++ b/core/res/res/values-is-rIS-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Forrit <xliff:g id="NUMBER_0">%1$d</xliff:g> af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it-watch/strings.xml b/core/res/res/values-it-watch/strings.xml
index a042221..111c2a2 100644
--- a/core/res/res/values-it-watch/strings.xml
+++ b/core/res/res/values-it-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> di <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-iw-watch/strings.xml b/core/res/res/values-iw-watch/strings.xml
index 64b194d..d0b4943 100644
--- a/core/res/res/values-iw-watch/strings.xml
+++ b/core/res/res/values-iw-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"אפליקציה <xliff:g id="NUMBER_0">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja-watch/strings.xml b/core/res/res/values-ja-watch/strings.xml
index b3c6d97..ec1257ef 100644
--- a/core/res/res/values-ja-watch/strings.xml
+++ b/core/res/res/values-ja-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"アプリ<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 2bb0972..545b963 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1024,7 +1024,7 @@
<string name="usb_ptp_notification_title" msgid="1347328437083192112">"USBを写真転送に使用"</string>
<string name="usb_midi_notification_title" msgid="4850904915889144654">"USBをMIDIに使用"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USBアクセサリを接続しました"</string>
- <string name="usb_notification_message" msgid="7347368030849048437">"タップするとその他のオプションが表示されます。"</string>
+ <string name="usb_notification_message" msgid="7347368030849048437">"タップしてその他のオプションを表示"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USBデバッグが接続されました"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"タップしてUSBデバッグを無効化"</string>
<string name="select_input_method" msgid="8547250819326693584">"キーボードの変更"</string>
@@ -1118,7 +1118,7 @@
<string name="no_file_chosen" msgid="6363648562170759465">"ファイルが選択されていません"</string>
<string name="reset" msgid="2448168080964209908">"リセット"</string>
<string name="submit" msgid="1602335572089911941">"送信"</string>
- <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"運転モードになっています"</string>
+ <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"運転モード中"</string>
<string name="car_mode_disable_notification_message" msgid="8035230537563503262">"タップすると運転モードを終了します"</string>
<string name="tethered_notification_title" msgid="3146694234398202601">"テザリングまたはアクセスポイントが有効です"</string>
<string name="tethered_notification_message" msgid="6857031760103062982">"タップしてセットアップします。"</string>
diff --git a/core/res/res/values-ka-rGE-watch/strings.xml b/core/res/res/values-ka-rGE-watch/strings.xml
index 4fe6d11..5aa9aaf 100644
--- a/core/res/res/values-ka-rGE-watch/strings.xml
+++ b/core/res/res/values-ka-rGE-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"აპი <xliff:g id="NUMBER_0">%1$d</xliff:g>, სულ <xliff:g id="NUMBER_1">%2$d</xliff:g>-დან."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kk-rKZ-watch/strings.xml b/core/res/res/values-kk-rKZ-watch/strings.xml
index 583eb19..e913230 100644
--- a/core/res/res/values-kk-rKZ-watch/strings.xml
+++ b/core/res/res/values-kk-rKZ-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> бағдарлама."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-km-rKH-watch/strings.xml b/core/res/res/values-km-rKH-watch/strings.xml
index 2b7e12f..01731f3 100644
--- a/core/res/res/values-km-rKH-watch/strings.xml
+++ b/core/res/res/values-km-rKH-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"កម្មវិធី <xliff:g id="NUMBER_0">%1$d</xliff:g> នៃ <xliff:g id="NUMBER_1">%2$d</xliff:g>។"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kn-rIN-watch/strings.xml b/core/res/res/values-kn-rIN-watch/strings.xml
index e01cee1..ea010b3 100644
--- a/core/res/res/values-kn-rIN-watch/strings.xml
+++ b/core/res/res/values-kn-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="NUMBER_0">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko-watch/strings.xml b/core/res/res/values-ko-watch/strings.xml
index df3288b..985f401 100644
--- a/core/res/res/values-ko-watch/strings.xml
+++ b/core/res/res/values-ko-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"앱 <xliff:g id="NUMBER_1">%2$d</xliff:g>개 중 <xliff:g id="NUMBER_0">%1$d</xliff:g>개"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ky-rKG-watch/strings.xml b/core/res/res/values-ky-rKG-watch/strings.xml
index 3f167ac..3c708961 100644
--- a/core/res/res/values-ky-rKG-watch/strings.xml
+++ b/core/res/res/values-ky-rKG-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_0">%1$d</xliff:g> колднм."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lo-rLA-watch/strings.xml b/core/res/res/values-lo-rLA-watch/strings.xml
index a8c9cd2..d7e97fb 100644
--- a/core/res/res/values-lo-rLA-watch/strings.xml
+++ b/core/res/res/values-lo-rLA-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"ແອັບ <xliff:g id="NUMBER_0">%1$d</xliff:g> ໃນ <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt-watch/strings.xml b/core/res/res/values-lt-watch/strings.xml
index ed8ccdb..bf32040 100644
--- a/core/res/res/values-lt-watch/strings.xml
+++ b/core/res/res/values-lt-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g> programa iš <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv-watch/strings.xml b/core/res/res/values-lv-watch/strings.xml
index a0d051e..3a7fd95 100644
--- a/core/res/res/values-lv-watch/strings.xml
+++ b/core/res/res/values-lv-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. lietotne no <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mcc219-mnc02/config.xml b/core/res/res/values-mcc219-mnc02/config.xml
new file mode 100644
index 0000000..2ac6ba6
--- /dev/null
+++ b/core/res/res/values-mcc219-mnc02/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 my 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>21901</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mk-rMK-watch/strings.xml b/core/res/res/values-mk-rMK-watch/strings.xml
index b4eb51a..5e67a61 100644
--- a/core/res/res/values-mk-rMK-watch/strings.xml
+++ b/core/res/res/values-mk-rMK-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Апликац. <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ml-rIN-watch/strings.xml b/core/res/res/values-ml-rIN-watch/strings.xml
index 079c42f..c10769e 100644
--- a/core/res/res/values-ml-rIN-watch/strings.xml
+++ b/core/res/res/values-ml-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> അപ്ലിക്കേഷൻ."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mn-rMN-watch/strings.xml b/core/res/res/values-mn-rMN-watch/strings.xml
index 49f829b..7b2e21b 100644
--- a/core/res/res/values-mn-rMN-watch/strings.xml
+++ b/core/res/res/values-mn-rMN-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>-ны <xliff:g id="NUMBER_1">%2$d</xliff:g> апп."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mr-rIN-watch/strings.xml b/core/res/res/values-mr-rIN-watch/strings.xml
index 49fa7d9..11af412 100644
--- a/core/res/res/values-mr-rIN-watch/strings.xml
+++ b/core/res/res/values-mr-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> पैकी <xliff:g id="NUMBER_0">%1$d</xliff:g> अॅप"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms-rMY-watch/strings.xml b/core/res/res/values-ms-rMY-watch/strings.xml
index 148f518..d8245ed 100644
--- a/core/res/res/values-ms-rMY-watch/strings.xml
+++ b/core/res/res/values-ms-rMY-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Apl <xliff:g id="NUMBER_0">%1$d</xliff:g> daripada <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-my-rMM-watch/strings.xml b/core/res/res/values-my-rMM-watch/strings.xml
index ec89e53..34bd033 100644
--- a/core/res/res/values-my-rMM-watch/strings.xml
+++ b/core/res/res/values-my-rMM-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g>၏ <xliff:g id="NUMBER_0">%1$d</xliff:g> အသေးစားဆော့ဝဲ"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb-watch/strings.xml b/core/res/res/values-nb-watch/strings.xml
index 3bd7fa5..aba8abb 100644
--- a/core/res/res/values-nb-watch/strings.xml
+++ b/core/res/res/values-nb-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ne-rNP-watch/strings.xml b/core/res/res/values-ne-rNP-watch/strings.xml
index e2453c89..fe331bd 100644
--- a/core/res/res/values-ne-rNP-watch/strings.xml
+++ b/core/res/res/values-ne-rNP-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> को <xliff:g id="NUMBER_0">%1$d</xliff:g> अनुप्रयोग।"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl-watch/strings.xml b/core/res/res/values-nl-watch/strings.xml
index 989fa27..bed8a11 100644
--- a/core/res/res/values-nl-watch/strings.xml
+++ b/core/res/res/values-nl-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index cfdd69b..d77dca1f 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -39,7 +39,7 @@
<string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
<string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> seconden"</string>
<string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> seconde"</string>
- <string name="untitled" msgid="4638956954852782576">"<Zonder titel>"</string>
+ <string name="untitled" msgid="4638956954852782576">"<Naamloos>"</string>
<string name="emptyPhoneNumber" msgid="7694063042079676517">"(Geen telefoonnummer)"</string>
<string name="unknownName" msgid="6867811765370350269">"Onbekend"</string>
<string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Voicemail"</string>
diff --git a/core/res/res/values-pa-rIN-watch/strings.xml b/core/res/res/values-pa-rIN-watch/strings.xml
index b30daa4..addaa6b 100644
--- a/core/res/res/values-pa-rIN-watch/strings.xml
+++ b/core/res/res/values-pa-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"ਐਪ <xliff:g id="NUMBER_1">%2$d</xliff:g> ਦਾ <xliff:g id="NUMBER_0">%1$d</xliff:g>"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pl-watch/strings.xml b/core/res/res/values-pl-watch/strings.xml
index d9608f3..f266d0a 100644
--- a/core/res/res/values-pl-watch/strings.xml
+++ b/core/res/res/values-pl-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikacja <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rBR-watch/strings.xml b/core/res/res/values-pt-rBR-watch/strings.xml
index 120e4a5..0eb0da3 100644
--- a/core/res/res/values-pt-rBR-watch/strings.xml
+++ b/core/res/res/values-pt-rBR-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rPT-watch/strings.xml b/core/res/res/values-pt-rPT-watch/strings.xml
index 69d2c0a..1654fc3 100644
--- a/core/res/res/values-pt-rPT-watch/strings.xml
+++ b/core/res/res/values-pt-rPT-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicação <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-watch/strings.xml b/core/res/res/values-pt-watch/strings.xml
index 120e4a5..0eb0da3 100644
--- a/core/res/res/values-pt-watch/strings.xml
+++ b/core/res/res/values-pt-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro-watch/strings.xml b/core/res/res/values-ro-watch/strings.xml
index 95c8ec3..dc3c9065 100644
--- a/core/res/res/values-ro-watch/strings.xml
+++ b/core/res/res/values-ro-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplic. <xliff:g id="NUMBER_0">%1$d</xliff:g> din <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 637ade49..d215d4c 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -50,7 +50,7 @@
<string name="serviceEnabledFor" msgid="6856228140453471041">"Serviciul a fost activat pentru:"</string>
<string name="serviceDisabled" msgid="1937553226592516411">"Serviciul a fost dezactivat."</string>
<string name="serviceRegistered" msgid="6275019082598102493">"Înregistrarea a reuşit."</string>
- <string name="serviceErased" msgid="1288584695297200972">"Ștergerea a reuşit."</string>
+ <string name="serviceErased" msgid="1288584695297200972">"Ștergerea a reușit."</string>
<string name="passwordIncorrect" msgid="7612208839450128715">"Parolă incorectă."</string>
<string name="mmiComplete" msgid="8232527495411698359">"MMI finalizat."</string>
<string name="badPin" msgid="9015277645546710014">"Codul PIN vechi introdus nu este corect."</string>
@@ -59,7 +59,7 @@
<string name="invalidPin" msgid="3850018445187475377">"Introduceţi un cod PIN alcătuit din 4 până la 8 cifre."</string>
<string name="invalidPuk" msgid="8761456210898036513">"Introduceţi un cod PUK care să aibă 8 cifre sau mai mult."</string>
<string name="needPuk" msgid="919668385956251611">"Cardul SIM este blocat cu codul PUK. Introduceţi codul PUK pentru a-l debloca."</string>
- <string name="needPuk2" msgid="4526033371987193070">"Introduceţi codul PUK2 pentru a debloca cardul SIM."</string>
+ <string name="needPuk2" msgid="4526033371987193070">"Introduceți codul PUK2 pentru a debloca cardul SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Operațiunea nu a reușit. Activați blocarea cardului SIM/RUIM."</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
<item quantity="few">V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> încercări până la blocarea cardului SIM.</item>
@@ -72,7 +72,7 @@
<string name="ClirMmi" msgid="7784673673446833091">"ID apelant"</string>
<string name="ColpMmi" msgid="3065121483740183974">"ID-ul liniei conectate"</string>
<string name="ColrMmi" msgid="4996540314421889589">"Restricționarea ID-ului liniei conectate"</string>
- <string name="CfMmi" msgid="5123218989141573515">"Redirecţionarea apelurilor"</string>
+ <string name="CfMmi" msgid="5123218989141573515">"Redirecționarea apelurilor"</string>
<string name="CwMmi" msgid="9129678056795016867">"Apel în aşteptare"</string>
<string name="BaMmi" msgid="455193067926770581">"Blocarea apelurilor"</string>
<string name="PwdMmi" msgid="7043715687905254199">"Modificare parolă"</string>
@@ -84,14 +84,14 @@
<string name="CndMmi" msgid="3116446237081575808">"Se apelează serviciul de furnizare a numerelor"</string>
<string name="DndMmi" msgid="1265478932418334331">"Nu deranjaţi"</string>
<string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"ID-ul apelantului este restricţionat în mod prestabilit. Apelul următor: restricţionat"</string>
- <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"ID-ul apelantului este restricţionat în mod prestabilit. Apelul următor: nerestricţionat"</string>
- <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"ID-ul apelantului este nerestricţionat în mod prestabilit. Apelul următor: Restricţionat."</string>
- <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID-ul apelantului este nerestricţionat în mod prestabilit. Apelul următor: nerestricţionat"</string>
+ <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"ID-ul apelantului este restricționat în mod prestabilit. Apelul următor: nerestricționat"</string>
+ <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"ID-ul apelantului este nerestricționat în mod prestabilit. Apelul următor: Restricționat."</string>
+ <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID-ul apelantului este nerestricționat în mod prestabilit. Apelul următor: nerestricționat"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Nu se asigură accesul la acest serviciu."</string>
- <string name="CLIRPermanent" msgid="3377371145926835671">"Nu puteţi să modificaţi setarea pentru ID-ul apelantului."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Acces restricţionat modificat"</string>
+ <string name="CLIRPermanent" msgid="3377371145926835671">"Nu puteți să modificaţi setarea pentru ID-ul apelantului."</string>
+ <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Acces restricționat modificat"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Serviciul de date este blocat."</string>
- <string name="RestrictedOnEmergency" msgid="6581163779072833665">"Serviciul de urgenţă este blocat."</string>
+ <string name="RestrictedOnEmergency" msgid="6581163779072833665">"Serviciul de urgență este blocat."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Serviciul de voce este blocat."</string>
<string name="RestrictedOnAllVoice" msgid="3396963652108151260">"Toate serviciile de voce sunt blocate."</string>
<string name="RestrictedOnSms" msgid="8314352327461638897">"Serviciul SMS este blocat."</string>
@@ -140,10 +140,10 @@
<string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> după <xliff:g id="TIME_DELAY">{2}</xliff:g> (de) secunde"</string>
<string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecţionat"</string>
<string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecţionat"</string>
- <string name="fcComplete" msgid="3118848230966886575">"Cod de funcţie complet."</string>
- <string name="fcError" msgid="3327560126588500777">"Problemă de conectare sau cod de funcţie nevalid."</string>
+ <string name="fcComplete" msgid="3118848230966886575">"Cod de funcție complet."</string>
+ <string name="fcError" msgid="3327560126588500777">"Problemă de conectare sau cod de funcție nevalid."</string>
<string name="httpErrorOk" msgid="1191919378083472204">"OK"</string>
- <string name="httpError" msgid="7956392511146698522">"A apărut o eroare de reţea."</string>
+ <string name="httpError" msgid="7956392511146698522">"A apărut o eroare de rețea."</string>
<string name="httpErrorLookup" msgid="4711687456111963163">"Nu s-a putut găsi adresa URL."</string>
<string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"Schema de autentificare a site-ului nu este acceptată."</string>
<string name="httpErrorAuth" msgid="1435065629438044534">"Nu s-a realizat autentificarea."</string>
@@ -151,7 +151,7 @@
<string name="httpErrorConnect" msgid="8714273236364640549">"Nu s-a putut stabili conexiunea cu serverul."</string>
<string name="httpErrorIO" msgid="2340558197489302188">"Nu s-a putut efectua comunicarea cu serverul. Încercați din nou mai târziu."</string>
<string name="httpErrorTimeout" msgid="4743403703762883954">"Conexiunea la server a expirat."</string>
- <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"Pagina conţine prea multe redirecţionări de server."</string>
+ <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"Pagina conține prea multe redirecționări de server."</string>
<string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"Protocolul nu este acceptat."</string>
<string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"Nu s-a putut stabili o conexiune securizată."</string>
<string name="httpErrorBadUrl" msgid="3636929722728881972">"Pagina nu a putut fi deschisă, deoarece adresa URL nu este validă."</string>
@@ -162,10 +162,10 @@
<string name="contentServiceSync" msgid="8353523060269335667">"Sincronizare"</string>
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronizare"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Prea multe ştergeri <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
- <string name="low_memory" product="tablet" msgid="6494019234102154896">"Stocarea pe tabletă este plină. Ștergeţi câteva fişiere pentru a elibera spaţiu."</string>
+ <string name="low_memory" product="tablet" msgid="6494019234102154896">"Stocarea pe tabletă este plină. Ștergeți câteva fișiere pentru a elibera spaţiu."</string>
<string name="low_memory" product="watch" msgid="4415914910770005166">"Spațiul de stocare de pe ceas este plin! Ștergeți câteva fișiere pentru a elibera spațiu."</string>
<string name="low_memory" product="tv" msgid="516619861191025923">"Spațiul de stocare al televizorului este plin. Ștergeți câteva fișiere pentru a elibera spațiu."</string>
- <string name="low_memory" product="default" msgid="3475999286680000541">"Stocarea pe telefon este plină. Ștergeţi câteva fişiere pentru a elibera spaţiu."</string>
+ <string name="low_memory" product="default" msgid="3475999286680000541">"Stocarea pe telefon este plină. Ștergeți câteva fișiere pentru a elibera spaţiu."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Rețeaua poate fi monitorizată"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"De o terță parte necunoscută"</string>
<string name="ssl_ca_cert_noti_by_administrator" msgid="550758088185764312">"De administratorul profilului de serviciu"</string>
@@ -180,9 +180,9 @@
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opţiuni tablet PC"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opțiuni TV"</string>
<string name="power_dialog" product="default" msgid="1319919075463988638">"Opţiuni telefon"</string>
- <string name="silent_mode" msgid="7167703389802618663">"Mod Silenţios"</string>
- <string name="turn_on_radio" msgid="3912793092339962371">"Activați funcţia wireless"</string>
- <string name="turn_off_radio" msgid="8198784949987062346">"Dezactivați funcţia wireless"</string>
+ <string name="silent_mode" msgid="7167703389802618663">"Mod Silențios"</string>
+ <string name="turn_on_radio" msgid="3912793092339962371">"Activați funcția wireless"</string>
+ <string name="turn_off_radio" msgid="8198784949987062346">"Dezactivați funcția wireless"</string>
<string name="screen_lock" msgid="799094655496098153">"Blocați ecranul"</string>
<string name="power_off" msgid="4266614107412865048">"Opriți alimentarea"</string>
<string name="silent_mode_silent" msgid="319298163018473078">"Sonerie dezactivată"</string>
@@ -199,20 +199,20 @@
<string name="shutdown_confirm" product="tv" msgid="476672373995075359">"Televizorul se va închide."</string>
<string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ceasul dvs. se va închide."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonul dvs. se va închide."</string>
- <string name="shutdown_confirm_question" msgid="2906544768881136183">"Doriţi să închideţi?"</string>
+ <string name="shutdown_confirm_question" msgid="2906544768881136183">"Doriți să închideţi?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reporniţi în modul sigur"</string>
- <string name="reboot_safemode_confirm" msgid="55293944502784668">"Doriţi să reporniţi în modul sigur? Astfel vor fi dezactivate toate aplicațiile terţă parte pe care le-aţi instalat. Acestea vor fi restabilite când reporniţi din nou."</string>
+ <string name="reboot_safemode_confirm" msgid="55293944502784668">"Doriți să reporniţi în modul sigur? Astfel vor fi dezactivate toate aplicațiile terţă parte pe care le-aţi instalat. Acestea vor fi restabilite când reporniţi din nou."</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
<string name="no_recent_tasks" msgid="8794906658732193473">"Nu există aplicații recente."</string>
<string name="global_actions" product="tablet" msgid="408477140088053665">"Opţiuni tablet PC"</string>
<string name="global_actions" product="tv" msgid="7240386462508182976">"Opțiuni TV"</string>
- <string name="global_actions" product="default" msgid="2406416831541615258">"Opţiuni telefon"</string>
+ <string name="global_actions" product="default" msgid="2406416831541615258">"Opțiuni telefon"</string>
<string name="global_action_lock" msgid="2844945191792119712">"Blocați ecranul"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Opriți alimentarea"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Raport despre erori"</string>
- <string name="bugreport_title" msgid="2667494803742548533">"Executaţi un raport despre erori"</string>
- <string name="bugreport_message" msgid="398447048750350456">"Acest raport va colecta informaţii despre starea actuală a dispozitivului, pentru a le trimite într-un e-mail. Aveți răbdare după pornirea raportului despre erori până când va fi gata de trimis."</string>
- <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Mod Silenţios"</string>
+ <string name="bugreport_title" msgid="2667494803742548533">"Executați un raport despre erori"</string>
+ <string name="bugreport_message" msgid="398447048750350456">"Acest raport va colecta informații despre starea actuală a dispozitivului, pentru a le trimite într-un e-mail. Aveți răbdare după pornirea raportului despre erori până când va fi gata de trimis."</string>
+ <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Mod Silențios"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Sunetul este DEZACTIVAT"</string>
<string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Sunetul este ACTIVAT"</string>
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mod Avion"</string>
@@ -266,11 +266,11 @@
<string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"redirecţionează apelurile efectuate"</string>
<string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permite aplicației să vadă numărul format în timpul unui apel de ieșire, cu opțiunea de a redirecționa apelul către un alt număr sau de a întrerupe apelul."</string>
<string name="permlab_receiveSms" msgid="8673471768947895082">"primeşte mesaje text (SMS)"</string>
- <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite aplicației să primească și să proceseze mesaje SMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau şterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
+ <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite aplicației să primească și să proceseze mesaje SMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
<string name="permlab_receiveMms" msgid="1821317344668257098">"primeşte mesaje text (MMS)"</string>
- <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite aplicației să primească și să proceseze mesaje MMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau şterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
+ <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite aplicației să primească și să proceseze mesaje MMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
<string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"citeşte mesajele cu transmisie celulară"</string>
- <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite aplicației să citească mesajele primite prin transmisie celulară de dispozitivul dvs. Alertele cu transmisie celulară sunt difuzate în unele locaţii pentru a vă avertiza cu privire la situaţiile de urgenţă. Aplicaţiile rău intenţionate pot afecta performanţa sau funcţionarea dispozitivului dvs. când este primită o transmisie celulară de urgenţă."</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite aplicației să citească mesajele primite prin transmisie celulară de dispozitivul dvs. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situaţiile de urgenţă. Aplicaţiile rău intenţionate pot afecta performanţa sau funcţionarea dispozitivului dvs. când este primită o transmisie celulară de urgenţă."</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"citire feeduri abonat"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Permite aplicației să obţină detalii despre feedurile sincronizate în prezent."</string>
<string name="permlab_sendSms" msgid="7544599214260982981">"trimite și vede mesajele SMS"</string>
@@ -280,9 +280,9 @@
<string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"Permite aplicației să citească mesajele SMS stocate pe televizor sau pe cardul SIM. Cu această permisiune, aplicația poate citi toate mesajele SMS, indiferent de conținutul sau de gradul de confidențialitate al acestora."</string>
<string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Permite aplicației să citească mesajele SMS stocate pe telefon sau pe cardul SIM. În acest fel, aplicația poate citi toate mesajele SMS, indiferent de conţinutul sau de gradul de confidenţialitate al acestora."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"primeşte mesaje text (WAP)"</string>
- <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite aplicației să primească și să proceseze mesaje WAP. Această permisiune include capacitatea de a monitoriza sau şterge mesajele care v-au fost trimise fără a vi le arăta."</string>
+ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite aplicației să primească și să proceseze mesaje WAP. Această permisiune include capacitatea de a monitoriza sau șterge mesajele care v-au fost trimise fără a vi le arăta."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"preluare aplicații care rulează"</string>
- <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite aplicației să preia informaţiile despre activităţile care rulează în prezent și care au rulat recent. În acest fel, aplicația poate descoperi informaţii despre aplicațiile care sunt utilizate pe dispozitiv."</string>
+ <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite aplicației să preia informațiile despre activităţile care rulează în prezent și care au rulat recent. În acest fel, aplicația poate descoperi informații despre aplicațiile care sunt utilizate pe dispozitiv."</string>
<string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"Gestionează proprietarii de profiluri și proprietarul dispozitivului"</string>
<string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"Permite aplicațiilor să seteze proprietarii de profiluri și proprietarul dispozitivului."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"reordonare aplicații care rulează"</string>
@@ -306,25 +306,25 @@
<string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"Permite aplicației să pornească imediat ce s-a terminat încărcarea sistemului. Din acest motiv, pornirea televizorului poate dura mai mult timp, iar funcționarea continuă a aplicației poate încetini televizorul."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Permite aplicației să pornească imediat ce s-a terminat încărcarea sistemului. Din acest motiv, pornirea telefonului poate dura mai mult timp, iar rularea continuă a aplicației poate încetini dispozitivul."</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"trimitere mesaj difuzat persistent"</string>
- <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcţii poate să încetinească sau să destabilizeze tableta, determinând-o să utilizeze prea multă memorie."</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcții poate să încetinească sau să destabilizeze tableta, determinând-o să utilizeze prea multă memorie."</string>
<string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcții poate să încetinească sau să destabilizeze televizorul, determinându-l să utilizeze prea multă memorie."</string>
- <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcţii poate să încetinească sau să destabilizeze telefonul, determinându-l să utilizeze prea multă memorie."</string>
+ <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcții poate să încetinească sau să destabilizeze telefonul, determinându-l să utilizeze prea multă memorie."</string>
<string name="permlab_readContacts" msgid="8348481131899886131">"citeşte agenda"</string>
<string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Permite aplicației să citească datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenţionate pot distribui datele de contact fără ştirea dvs."</string>
<string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"Permite aplicației să citească datele despre persoanele de contact salvate pe televizor, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune, aplicațiile pot salva datele de contact, iar aplicațiile rău-intenționate pot permite accesul la datele de contact fără cunoștința dvs."</string>
<string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Permite aplicației să citească datele despre persoanele din agenda stocată pe telefon, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenţionate pot distribui datele de contact fără ştirea dvs."</string>
<string name="permlab_writeContacts" msgid="5107492086416793544">"modifică agenda"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate şterge datele de contact."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
<string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Permite aplicației să modifice datele despre persoanele de contact salvate pe televizor, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane de contact. Cu această permisiune, aplicația poate șterge datele de contact."</string>
- <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe telefon, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate şterge datele de contact."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe telefon, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"citeşte jurnalul de apeluri"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Permite aplicației să citească jurnalul de apeluri al tabletei, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune aplicația salvează datele dvs. din jurnalul de apeluri, iar aplicațiile rău intenţionate pot distribui aceste date fără ştirea dvs."</string>
<string name="permdesc_readCallLog" product="tv" msgid="5611770887047387926">"Permite aplicației să citească jurnalul de apeluri al televizorului, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune, aplicațiile pot să salveze datele din jurnalul de apeluri, iar aplicațiile rău-intenționate pot permite accesul la datele din jurnalul de apeluri fără cunoștința dvs."</string>
<string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Permite aplicației să citească jurnalul de apeluri al telefonului, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune aplicația salvează datele dvs. din jurnalul de apeluri, iar aplicațiile rău intenţionate pot distribui aceste date fără ştirea dvs."</string>
<string name="permlab_writeCallLog" msgid="8552045664743499354">"scrie jurnalul de apeluri"</string>
- <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Permite aplicației să modifice jurnalul de apeluri al tabletei dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a şterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
+ <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Permite aplicației să modifice jurnalul de apeluri al tabletei dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
<string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Permite aplicației să modifice jurnalul de apeluri al televizorului, inclusiv datele despre apelurile primite sau efectuate. Aplicațiile rău-intenționate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul de apeluri."</string>
- <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite aplicației să modifice jurnalul de apeluri al telefonului dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a şterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
+ <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite aplicației să modifice jurnalul de apeluri al telefonului dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
<string name="permlab_bodySensors" msgid="4871091374767171066">"senzori (ex.: senzori de ritm cardiac)"</string>
<string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite aplicației să acceseze date de la senzorii care vă monitorizează starea fizică, cum ar fi ritmul cardiac."</string>
<string name="permlab_readCalendar" msgid="5972727560257612398">"citirea evenimentelor din calendar și a informaţiilor confidenţiale"</string>
@@ -332,15 +332,15 @@
<string name="permdesc_readCalendar" product="tv" msgid="3191352452242394196">"Permite aplicației să citească toate evenimentele din calendar stocate pe televizor, inclusiv cele ale prietenilor sau colegilor. Cu această permisiune, aplicația poate să permită accesul la datele din calendar sau să le salveze, indiferent dacă acestea sunt confidențiale sau sensibile."</string>
<string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Permite aplicației să citească toate evenimentele din calendar stocate pe telefon, inclusiv cele ale prietenilor sau colegilor. Acest lucru poate permite aplicației să distribuie sau să salveze datele din calendar, indiferent dacă acestea sunt confidenţiale sau sensibile."</string>
<string name="permlab_writeCalendar" msgid="8438874755193825647">"adăugarea sau modificarea evenimentelor din calendar și trimiterea de e-mailuri invitaţilor fără ştirea proprietarului"</string>
- <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteţi modifica pe tabletă, inclusiv cele ale prietenilor sau colegilor dvs. În acest fel, aplicația poate trimite mesaje care par să vină de la proprietarii calendarelor sau să modifice evenimentele fără ştirea proprietarilor."</string>
+ <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteți modifica pe tabletă, inclusiv cele ale prietenilor sau colegilor dvs. În acest fel, aplicația poate trimite mesaje care par să vină de la proprietarii calendarelor sau să modifice evenimentele fără ştirea proprietarilor."</string>
<string name="permdesc_writeCalendar" product="tv" msgid="1273290605500902507">"Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteți modifica pe televizor, inclusiv pe cele ale prietenilor sau ale colegilor. Cu această permisiune, aplicația poate să trimită mesaje care par că vin din partea proprietarilor calendarului sau să modifice evenimentele fără cunoștința acestora."</string>
- <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteţi modifica pe telefon, inclusiv cele ale prietenilor sau colegilor dvs. În acest fel, aplicația poate trimite mesaje care par să vină de la proprietarii calendarelor sau să modifice evenimentele fără ştirea proprietarilor."</string>
- <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accesare comenzi suplimentare ale furnizorului locaţiei"</string>
+ <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteți modifica pe telefon, inclusiv cele ale prietenilor sau colegilor dvs. În acest fel, aplicația poate trimite mesaje care par să vină de la proprietarii calendarelor sau să modifice evenimentele fără ştirea proprietarilor."</string>
+ <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accesare comenzi suplimentare ale furnizorului locației"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite aplicației să acceseze comenzi suplimentare pentru furnizorul locației. Aplicația ar putea să utilizeze această permisiune pentru a influența operațiile GPS sau ale altor surse de locații."</string>
- <string name="permlab_accessFineLocation" msgid="1191898061965273372">"locaţia exactă (bazată pe reţea și GPS)"</string>
- <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permite aplicației să obţină locaţia dvs. exactă utilizând sistemul GPS (Global Positioning System) sau surse de localizare prin reţele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locaţia dvs. și pot să consume mai multă energie a bateriei."</string>
- <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"locaţia aproximativă (bazată pe reţea)"</string>
- <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permite aplicației să obţină locaţia dvs. aproximativă. Această locaţie este dedusă de serviciile de localizare utilizând surse de localizare prin reţele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locaţia dvs. aproximativă."</string>
+ <string name="permlab_accessFineLocation" msgid="1191898061965273372">"locaţia exactă (bazată pe rețea și GPS)"</string>
+ <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permite aplicației să obţină locaţia dvs. exactă utilizând sistemul GPS (Global Positioning System) sau surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locaţia dvs. și pot să consume mai multă energie a bateriei."</string>
+ <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"locaţia aproximativă (bazată pe rețea)"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permite aplicației să obţină locaţia dvs. aproximativă. Această locație este dedusă de serviciile de localizare utilizând surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locaţia dvs. aproximativă."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modificare setări audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite aplicației să modifice setările audio globale, cum ar fi volumul și difuzorul care este utilizat pentru ieșire."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"înregistrare audio"</string>
@@ -381,28 +381,28 @@
<string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Permite aplicației să obţină lista de conturi cunoscute de tabletă. Aceasta poate include conturile create de aplicațiile pe care le-aţi instalat."</string>
<string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Permite aplicației să obțină lista de conturi cunoscute de televizor. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat."</string>
<string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Permite aplicației să obţină lista de conturi cunoscute de telefon. Aceasta poate include conturile create de aplicațiile pe care le-aţi instalat."</string>
- <string name="permlab_accessNetworkState" msgid="4951027964348974773">"vizualizează conexiunile la reţea"</string>
- <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Permite aplicației să vadă informaţiile despre conexiunile la reţea, cum ar fi reţelele existente și cele care sunt conectate."</string>
- <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"acces deplin la reţea"</string>
- <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Permite aplicației să creeze socluri de reţea și să utilizeze protocoale de reţea personalizate. Browserul și alte aplicații oferă mijloacele de trimitere a datelor pe internet, astfel încât această permisiune nu este necesară pentru trimiterea datelor pe internet."</string>
- <string name="permlab_changeNetworkState" msgid="958884291454327309">"modificare conectivitate în reţea"</string>
- <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Permite aplicației să modifice starea de conectivitate la reţea."</string>
+ <string name="permlab_accessNetworkState" msgid="4951027964348974773">"vizualizează conexiunile la rețea"</string>
+ <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Permite aplicației să vadă informaţiile despre conexiunile la rețea, cum ar fi reţelele existente și cele care sunt conectate."</string>
+ <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"acces deplin la rețea"</string>
+ <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Permite aplicației să creeze socluri de rețea și să utilizeze protocoale de rețea personalizate. Browserul și alte aplicații oferă mijloacele de trimitere a datelor pe internet, astfel încât această permisiune nu este necesară pentru trimiterea datelor pe internet."</string>
+ <string name="permlab_changeNetworkState" msgid="958884291454327309">"modificare conectivitate în rețea"</string>
+ <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Permite aplicației să modifice starea de conectivitate la rețea."</string>
<string name="permlab_changeTetherState" msgid="5952584964373017960">"modificare conectivitate tethering"</string>
- <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Permite aplicației să modifice starea de conectivitate prin tethering la reţea."</string>
+ <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Permite aplicației să modifice starea de conectivitate prin tethering la rețea."</string>
<string name="permlab_accessWifiState" msgid="5202012949247040011">"vizualizează conexiunile Wi-Fi"</string>
- <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permite aplicației să vadă informaţiile despre reţelele Wi-Fi, de ex. dacă o reţea Wi-Fi este activată, precum și numele dispozitivelor conectate la reţeaua Wi-Fi."</string>
+ <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permite aplicației să vadă informaţiile despre reţelele Wi-Fi, de ex. dacă o rețea Wi-Fi este activată, precum și numele dispozitivelor conectate la rețeaua Wi-Fi."</string>
<string name="permlab_changeWifiState" msgid="6550641188749128035">"se conectează și se deconectează de la Wi-Fi"</string>
<string name="permdesc_changeWifiState" msgid="7137950297386127533">"Permite aplicației să se conecteze și să se deconecteze de la punctele de acces Wi-Fi, precum și să efectueze modificări în configuraţia dispozitivului pentru reţelele Wi-Fi."</string>
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"permitere recepţionare difuzare multiplă Wi-Fi"</string>
- <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o reţea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar tableta dvs. Această funcţie utilizează mai multă energie decât modul fără difuzare multiplă."</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o rețea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar tableta dvs. Această funcție utilizează mai multă energie decât modul fără difuzare multiplă."</string>
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o rețea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar televizorul dvs. Această funcție utilizează mai multă energie decât modul fără difuzare multiplă."</string>
- <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o reţea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar telefonul dvs. Această funcţie utilizează mai multă energie decât modul fără difuzare multiplă."</string>
+ <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o rețea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar telefonul dvs. Această funcție utilizează mai multă energie decât modul fără difuzare multiplă."</string>
<string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"accesează setările Bluetooth"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite aplicației să configureze tableta Bluetooth locală, să descopere și să se împerecheze cu dispozitive la distanţă."</string>
<string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"Permite aplicației să configureze televizorul Bluetooth local, precum și să descopere și să se asocieze cu dispozitive la distanță."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite aplicației să configureze telefonul Bluetooth local, să descopere și să se împerecheze cu dispozitive la distanţă."</string>
<string name="permlab_accessWimaxState" msgid="4195907010610205703">"se conectează și se deconectează de la WiMAX"</string>
- <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite aplicației să stabilească dacă o reţea WiMAX este activată și să vadă informaţiile cu privire la toate reţelele WiMAX conectate."</string>
+ <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite aplicației să stabilească dacă o rețea WiMAX este activată și să vadă informaţiile cu privire la toate reţelele WiMAX conectate."</string>
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Schimbaţi starea WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite aplicației să conecteze și să deconecteze tableta la și de la reţelele WiMAX."</string>
<string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"Permite aplicației să conecteze și să deconecteze televizorul la și de la rețelele WiMAX."</string>
@@ -446,8 +446,8 @@
<string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"citeşte conţinutul cardului SD"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"Permite aplic. citirea conținutului stoc. USB."</string>
<string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"Permite aplicației citirea conținutul cardului SD."</string>
- <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modifică sau şterge conţinutul stocării USB"</string>
- <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifică sau şterge conţinutul cardului SD"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modifică sau șterge conţinutul stocării USB"</string>
+ <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifică sau șterge conţinutul cardului SD"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Permite scriere în stoc. USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Permite aplicației să scrie pe cardul SD."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"efectuarea/primirea apelurilor SIP"</string>
@@ -464,12 +464,12 @@
<string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Permite aplicației să interacționeze cu servicii de telefonie pentru a da / a primi apeluri."</string>
<string name="permlab_control_incall_experience" msgid="9061024437607777619">"oferă o experiență de utilizare în timpul unui apel"</string>
<string name="permdesc_control_incall_experience" msgid="915159066039828124">"Permite aplicației să ofere o experiență de utilizare în timpul unui apel."</string>
- <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"citeşte utilizarea statistică a reţelei"</string>
- <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Permite aplicației să citească utilizarea statistică a reţelei pentru anumite reţele și aplicații."</string>
- <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gestionează politica de reţea"</string>
- <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite aplicației să gestioneze politicile de reţea și să definească regulile specifice aplicațiilor."</string>
- <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificaţi modul de calcul al utilizării reţelei"</string>
- <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite aplicației să modifice modul în care este calculată utilizarea reţelei pentru aplicații. Nu se utilizează de aplicațiile obişnuite."</string>
+ <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"citeşte utilizarea statistică a rețelei"</string>
+ <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Permite aplicației să citească utilizarea statistică a rețelei pentru anumite rețele și aplicații."</string>
+ <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gestionează politica de rețea"</string>
+ <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite aplicației să gestioneze politicile de rețea și să definească regulile specifice aplicațiilor."</string>
+ <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificaţi modul de calcul al utilizării rețelei"</string>
+ <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite aplicației să modifice modul în care este calculată utilizarea rețelei pentru aplicații. Nu se utilizează de aplicațiile obişnuite."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"accesare notificări"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite aplicației să recupereze, să examineze și să șteargă notificări, inclusiv pe cele postate de alte aplicații."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"conectare la un serviciu de citire a notificărilor"</string>
@@ -510,9 +510,9 @@
<string name="policylab_forceLock" msgid="2274085384704248431">"Blocați ecranul"</string>
<string name="policydesc_forceLock" msgid="1141797588403827138">"Stabiliți modul și timpul în care se blochează ecranul."</string>
<string name="policylab_wipeData" msgid="3910545446758639713">"Ștergere integrală date"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Ștergeţi datele de pe tabletă fără avertisment, efectuând resetarea configurării din fabrică."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Ștergeți datele de pe tabletă fără avertisment, efectuând resetarea configurării din fabrică."</string>
<string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Ștergeți datele de pe televizor fără avertisment, prin revenirea la setările din fabrică."</string>
- <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Ștergeţi datele din telefon fără avertisment, efectuând resetarea configurării din fabrică."</string>
+ <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Ștergeți datele din telefon fără avertisment, efectuând resetarea configurării din fabrică."</string>
<string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"Ștergeți datele utilizatorului"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"Ștergeți datele acestui utilizator de pe această tabletă fără avertisment."</string>
<string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"Ștergeți datele acestui utilizator de pe acest televizor fără avertisment."</string>
@@ -645,15 +645,15 @@
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Introduceţi codul PUK și noul cod PIN"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Codul PUK"</string>
<string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"Noul cod PIN"</string>
- <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"Atingeţi și introduceţi parola"</font></string>
+ <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"Atingeți și introduceţi parola"</font></string>
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Introduceţi parola pentru a debloca"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Introduceţi codul PIN pentru a debloca"</string>
<string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Cod PIN incorect."</string>
<string name="keyguard_label_text" msgid="861796461028298424">"Pentru a debloca, apăsaţi Meniu, apoi 0."</string>
- <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Număr de urgenţă"</string>
+ <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Număr de urgență"</string>
<string name="lockscreen_carrier_default" msgid="8963839242565653192">"Fără serviciu."</string>
<string name="lockscreen_screen_locked" msgid="7288443074806832904">"Ecranul este blocat."</string>
- <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Apăsaţi Meniu pentru a debloca sau pentru a efectua apeluri de urgenţă."</string>
+ <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Apăsați Meniu pentru a debloca sau pentru a efectua apeluri de urgență."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Apăsaţi Meniu pentru deblocare."</string>
<string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Desenaţi modelul pentru a debloca"</string>
<string name="lockscreen_emergency_call" msgid="5298642613417801888">"Urgență"</string>
@@ -678,7 +678,7 @@
<string name="lockscreen_transport_rew_description" msgid="6944412838651990410">"Derulaţi"</string>
<string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"Derulaţi rapid înainte"</string>
<string name="emergency_calls_only" msgid="6733978304386365407">"Numai apeluri de urgenţă"</string>
- <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Reţea blocată"</string>
+ <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rețea blocată"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Cardul SIM este blocat cu codul PUK."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Consultaţi Ghidul de utilizare sau contactaţi Serviciul de relaţii cu clienţii."</string>
<string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Cardul SIM este blocat."</string>
@@ -696,7 +696,7 @@
<string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a televizorului. Televizorul va reveni acum la setările prestabilite din fabrică."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Aţi efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Acesta va fi acum resetat la setările prestabilite din fabrică."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Încercați din nou peste <xliff:g id="NUMBER">%d</xliff:g> (de) secunde."</string>
- <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Aţi uitat modelul?"</string>
+ <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Ați uitat modelul?"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Deblocare cont"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Prea multe încercări de desenare a modelului"</string>
<string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Pentru a debloca, conectaţi-vă folosind Contul Google."</string>
@@ -704,13 +704,13 @@
<string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Parolă"</string>
<string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Conectați-vă"</string>
<string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Nume de utilizator sau parolă nevalide."</string>
- <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"Aţi uitat numele de utilizator sau parola?\nAccesaţi "<b>"google.com/accounts/recovery"</b>"."</string>
+ <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"Aţi uitat numele de utilizator sau parola?\nAccesați "<b>"google.com/accounts/recovery"</b>"."</string>
<string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"Se verifică..."</string>
<string name="lockscreen_unlock_label" msgid="737440483220667054">"Deblocaţi"</string>
<string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Sunet activat"</string>
<string name="lockscreen_sound_off_label" msgid="996822825154319026">"Sunet dezactivat"</string>
<string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Desenarea modelului a început"</string>
- <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Modelul a fost şters"</string>
+ <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Modelul a fost șters"</string>
<string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Celulă adăugată"</string>
<string name="lockscreen_access_pattern_cell_added_verbose" msgid="7264580781744026939">"Celula <xliff:g id="CELL_INDEX">%1$s</xliff:g> a fost adăugată"</string>
<string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Modelul a fost desenat"</string>
@@ -748,14 +748,14 @@
<string name="factorytest_failed" msgid="5410270329114212041">"Testarea de fabrică nu a reuşit"</string>
<string name="factorytest_not_system" msgid="4435201656767276723">"Acţiunea FACTORY_TEST este acceptată doar pentru pachetele instalate în /system/app."</string>
<string name="factorytest_no_action" msgid="872991874799998561">"Nu s-a găsit niciun pachet care să ofere acţiunea FACTORY_TEST."</string>
- <string name="factorytest_reboot" msgid="6320168203050791643">"Reporniţi"</string>
+ <string name="factorytest_reboot" msgid="6320168203050791643">"Reporniți"</string>
<string name="js_dialog_title" msgid="1987483977834603872">"La pagina de la „<xliff:g id="TITLE">%s</xliff:g>” apare:"</string>
<string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
<string name="js_dialog_before_unload_title" msgid="2619376555525116593">"Confirmați părăsirea paginii"</string>
<string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"Părăsiți această pagină"</string>
<string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"Rămâneți în această pagină"</string>
<string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nSigur doriți să părăsiți această pagină?"</string>
- <string name="save_password_label" msgid="6860261758665825069">"Confirmaţi"</string>
+ <string name="save_password_label" msgid="6860261758665825069">"Confirmați"</string>
<string name="double_tap_toast" msgid="4595046515400268881">"Sfat: măriţi și micşoraţi prin dublă atingere."</string>
<string name="autofill_this_form" msgid="4616758841157816676">"Automat"</string>
<string name="setup_autofill" msgid="7103495070180590814">"Conf.Compl.auto."</string>
@@ -778,16 +778,16 @@
<string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"citeşte marcajele și istoricul web"</string>
<string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Permite aplicației să citească istoricul tuturor adreselor URL accesate de Browser și toate marcajele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicații cu capacităţi de navigare pe web."</string>
<string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"scrie în marcajele și în istoricul web"</string>
- <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Permite aplicației să modifice istoricul Browserului sau marcajele stocate pe tabletă. În acest fel, aplicația poate şterge sau modifica datele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicații cu capacităţi de navigare pe web."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Permite aplicației să modifice istoricul Browserului sau marcajele stocate pe tabletă. În acest fel, aplicația poate șterge sau modifica datele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicații cu capacităţi de navigare pe web."</string>
<string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"Permite aplicației să modifice istoricul sau marcajele browserului stocate pe televizor. Cu această permisiune, aplicația poate șterge sau modifica datele din browser. Notă: această permisiune nu poate fi aplicată de browsere terță parte sau de alte aplicații cu capacități de navigare pe web."</string>
- <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite aplicației să modifice istoricul Browserului sau marcajele stocate pe telefon. În acest fel, aplicația poate şterge sau modifica datele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicații cu capacităţi de navigare pe web."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite aplicației să modifice istoricul Browserului sau marcajele stocate pe telefon. În acest fel, aplicația poate șterge sau modifica datele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicații cu capacităţi de navigare pe web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"setează o alarmă"</string>
- <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite aplicației să seteze o alarmă într-o aplicație de ceas cu alarmă instalată. Este posibil ca unele aplicații de ceas cu alarmă să nu implementeze această funcţie."</string>
+ <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite aplicației să seteze o alarmă într-o aplicație de ceas cu alarmă instalată. Este posibil ca unele aplicații de ceas cu alarmă să nu implementeze această funcție."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"adăugare mesagerie vocală"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite aplicației să adauge mesaje în Mesaje primite în mesageria vocală."</string>
<string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modificare permisiuni pentru locaţia geografică a browserului"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite aplicației să modifice permisiunile privind locaţia geografică a browserului. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a permite trimiterea informaţiilor privind locaţia către site-uri web arbitrare."</string>
- <string name="save_password_message" msgid="767344687139195790">"Doriţi ca browserul să reţină această parolă?"</string>
+ <string name="save_password_message" msgid="767344687139195790">"Doriți ca browserul să reţină această parolă?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Nu acum"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Reţineţi"</string>
<string name="save_password_never" msgid="8274330296785855105">"Niciodată"</string>
@@ -795,19 +795,19 @@
<string name="text_copied" msgid="4985729524670131385">"Text copiat în clipboard."</string>
<string name="more_item_label" msgid="4650918923083320495">"Mai multe"</string>
<string name="prepend_shortcut_label" msgid="2572214461676015642">"Meniu+"</string>
- <string name="menu_space_shortcut_label" msgid="2410328639272162537">"spaţiu"</string>
+ <string name="menu_space_shortcut_label" msgid="2410328639272162537">"spațiu"</string>
<string name="menu_enter_shortcut_label" msgid="2743362785111309668">"enter"</string>
<string name="menu_delete_shortcut_label" msgid="3658178007202748164">"delete"</string>
- <string name="search_go" msgid="8298016669822141719">"Căutaţi"</string>
+ <string name="search_go" msgid="8298016669822141719">"Căutați"</string>
<string name="search_hint" msgid="1733947260773056054">"Căutați…"</string>
- <string name="searchview_description_search" msgid="6749826639098512120">"Căutaţi"</string>
+ <string name="searchview_description_search" msgid="6749826639098512120">"Căutați"</string>
<string name="searchview_description_query" msgid="5911778593125355124">"Interogare de căutare"</string>
- <string name="searchview_description_clear" msgid="1330281990951833033">"Ștergeţi interogarea"</string>
+ <string name="searchview_description_clear" msgid="1330281990951833033">"Ștergeți interogarea"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"Trimiteţi interogarea"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"Căutare vocală"</string>
<string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"Activați Exploraţi prin atingere?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> doreşte să activeze funcţia Exploraţi prin atingere. Când această funcţie este activată, puteţi auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteţi efectua gesturi pentru a interacţiona cu tableta."</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> doreşte să activeze funcţia Exploraţi prin atingere. Când această funcţie este activată, puteţi auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteţi efectua gesturi pentru a interacţiona cu telefonul."</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> doreşte să activeze funcţia Exploraţi prin atingere. Când această funcție este activată, puteți auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteți efectua gesturi pentru a interacţiona cu tableta."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> doreşte să activeze funcţia Exploraţi prin atingere. Când această funcție este activată, puteți auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteți efectua gesturi pentru a interacţiona cu telefonul."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"cu 1 lună în urmă"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Cu mai mult de 1 lună în urmă"</string>
<plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
@@ -849,7 +849,7 @@
</plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problemă video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Acest fişier video nu este valid pentru a fi transmis în flux către acest dispozitiv."</string>
- <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nu puteţi reda acest videoclip"</string>
+ <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nu puteți reda acest videoclip"</string>
<string name="VideoView_error_button" msgid="2822238215100679592">"OK"</string>
<string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="noon" msgid="7245353528818587908">"prânz"</string>
@@ -858,21 +858,21 @@
<string name="Midnight" msgid="5630806906897892201">"Miezul nopţii"</string>
<string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
- <string name="selectAll" msgid="6876518925844129331">"Selectaţi-le pe toate"</string>
+ <string name="selectAll" msgid="6876518925844129331">"Selectați-le pe toate"</string>
<string name="cut" msgid="3092569408438626261">"Decupaţi"</string>
- <string name="copy" msgid="2681946229533511987">"Copiaţi"</string>
+ <string name="copy" msgid="2681946229533511987">"Copiați"</string>
<string name="paste" msgid="5629880836805036433">"Inseraţi"</string>
<string name="replace" msgid="5781686059063148930">"Înlocuiţi..."</string>
- <string name="delete" msgid="6098684844021697789">"Ștergeţi"</string>
- <string name="copyUrl" msgid="2538211579596067402">"Copiaţi adresa URL"</string>
- <string name="selectTextMode" msgid="1018691815143165326">"Selectaţi text"</string>
+ <string name="delete" msgid="6098684844021697789">"Ștergeți"</string>
+ <string name="copyUrl" msgid="2538211579596067402">"Copiați adresa URL"</string>
+ <string name="selectTextMode" msgid="1018691815143165326">"Selectați text"</string>
<string name="textSelectionCABTitle" msgid="5236850394370820357">"Selectare text"</string>
<string name="addToDictionary" msgid="4352161534510057874">"Adăugaţi în dicţionar"</string>
- <string name="deleteText" msgid="6979668428458199034">"Ștergeţi"</string>
+ <string name="deleteText" msgid="6979668428458199034">"Ștergeți"</string>
<string name="inputMethod" msgid="1653630062304567879">"Metodă de intrare"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"Acţiuni pentru text"</string>
<string name="low_internal_storage_view_title" msgid="5576272496365684834">"Spaţiul de stocare aproape ocupat"</string>
- <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Este posibil ca unele funcţii de sistem să nu funcţioneze"</string>
+ <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Este posibil ca unele funcții de sistem să nu funcţioneze"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Spațiu de stocare insuficient pentru sistem. Asigurați-vă că aveți 250 MB de spațiu liber și reporniți."</string>
<string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> rulează acum"</string>
<string name="app_running_notification_text" msgid="4653586947747330058">"Atingeți pentru mai multe informații sau pentru a opri aplicația."</string>
@@ -884,7 +884,7 @@
<string name="loading" msgid="7933681260296021180">"Se încarcă…"</string>
<string name="capital_on" msgid="1544682755514494298">"DA"</string>
<string name="capital_off" msgid="6815870386972805832">"NU"</string>
- <string name="whichApplication" msgid="4533185947064773386">"Finalizare acţiune utilizând"</string>
+ <string name="whichApplication" msgid="4533185947064773386">"Finalizare acțiune utilizând"</string>
<string name="whichApplicationNamed" msgid="8260158865936942783">"Finalizați acțiunea utilizând %1$s"</string>
<string name="whichViewApplication" msgid="3272778576700572102">"Deschideți cu"</string>
<string name="whichViewApplicationNamed" msgid="2286418824011249620">"Deschideți cu %1$s"</string>
@@ -896,7 +896,7 @@
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Utilizați %1$s ca ecran de pornire"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Se utilizează în mod prestabilit pentru această acţiune."</string>
<string name="use_a_different_app" msgid="8134926230585710243">"Utilizați altă aplicație"</string>
- <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Ștergeţi setările prestabilite din Setări de sistem > Aplicaţii > Descărcate."</string>
+ <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Ștergeți setările prestabilite din Setări de sistem > Aplicații > Descărcate."</string>
<string name="chooseActivity" msgid="7486876147751803333">"Alegeţi o acţiune"</string>
<string name="chooseUsbActivity" msgid="6894748416073583509">"Alegeţi o aplicație pentru dispozitivul USB"</string>
<string name="noApplications" msgid="2991814273936504689">"Această acţiune nu poate fi efectuată de nicio aplicație."</string>
@@ -905,20 +905,20 @@
<string name="aerr_process" msgid="4507058997035697579">"Din păcate, procesul <xliff:g id="PROCESS">%1$s</xliff:g> s-a oprit."</string>
<string name="aerr_process_silence" msgid="4226685530196000222">"Nu mai afișa blocările aplicației <xliff:g id="PROCESS">%1$s</xliff:g> până la repornire."</string>
<string name="anr_title" msgid="4351948481459135709"></string>
- <string name="anr_activity_application" msgid="1904477189057199066">"Aplicaţia <xliff:g id="APPLICATION">%2$s</xliff:g> nu răspunde.\n\nDoriţi să o închideţi?"</string>
- <string name="anr_activity_process" msgid="5776209883299089767">"Activitatea <xliff:g id="ACTIVITY">%1$s</xliff:g> nu răspunde.\n\nDoriţi să o închideţi?"</string>
- <string name="anr_application_process" msgid="8941757607340481057">"Aplicaţia <xliff:g id="APPLICATION">%1$s</xliff:g> nu răspunde. Doriţi să o închideţi?"</string>
- <string name="anr_process" msgid="6513209874880517125">"Procesul <xliff:g id="PROCESS">%1$s</xliff:g> nu răspunde.\n\nDoriţi să îl închideţi?"</string>
+ <string name="anr_activity_application" msgid="1904477189057199066">"Aplicaţia <xliff:g id="APPLICATION">%2$s</xliff:g> nu răspunde.\n\nDoriți să o închideţi?"</string>
+ <string name="anr_activity_process" msgid="5776209883299089767">"Activitatea <xliff:g id="ACTIVITY">%1$s</xliff:g> nu răspunde.\n\nDoriți să o închideţi?"</string>
+ <string name="anr_application_process" msgid="8941757607340481057">"Aplicaţia <xliff:g id="APPLICATION">%1$s</xliff:g> nu răspunde. Doriți să o închideţi?"</string>
+ <string name="anr_process" msgid="6513209874880517125">"Procesul <xliff:g id="PROCESS">%1$s</xliff:g> nu răspunde.\n\nDoriți să îl închideţi?"</string>
<string name="force_close" msgid="8346072094521265605">"OK"</string>
<string name="report" msgid="4060218260984795706">"Raportaţi"</string>
<string name="wait" msgid="7147118217226317732">"Aşteptaţi"</string>
- <string name="webpage_unresponsive" msgid="3272758351138122503">"Pagina a devenit inactivă.\n\nDoriţi să o închideţi?"</string>
+ <string name="webpage_unresponsive" msgid="3272758351138122503">"Pagina a devenit inactivă.\n\nDoriți să o închideţi?"</string>
<string name="launch_warning_title" msgid="1547997780506713581">"Aplicaţie redirecţionată"</string>
<string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> funcţionează acum."</string>
<string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> a fost lansată iniţial."</string>
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Scară"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Afişaţi întotdeauna"</string>
- <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Reactivaţi acest mod din Setări de sistem > Aplicaţii > Descărcate."</string>
+ <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Reactivaţi acest mod din Setări de sistem > Aplicații > Descărcate."</string>
<string name="smv_application" msgid="3307209192155442829">"Aplicaţia <xliff:g id="APPLICATION">%1$s</xliff:g> (procesul <xliff:g id="PROCESS">%2$s</xliff:g>) a încălcat propria politică StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Procesul <xliff:g id="PROCESS">%1$s</xliff:g> a încălcat propria politică StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android trece la o versiune superioară..."</string>
@@ -929,7 +929,7 @@
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Se pornesc aplicațiile."</string>
<string name="android_upgrading_complete" msgid="1405954754112999229">"Se finalizează pornirea."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"Rulează <xliff:g id="APP">%1$s</xliff:g>"</string>
- <string name="heavy_weight_notification_detail" msgid="1721681741617898865">"Atingeţi pentru a comuta la aplicație"</string>
+ <string name="heavy_weight_notification_detail" msgid="1721681741617898865">"Atingeți pentru a comuta la aplicație"</string>
<string name="heavy_weight_switcher_title" msgid="7153167085403298169">"Comutaţi între aplicații?"</string>
<string name="heavy_weight_switcher_text" msgid="7022631924534406403">"O altă aplicație rulează deja și trebuie oprită înainte a putea porni o aplicație nouă."</string>
<string name="old_app_action" msgid="493129172238566282">"Reveniţi la <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
@@ -985,7 +985,7 @@
<string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Porniţi Wi-Fi Direct. Acest lucru va dezactiva clientul/hotspotul Wi-Fi."</string>
<string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Direct nu a putut porni."</string>
<string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct este activat"</string>
- <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Atingeţi pentru setări"</string>
+ <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Atingeți pentru setări"</string>
<string name="accept" msgid="1645267259272829559">"Acceptaţi"</string>
<string name="decline" msgid="2112225451706137894">"Refuzaţi"</string>
<string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Invitaţia a fost trimisă."</string>
@@ -999,8 +999,8 @@
<string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefonul se va deconecta temporar de la reţeaua Wi-Fi cât timp este conectat la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Introduceţi caracterul"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Se trimit mesaje SMS"</string>
- <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> trimite un număr mare de mesaje SMS. Permiteţi acestei aplicații să trimită în continuare mesaje?"</string>
- <string name="sms_control_yes" msgid="3663725993855816807">"Permiteţi"</string>
+ <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> trimite un număr mare de mesaje SMS. Permiteți acestei aplicații să trimită în continuare mesaje?"</string>
+ <string name="sms_control_yes" msgid="3663725993855816807">"Permiteți"</string>
<string name="sms_control_no" msgid="625438561395534982">"Refuzaţi"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> intenţionează să trimită un mesaj la <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
<string name="sms_short_code_details" msgid="5873295990846059400">"Acest lucru "<b>"poate genera costuri"</b>" în contul dvs. mobil."</string>
@@ -1008,9 +1008,9 @@
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Trimiteţi"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Anulați"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Doresc să se reţină opţiunea"</string>
- <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Puteţi modifica ulterior în Setări > Aplicaţii"</string>
- <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permiteţi întotdeauna"</string>
- <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nu permiteţi niciodată"</string>
+ <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Puteți modifica ulterior în Setări > Aplicații"</string>
+ <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permiteți întotdeauna"</string>
+ <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nu permiteți niciodată"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Card SIM eliminat"</string>
<string name="sim_removed_message" msgid="5450336489923274918">"Rețeaua mobilă va fi indisponibilă până când reporniți cu un card SIM valabil introdus."</string>
<string name="sim_done_button" msgid="827949989369963775">"Terminat"</string>
@@ -1019,7 +1019,7 @@
<string name="sim_restart_button" msgid="4722407842815232347">"Reporniţi"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Setaţi ora"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Setaţi data"</string>
- <string name="date_time_set" msgid="5777075614321087758">"Setaţi"</string>
+ <string name="date_time_set" msgid="5777075614321087758">"Setați"</string>
<string name="date_time_done" msgid="2507683751759308828">"Terminat"</string>
<string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOU: "</font></string>
<string name="perms_description_app" msgid="5139836143293299417">"Furnizată de <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
@@ -1033,13 +1033,13 @@
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Conectat la un accesoriu USB"</string>
<string name="usb_notification_message" msgid="7347368030849048437">"Atingeți pentru mai multe opțiuni."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depanarea USB este conectată"</string>
- <string name="adb_active_notification_message" msgid="1016654627626476142">"Atingeţi pentru a dezactiva depanarea USB."</string>
+ <string name="adb_active_notification_message" msgid="1016654627626476142">"Atingeți pentru a dezactiva depanarea USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Schimbați tastatura"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Alegeți tastaturi"</string>
<string name="show_ime" msgid="9157568568695230830">"Afișați metoda de introducere a textului"</string>
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
- <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selectaţi aspectul tastaturii"</string>
- <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Atingeţi pentru a selecta un aspect de tastatură."</string>
+ <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selectați aspectul tastaturii"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Atingeți pentru a selecta un aspect de tastatură."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidaţi"</u></string>
@@ -1086,21 +1086,21 @@
<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="1772330282283082214">"Solicită instalarea pachetelor"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite unei aplicații să solicite instalarea pachetelor."</string>
- <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Atingeţi de două ori pentru a mări/micşora"</string>
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Atingeți de două ori pentru a mări/micşora"</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>
- <string name="ime_action_search" msgid="658110271822807811">"Căutaţi"</string>
- <string name="ime_action_send" msgid="2316166556349314424">"Trimiteţi"</string>
+ <string name="ime_action_go" msgid="8320845651737369027">"Accesați"</string>
+ <string name="ime_action_search" msgid="658110271822807811">"Căutați"</string>
+ <string name="ime_action_send" msgid="2316166556349314424">"Trimiteți"</string>
<string name="ime_action_next" msgid="3138843904009813834">"Înainte"</string>
<string name="ime_action_done" msgid="8971516117910934605">"Terminat"</string>
<string name="ime_action_previous" msgid="1443550039250105948">"Înapoi"</string>
- <string name="ime_action_default" msgid="2840921885558045721">"Executaţi"</string>
+ <string name="ime_action_default" msgid="2840921885558045721">"Executați"</string>
<string name="dial_number_using" msgid="5789176425167573586">"Formaţi numărul\nutilizând <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="4947405226788104538">"Creaţi contactul\nutilizând <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"Următoarele aplicații solicită permisiunea de a accesa contul dvs. acum și în viitor."</string>
- <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Permiteţi această solicitare?"</string>
+ <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Permiteți această solicitare?"</string>
<string name="grant_permissions_header_text" msgid="6874497408201826708">"Solicitare de acces"</string>
- <string name="allow" msgid="7225948811296386551">"Permiteţi"</string>
+ <string name="allow" msgid="7225948811296386551">"Permiteți"</string>
<string name="deny" msgid="2081879885755434506">"Refuzaţi"</string>
<string name="permission_request_notification_title" msgid="6486759795926237907">"Permisiune solicitată"</string>
<string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"Permisiune solicitată\npentru contul <xliff:g id="ACCOUNT">%s</xliff:g>."</string>
@@ -1115,20 +1115,20 @@
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Furnizor de condiții"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN activat"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string>
- <string name="vpn_text" msgid="3011306607126450322">"Atingeţi pentru a gestiona reţeaua."</string>
- <string name="vpn_text_long" msgid="6407351006249174473">"Conectat la <xliff:g id="SESSION">%s</xliff:g>. Atingeţi pentru a gestiona reţeaua."</string>
+ <string name="vpn_text" msgid="3011306607126450322">"Atingeți pentru a gestiona reţeaua."</string>
+ <string name="vpn_text_long" msgid="6407351006249174473">"Conectat la <xliff:g id="SESSION">%s</xliff:g>. Atingeți pentru a gestiona reţeaua."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Se efectuează conectarea la reţeaua VPN activată permanent…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Conectat(ă) la reţeaua VPN activată permanent"</string>
- <string name="vpn_lockdown_error" msgid="6009249814034708175">"Eroare de reţea VPN activată permanent"</string>
+ <string name="vpn_lockdown_error" msgid="6009249814034708175">"Eroare de rețea VPN activată permanent"</string>
<string name="vpn_lockdown_config" msgid="6415899150671537970">"Atingeți pentru a configura"</string>
<string name="upload_file" msgid="2897957172366730416">"Alegeţi un fişier"</string>
- <string name="no_file_chosen" msgid="6363648562170759465">"Nu au fost găsite fişiere"</string>
+ <string name="no_file_chosen" msgid="6363648562170759465">"Nu au fost găsite fișiere"</string>
<string name="reset" msgid="2448168080964209908">"Resetaţi"</string>
<string name="submit" msgid="1602335572089911941">"Trimiteţi"</string>
<string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mod Maşină activat"</string>
- <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Atingeţi pentru a ieşi din modul Maşină."</string>
+ <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Atingeți pentru a ieşi din modul Maşină."</string>
<string name="tethered_notification_title" msgid="3146694234398202601">"Tethering sau hotspot activ"</string>
- <string name="tethered_notification_message" msgid="6857031760103062982">"Atingeţi pentru a configura."</string>
+ <string name="tethered_notification_message" msgid="6857031760103062982">"Atingeți pentru a configura."</string>
<string name="back_button_label" msgid="2300470004503343439">"Înapoi"</string>
<string name="next_button_label" msgid="1080555104677992408">"Înainte"</string>
<string name="skip_button_label" msgid="1275362299471631819">"Omiteţi"</string>
@@ -1140,21 +1140,21 @@
<item quantity="one">Un rezultat</item>
</plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Terminat"</string>
- <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Se şterge stocarea USB..."</string>
- <string name="progress_erasing" product="default" msgid="6596988875507043042">"Se şterge cardul SD..."</string>
+ <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Se șterge stocarea USB..."</string>
+ <string name="progress_erasing" product="default" msgid="6596988875507043042">"Se șterge cardul SD..."</string>
<string name="share" msgid="1778686618230011964">"Distribuiţi"</string>
<string name="find" msgid="4808270900322985960">"Găsiţi"</string>
<string name="websearch" msgid="4337157977400211589">"Căutare pe web"</string>
<string name="find_next" msgid="5742124618942193978">"Următorul rezultat"</string>
<string name="find_previous" msgid="2196723669388360506">"Rezultatul anterior"</string>
- <string name="gpsNotifTicker" msgid="5622683912616496172">"Solicitare de locaţie de la <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="5446858717157416839">"Solicitare de locaţie"</string>
+ <string name="gpsNotifTicker" msgid="5622683912616496172">"Solicitare de locație de la <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Solicitare de locație"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"Solicitat de <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Da"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Nu"</string>
<string name="sync_too_many_deletes" msgid="5296321850662746890">"Limita pentru ştergere a fost depăşită"</string>
- <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Există <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> (de) elemente şterse pentru <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, contul <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Ce doriţi să faceţi?"</string>
- <string name="sync_really_delete" msgid="2572600103122596243">"Ștergeţi elementele"</string>
+ <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Există <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> (de) elemente şterse pentru <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, contul <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Ce doriți să faceţi?"</string>
+ <string name="sync_really_delete" msgid="2572600103122596243">"Ștergeți elementele"</string>
<string name="sync_undo_deletes" msgid="2941317360600338602">"Anulați aceste ştergeri"</string>
<string name="sync_do_nothing" msgid="3743764740430821845">"Nu trebuie să luaţi nicio măsură deocamdată"</string>
<string name="choose_account_label" msgid="5655203089746423927">"Alegeţi un cont"</string>
@@ -1162,7 +1162,7 @@
<string name="add_account_button_label" msgid="3611982894853435874">"Adăugaţi un cont"</string>
<string name="number_picker_increment_button" msgid="2412072272832284313">"Creşteţi"</string>
<string name="number_picker_decrement_button" msgid="476050778386779067">"Reduceţi"</string>
- <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Atingeţi și ţineţi apăsat <xliff:g id="VALUE">%s</xliff:g>."</string>
+ <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Atingeți și țineți apăsat <xliff:g id="VALUE">%s</xliff:g>."</string>
<string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Glisaţi în sus pentru a creşte și în jos pentru a reduce."</string>
<string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Creşteţi valoarea pentru minute"</string>
<string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Reduceţi valoarea pentru minute"</string>
@@ -1180,16 +1180,16 @@
<string name="date_picker_next_month_button" msgid="5559507736887605055">"Luna viitoare"</string>
<string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
<string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Anulați"</string>
- <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Ștergeţi"</string>
+ <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Ștergeți"</string>
<string name="keyboardview_keycode_done" msgid="1992571118466679775">"Terminat"</string>
<string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"Schimbarea modului"</string>
<string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
<string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
<string name="activitychooserview_choose_application" msgid="2125168057199941199">"Alegeţi o aplicație"</string>
<string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"Nu s-a putut lansa <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
- <string name="shareactionprovider_share_with" msgid="806688056141131819">"Permiteţi accesul pentru"</string>
- <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Permiteţi accesul pentru <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
- <string name="content_description_sliding_handle" msgid="415975056159262248">"Mâner glisant. Atingeţi și ţineţi apăsat."</string>
+ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Permiteți accesul pentru"</string>
+ <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Permiteți accesul pentru <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="content_description_sliding_handle" msgid="415975056159262248">"Mâner glisant. Atingeți și țineți apăsat."</string>
<string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glisaţi pentru a debloca."</string>
<string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conectaţi un set căşti-microfon pentru a auzi tastele apăsate când introduceţi parola."</string>
<string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punct."</string>
@@ -1206,7 +1206,7 @@
<string name="storage_usb" msgid="3017954059538517278">"Dsipozitiv de stocare USB"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"Editaţi"</string>
<string name="data_usage_warning_title" msgid="1955638862122232342">"Avertisment de utiliz. a datelor"</string>
- <string name="data_usage_warning_body" msgid="2814673551471969954">"Atingeţi pt. a afişa utiliz./set."</string>
+ <string name="data_usage_warning_body" msgid="2814673551471969954">"Atingeți pt. a afişa utiliz./set."</string>
<string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Ați atins limita de date 2G-3G"</string>
<string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Ați atins limita de date 4G"</string>
<string name="data_usage_mobile_limit_title" msgid="557158376602636112">"Ați atins limita de date mobile"</string>
@@ -1218,7 +1218,7 @@
<string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"S-a depăşit limita de date Wi-Fi"</string>
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> peste limita specificată."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Datele de fundal restricţionate"</string>
- <string name="data_usage_restricted_body" msgid="6741521330997452990">"Atingeţi pt. a elimina limita."</string>
+ <string name="data_usage_restricted_body" msgid="6741521330997452990">"Atingeți pt. a elimina limita."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificat de securitate"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certificatul este valid."</string>
<string name="issued_to" msgid="454239480274921032">"Emis către:"</string>
@@ -1291,7 +1291,7 @@
<string name="kg_login_password_hint" msgid="9057289103827298549">"Parolă"</string>
<string name="kg_login_submit_button" msgid="5355904582674054702">"Conectați-vă"</string>
<string name="kg_login_invalid_input" msgid="5754664119319872197">"Nume de utilizator sau parolă nevalide."</string>
- <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Aţi uitat numele de utilizator sau parola?\nAccesaţi "<b>"google.com/accounts/recovery"</b>"."</string>
+ <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Aţi uitat numele de utilizator sau parola?\nAccesați "<b>"google.com/accounts/recovery"</b>"."</string>
<string name="kg_login_checking_password" msgid="1052685197710252395">"Se verifică contul…"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Aţi introdus incorect codul PIN de <xliff:g id="NUMBER_0">%d</xliff:g> ori.\n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%d</xliff:g> (de) secunde."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Aţi introdus incorect parola de <xliff:g id="NUMBER_0">%d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%d</xliff:g> (de) secunde."</string>
diff --git a/core/res/res/values-ru-watch/strings.xml b/core/res/res/values-ru-watch/strings.xml
index f32f63b..cd536c5 100644
--- a/core/res/res/values-ru-watch/strings.xml
+++ b/core/res/res/values-ru-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Приложение <xliff:g id="NUMBER_0">%1$d</xliff:g> из <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index e0ea9c0f0..821342a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1132,7 +1132,7 @@
<string name="no_file_chosen" msgid="6363648562170759465">"Не выбран файл"</string>
<string name="reset" msgid="2448168080964209908">"Сбросить"</string>
<string name="submit" msgid="1602335572089911941">"Отправить"</string>
- <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Включен режим \"Штурман\""</string>
+ <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Режим \"В автомобиле\""</string>
<string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Чтобы выйти, нажмите здесь."</string>
<string name="tethered_notification_title" msgid="3146694234398202601">"Включен режим модема"</string>
<string name="tethered_notification_message" msgid="6857031760103062982">"Нажмите для настройки."</string>
diff --git a/core/res/res/values-si-rLK-watch/strings.xml b/core/res/res/values-si-rLK-watch/strings.xml
index b55687f..4adfbb5 100644
--- a/core/res/res/values-si-rLK-watch/strings.xml
+++ b/core/res/res/values-si-rLK-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g> හි <xliff:g id="NUMBER_1">%2$d</xliff:g> යෙදුම."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk-watch/strings.xml b/core/res/res/values-sk-watch/strings.xml
index 601c016..24bed89 100644
--- a/core/res/res/values-sk-watch/strings.xml
+++ b/core/res/res/values-sk-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikácia <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl-watch/strings.xml b/core/res/res/values-sl-watch/strings.xml
index bf1190f..5bc0ea5 100644
--- a/core/res/res/values-sl-watch/strings.xml
+++ b/core/res/res/values-sl-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. aplikac. od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sq-rAL-watch/strings.xml b/core/res/res/values-sq-rAL-watch/strings.xml
index d1637ba..1b0bdaf 100644
--- a/core/res/res/values-sq-rAL-watch/strings.xml
+++ b/core/res/res/values-sq-rAL-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikacioni <xliff:g id="NUMBER_0">%1$d</xliff:g> nga <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sr-watch/strings.xml b/core/res/res/values-sr-watch/strings.xml
index 484977e..ae70ab1 100644
--- a/core/res/res/values-sr-watch/strings.xml
+++ b/core/res/res/values-sr-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Апликација <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv-watch/strings.xml b/core/res/res/values-sv-watch/strings.xml
index 3bd7fa5..aba8abb 100644
--- a/core/res/res/values-sv-watch/strings.xml
+++ b/core/res/res/values-sv-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw-watch/strings.xml b/core/res/res/values-sw-watch/strings.xml
index 5a8c72e..929022f 100644
--- a/core/res/res/values-sw-watch/strings.xml
+++ b/core/res/res/values-sw-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Programu ya <xliff:g id="NUMBER_0">%1$d</xliff:g> kati ya <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ta-rIN-watch/strings.xml b/core/res/res/values-ta-rIN-watch/strings.xml
index 4c05cab..23accbc 100644
--- a/core/res/res/values-ta-rIN-watch/strings.xml
+++ b/core/res/res/values-ta-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"பயன்பாடு: <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-te-rIN-watch/strings.xml b/core/res/res/values-te-rIN-watch/strings.xml
index 6b4b900..0843471 100644
--- a/core/res/res/values-te-rIN-watch/strings.xml
+++ b/core/res/res/values-te-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g>లో <xliff:g id="NUMBER_0">%1$d</xliff:g>వ అనువర్తనం."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-th-watch/strings.xml b/core/res/res/values-th-watch/strings.xml
index 568b083..9cc21b0 100644
--- a/core/res/res/values-th-watch/strings.xml
+++ b/core/res/res/values-th-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"แอป <xliff:g id="NUMBER_0">%1$d</xliff:g> จาก <xliff:g id="NUMBER_1">%2$d</xliff:g> แอป"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl-watch/strings.xml b/core/res/res/values-tl-watch/strings.xml
index bb0dc4b..3fba2dc 100644
--- a/core/res/res/values-tl-watch/strings.xml
+++ b/core/res/res/values-tl-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> ng <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr-watch/strings.xml b/core/res/res/values-tr-watch/strings.xml
index d9c3923..b34ad74 100644
--- a/core/res/res/values-tr-watch/strings.xml
+++ b/core/res/res/values-tr-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Uygulama <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk-watch/strings.xml b/core/res/res/values-uk-watch/strings.xml
index 02e6466..4141b08 100644
--- a/core/res/res/values-uk-watch/strings.xml
+++ b/core/res/res/values-uk-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Додаток <xliff:g id="NUMBER_0">%1$d</xliff:g> з <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ur-rPK-watch/strings.xml b/core/res/res/values-ur-rPK-watch/strings.xml
index 0fd24c9..f90af0b 100644
--- a/core/res/res/values-ur-rPK-watch/strings.xml
+++ b/core/res/res/values-ur-rPK-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"ایپ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>۔"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uz-rUZ-watch/strings.xml b/core/res/res/values-uz-rUZ-watch/strings.xml
index 7abd603..42fe54a 100644
--- a/core/res/res/values-uz-rUZ-watch/strings.xml
+++ b/core/res/res/values-uz-rUZ-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g>dan <xliff:g id="NUMBER_0">%1$d</xliff:g> ilova."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-vi-watch/strings.xml b/core/res/res/values-vi-watch/strings.xml
index f419bdf..634d890 100644
--- a/core/res/res/values-vi-watch/strings.xml
+++ b/core/res/res/values-vi-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Ứng dụng <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-watch/strings.xml b/core/res/res/values-watch/strings.xml
index 4ea2b52..e5991fc 100644
--- a/core/res/res/values-watch/strings.xml
+++ b/core/res/res/values-watch/strings.xml
@@ -23,4 +23,50 @@
<string name="android_upgrading_apk">App
<xliff:g id="number" example="123">%1$d</xliff:g> of
<xliff:g id="number" example="123">%2$d</xliff:g>.</string>
+
+ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. Override from base which says "Body Sensors". [CHAR_LIMIT=25] -->
+ <string name="permgrouplab_sensors">Sensors</string>
+
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permgrouplab_contactswear">access your contacts</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permgrouplab_locationwear">access this watch\'s location</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permgrouplab_calendarwear">access your calendar</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permgrouplab_smswear">send and view SMS messages</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permgrouplab_storagewear">access photos, media, and files on your watch</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permgrouplab_microphonewear">record audio</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permgrouplab_camerawear">take pictures and record video</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permgrouplab_phonewear">make and manage phone calls</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permgrouplab_sensorswear">access sensor data about your vital signs</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_statusBarServicewear">be the status bar</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_bodySensorswear">access body sensors (like heart rate monitors)</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_accessFineLocationwear">access precise location (GPS and network-based)</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_accessCoarseLocationwear">access approximate location (network-based)</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_sim_communicationwear">send commands to the SIM</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_createNetworkSocketswear">have full network access</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_manageProfileAndDeviceOwnerswear">manage profile and device owners</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_changeWimaxStatewear">change WiMAX state</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_handoverStatuswear">receive Android Beam transfer status</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_route_media_outputwear">route media output</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_readInstallSessionswear">read install sessions</string>
+ <!-- Description of a permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+ <string name="permlab_requestInstallPackageswear">request install packages</string>
</resources>
diff --git a/core/res/res/values-zh-rCN-watch/strings.xml b/core/res/res/values-zh-rCN-watch/strings.xml
index 9c9e49d..8864701 100644
--- a/core/res/res/values-zh-rCN-watch/strings.xml
+++ b/core/res/res/values-zh-rCN-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"应用:<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>。"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rHK-watch/strings.xml b/core/res/res/values-zh-rHK-watch/strings.xml
index 3b5fb8e..356e853 100644
--- a/core/res/res/values-zh-rHK-watch/strings.xml
+++ b/core/res/res/values-zh-rHK-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"應用程式 (<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>)"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW-watch/strings.xml b/core/res/res/values-zh-rTW-watch/strings.xml
index 87f3abb..20ef6ba 100644
--- a/core/res/res/values-zh-rTW-watch/strings.xml
+++ b/core/res/res/values-zh-rTW-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"應用程式 <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>。"</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu-watch/strings.xml b/core/res/res/values-zu-watch/strings.xml
index acd153b..22b8af7 100644
--- a/core/res/res/values-zu-watch/strings.xml
+++ b/core/res/res/values-zu-watch/strings.xml
@@ -21,4 +21,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Uhlelo lokusebenza olungu-<xliff:g id="NUMBER_0">%1$d</xliff:g> kokungu-<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+ <skip />
+ <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+ <skip />
+ <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+ <skip />
+ <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+ <skip />
+ <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+ <skip />
+ <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+ <skip />
+ <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+ <skip />
+ <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+ <skip />
+ <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+ <skip />
+ <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+ <skip />
+ <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+ <skip />
+ <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+ <skip />
+ <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+ <skip />
+ <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+ <skip />
+ <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+ <skip />
+ <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+ <skip />
+ <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+ <skip />
+ <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+ <skip />
+ <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+ <skip />
+ <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+ <skip />
+ <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+ <skip />
+ <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 1a45b3a..4531f75 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1816,9 +1816,9 @@
<attr name="uiOptions" />
<attr name="parentActivityName" />
<attr name="singleUser" />
- <!-- @hide This broacast receiver will only receive broadcasts for the
- primary user. Can only be used with receivers. -->
- <attr name="primaryUserOnly" format="boolean" />
+ <!-- @hide This broadcast receiver or activity will only receive broadcasts for the
+ system user-->
+ <attr name="systemUserOnly" format="boolean" />
<attr name="persistableMode" />
<attr name="allowEmbedded" />
<attr name="documentLaunchMode" />
@@ -2195,4 +2195,18 @@
<attr name="name" />
</declare-styleable>
+ <!-- <code>initial-layout</code> tag allows configuring the initial layout for the activity
+ within multi-window environment. -->
+ <declare-styleable name="AndroidManifestInitialLayout" parent="AndroidManifestActivity">
+ <!-- Initial width of the activity. Can be either a fixed value or fraction, in which case
+ the width will be constructed as a fraction of the total available width. -->
+ <attr name="activityWidth" format="dimension|fraction" />
+ <!-- Initial height of the activity. Can be either a fixed value or fraction, in which case
+ the height will be constructed as a fraction of the total available height. -->
+ <attr name="activityHeight" format="dimension|fraction" />
+ <!-- Where to initially position the activity inside the available space. Uses constants
+ defined in {@link android.view.Gravity}. -->
+ <attr name="gravity" />
+ </declare-styleable>
+
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7acc25d..ef4e261 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -619,6 +619,17 @@
<!-- rotation: 270 (rotate CW) --> <item>-25</item> <item>65</item>
</integer-array>
+ <!-- Indicate the name of the window orientation sensor type if present. A
+ window orientation sensor produces values to be used in lieu of the
+ typical, accelerometer based sensor. It must only produce integral
+ values between 0 and 3, inclusive, with each one corresponding to a
+ given rotation:
+ 0: 0 degrees of rotation (natural)
+ 1: 90 degrees of rotation (rotate CCW)
+ 2: 180 degrees of rotation (reverse)
+ 3: 270 degrees of rotation (rotate CW) -->
+ <string name="config_orientationSensorType" translatable="false">@null</string>
+
<!-- Lid switch behavior -->
<!-- The number of degrees to rotate the display when the keyboard is open.
@@ -2018,10 +2029,6 @@
IMS service implementation will do both.i.e.hold followed by merge. -->
<bool name="skipHoldBeforeMerge">true</bool>
- <!-- Flag indicating emergency calls will always use IMS irrespective of the state of
- the IMS connection -->
- <bool name="useImsAlwaysForEmergencyCall">true</bool>
-
<!-- Flag indicating whether the IMS service can be turned off. If false then
the service will not be turned-off completely (the ImsManager.turnOffIms() will
be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index cabb56c..d2089cd 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2679,5 +2679,7 @@
<public type="style" name="Theme.Material.DayNight.DialogWhenLarge.DarkActionBar" />
<public type="id" name="accessibilityActionSetProgress" />
+ <public type="attr" name="activityWidth" />
+ <public type="attr" name="activityHeight" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 004407f..e04c743 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1545,6 +1545,7 @@
<java-symbol type="string" name="bugreport_title" />
<java-symbol type="string" name="bugreport_message" />
<java-symbol type="string" name="bugreport_status" />
+ <java-symbol type="string" name="config_orientationSensorType" />
<java-symbol type="string" name="faceunlock_multiple_failures" />
<java-symbol type="string" name="global_action_power_off" />
<java-symbol type="string" name="global_actions_airplane_mode_off_status" />
@@ -2137,7 +2138,6 @@
<java-symbol type="bool" name="config_carrier_vt_available" />
<java-symbol type="bool" name="config_device_wfc_ims_available" />
<java-symbol type="bool" name="config_carrier_wfc_ims_available" />
- <java-symbol type="bool" name="useImsAlwaysForEmergencyCall" />
<java-symbol type="attr" name="touchscreenBlocksFocus" />
<java-symbol type="layout" name="resolver_list_with_default" />
<java-symbol type="string" name="whichApplicationNamed" />
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
new file mode 100644
index 0000000..d99ee80
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -0,0 +1,551 @@
+/*
+* Copyright (C) 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package android.animation;
+
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import static android.test.MoreAsserts.assertNotEqual;
+
+public class ValueAnimatorTests extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> {
+ private ValueAnimator a1;
+ private ValueAnimator a2;
+
+ // Tolerance of error in calculations related to duration, frame time, etc. due to frame delay.
+ private final static long TOLERANCE = 100; // ms
+ private final static long POLL_INTERVAL = 100; // ms
+
+ private final static float A1_START_VALUE = 0f;
+ private final static float A1_END_VALUE = 1f;
+ private final static int A2_START_VALUE = 100;
+ private final static int A2_END_VALUE = 200;
+
+ public ValueAnimatorTests() {
+ super(BasicAnimatorActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ a1 = ValueAnimator.ofFloat(A1_START_VALUE, A1_END_VALUE).setDuration(300);
+ a2 = ValueAnimator.ofInt(A2_START_VALUE, A2_END_VALUE).setDuration(500);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ a1 = null;
+ a2 = null;
+ }
+
+ @SmallTest
+ public void testStartDelay() throws Throwable {
+ final ValueAnimator a = ValueAnimator.ofFloat(5f, 20f);
+ assertEquals(a.getStartDelay(), 0);
+ final long delay = 200;
+ a.setStartDelay(delay);
+ assertEquals(a.getStartDelay(), delay);
+
+ final MyUpdateListener listener = new MyUpdateListener();
+ a.addUpdateListener(listener);
+ final long[] startTime = new long[1];
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Test the time between isRunning() and isStarted()
+ assertFalse(a.isStarted());
+ assertFalse(a.isRunning());
+ a.start();
+ startTime[0] = SystemClock.uptimeMillis();
+ assertTrue(a.isStarted());
+ assertFalse(a.isRunning());
+ }
+ });
+
+ Thread.sleep(a.getTotalDuration());
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(listener.wasRunning);
+ assertTrue(listener.firstRunningFrameTime - startTime[0] >= delay);
+ }
+ });
+
+ Thread.sleep(a.getTotalDuration());
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(a.isStarted());
+ }
+ });
+ }
+
+ @SmallTest
+ public void testListenerCallbacks() throws Throwable {
+ final MyListener l1 = new MyListener();
+ final MyListener l2 = new MyListener();
+ a1.addListener(l1);
+ a2.addListener(l2);
+ a2.setStartDelay(400);
+
+ assertFalse(l1.startCalled);
+ assertFalse(l1.cancelCalled);
+ assertFalse(l1.endCalled);
+ assertFalse(l2.startCalled);
+ assertFalse(l2.cancelCalled);
+ assertFalse(l2.endCalled);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ a1.start();
+ a2.start();
+ }
+ });
+
+ long wait = 0;
+ Thread.sleep(POLL_INTERVAL);
+ wait += POLL_INTERVAL;
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(l1.cancelCalled);
+ a1.cancel();
+ assertTrue(l1.cancelCalled);
+ assertTrue(l1.endCalled);
+ }
+ });
+
+ while (wait < a2.getStartDelay()) {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Make sure a2's start listener isn't called during start delay.
+ assertTrue(l1.startCalled);
+ assertFalse(l2.startCalled);
+ }
+ });
+ Thread.sleep(POLL_INTERVAL);
+ wait += POLL_INTERVAL;
+ }
+
+ long delay = Math.max(a1.getTotalDuration(), a2.getTotalDuration()) + TOLERANCE;
+ Thread.sleep(delay);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // a1 is canceled.
+ assertTrue(l1.startCalled);
+ assertTrue(l1.cancelCalled);
+ assertTrue(l1.endCalled);
+
+ // a2 is supposed to finish normally
+ assertTrue(l2.startCalled);
+ assertFalse(l2.cancelCalled);
+ assertTrue(l2.endCalled);
+ }
+ });
+ }
+
+ @SmallTest
+ public void testIsStarted() throws Throwable {
+ assertFalse(a1.isStarted());
+ assertFalse(a2.isStarted());
+ assertFalse(a1.isRunning());
+ assertFalse(a2.isRunning());
+ final long startDelay = 150;
+ a1.setStartDelay(startDelay);
+ final long[] startTime = new long[1];
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ a1.start();
+ a2.start();
+ startTime[0] = SystemClock.uptimeMillis();
+ assertTrue(a1.isStarted());
+ assertTrue(a2.isStarted());
+ }
+ });
+ long delayMs = 0;
+ while (delayMs < startDelay) {
+ Thread.sleep(POLL_INTERVAL);
+ delayMs += POLL_INTERVAL;
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (SystemClock.uptimeMillis() - startTime[0] < startDelay) {
+ assertFalse(a1.isRunning());
+ }
+ }
+ });
+ }
+
+ Thread.sleep(startDelay);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(a1.isRunning());
+ assertTrue(a2.isRunning());
+ }
+ });
+
+ long delay = Math.max(a1.getTotalDuration(), a2.getTotalDuration()) * 2;
+ Thread.sleep(delay);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(a1.isStarted());
+ assertFalse(a1.isRunning());
+ assertFalse(a2.isStarted());
+ assertFalse(a2.isRunning());
+ }
+ });
+ }
+
+ @SmallTest
+ public void testPause() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(a1.isPaused());
+ assertFalse(a2.isPaused());
+
+ a1.start();
+ a2.start();
+
+ assertFalse(a1.isPaused());
+ assertFalse(a2.isPaused());
+ assertTrue(a1.isStarted());
+ assertTrue(a2.isStarted());
+ }
+ });
+
+ Thread.sleep(POLL_INTERVAL);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(a1.isRunning());
+ assertTrue(a2.isRunning());
+ a1.pause();
+ assertTrue(a1.isPaused());
+ assertFalse(a2.isPaused());
+ assertTrue(a1.isRunning());
+ }
+ });
+
+ Thread.sleep(a2.getTotalDuration());
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // By this time, a2 should have finished, and a1 is still paused
+ assertFalse(a2.isStarted());
+ assertFalse(a2.isRunning());
+ assertTrue(a1.isStarted());
+ assertTrue(a1.isRunning());
+ assertTrue(a1.isPaused());
+
+ a1.resume();
+ }
+ });
+
+ Thread.sleep(POLL_INTERVAL);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(a1.isRunning());
+ assertTrue(a1.isStarted());
+ assertFalse(a1.isPaused());
+ }
+ });
+
+ Thread.sleep(a1.getTotalDuration());
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // a1 should finish by now.
+ assertFalse(a1.isRunning());
+ assertFalse(a1.isStarted());
+ assertFalse(a1.isPaused());
+ }
+ });
+
+ }
+
+ @SmallTest
+ public void testPauseListener() throws Throwable {
+ MyPauseListener l1 = new MyPauseListener();
+ MyPauseListener l2 = new MyPauseListener();
+ a1.addPauseListener(l1);
+ a2.addPauseListener(l2);
+
+ assertFalse(l1.pauseCalled);
+ assertFalse(l1.resumeCalled);
+ assertFalse(l2.pauseCalled);
+ assertFalse(l2.resumeCalled);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ a1.start();
+ a2.start();
+ }
+ });
+
+ Thread.sleep(a1.getTotalDuration() / 2);
+ a1.pause();
+
+ Thread.sleep(a2.getTotalDuration());
+
+ // Only a1's pause listener should be called.
+ assertTrue(l1.pauseCalled);
+ assertFalse(l1.resumeCalled);
+ a1.resume();
+
+ Thread.sleep(a1.getTotalDuration());
+
+ assertTrue(l1.pauseCalled);
+ assertTrue(l1.resumeCalled);
+ assertFalse(l2.pauseCalled);
+ assertFalse(l2.resumeCalled);
+ }
+
+ @SmallTest
+ public void testResume() throws Throwable {
+ final MyUpdateListener l1 = new MyUpdateListener();
+ final long totalDuration = a1.getTotalDuration();
+ a1.addUpdateListener(l1);
+ // Set a longer duration on a1 for this test
+ a1.setDuration(1000);
+ assertTrue(l1.firstRunningFrameTime < 0);
+ assertTrue(l1.lastUpdateTime < 0);
+
+ final long[] lastUpdate = new long[1];
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ a1.start();
+ }
+ });
+
+ Thread.sleep(totalDuration / 2);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(l1.firstRunningFrameTime > 0);
+ assertTrue(l1.lastUpdateTime > l1.firstRunningFrameTime);
+ lastUpdate[0] = l1.lastUpdateTime;
+ a1.pause();
+ }
+ });
+
+ Thread.sleep(totalDuration);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // There should be no update after pause()
+ assertEquals(lastUpdate[0], l1.lastUpdateTime);
+ a1.resume();
+ }
+ });
+
+ do {
+ Thread.sleep(POLL_INTERVAL);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(l1.lastUpdateTime > lastUpdate[0]);
+ lastUpdate[0] = l1.lastUpdateTime;
+ }
+ });
+ } while (!a1.isStarted());
+
+ // Time between pause and resume: totalDuration
+ long entireSpan = totalDuration * 2;
+ long frameDelta = l1.lastUpdateTime - l1.firstRunningFrameTime;
+ assertTrue(Math.abs(entireSpan - frameDelta) < TOLERANCE);
+ }
+
+ @SmallTest
+ public void testEnd() throws Throwable {
+ final MyListener l1 = new MyListener();
+ final MyListener l2 = new MyListener();
+ a1.addListener(l1);
+ a2.addListener(l2);
+ a1.addListener(new MyListener() {
+ @Override
+ public void onAnimationEnd(Animator anim) {
+ anim.cancel();
+ }
+ });
+ a2.addListener(new MyListener() {
+ @Override
+ public void onAnimationCancel(Animator anim) {
+ anim.end();
+ }
+ });
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(l1.cancelCalled);
+ assertFalse(l1.endCalled);
+ assertFalse(l2.cancelCalled);
+ assertFalse(l2.endCalled);
+ a1.start();
+ a2.start();
+ }
+ });
+ Thread.sleep(POLL_INTERVAL);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ a1.end();
+ a2.cancel();
+ }
+ });
+ Thread.sleep(POLL_INTERVAL);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Calling cancel from onAnimationEnd will be ignored.
+ assertFalse(l1.cancelCalled);
+ assertTrue(l1.endCalled);
+ assertTrue(l2.cancelCalled);
+ assertTrue(l2.endCalled);
+
+ float value1 = (Float) a1.getAnimatedValue();
+ int value2 = (Integer) a2.getAnimatedValue();
+ assertEquals(A1_END_VALUE, value1);
+ assertEquals(A2_END_VALUE, value2);
+ }
+ });
+
+ }
+
+ @SmallTest
+ public void testEndValue() throws Throwable {
+ final MyListener l1 = new MyListener();
+ a1.addListener(l1);
+
+ final MyListener l2 = new MyListener();
+ a2.addListener(l2);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ a1.start();
+ a2.start();
+ }
+ });
+
+ Thread.sleep(POLL_INTERVAL);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Animation has started but not finished, check animated values against end values
+ assertFalse(l1.endCalled);
+ assertFalse(l2.endCalled);
+ assertNotEqual(A1_END_VALUE, a1.getAnimatedValue());
+ assertNotEqual(A1_END_VALUE, a2.getAnimatedValue());
+
+ // Force a2 to end.
+ a2.end();
+ }
+ });
+
+ Thread.sleep(a1.getTotalDuration());
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(l1.cancelCalled);
+ assertTrue(l1.endCalled);
+ assertFalse(l2.cancelCalled);
+ assertTrue(l2.endCalled);
+
+ // By now a1 should have finished normally and a2 has skipped to the end, check
+ // their end values.
+ assertEquals(A1_END_VALUE, ((Float) (a1.getAnimatedValue())).floatValue());
+ assertEquals(A2_END_VALUE, ((Integer) (a2.getAnimatedValue())).intValue());
+ }
+ });
+ }
+
+ class MyUpdateListener implements ValueAnimator.AnimatorUpdateListener {
+ boolean wasRunning = false;
+ long firstRunningFrameTime = -1;
+ long lastUpdateTime = -1;
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ lastUpdateTime = SystemClock.uptimeMillis();
+ if (animation.isRunning() && !wasRunning) {
+ // Delay has passed
+ firstRunningFrameTime = lastUpdateTime;
+ wasRunning = animation.isRunning();
+ }
+ }
+ }
+
+ class MyListener implements Animator.AnimatorListener {
+ boolean startCalled = false;
+ boolean cancelCalled = false;
+ boolean endCalled = false;
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ startCalled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endCalled = true;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ cancelCalled = true;
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+ }
+
+ class MyPauseListener implements Animator.AnimatorPauseListener {
+ boolean pauseCalled = false;
+ boolean resumeCalled = false;
+
+ @Override
+ public void onAnimationPause(Animator animation) {
+ pauseCalled = true;
+ }
+
+ @Override
+ public void onAnimationResume(Animator animation) {
+ resumeCalled = true;
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/app/backup/FullBackupTest.java b/core/tests/coretests/src/android/app/backup/FullBackupTest.java
index 8c9c63c..c3afbf6 100644
--- a/core/tests/coretests/src/android/app/backup/FullBackupTest.java
+++ b/core/tests/coretests/src/android/app/backup/FullBackupTest.java
@@ -114,12 +114,14 @@
public void testparseBackupSchemeFromXml_lotsOfIncludesAndExcludes() throws Exception {
mXpp.setInput(new StringReader(
"<full-backup-content>" +
- "<exclude path=\"exclude1.txt\" domain=\"file\"/>" +
+ "<exclude path=\"exclude1.txt\" domain=\"file\"/>" +
"<include path=\"include1.txt\" domain=\"file\"/>" +
"<exclude path=\"exclude2.txt\" domain=\"database\"/>" +
"<include path=\"include2.txt\" domain=\"database\"/>" +
- "<exclude path=\"exclude3.txt\" domain=\"sharedpref\"/>" +
- "<include path=\"include3.txt\" domain=\"sharedpref\"/>" +
+ "<exclude path=\"exclude3\" domain=\"sharedpref\"/>" +
+ "<include path=\"include3\" domain=\"sharedpref\"/>" +
+ "<exclude path=\"exclude4.xml\" domain=\"sharedpref\"/>" +
+ "<include path=\"include4.xml\" domain=\"sharedpref\"/>" +
"</full-backup-content>"));
@@ -146,16 +148,27 @@
"include2.txt-journal")
.getCanonicalPath()));
- Set<String> sharedPrefDomainIncludes = includeMap.get(FullBackup.SHAREDPREFS_TREE_TOKEN);
+ List<String> sharedPrefDomainIncludes = new ArrayList<String>(
+ includeMap.get(FullBackup.SHAREDPREFS_TREE_TOKEN));
+ Collections.sort(sharedPrefDomainIncludes);
+
assertEquals("Didn't find expected sharedpref domain include.",
- 1, sharedPrefDomainIncludes.size());
+ 3, sharedPrefDomainIncludes.size());
assertEquals("Invalid path parsed for <include/>",
- new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include3.txt")
+ new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include3")
.getCanonicalPath(),
- sharedPrefDomainIncludes.iterator().next());
+ sharedPrefDomainIncludes.get(0));
+ assertEquals("Invalid path parsed for <include/>",
+ new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include3.xml")
+ .getCanonicalPath(),
+ sharedPrefDomainIncludes.get(1));
+ assertEquals("Invalid path parsed for <include/>",
+ new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include4.xml")
+ .getCanonicalPath(),
+ sharedPrefDomainIncludes.get(2));
- assertEquals("Unexpected number of <exclude/>s", 4, excludesSet.size());
+ assertEquals("Unexpected number of <exclude/>s", 6, excludesSet.size());
// Sets are annoying to iterate over b/c order isn't enforced - convert to an array and
// sort lexicographically.
List<String> arrayedSet = new ArrayList<String>(excludesSet);
@@ -173,9 +186,17 @@
new File(mContext.getFilesDir(), "exclude1.txt").getCanonicalPath(),
arrayedSet.get(2));
assertEquals("Invalid path parsed for <exclude/>",
- new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude3.txt")
+ new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude3")
.getCanonicalPath(),
arrayedSet.get(3));
+ assertEquals("Invalid path parsed for <exclude/>",
+ new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude3.xml")
+ .getCanonicalPath(),
+ arrayedSet.get(4));
+ assertEquals("Invalid path parsed for <exclude/>",
+ new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude4.xml")
+ .getCanonicalPath(),
+ arrayedSet.get(5));
}
public void testParseBackupSchemeFromXml_invalidXmlFails() throws Exception {
diff --git a/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java b/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java
new file mode 100644
index 0000000..80181cf
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.content.pm;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+import android.test.AndroidTestCase;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+public class AppsQueryHelperTests extends AndroidTestCase {
+
+ private AppsQueryHelper mAppsQueryHelper;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mAppsQueryHelper = new AppsQueryHelperTestable(getContext());
+ }
+
+ public void testQueryAppsSystemAppsOnly() {
+ List<String> apps = mAppsQueryHelper.queryApps(0, true, UserHandle.SYSTEM);
+ assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app2", "sys_app3"), apps);
+
+ apps = mAppsQueryHelper.queryApps(0, false, UserHandle.SYSTEM);
+ assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app2", "sys_app3", "app4"), apps);
+ }
+
+ public void testQueryAppsNonLaunchable() {
+ List<String> apps = mAppsQueryHelper.queryApps(AppsQueryHelper.GET_NON_LAUNCHABLE_APPS,
+ true, UserHandle.SYSTEM);
+ assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app3"), apps);
+
+ apps = mAppsQueryHelper.queryApps(AppsQueryHelper.GET_NON_LAUNCHABLE_APPS,
+ false, UserHandle.SYSTEM);
+ assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app3"), apps);
+ }
+
+ public void testQueryAppsInteractAcrossUser() {
+ List<String> apps = mAppsQueryHelper.queryApps(
+ AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM, true, UserHandle.SYSTEM);
+ assertEqualsIgnoreOrder(Arrays.asList("sys_app1"), apps);
+
+ apps = mAppsQueryHelper.queryApps(
+ AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM, false, UserHandle.SYSTEM);
+ assertEqualsIgnoreOrder(Arrays.asList("sys_app1"), apps);
+ }
+
+ public void testQueryApps() {
+ List<String> apps = mAppsQueryHelper.queryApps(
+ AppsQueryHelper.GET_NON_LAUNCHABLE_APPS
+ |AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM,
+ true, UserHandle.SYSTEM);
+ assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app3"), apps);
+
+ apps = mAppsQueryHelper.queryApps(
+ AppsQueryHelper.GET_NON_LAUNCHABLE_APPS
+ |AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM,
+ false, UserHandle.SYSTEM);
+ assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app3"), apps);
+ }
+
+ private class AppsQueryHelperTestable extends AppsQueryHelper {
+
+ public AppsQueryHelperTestable(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected List<ApplicationInfo> getAllApps(int userId) {
+ final ApplicationInfo ai1 = new ApplicationInfo();
+ ai1.flags |= ApplicationInfo.FLAG_SYSTEM;
+ ai1.packageName = "sys_app1";
+ final ApplicationInfo ai2 = new ApplicationInfo();
+ ai2.flags |= ApplicationInfo.FLAG_SYSTEM;
+ ai2.packageName = "sys_app2";
+ ai2.flags |= ApplicationInfo.FLAG_SYSTEM;
+ final ApplicationInfo ai3 = new ApplicationInfo();
+ ai3.packageName = "sys_app3";
+ ai3.flags |= ApplicationInfo.FLAG_SYSTEM;
+ final ApplicationInfo ai4 = new ApplicationInfo();
+ ai4.packageName = "app4";
+ return Arrays.asList(ai1, ai2, ai3, ai4);
+ }
+
+ @Override
+ protected List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int userId) {
+ assertEquals(Intent.CATEGORY_LAUNCHER, intent.getCategories().iterator().next());
+ final ResolveInfo r2 = new ResolveInfo();
+ r2.activityInfo = new ActivityInfo();
+ r2.activityInfo.packageName = "sys_app2";
+ r2.activityInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ final ResolveInfo r4 = new ResolveInfo();
+ r4.activityInfo = new ActivityInfo();
+ r4.activityInfo.packageName = "app4";
+ return Arrays.asList(r2, r4);
+ }
+
+ @Override
+ protected List<PackageInfo> getPackagesHoldingPermission(String perm, int userId) {
+ final PackageInfo p1 = new PackageInfo();
+ p1.packageName = "sys_app1";
+ p1.applicationInfo = new ApplicationInfo();
+ p1.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ return Arrays.asList(p1);
+ }
+ }
+
+ private static void assertEqualsIgnoreOrder(List<String> expected, List<String> actual) {
+ assertTrue("Lists not equal. Expected " + expected + " but was " + actual,
+ (expected.size() == actual.size())
+ && (new HashSet<>(expected).equals(new HashSet<>(actual))));
+ }
+}
diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java
index d2e2131..be6e7ea 100644
--- a/core/tests/coretests/src/android/text/format/FormatterTest.java
+++ b/core/tests/coretests/src/android/text/format/FormatterTest.java
@@ -56,14 +56,14 @@
public void testFormatBytes() {
setLocale(Locale.ENGLISH);
- checkFormatBytes(0, true, "0.00", 0);
- checkFormatBytes(0, false, "0.00", 0);
+ checkFormatBytes(0, true, "0", 0);
+ checkFormatBytes(0, false, "0", 0);
- checkFormatBytes(1, true, "1.0", 1);
- checkFormatBytes(1, false, "1.00", 1);
+ checkFormatBytes(1, true, "1", 1);
+ checkFormatBytes(1, false, "1", 1);
checkFormatBytes(12, true, "12", 12);
- checkFormatBytes(12, false, "12.00", 12);
+ checkFormatBytes(12, false, "12", 12);
checkFormatBytes(123, true, "123", 123);
checkFormatBytes(123, false, "123", 123);
@@ -80,13 +80,15 @@
checkFormatBytes(9123000, true, "8.7", 9122611);
checkFormatBytes(9123000, false, "8.70", 9122611);
- // The method doesn't really support negative values, but apparently people pass -1...
- checkFormatBytes(-1, true, "-1.00", -1);
- checkFormatBytes(-1, false, "-1.00", -1);
+ checkFormatBytes(-1, true, "-1", -1);
+ checkFormatBytes(-1, false, "-1", -1);
+
+ checkFormatBytes(-912, true, "-0.89", -911);
+ checkFormatBytes(-912, false, "-0.89", -911);
// Missing FLAG_CALCULATE_ROUNDED case.
BytesResult r = Formatter.formatBytes(getContext().getResources(), 1, 0);
- assertEquals("1.00", r.value);
+ assertEquals("1", r.value);
assertEquals(0, r.roundedBytes); // Didn't pass FLAG_CALCULATE_ROUNDED
// Make sure it works on different locales.
diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
new file mode 100644
index 0000000..e5d5542
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.Selection;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.TextPaint;
+import android.text.style.SuggestionSpan;
+import android.text.style.TextAppearanceSpan;
+
+import com.android.frameworks.coretests.R;
+
+/**
+ * SuggestionsPopupWindowTest tests.
+ */
+public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2<TextViewActivity> {
+
+ public SuggestionsPopupWindowTest() {
+ super(TextViewActivity.class);
+ }
+
+ @SmallTest
+ public void testTextAndAppearanceInSuggestionsPopup() {
+ final Activity activity = getActivity();
+
+ final String sampleText = "abc def ghi";
+ final String[] candidate = {"DEF", "Def"};
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(activity, candidate,
+ SuggestionSpan.FLAG_AUTO_CORRECTION);
+ final int spanStart = 4;
+ final int spanEnd = 7;
+ TextAppearanceSpan expectedSpan = new TextAppearanceSpan(activity,
+ android.R.style.TextAppearance_SuggestionHighlight);
+ TextPaint tmpTp = new TextPaint();
+ expectedSpan.updateDrawState(tmpTp);
+ final int expectedHighlightTextColor = tmpTp.getColor();
+ final float expectedHighlightTextSize = tmpTp.getTextSize();
+
+ // Create and wait until SuggestionsPopupWindow is shown.
+ final EditText editText = (EditText) activity.findViewById(R.id.textview);
+ final Editor editor = editText.getEditorForTesting();
+ assertNotNull(editor);
+ activity.runOnUiThread(new Runnable() {
+ public void run() {
+ SpannableStringBuilder ssb = new SpannableStringBuilder();
+ ssb.append(sampleText);
+ ssb.setSpan(suggestionSpan, spanStart, spanEnd, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ editText.setText(ssb);
+
+ Selection.setSelection(editText.getText(), spanStart, spanEnd);
+ editText.onTextContextMenuItem(TextView.ID_REPLACE);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ // In this test, the SuggestionsPopupWindow looks like
+ // abc def ghi
+ // ----------
+ // | *DEF* |
+ // | *Def* |
+ // | DELETE |
+ // ----------
+ // *XX* means that XX is highlighted.
+ activity.runOnUiThread(new Runnable() {
+ public void run() {
+ Editor.SuggestionsPopupWindow popupWindow =
+ editor.getSuggestionsPopupWindowForTesting();
+ assertNotNull(popupWindow);
+
+ ListView listView = (ListView) popupWindow.getContentViewForTesting();
+ assertNotNull(listView);
+
+ int childNum = listView.getChildCount();
+ // +1 for "DELETE" command.
+ assertEquals(candidate.length + 1, childNum);
+
+ for (int i = 0; i < candidate.length; ++i) {
+ TextView textView = (TextView) listView.getChildAt(i);
+ assertNotNull(textView);
+
+ Spanned spanned = (Spanned) textView.getText();
+ assertNotNull(spanned);
+
+ // Check that the suggestion item order is kept.
+ assertEquals(candidate[i], spanned.toString());
+
+ // Check that the text is highlighted with correct color and text size.
+ TextAppearanceSpan[] taSpan = spanned.getSpans(0, candidate[i].length(),
+ TextAppearanceSpan.class);
+ assertEquals(1, taSpan.length);
+ TextPaint tp = new TextPaint();
+ taSpan[0].updateDrawState(tp);
+ assertEquals(expectedHighlightTextColor, tp.getColor());
+ assertEquals(expectedHighlightTextSize, tp.getTextSize());
+ }
+ }
+ });
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 0b94f8b..49d9115 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -18,7 +18,7 @@
import android.app.Activity;
import android.content.Intent;
-import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.GetChars;
import android.text.Selection;
@@ -27,11 +27,15 @@
/**
* TextViewTest tests {@link TextView}.
*/
-public class TextViewTest extends AndroidTestCase {
+public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActivity> {
+
+ public TextViewTest() {
+ super(TextViewActivity.class);
+ }
@SmallTest
public void testArray() throws Exception {
- TextView tv = new TextView(mContext);
+ TextView tv = new TextView(getActivity());
char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ',
'W', 'o', 'r', 'l', 'd', '!' };
@@ -59,25 +63,34 @@
assertEquals('\0', c2[5]);
}
+ @SmallTest
public void testProcessTextActivityResultNonEditable() {
- TextView tv = new TextView(mContext);
+ final TextView tv = new TextView(getActivity());
CharSequence originalText = "This is some text.";
tv.setText(originalText, TextView.BufferType.SPANNABLE);
assertEquals(originalText, tv.getText().toString());
tv.setTextIsSelectable(true);
Selection.setSelection((Spannable) tv.getText(), 0, tv.getText().length());
- CharSequence newText = "Text is replaced.";
- Intent data = new Intent();
- data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
- tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
+ // We need to run this in the UI thread, as it will create a Toast.
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ CharSequence newText = "Text is replaced.";
+ Intent data = new Intent();
+ data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
+ tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
// This is a TextView, which can't be modified. Hence no change should have been made.
assertEquals(originalText, tv.getText().toString());
}
+ @SmallTest
public void testProcessTextActivityResultEditable() {
- EditText tv = new EditText(mContext);
+ EditText tv = new EditText(getActivity());
CharSequence originalText = "This is some text.";
tv.setText(originalText, TextView.BufferType.SPANNABLE);
assertEquals(originalText, tv.getText().toString());
@@ -92,8 +105,9 @@
assertEquals(newText, tv.getText().toString());
}
+ @SmallTest
public void testProcessTextActivityResultCancel() {
- EditText tv = new EditText(mContext);
+ EditText tv = new EditText(getActivity());
CharSequence originalText = "This is some text.";
tv.setText(originalText, TextView.BufferType.SPANNABLE);
assertEquals(originalText, tv.getText().toString());
@@ -108,8 +122,9 @@
assertEquals(originalText, tv.getText().toString());
}
+ @SmallTest
public void testProcessTextActivityNoData() {
- EditText tv = new EditText(mContext);
+ EditText tv = new EditText(getActivity());
CharSequence originalText = "This is some text.";
tv.setText(originalText, TextView.BufferType.SPANNABLE);
assertEquals(originalText, tv.getText().toString());
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 350310c..27c6620 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -143,4 +143,7 @@
access while in power save mode, even if they aren't in the foreground. -->
<allow-in-power-save-except-idle package="com.android.providers.downloads" />
+ <!-- These are the packages that shouldn't run as system user -->
+ <system-user-blacklisted-app package="com.android.wallpaper.livepicker" />
+ <system-user-blacklisted-app package="com.android.settings" />
</permissions>
diff --git a/docs/html/design/media/wear/1-tap-launch.png b/docs/html/design/media/wear/1-tap-launch.png
new file mode 100644
index 0000000..c0c9aca
--- /dev/null
+++ b/docs/html/design/media/wear/1-tap-launch.png
Binary files differ
diff --git a/docs/html/design/media/wear/2-tap-launch.png b/docs/html/design/media/wear/2-tap-launch.png
new file mode 100644
index 0000000..395a3ce
--- /dev/null
+++ b/docs/html/design/media/wear/2-tap-launch.png
Binary files differ
diff --git a/docs/html/design/media/wear/aesthetic.png b/docs/html/design/media/wear/aesthetic.png
new file mode 100644
index 0000000..f6e5f3e
--- /dev/null
+++ b/docs/html/design/media/wear/aesthetic.png
Binary files differ
diff --git a/docs/html/design/media/wear/available_gestures.png b/docs/html/design/media/wear/available_gestures.png
new file mode 100644
index 0000000..677076b
--- /dev/null
+++ b/docs/html/design/media/wear/available_gestures.png
Binary files differ
diff --git a/docs/html/design/media/wear/available_gestures_2x.png b/docs/html/design/media/wear/available_gestures_2x.png
new file mode 100644
index 0000000..eced0c7
--- /dev/null
+++ b/docs/html/design/media/wear/available_gestures_2x.png
Binary files differ
diff --git a/docs/html/design/media/wear/changing-target.png b/docs/html/design/media/wear/changing-target.png
new file mode 100644
index 0000000..427531f
--- /dev/null
+++ b/docs/html/design/media/wear/changing-target.png
Binary files differ
diff --git a/docs/html/design/media/wear/revealing-info.png b/docs/html/design/media/wear/revealing-info.png
new file mode 100644
index 0000000..e419e9f
--- /dev/null
+++ b/docs/html/design/media/wear/revealing-info.png
Binary files differ
diff --git a/docs/html/design/media/wear/toggling-states.png b/docs/html/design/media/wear/toggling-states.png
new file mode 100644
index 0000000..93398e6
--- /dev/null
+++ b/docs/html/design/media/wear/toggling-states.png
Binary files differ
diff --git a/docs/html/design/media/wear/visual_feedback.gif b/docs/html/design/media/wear/visual_feedback.gif
new file mode 100644
index 0000000..e07000a
--- /dev/null
+++ b/docs/html/design/media/wear/visual_feedback.gif
Binary files differ
diff --git a/docs/html/design/wear/watchfaces.jd b/docs/html/design/wear/watchfaces.jd
index e018523..c8c6d5a 100644
--- a/docs/html/design/wear/watchfaces.jd
+++ b/docs/html/design/wear/watchfaces.jd
@@ -288,6 +288,107 @@
with an actual watch screen before you start coding.</p>
+<h2 id="interactive">Design Interactive Watch Faces</h2>
+
+<p>Your watch face can respond to a single-tap gesture from the user, as long as
+there’s not another UI element that also responds to that gesture. Some possible use cases for
+interacting with the watch face include:</p>
+
+<ul>
+ <li><strong>Causing an aesthetic change</strong> on the watch face, for example inverting
+ the color scheme.</li>
+ <li><strong>Showing more information</strong> inline on the watch face, for example displaying a
+ detailed step count.</li>
+ <li><strong>Completing an action</strong> inline or in the background, for example starting a
+ timer.</li>
+ <li><strong>Launching a specific activity,</strong> for example a starting a conversation in a
+ messaging application.</li>
+</ul>
+
+<h3 id="ag">Available gestures</h3>
+<p>Only single taps are available. This restriction is important for maintaining clear and
+consistent system interactions, and for making watch face interactions as simple as
+possible: Neither you nor the user should think of watch faces as full-fledged apps. Figure 1
+summarizes the categories of gestures, and their uses.</p>
+
+<img src="{@docRoot}design/media/wear/available_gestures.png"
+srcset="{@docRoot}design/media/wear/available_gestures.png 1x,
+{@docRoot}design/media/wear/available_gestures_2x.png 2x"
+alt="Single tap is the only available gesture." width="740" height="" id="available-gestures" />
+<p class="img-caption">
+ <strong>Figure 1.</strong> Available, reserved, and blocked gestures.
+</p>
+
+As a rule, watch-face interaction should be lightweight, with the user completing their desired
+action within one or two touches.
+
+<h3>Tap targets</h3>
+
+<p>If you want to cause a simple state change on the watch face, such as a purely aesthetic
+change, you can use the entire canvas of the watch face as the tap target.</p>
+
+<p>For a more significant change or action, such as launching an activity or sending a message to a
+friend, it’s important to keep targets smaller, between 48-90 dpi, to avoid false-positive taps.
+There should be a gap between targets of at least 8-16 dpi. For an optimized tappable experience,
+display a maximum of 7 to 9 targets at once.</p>
+
+<h3 id=”areas”>Tap regions</h3>
+
+<p>You can also use different regions of the screen to trigger different changes to the watch face.
+For example, tapping on the entire canvas could toggle states for the entire face. Tapping a specific target
+could produce an inline display of information related to the target. Last, tapping outside the
+target could restore the watch face to its default state.</p>
+
+<div style="float:right;margin-bottom:20px;margin-left:20px">
+ <img src="/design/media/wear/visual_feedback.gif" width="200"
+ height="196" alt="The watch face should show where the user’s finger has made contact." style="margin-top:-10px;margin-left:13px">
+</div>
+
+
+<h3>Visual feedback</h3>
+
+<p>Provide visual feedback when the user’s finger touches down on the watch face. The tap
+event does not trigger until the user lifts their finger, but visual feedback on touchdown helps
+indicate that the system has received the touch, and also helps the user know where the touch
+landed.</p>
+
+<p class=”warning”><strong>Warning:</strong> Do not immediately launch a UI on touchdown. A UI that
+you launch on touchdown conflicts with gestures for interacting with system UI elements including
+the watch face picker, notification stream, settings shade, and app launcher.</p>
+
+<h3>Design examples</h3>
+
+Here are some examples of approaches for interactive watch faces:
+
+<h4>Applying an aesthetic change</h4>
+
+<img src="{@docRoot}design/media/wear/aesthetic.png"
+alt="" width="686" height="" id="descriptive-id" />
+
+<h4>Toggling states</h4>
+
+<img src="{@docRoot}design/media/wear/toggling-states.png"
+alt="" width="686" height="" id="descriptive-id" />
+
+<h4>Changing a targeted UI element</h4>
+
+<img src="{@docRoot}design/media/wear/changing-target.png"
+alt="" width="686" height="" id="descriptive-id" />
+
+<h4>Revealing information inline</h4>
+
+<img src="{@docRoot}design/media/wear/revealing-info.png"
+alt="" width="686" height="" id="descriptive-id" />
+
+<h4>Launching an activity with a single tap</h4>
+
+<img src="{@docRoot}design/media/wear/1-tap-launch.png"
+alt="" width="751" height="" id="descriptive-id" />
+
+<h4>Launching an activity with two taps</h4>
+
+<img src="{@docRoot}design/media/wear/2-tap-launch.png"
+alt="" width="751" height="" id="descriptive-id" />
<h2 id="CompanionApp">Support the Android Wear Companion App</h2>
diff --git a/docs/html/images/training/auto-desktop-head-unit-context-menu-enabled.png b/docs/html/images/training/auto-desktop-head-unit-context-menu-enabled.png
new file mode 100644
index 0000000..99e60e9
--- /dev/null
+++ b/docs/html/images/training/auto-desktop-head-unit-context-menu-enabled.png
Binary files differ
diff --git a/docs/html/images/training/auto-desktop-head-unit-launch.png b/docs/html/images/training/auto-desktop-head-unit-launch.png
new file mode 100644
index 0000000..012857a4
--- /dev/null
+++ b/docs/html/images/training/auto-desktop-head-unit-launch.png
Binary files differ
diff --git a/docs/html/images/training/auto-desktop-head-unit-server-running.png b/docs/html/images/training/auto-desktop-head-unit-server-running.png
new file mode 100644
index 0000000..5aa3b83
--- /dev/null
+++ b/docs/html/images/training/auto-desktop-head-unit-server-running.png
Binary files differ
diff --git a/docs/html/images/training/auto-desktop-head-unit-wkst-launch.png b/docs/html/images/training/auto-desktop-head-unit-wkst-launch.png
new file mode 100644
index 0000000..4d48ac4
--- /dev/null
+++ b/docs/html/images/training/auto-desktop-head-unit-wkst-launch.png
Binary files differ
diff --git a/docs/html/preview/features/runtime-permissions.jd b/docs/html/preview/features/runtime-permissions.jd
index 8ab7619..62e49b9 100644
--- a/docs/html/preview/features/runtime-permissions.jd
+++ b/docs/html/preview/features/runtime-permissions.jd
@@ -916,8 +916,11 @@
</dt>
<dd>
- Returns <code>true</code> if the app has the specified permission, whether
- or not the device is using the M Preview.
+ Returns {@link android.content.pm.PackageManager#PERMISSION_GRANTED
+ PERMISSION_GRANTED} if the app has the specified permission, whether
+ or not the device is using the M Preview. If the app does not have the
+ specified permission, returns {@link
+ android.content.pm.PackageManager#PERMISSION_DENIED PERMISSION_DENIED}.
</dd>
<dt>
diff --git a/docs/html/reference/android/support/wearable/R.anim.html b/docs/html/reference/android/support/wearable/R.anim.html
index 11d766d..8976afe 100644
--- a/docs/html/reference/android/support/wearable/R.anim.html
+++ b/docs/html/reference/android/support/wearable/R.anim.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1322,6 +1323,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.animator.html b/docs/html/reference/android/support/wearable/R.animator.html
index 9fa6445..7ab63f2 100644
--- a/docs/html/reference/android/support/wearable/R.animator.html
+++ b/docs/html/reference/android/support/wearable/R.animator.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1134,6 +1135,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.attr.html b/docs/html/reference/android/support/wearable/R.attr.html
index 1f043a2..099c981 100644
--- a/docs/html/reference/android/support/wearable/R.attr.html
+++ b/docs/html/reference/android/support/wearable/R.attr.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -697,6 +698,23 @@
static
int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#buttonRippleColor">buttonRippleColor</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+
+ int</nobr></td>
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#circle_border_color">circle_border_color</a></td>
<td class="jd-descrcol" width="100%">
<p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
@@ -708,7 +726,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -724,7 +742,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -741,7 +759,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -757,7 +775,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -773,7 +791,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -789,7 +807,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -805,7 +823,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -821,6 +839,23 @@
</tr>
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+
+ int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#color_sequence">color_sequence</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+
+
+
+ </td>
+ </tr>
+
+
<tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
@@ -1054,6 +1089,55 @@
static
int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#image_circle_percentage">image_circle_percentage</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+
+ int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#image_horizontal_offcenter_percentage">image_horizontal_offcenter_percentage</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+
+ int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#image_tint">image_tint</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+
+ int</nobr></td>
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#layout_box">layout_box</a></td>
<td class="jd-descrcol" width="100%">
<p>Must be one or more (separated by '|') of the following constant values.
@@ -1064,7 +1148,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1080,7 +1164,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1096,7 +1180,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1112,7 +1196,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1128,7 +1212,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1144,7 +1228,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1160,7 +1244,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1176,7 +1260,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1192,7 +1276,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1208,7 +1292,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1224,13 +1308,13 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
int</nobr></td>
- <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#pressedTranslationZ">pressedTranslationZ</a></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#pressedButtonTranslationZ">pressedButtonTranslationZ</a></td>
<td class="jd-descrcol" width="100%">
<p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
@@ -1240,7 +1324,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1257,23 +1341,6 @@
</tr>
- <tr class=" api apilevel-" >
- <td class="jd-typecol"><nobr>
- public
- static
-
- int</nobr></td>
- <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#rippleColor">rippleColor</a></td>
- <td class="jd-descrcol" width="100%">
- <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
-or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
-
-
-
- </td>
- </tr>
-
-
<tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
@@ -1605,6 +1672,41 @@
+<A NAME="buttonRippleColor"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ buttonRippleColor
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+</p></div>
+
+
+ </div>
+</div>
+
+
+
<A NAME="circle_border_color"></A>
<div class="jd-details api apilevel-">
@@ -1921,6 +2023,41 @@
+<A NAME="color_sequence"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ color_sequence
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+</p></div>
+
+
+ </div>
+</div>
+
+
+
<A NAME="dotColor"></A>
<div class="jd-details api apilevel-">
@@ -2457,6 +2594,122 @@
+<A NAME="image_circle_percentage"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ image_circle_percentage
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+</p></div>
+
+
+ </div>
+</div>
+
+
+
+<A NAME="image_horizontal_offcenter_percentage"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ image_horizontal_offcenter_percentage
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+</p></div>
+
+
+ </div>
+</div>
+
+
+
+<A NAME="image_tint"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ image_tint
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+</p></div>
+
+
+ </div>
+</div>
+
+
+
<A NAME="layout_box"></A>
<div class="jd-details api apilevel-">
@@ -2903,7 +3156,7 @@
-<A NAME="pressedTranslationZ"></A>
+<A NAME="pressedButtonTranslationZ"></A>
<div class="jd-details api apilevel-">
<h4 class="jd-details-title">
@@ -2913,7 +3166,7 @@
int
</span>
- pressedTranslationZ
+ pressedButtonTranslationZ
</h4>
<div class="api-level">
@@ -2975,41 +3228,6 @@
-<A NAME="rippleColor"></A>
-
-<div class="jd-details api apilevel-">
- <h4 class="jd-details-title">
- <span class="normal">
- public
- static
-
- int
- </span>
- rippleColor
- </h4>
- <div class="api-level">
-
-
-
-
- </div>
- <div class="jd-details-descr">
-
-
-
-
- <div class="jd-tagdata jd-tagdescr"><p><p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
-or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
-<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
-"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
-</p></div>
-
-
- </div>
-</div>
-
-
-
<A NAME="roundLayout"></A>
<div class="jd-details api apilevel-">
@@ -3233,6 +3451,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.color.html b/docs/html/reference/android/support/wearable/R.color.html
index cdfd0a8..07b5e0c 100644
--- a/docs/html/reference/android/support/wearable/R.color.html
+++ b/docs/html/reference/android/support/wearable/R.color.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -2450,6 +2451,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.dimen.html b/docs/html/reference/android/support/wearable/R.dimen.html
index c24ef8d..215b2b3 100644
--- a/docs/html/reference/android/support/wearable/R.dimen.html
+++ b/docs/html/reference/android/support/wearable/R.dimen.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1839,6 +1840,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.drawable.html b/docs/html/reference/android/support/wearable/R.drawable.html
index 167c8ab..c83cd2e 100644
--- a/docs/html/reference/android/support/wearable/R.drawable.html
+++ b/docs/html/reference/android/support/wearable/R.drawable.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1557,6 +1558,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.html b/docs/html/reference/android/support/wearable/R.html
index fd87f79..714f287 100644
--- a/docs/html/reference/android/support/wearable/R.html
+++ b/docs/html/reference/android/support/wearable/R.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -717,7 +718,7 @@
class</nobr></td>
- <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></td>
<td class="jd-descrcol" width="100%">
@@ -734,6 +735,23 @@
class</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></td>
+ <td class="jd-descrcol" width="100%">
+
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+ class</nobr></td>
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></td>
<td class="jd-descrcol" width="100%">
@@ -744,7 +762,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -761,7 +779,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -778,7 +796,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -795,7 +813,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -812,7 +830,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -829,7 +847,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -846,7 +864,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -863,7 +881,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1283,6 +1301,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.id.html b/docs/html/reference/android/support/wearable/R.id.html
index 2b3db85..c6bad3b 100644
--- a/docs/html/reference/android/support/wearable/R.id.html
+++ b/docs/html/reference/android/support/wearable/R.id.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -2262,6 +2263,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.interpolator.html b/docs/html/reference/android/support/wearable/R.interpolator.html
index ae6cac1..01391a8 100644
--- a/docs/html/reference/android/support/wearable/R.interpolator.html
+++ b/docs/html/reference/android/support/wearable/R.interpolator.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1369,6 +1370,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.layout.html b/docs/html/reference/android/support/wearable/R.layout.html
index 7a87cf2..4987ba7 100644
--- a/docs/html/reference/android/support/wearable/R.layout.html
+++ b/docs/html/reference/android/support/wearable/R.layout.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1275,6 +1276,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.string.html b/docs/html/reference/android/support/wearable/R.string.html
index 3d13614..c8707ef 100644
--- a/docs/html/reference/android/support/wearable/R.string.html
+++ b/docs/html/reference/android/support/wearable/R.string.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1134,6 +1135,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.style.html b/docs/html/reference/android/support/wearable/R.style.html
index 48837d0..38ce308 100644
--- a/docs/html/reference/android/support/wearable/R.style.html
+++ b/docs/html/reference/android/support/wearable/R.style.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -2262,6 +2263,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.styleable.html b/docs/html/reference/android/support/wearable/R.styleable.html
index d1e4ca3..e43e070 100644
--- a/docs/html/reference/android/support/wearable/R.styleable.html
+++ b/docs/html/reference/android/support/wearable/R.styleable.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -473,6 +473,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1137,6 +1138,23 @@
static
int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_buttonRippleColor">ActionPage_buttonRippleColor</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#buttonRippleColor">buttonRippleColor</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+
+ int</nobr></td>
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_imageScaleMode">ActionPage_imageScaleMode</a></td>
<td class="jd-descrcol" width="100%">
<p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#imageScaleMode">imageScaleMode</a></code>
@@ -1148,7 +1166,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1165,7 +1183,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1182,32 +1200,15 @@
</tr>
- <tr class=" api apilevel-" >
- <td class="jd-typecol"><nobr>
- public
- static
-
- int</nobr></td>
- <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedTranslationZ">ActionPage_pressedTranslationZ</a></td>
- <td class="jd-descrcol" width="100%">
- <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedTranslationZ">pressedTranslationZ</a></code>
- attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
-
-
-
- </td>
- </tr>
-
-
<tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
int</nobr></td>
- <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_rippleColor">ActionPage_rippleColor</a></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedButtonTranslationZ">ActionPage_pressedButtonTranslationZ</a></td>
<td class="jd-descrcol" width="100%">
- <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#rippleColor">rippleColor</a></code>
+ <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedButtonTranslationZ">pressedButtonTranslationZ</a></code>
attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
@@ -1390,6 +1391,57 @@
static
int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_circle_percentage">CircledImageView_image_circle_percentage</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_circle_percentage">image_circle_percentage</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+
+ int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_horizontal_offcenter_percentage">CircledImageView_image_horizontal_offcenter_percentage</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_horizontal_offcenter_percentage">image_horizontal_offcenter_percentage</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+
+ int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_tint">CircledImageView_image_tint</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_tint">image_tint</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+
+ int</nobr></td>
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_shadow_width">CircledImageView_shadow_width</a></td>
<td class="jd-descrcol" width="100%">
<p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#shadow_width">shadow_width</a></code>
@@ -1401,7 +1453,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1417,7 +1469,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1434,7 +1486,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1451,7 +1503,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1468,7 +1520,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1485,6 +1537,23 @@
</tr>
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+
+ int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_buttonRippleColor">CircularButton_buttonRippleColor</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#buttonRippleColor">buttonRippleColor</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
+
+
+
+ </td>
+ </tr>
+
+
<tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
@@ -1508,9 +1577,9 @@
static
int</nobr></td>
- <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedTranslationZ">CircularButton_pressedTranslationZ</a></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedButtonTranslationZ">CircularButton_pressedButtonTranslationZ</a></td>
<td class="jd-descrcol" width="100%">
- <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedTranslationZ">pressedTranslationZ</a></code>
+ <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedButtonTranslationZ">pressedButtonTranslationZ</a></code>
attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
@@ -1523,23 +1592,6 @@
<td class="jd-typecol"><nobr>
public
static
-
- int</nobr></td>
- <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_rippleColor">CircularButton_rippleColor</a></td>
- <td class="jd-descrcol" width="100%">
- <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#rippleColor">rippleColor</a></code>
- attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
-
-
-
- </td>
- </tr>
-
-
- <tr class="alt-color api apilevel-" >
- <td class="jd-typecol"><nobr>
- public
- static
final
int[]</nobr></td>
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#DelayedConfirmationView">DelayedConfirmationView</a></td>
@@ -1552,7 +1604,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1569,7 +1621,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1585,7 +1637,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1602,7 +1654,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1619,7 +1671,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1636,7 +1688,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1653,7 +1705,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1670,7 +1722,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1687,7 +1739,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1704,7 +1756,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1721,7 +1773,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1738,7 +1790,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1755,7 +1807,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1772,7 +1824,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1789,7 +1841,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1806,10 +1858,43 @@
</tr>
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
+ final
+ int[]</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner">ProgressSpinner</a></td>
+ <td class="jd-descrcol" width="100%">
+ Attributes that can be used with a ProgressSpinner.
+
+
+
+ </td>
+ </tr>
+
+
<tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
+
+ int</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner_color_sequence">ProgressSpinner_color_sequence</a></td>
+ <td class="jd-descrcol" width="100%">
+ <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#color_sequence">color_sequence</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner">ProgressSpinner</a></code> array.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+ public
+ static
final
int[]</nobr></td>
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#WatchViewStub">WatchViewStub</a></td>
@@ -1822,7 +1907,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1839,7 +1924,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1856,7 +1941,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1872,7 +1957,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1889,7 +1974,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1906,7 +1991,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1923,7 +2008,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1940,7 +2025,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1957,7 +2042,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1974,7 +2059,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -1991,7 +2076,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -2008,7 +2093,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -2025,7 +2110,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -2042,7 +2127,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -2059,7 +2144,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -2076,7 +2161,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -2092,7 +2177,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -2109,7 +2194,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
public
static
@@ -2875,15 +2960,15 @@
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textColor">android:textColor</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textStyle">android:textStyle</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_typeface">android:typeface</a></code></code></td><td></td></tr>
+ <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_buttonRippleColor">android.support.wearable:buttonRippleColor</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_imageScaleMode">android.support.wearable:imageScaleMode</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_maxTextSize">android.support.wearable:maxTextSize</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_minTextSize">android.support.wearable:minTextSize</a></code></code></td><td></td></tr>
- <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedTranslationZ">android.support.wearable:pressedTranslationZ</a></code></code></td><td></td></tr>
- <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_rippleColor">android.support.wearable:rippleColor</a></code></code></td><td></td></tr>
+ <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedButtonTranslationZ">android.support.wearable:pressedButtonTranslationZ</a></code></code></td><td></td></tr>
</table></p></div>
<div class="jd-tagdata">
<h5 class="jd-tagtitle">See Also</h5>
- <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_color">ActionPage_android_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_elevation">ActionPage_android_elevation</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_fontFamily">ActionPage_android_fontFamily</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_gravity">ActionPage_android_gravity</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_lineSpacingExtra">ActionPage_android_lineSpacingExtra</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_lineSpacingMultiplier">ActionPage_android_lineSpacingMultiplier</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_maxLines">ActionPage_android_maxLines</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_src">ActionPage_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_stateListAnimator">ActionPage_android_stateListAnimator</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_text">ActionPage_android_text</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textColor">ActionPage_android_textColor</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textStyle">ActionPage_android_textStyle</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_typeface">ActionPage_android_typeface</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_imageScaleMode">ActionPage_imageScaleMode</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_maxTextSize">ActionPage_maxTextSize</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_minTextSize">ActionPage_minTextSize</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedTranslationZ">ActionPage_pressedTranslationZ</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_rippleColor">ActionPage_rippleColor</a></code></li>
+ <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_color">ActionPage_android_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_elevation">ActionPage_android_elevation</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_fontFamily">ActionPage_android_fontFamily</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_gravity">ActionPage_android_gravity</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_lineSpacingExtra">ActionPage_android_lineSpacingExtra</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_lineSpacingMultiplier">ActionPage_android_lineSpacingMultiplier</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_maxLines">ActionPage_android_maxLines</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_src">ActionPage_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_stateListAnimator">ActionPage_android_stateListAnimator</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_text">ActionPage_android_text</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textColor">ActionPage_android_textColor</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textStyle">ActionPage_android_textStyle</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_typeface">ActionPage_android_typeface</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_buttonRippleColor">ActionPage_buttonRippleColor</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_imageScaleMode">ActionPage_imageScaleMode</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_maxTextSize">ActionPage_maxTextSize</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_minTextSize">ActionPage_minTextSize</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedButtonTranslationZ">ActionPage_pressedButtonTranslationZ</a></code></li>
</ul>
</div>
@@ -3309,6 +3394,44 @@
+<A NAME="ActionPage_buttonRippleColor"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ ActionPage_buttonRippleColor
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#buttonRippleColor">buttonRippleColor</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
+
+
+ <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".</p></div>
+
+
+ </div>
+</div>
+
+
+
<A NAME="ActionPage_imageScaleMode"></A>
<div class="jd-details api apilevel-">
@@ -3436,7 +3559,7 @@
-<A NAME="ActionPage_pressedTranslationZ"></A>
+<A NAME="ActionPage_pressedButtonTranslationZ"></A>
<div class="jd-details api apilevel-">
<h4 class="jd-details-title">
@@ -3446,7 +3569,7 @@
int
</span>
- ActionPage_pressedTranslationZ
+ ActionPage_pressedButtonTranslationZ
</h4>
<div class="api-level">
@@ -3459,7 +3582,7 @@
- <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedTranslationZ">pressedTranslationZ</a></code>
+ <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedButtonTranslationZ">pressedButtonTranslationZ</a></code>
attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
@@ -3478,44 +3601,6 @@
-<A NAME="ActionPage_rippleColor"></A>
-
-<div class="jd-details api apilevel-">
- <h4 class="jd-details-title">
- <span class="normal">
- public
- static
-
- int
- </span>
- ActionPage_rippleColor
- </h4>
- <div class="api-level">
-
-
-
-
- </div>
- <div class="jd-details-descr">
-
-
-
-
- <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#rippleColor">rippleColor</a></code>
- attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
-
-
- <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
-or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
-<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
-"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".</p></div>
-
-
- </div>
-</div>
-
-
-
<A NAME="BoxInsetLayout_Layout"></A>
<div class="jd-details api apilevel-">
@@ -3641,11 +3726,14 @@
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_padding">android.support.wearable:circle_padding</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius">android.support.wearable:circle_radius</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius_pressed">android.support.wearable:circle_radius_pressed</a></code></code></td><td></td></tr>
+ <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_circle_percentage">android.support.wearable:image_circle_percentage</a></code></code></td><td></td></tr>
+ <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_horizontal_offcenter_percentage">android.support.wearable:image_horizontal_offcenter_percentage</a></code></code></td><td></td></tr>
+ <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_tint">android.support.wearable:image_tint</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_shadow_width">android.support.wearable:shadow_width</a></code></code></td><td></td></tr>
</table></p></div>
<div class="jd-tagdata">
<h5 class="jd-tagtitle">See Also</h5>
- <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_android_src">CircledImageView_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_border_color">CircledImageView_circle_border_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_border_width">CircledImageView_circle_border_width</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_color">CircledImageView_circle_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_padding">CircledImageView_circle_padding</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius">CircledImageView_circle_radius</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius_pressed">CircledImageView_circle_radius_pressed</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_shadow_width">CircledImageView_shadow_width</a></code></li>
+ <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_android_src">CircledImageView_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_border_color">CircledImageView_circle_border_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_border_width">CircledImageView_circle_border_width</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_color">CircledImageView_circle_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_padding">CircledImageView_circle_padding</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius">CircledImageView_circle_radius</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius_pressed">CircledImageView_circle_radius_pressed</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_circle_percentage">CircledImageView_image_circle_percentage</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_horizontal_offcenter_percentage">CircledImageView_image_horizontal_offcenter_percentage</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_tint">CircledImageView_image_tint</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_shadow_width">CircledImageView_shadow_width</a></code></li>
</ul>
</div>
@@ -3937,6 +4025,131 @@
+<A NAME="CircledImageView_image_circle_percentage"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ CircledImageView_image_circle_percentage
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_circle_percentage">image_circle_percentage</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+
+
+ <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.</p></div>
+
+
+ </div>
+</div>
+
+
+
+<A NAME="CircledImageView_image_horizontal_offcenter_percentage"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ CircledImageView_image_horizontal_offcenter_percentage
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_horizontal_offcenter_percentage">image_horizontal_offcenter_percentage</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+
+
+ <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.</p></div>
+
+
+ </div>
+</div>
+
+
+
+<A NAME="CircledImageView_image_tint"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ CircledImageView_image_tint
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_tint">image_tint</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+
+
+ <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.</p></div>
+
+
+ </div>
+</div>
+
+
+
<A NAME="CircledImageView_shadow_width"></A>
<div class="jd-details api apilevel-">
@@ -4012,13 +4225,13 @@
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_elevation">android:elevation</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_src">android:src</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_stateListAnimator">android:stateListAnimator</a></code></code></td><td></td></tr>
+ <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_buttonRippleColor">android.support.wearable:buttonRippleColor</a></code></code></td><td></td></tr>
<tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_imageScaleMode">android.support.wearable:imageScaleMode</a></code></code></td><td></td></tr>
- <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedTranslationZ">android.support.wearable:pressedTranslationZ</a></code></code></td><td></td></tr>
- <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_rippleColor">android.support.wearable:rippleColor</a></code></code></td><td></td></tr>
+ <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedButtonTranslationZ">android.support.wearable:pressedButtonTranslationZ</a></code></code></td><td></td></tr>
</table></p></div>
<div class="jd-tagdata">
<h5 class="jd-tagtitle">See Also</h5>
- <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_color">CircularButton_android_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_elevation">CircularButton_android_elevation</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_src">CircularButton_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_stateListAnimator">CircularButton_android_stateListAnimator</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_imageScaleMode">CircularButton_imageScaleMode</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedTranslationZ">CircularButton_pressedTranslationZ</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_rippleColor">CircularButton_rippleColor</a></code></li>
+ <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_color">CircularButton_android_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_elevation">CircularButton_android_elevation</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_src">CircularButton_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_stateListAnimator">CircularButton_android_stateListAnimator</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_buttonRippleColor">CircularButton_buttonRippleColor</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_imageScaleMode">CircularButton_imageScaleMode</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedButtonTranslationZ">CircularButton_pressedButtonTranslationZ</a></code></li>
</ul>
</div>
@@ -4156,6 +4369,44 @@
+<A NAME="CircularButton_buttonRippleColor"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ CircularButton_buttonRippleColor
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#buttonRippleColor">buttonRippleColor</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
+
+
+ <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".</p></div>
+
+
+ </div>
+</div>
+
+
+
<A NAME="CircularButton_imageScaleMode"></A>
<div class="jd-details api apilevel-">
@@ -4199,7 +4450,7 @@
-<A NAME="CircularButton_pressedTranslationZ"></A>
+<A NAME="CircularButton_pressedButtonTranslationZ"></A>
<div class="jd-details api apilevel-">
<h4 class="jd-details-title">
@@ -4209,7 +4460,7 @@
int
</span>
- CircularButton_pressedTranslationZ
+ CircularButton_pressedButtonTranslationZ
</h4>
<div class="api-level">
@@ -4222,7 +4473,7 @@
- <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedTranslationZ">pressedTranslationZ</a></code>
+ <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedButtonTranslationZ">pressedButtonTranslationZ</a></code>
attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
@@ -4241,44 +4492,6 @@
-<A NAME="CircularButton_rippleColor"></A>
-
-<div class="jd-details api apilevel-">
- <h4 class="jd-details-title">
- <span class="normal">
- public
- static
-
- int
- </span>
- CircularButton_rippleColor
- </h4>
- <div class="api-level">
-
-
-
-
- </div>
- <div class="jd-details-descr">
-
-
-
-
- <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#rippleColor">rippleColor</a></code>
- attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
-
-
- <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
-or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
-<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
-"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".</p></div>
-
-
- </div>
-</div>
-
-
-
<A NAME="DelayedConfirmationView"></A>
<div class="jd-details api apilevel-">
@@ -4952,6 +5165,87 @@
+<A NAME="ProgressSpinner"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+ final
+ int[]
+ </span>
+ ProgressSpinner
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Attributes that can be used with a ProgressSpinner.
+ <p>Includes the following attributes:</p>
+ <table>
+ <colgroup align="left" />
+ <colgroup align="left" />
+ <tr><th>Attribute</th><th>Description</th></tr>
+ <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner_color_sequence">android.support.wearable:color_sequence</a></code></code></td><td></td></tr>
+ </table></p></div>
+ <div class="jd-tagdata">
+ <h5 class="jd-tagtitle">See Also</h5>
+ <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner_color_sequence">ProgressSpinner_color_sequence</a></code></li>
+ </ul>
+ </div>
+
+
+ </div>
+</div>
+
+
+
+<A NAME="ProgressSpinner_color_sequence"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+
+ int
+ </span>
+ ProgressSpinner_color_sequence
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#color_sequence">color_sequence</a></code>
+ attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner">ProgressSpinner</a></code> array.
+
+
+ <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".</p></div>
+
+
+ </div>
+</div>
+
+
+
<A NAME="WatchViewStub"></A>
<div class="jd-details api apilevel-">
@@ -5847,6 +6141,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/activity/ConfirmationActivity.html b/docs/html/reference/android/support/wearable/activity/ConfirmationActivity.html
index f7cd613..92bfeca 100644
--- a/docs/html/reference/android/support/wearable/activity/ConfirmationActivity.html
+++ b/docs/html/reference/android/support/wearable/activity/ConfirmationActivity.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -713,7 +713,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -10110,6 +10110,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/activity/WearableActivity.html b/docs/html/reference/android/support/wearable/activity/WearableActivity.html
index 2698dca..6f70f74 100644
--- a/docs/html/reference/android/support/wearable/activity/WearableActivity.html
+++ b/docs/html/reference/android/support/wearable/activity/WearableActivity.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -716,7 +716,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -10513,6 +10513,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/activity/package-summary.html b/docs/html/reference/android/support/wearable/activity/package-summary.html
index 4dd01b7..e3a691a 100644
--- a/docs/html/reference/android/support/wearable/activity/package-summary.html
+++ b/docs/html/reference/android/support/wearable/activity/package-summary.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -542,7 +542,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
@@ -654,6 +654,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/companion/WatchFaceCompanion.html b/docs/html/reference/android/support/wearable/companion/WatchFaceCompanion.html
index ce369f2..8174777 100644
--- a/docs/html/reference/android/support/wearable/companion/WatchFaceCompanion.html
+++ b/docs/html/reference/android/support/wearable/companion/WatchFaceCompanion.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -599,7 +599,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1158,6 +1158,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/companion/package-summary.html b/docs/html/reference/android/support/wearable/companion/package-summary.html
index 0447708..7404dcd 100644
--- a/docs/html/reference/android/support/wearable/companion/package-summary.html
+++ b/docs/html/reference/android/support/wearable/companion/package-summary.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -541,7 +541,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
@@ -641,6 +641,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/input/RemoteInputConstants.html b/docs/html/reference/android/support/wearable/input/RemoteInputConstants.html
index f3cb90c..35fe2d5 100644
--- a/docs/html/reference/android/support/wearable/input/RemoteInputConstants.html
+++ b/docs/html/reference/android/support/wearable/input/RemoteInputConstants.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -603,7 +603,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1151,6 +1151,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/input/RemoteInputIntent.html b/docs/html/reference/android/support/wearable/input/RemoteInputIntent.html
index 92d90bc..34ae2d5 100644
--- a/docs/html/reference/android/support/wearable/input/RemoteInputIntent.html
+++ b/docs/html/reference/android/support/wearable/input/RemoteInputIntent.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -603,7 +603,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -644,7 +644,7 @@
new RemoteInput.Builder(KEY_QUICK_REPLY_TEXT).setLabel("Quick reply").build()
};
Intent intent = new Intent(ACTION_REMOTE_INPUT);
- intent.putExtra(EXTRA_REMOTE_INPUT, remoteInputs);
+ intent.putExtra(EXTRA_REMOTE_INPUTS, remoteInputs);
startActivity(intent);
</pre>
@@ -1496,6 +1496,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/input/package-summary.html b/docs/html/reference/android/support/wearable/input/package-summary.html
index 2071e28..314838d 100644
--- a/docs/html/reference/android/support/wearable/input/package-summary.html
+++ b/docs/html/reference/android/support/wearable/input/package-summary.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -542,7 +542,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
@@ -653,6 +653,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/media/MediaControlConstants.html b/docs/html/reference/android/support/wearable/media/MediaControlConstants.html
index 42c141b..30ddc45 100644
--- a/docs/html/reference/android/support/wearable/media/MediaControlConstants.html
+++ b/docs/html/reference/android/support/wearable/media/MediaControlConstants.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -602,7 +602,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1370,6 +1370,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/media/package-summary.html b/docs/html/reference/android/support/wearable/media/package-summary.html
index 3310b5a..72dce84 100644
--- a/docs/html/reference/android/support/wearable/media/package-summary.html
+++ b/docs/html/reference/android/support/wearable/media/package-summary.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -541,7 +541,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
@@ -641,6 +641,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/package-summary.html b/docs/html/reference/android/support/wearable/package-summary.html
index a8e3db057..a4ef376 100644
--- a/docs/html/reference/android/support/wearable/package-summary.html
+++ b/docs/html/reference/android/support/wearable/package-summary.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -474,6 +474,7 @@
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+ <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
<li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -553,7 +554,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
@@ -607,6 +608,17 @@
<tr class=" api apilevel-" >
+ <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></td>
+ <td class="jd-descrcol" width="100%">
+
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></td>
<td class="jd-descrcol" width="100%">
@@ -617,7 +629,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></td>
<td class="jd-descrcol" width="100%">
@@ -628,7 +640,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></td>
<td class="jd-descrcol" width="100%">
@@ -639,7 +651,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.drawable.html">R.drawable</a></td>
<td class="jd-descrcol" width="100%">
@@ -650,7 +662,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.id.html">R.id</a></td>
<td class="jd-descrcol" width="100%">
@@ -661,7 +673,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.interpolator.html">R.interpolator</a></td>
<td class="jd-descrcol" width="100%">
@@ -672,7 +684,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.layout.html">R.layout</a></td>
<td class="jd-descrcol" width="100%">
@@ -683,7 +695,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.string.html">R.string</a></td>
<td class="jd-descrcol" width="100%">
@@ -694,7 +706,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.style.html">R.style</a></td>
<td class="jd-descrcol" width="100%">
@@ -705,7 +717,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html">R.styleable</a></td>
<td class="jd-descrcol" width="100%">
@@ -785,6 +797,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Attendees.html b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Attendees.html
index ba439b3..794973f 100644
--- a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Attendees.html
+++ b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Attendees.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -602,7 +602,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1063,6 +1063,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Instances.html b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Instances.html
index 70ad4d9..77c3c67 100644
--- a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Instances.html
+++ b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Instances.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -602,7 +602,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1063,6 +1063,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Reminders.html b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Reminders.html
index 752da5e..9dfd7f7 100644
--- a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Reminders.html
+++ b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Reminders.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -602,7 +602,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1063,6 +1063,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.html b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.html
index 919306b..588ae71 100644
--- a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.html
+++ b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -611,7 +611,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1265,6 +1265,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/provider/package-summary.html b/docs/html/reference/android/support/wearable/provider/package-summary.html
index f82ce5c..bb4c581 100644
--- a/docs/html/reference/android/support/wearable/provider/package-summary.html
+++ b/docs/html/reference/android/support/wearable/provider/package-summary.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -544,7 +544,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
@@ -677,6 +677,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/ActionLabel.html b/docs/html/reference/android/support/wearable/view/ActionLabel.html
index 3716018..f8cb733 100644
--- a/docs/html/reference/android/support/wearable/view/ActionLabel.html
+++ b/docs/html/reference/android/support/wearable/view/ActionLabel.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -684,7 +685,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -12362,6 +12363,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/ActionPage.html b/docs/html/reference/android/support/wearable/view/ActionPage.html
index 268bba1..69c4dfb 100644
--- a/docs/html/reference/android/support/wearable/view/ActionPage.html
+++ b/docs/html/reference/android/support/wearable/view/ActionPage.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -714,7 +715,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -15449,6 +15450,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/BoxInsetLayout.LayoutParams.html b/docs/html/reference/android/support/wearable/view/BoxInsetLayout.LayoutParams.html
index 43097b4..d716836 100644
--- a/docs/html/reference/android/support/wearable/view/BoxInsetLayout.LayoutParams.html
+++ b/docs/html/reference/android/support/wearable/view/BoxInsetLayout.LayoutParams.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -687,7 +688,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -2431,6 +2432,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/BoxInsetLayout.html b/docs/html/reference/android/support/wearable/view/BoxInsetLayout.html
index 5619e75..d315135 100644
--- a/docs/html/reference/android/support/wearable/view/BoxInsetLayout.html
+++ b/docs/html/reference/android/support/wearable/view/BoxInsetLayout.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -725,7 +726,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -15573,6 +15574,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CardFragment.html b/docs/html/reference/android/support/wearable/view/CardFragment.html
index 9437e93..b73c6ca 100644
--- a/docs/html/reference/android/support/wearable/view/CardFragment.html
+++ b/docs/html/reference/android/support/wearable/view/CardFragment.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -679,7 +680,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -4875,6 +4876,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CardFrame.html b/docs/html/reference/android/support/wearable/view/CardFrame.html
index 1beeda2..32224d5 100644
--- a/docs/html/reference/android/support/wearable/view/CardFrame.html
+++ b/docs/html/reference/android/support/wearable/view/CardFrame.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -714,7 +715,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -15930,6 +15931,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CardScrollView.html b/docs/html/reference/android/support/wearable/view/CardScrollView.html
index 0364eb9..a361847 100644
--- a/docs/html/reference/android/support/wearable/view/CardScrollView.html
+++ b/docs/html/reference/android/support/wearable/view/CardScrollView.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -722,7 +723,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -15898,6 +15899,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CircledImageView.html b/docs/html/reference/android/support/wearable/view/CircledImageView.html
index 1c9451b..a2ba3f7 100644
--- a/docs/html/reference/android/support/wearable/view/CircledImageView.html
+++ b/docs/html/reference/android/support/wearable/view/CircledImageView.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -684,7 +685,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -2857,12 +2858,44 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageCirclePercentage(float)">setImageCirclePercentage</a></span>(float percentage)</nobr>
+
+ </td></tr>
+
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
<span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageDrawable(android.graphics.drawable.Drawable)">setImageDrawable</a></span>(Drawable drawable)</nobr>
</td></tr>
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageHorizontalOffcenterPercentage(float)">setImageHorizontalOffcenterPercentage</a></span>(float percentage)</nobr>
+
+ </td></tr>
+
+
+
<tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -2889,7 +2922,7 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
- <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setPressed(boolean)">setPressed</a></span>(boolean pressed)</nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageTint(int)">setImageTint</a></span>(int tint)</nobr>
</td></tr>
@@ -2905,7 +2938,7 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
- <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setProgress(float)">setProgress</a></span>(float progress)</nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setPressed(boolean)">setPressed</a></span>(boolean pressed)</nobr>
</td></tr>
@@ -2921,6 +2954,22 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setProgress(float)">setProgress</a></span>(float progress)</nobr>
+
+ </td></tr>
+
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
<span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setShadowVisibility(float)">setShadowVisibility</a></span>(float shadowVisibility)</nobr>
<div class="jd-descrdiv">
@@ -2934,7 +2983,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -11857,6 +11906,38 @@
</div>
+<A NAME="setImageCirclePercentage(float)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+
+
+
+ void
+ </span>
+ <span class="sympad">setImageCirclePercentage</span>
+ <span class="normal">(float percentage)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+ </div>
+</div>
+
+
<A NAME="setImageDrawable(android.graphics.drawable.Drawable)"></A>
<div class="jd-details api apilevel-">
@@ -11889,6 +11970,38 @@
</div>
+<A NAME="setImageHorizontalOffcenterPercentage(float)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+
+
+
+ void
+ </span>
+ <span class="sympad">setImageHorizontalOffcenterPercentage</span>
+ <span class="normal">(float percentage)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+ </div>
+</div>
+
+
<A NAME="setImageResource(int)"></A>
<div class="jd-details api apilevel-">
@@ -11921,6 +12034,38 @@
</div>
+<A NAME="setImageTint(int)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+
+
+
+ void
+ </span>
+ <span class="sympad">setImageTint</span>
+ <span class="normal">(int tint)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+ </div>
+</div>
+
+
<A NAME="setPressed(boolean)"></A>
<div class="jd-details api apilevel-">
@@ -12330,6 +12475,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CircularButton.html b/docs/html/reference/android/support/wearable/view/CircularButton.html
index edcb3f2..ff626ce 100644
--- a/docs/html/reference/android/support/wearable/view/CircularButton.html
+++ b/docs/html/reference/android/support/wearable/view/CircularButton.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -687,7 +688,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -11986,6 +11987,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CrossfadeDrawable.html b/docs/html/reference/android/support/wearable/view/CrossfadeDrawable.html
index f346b82..176e532 100644
--- a/docs/html/reference/android/support/wearable/view/CrossfadeDrawable.html
+++ b/docs/html/reference/android/support/wearable/view/CrossfadeDrawable.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -665,7 +666,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -3562,6 +3563,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.DelayedConfirmationListener.html b/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.DelayedConfirmationListener.html
index 6159875..459b683 100644
--- a/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.DelayedConfirmationListener.html
+++ b/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.DelayedConfirmationListener.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -908,6 +909,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.html b/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.html
index 3b61bf0..10e10b9 100644
--- a/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.html
+++ b/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -698,7 +699,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -3164,12 +3165,44 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageCirclePercentage(float)">setImageCirclePercentage</a></span>(float percentage)</nobr>
+
+ </td></tr>
+
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
<span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageDrawable(android.graphics.drawable.Drawable)">setImageDrawable</a></span>(Drawable drawable)</nobr>
</td></tr>
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageHorizontalOffcenterPercentage(float)">setImageHorizontalOffcenterPercentage</a></span>(float percentage)</nobr>
+
+ </td></tr>
+
+
+
<tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -3196,7 +3229,7 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
- <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setPressed(boolean)">setPressed</a></span>(boolean pressed)</nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageTint(int)">setImageTint</a></span>(int tint)</nobr>
</td></tr>
@@ -3212,7 +3245,7 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
- <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setProgress(float)">setProgress</a></span>(float progress)</nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setPressed(boolean)">setPressed</a></span>(boolean pressed)</nobr>
</td></tr>
@@ -3228,6 +3261,22 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setProgress(float)">setProgress</a></span>(float progress)</nobr>
+
+ </td></tr>
+
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
<span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setShadowVisibility(float)">setShadowVisibility</a></span>(float shadowVisibility)</nobr>
<div class="jd-descrdiv">
@@ -3241,7 +3290,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -11914,6 +11963,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/DismissOverlayView.html b/docs/html/reference/android/support/wearable/view/DismissOverlayView.html
index f455403..f146daf 100644
--- a/docs/html/reference/android/support/wearable/view/DismissOverlayView.html
+++ b/docs/html/reference/android/support/wearable/view/DismissOverlayView.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -719,7 +720,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -15317,6 +15318,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/DotsPageIndicator.html b/docs/html/reference/android/support/wearable/view/DotsPageIndicator.html
index 006a270..634cf95 100644
--- a/docs/html/reference/android/support/wearable/view/DotsPageIndicator.html
+++ b/docs/html/reference/android/support/wearable/view/DotsPageIndicator.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -705,7 +706,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -13437,6 +13438,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/FragmentGridPagerAdapter.html b/docs/html/reference/android/support/wearable/view/FragmentGridPagerAdapter.html
index 9df4ae7..ed7fecd 100644
--- a/docs/html/reference/android/support/wearable/view/FragmentGridPagerAdapter.html
+++ b/docs/html/reference/android/support/wearable/view/FragmentGridPagerAdapter.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -611,6 +612,9 @@
+ | <a href="#promethods">Protected Methods</a>
+
+
| <a href="#inhmethods">Inherited Methods</a>
@@ -660,7 +664,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -965,6 +969,22 @@
+ Fragment</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/FragmentGridPagerAdapter.html#findExistingFragment(int, int)">findExistingFragment</a></span>(int row, int column)</nobr>
+
+ </td></tr>
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
@@ -981,7 +1001,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1004,7 +1024,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
abstract
@@ -1027,7 +1047,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1050,7 +1070,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1074,7 +1094,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1097,7 +1117,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1126,6 +1146,71 @@
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="promethods" class="jd-sumtable"><tr><th colspan="12">Protected Methods</th></tr>
+
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/FragmentGridPagerAdapter.html#applyItemPosition(java.lang.Object, android.graphics.Point)">applyItemPosition</a></span>(Object object, Point position)</nobr>
+
+ <div class="jd-descrdiv">
+ Called after <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code> to allow superclasses to update their
+ internal bookkeeping if a subclass has overridden <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/FragmentGridPagerAdapter.html#removeFragment(android.app.Fragment, android.app.FragmentTransaction)">removeFragment</a></span>(Fragment fragment, FragmentTransaction transaction)</nobr>
+
+ </td></tr>
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/FragmentGridPagerAdapter.html#restoreFragment(android.app.Fragment, android.app.FragmentTransaction)">restoreFragment</a></span>(Fragment fragment, FragmentTransaction transaction)</nobr>
+
+ </td></tr>
+
+
+
+</table>
+
+
@@ -1157,6 +1242,30 @@
<tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#applyItemPosition(java.lang.Object, android.graphics.Point)">applyItemPosition</a></span>(Object object, Point position)</nobr>
+
+ <div class="jd-descrdiv">
+ Called after <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code> to allow superclasses to update their
+ internal bookkeeping if a subclass has overridden <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
abstract
@@ -1178,7 +1287,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1201,7 +1310,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1224,7 +1333,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1247,7 +1356,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
abstract
@@ -1270,7 +1379,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1293,7 +1402,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1316,7 +1425,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1339,7 +1448,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
abstract
@@ -1362,7 +1471,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
abstract
@@ -1385,7 +1494,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
abstract
@@ -1409,7 +1518,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1433,7 +1542,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1457,7 +1566,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1481,7 +1590,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1504,7 +1613,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1527,7 +1636,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1550,7 +1659,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1573,7 +1682,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1596,7 +1705,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1964,6 +2073,38 @@
</div>
+<A NAME="findExistingFragment(int, int)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+
+
+
+ Fragment
+ </span>
+ <span class="sympad">findExistingFragment</span>
+ <span class="normal">(int row, int column)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+ </div>
+</div>
+
+
<A NAME="finishUpdate(android.view.ViewGroup)"></A>
<div class="jd-details api apilevel-">
@@ -2331,6 +2472,122 @@
<!-- ========= METHOD DETAIL ======== -->
+<h2>Protected Methods</h2>
+
+
+
+<A NAME="applyItemPosition(java.lang.Object, android.graphics.Point)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ protected
+
+
+
+
+ void
+ </span>
+ <span class="sympad">applyItemPosition</span>
+ <span class="normal">(Object object, Point position)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Called after <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code> to allow superclasses to update their
+ internal bookkeeping if a subclass has overridden <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.</p></div>
+ <div class="jd-tagdata">
+ <h5 class="jd-tagtitle">Parameters</h5>
+ <table class="jd-tagtable">
+ <tr>
+ <th>object</td>
+ <td>Object representing the item passed to <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.</td>
+ </tr>
+ <tr>
+ <th>position</td>
+ <td>position which was returned from <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.
+</td>
+ </tr>
+ </table>
+ </div>
+
+ </div>
+</div>
+
+
+<A NAME="removeFragment(android.app.Fragment, android.app.FragmentTransaction)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ protected
+
+
+
+
+ void
+ </span>
+ <span class="sympad">removeFragment</span>
+ <span class="normal">(Fragment fragment, FragmentTransaction transaction)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+ </div>
+</div>
+
+
+<A NAME="restoreFragment(android.app.Fragment, android.app.FragmentTransaction)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ protected
+
+
+
+
+ void
+ </span>
+ <span class="sympad">restoreFragment</span>
+ <span class="normal">(Fragment fragment, FragmentTransaction transaction)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+ </div>
+</div>
+
+
+
<!-- ========= END OF CLASS DATA ========= -->
@@ -2389,6 +2646,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridPageOptions.BackgroundListener.html b/docs/html/reference/android/support/wearable/view/GridPageOptions.BackgroundListener.html
index a37d8f8a..1e066c1 100644
--- a/docs/html/reference/android/support/wearable/view/GridPageOptions.BackgroundListener.html
+++ b/docs/html/reference/android/support/wearable/view/GridPageOptions.BackgroundListener.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -853,6 +854,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridPageOptions.html b/docs/html/reference/android/support/wearable/view/GridPageOptions.html
index 56cfa05..8c22582 100644
--- a/docs/html/reference/android/support/wearable/view/GridPageOptions.html
+++ b/docs/html/reference/android/support/wearable/view/GridPageOptions.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -948,6 +949,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridPagerAdapter.html b/docs/html/reference/android/support/wearable/view/GridPagerAdapter.html
index 9876a82..b157c39 100644
--- a/docs/html/reference/android/support/wearable/view/GridPagerAdapter.html
+++ b/docs/html/reference/android/support/wearable/view/GridPagerAdapter.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -600,6 +601,9 @@
+ | <a href="#promethods">Protected Methods</a>
+
+
| <a href="#inhmethods">Inherited Methods</a>
@@ -645,7 +649,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1369,6 +1373,39 @@
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="promethods" class="jd-sumtable"><tr><th colspan="12">Protected Methods</th></tr>
+
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#applyItemPosition(java.lang.Object, android.graphics.Point)">applyItemPosition</a></span>(Object object, Point position)</nobr>
+
+ <div class="jd-descrdiv">
+ Called after <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code> to allow superclasses to update their
+ internal bookkeeping if a subclass has overridden <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+</table>
+
+
@@ -2742,6 +2779,58 @@
<!-- ========= METHOD DETAIL ======== -->
+<h2>Protected Methods</h2>
+
+
+
+<A NAME="applyItemPosition(java.lang.Object, android.graphics.Point)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ protected
+
+
+
+
+ void
+ </span>
+ <span class="sympad">applyItemPosition</span>
+ <span class="normal">(Object object, Point position)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Called after <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code> to allow superclasses to update their
+ internal bookkeeping if a subclass has overridden <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.</p></div>
+ <div class="jd-tagdata">
+ <h5 class="jd-tagtitle">Parameters</h5>
+ <table class="jd-tagtable">
+ <tr>
+ <th>object</td>
+ <td>Object representing the item passed to <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.</td>
+ </tr>
+ <tr>
+ <th>position</td>
+ <td>position which was returned from <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.
+</td>
+ </tr>
+ </table>
+ </div>
+
+ </div>
+</div>
+
+
+
<!-- ========= END OF CLASS DATA ========= -->
@@ -2800,6 +2889,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridViewPager.LayoutParams.html b/docs/html/reference/android/support/wearable/view/GridViewPager.LayoutParams.html
index 9db55c9..c4d63e22 100644
--- a/docs/html/reference/android/support/wearable/view/GridViewPager.LayoutParams.html
+++ b/docs/html/reference/android/support/wearable/view/GridViewPager.LayoutParams.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -673,7 +674,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1787,6 +1788,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridViewPager.OnAdapterChangeListener.html b/docs/html/reference/android/support/wearable/view/GridViewPager.OnAdapterChangeListener.html
index 1cbec14..fcd6a3d 100644
--- a/docs/html/reference/android/support/wearable/view/GridViewPager.OnAdapterChangeListener.html
+++ b/docs/html/reference/android/support/wearable/view/GridViewPager.OnAdapterChangeListener.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -621,7 +622,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -968,6 +969,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridViewPager.OnPageChangeListener.html b/docs/html/reference/android/support/wearable/view/GridViewPager.OnPageChangeListener.html
index fd81fbe..072f6c5 100644
--- a/docs/html/reference/android/support/wearable/view/GridViewPager.OnPageChangeListener.html
+++ b/docs/html/reference/android/support/wearable/view/GridViewPager.OnPageChangeListener.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -621,7 +622,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1085,6 +1086,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridViewPager.html b/docs/html/reference/android/support/wearable/view/GridViewPager.html
index b92720c..3e2179d 100644
--- a/docs/html/reference/android/support/wearable/view/GridViewPager.html
+++ b/docs/html/reference/android/support/wearable/view/GridViewPager.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -717,7 +718,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -16881,6 +16882,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/SimpleAnimatorListener.html b/docs/html/reference/android/support/wearable/view/SimpleAnimatorListener.html
index 454f420..9940f3b 100644
--- a/docs/html/reference/android/support/wearable/view/SimpleAnimatorListener.html
+++ b/docs/html/reference/android/support/wearable/view/SimpleAnimatorListener.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -651,7 +652,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1525,6 +1526,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WatchViewStub.OnLayoutInflatedListener.html b/docs/html/reference/android/support/wearable/view/WatchViewStub.OnLayoutInflatedListener.html
index b05ce34..9492429 100644
--- a/docs/html/reference/android/support/wearable/view/WatchViewStub.OnLayoutInflatedListener.html
+++ b/docs/html/reference/android/support/wearable/view/WatchViewStub.OnLayoutInflatedListener.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -847,6 +848,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WatchViewStub.html b/docs/html/reference/android/support/wearable/view/WatchViewStub.html
index 8fd5fee..170a165 100644
--- a/docs/html/reference/android/support/wearable/view/WatchViewStub.html
+++ b/docs/html/reference/android/support/wearable/view/WatchViewStub.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -725,7 +726,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -15465,6 +15466,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableFrameLayout.LayoutParams.html b/docs/html/reference/android/support/wearable/view/WearableFrameLayout.LayoutParams.html
index 93f4b0d..fb54c95 100644
--- a/docs/html/reference/android/support/wearable/view/WearableFrameLayout.LayoutParams.html
+++ b/docs/html/reference/android/support/wearable/view/WearableFrameLayout.LayoutParams.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -684,7 +685,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -2322,6 +2323,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableFrameLayout.html b/docs/html/reference/android/support/wearable/view/WearableFrameLayout.html
index f2b0df7..e269ab8 100644
--- a/docs/html/reference/android/support/wearable/view/WearableFrameLayout.html
+++ b/docs/html/reference/android/support/wearable/view/WearableFrameLayout.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -714,7 +715,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -16352,6 +16353,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.Adapter.html b/docs/html/reference/android/support/wearable/view/WearableListView.Adapter.html
index 9619c5d..0686ff2 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.Adapter.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.Adapter.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -647,7 +648,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1561,6 +1562,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.ClickListener.html b/docs/html/reference/android/support/wearable/view/WearableListView.ClickListener.html
index 84cb188..17431c4 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.ClickListener.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.ClickListener.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -919,6 +920,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.OnCenterProximityListener.html b/docs/html/reference/android/support/wearable/view/WearableListView.OnCenterProximityListener.html
index b2b9246..936a163 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.OnCenterProximityListener.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.OnCenterProximityListener.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -930,6 +931,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.OnCentralPositionChangedListener.html b/docs/html/reference/android/support/wearable/view/WearableListView.OnCentralPositionChangedListener.html
index 66eeac3..c49bbcc 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.OnCentralPositionChangedListener.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.OnCentralPositionChangedListener.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -861,6 +862,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.OnScrollListener.html b/docs/html/reference/android/support/wearable/view/WearableListView.OnScrollListener.html
index de2bcd7..2871600 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.OnScrollListener.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.OnScrollListener.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1065,6 +1066,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.ViewHolder.html b/docs/html/reference/android/support/wearable/view/WearableListView.ViewHolder.html
index b7953d4..270d8d8 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.ViewHolder.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.ViewHolder.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -652,7 +653,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1346,6 +1347,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.html b/docs/html/reference/android/support/wearable/view/WearableListView.html
index eec5c32..7fb9565 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -501,6 +501,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -724,7 +725,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -3236,7 +3237,7 @@
boolean</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
- <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#onInterceptTouchEvent(android.view.MotionEvent)">onInterceptTouchEvent</a></span>(MotionEvent event)</nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#isAtTop()">isAtTop</a></span>()</nobr>
</td></tr>
@@ -3252,7 +3253,7 @@
boolean</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
- <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#onTouchEvent(android.view.MotionEvent)">onTouchEvent</a></span>(MotionEvent event)</nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#onInterceptTouchEvent(android.view.MotionEvent)">onInterceptTouchEvent</a></span>(MotionEvent event)</nobr>
</td></tr>
@@ -3265,6 +3266,22 @@
+ boolean</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#onTouchEvent(android.view.MotionEvent)">onTouchEvent</a></span>(MotionEvent event)</nobr>
+
+ </td></tr>
+
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
@@ -3281,7 +3298,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -3304,7 +3321,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -3327,7 +3344,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -3343,7 +3360,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -3366,7 +3383,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -3390,7 +3407,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -3413,7 +3430,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -3436,6 +3453,22 @@
</td></tr>
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#smoothScrollToPosition(int, android.support.v7.widget.RecyclerView.SmoothScroller)">smoothScrollToPosition</a></span>(int position, RecyclerView.SmoothScroller smoothScroller)</nobr>
+
+ </td></tr>
+
+
</table>
@@ -16613,6 +16646,43 @@
</div>
+<A NAME="isAtTop()"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+
+
+
+ boolean
+ </span>
+ <span class="sympad">isAtTop</span>
+ <span class="normal">()</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p></p></div>
+ <div class="jd-tagdata">
+ <h5 class="jd-tagtitle">Returns</h5>
+ <ul class="nolist"><li>true if the list is scrolled all the way to the top.
+</li></ul>
+ </div>
+
+ </div>
+</div>
+
+
<A NAME="onInterceptTouchEvent(android.view.MotionEvent)"></A>
<div class="jd-details api apilevel-">
@@ -16963,6 +17033,38 @@
</div>
+<A NAME="smoothScrollToPosition(int, android.support.v7.widget.RecyclerView.SmoothScroller)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+
+
+
+ void
+ </span>
+ <span class="sympad">smoothScrollToPosition</span>
+ <span class="normal">(int position, RecyclerView.SmoothScroller smoothScroller)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+ </div>
+</div>
+
+
@@ -17026,6 +17128,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/package-summary.html b/docs/html/reference/android/support/wearable/view/package-summary.html
index 28f94db..f76e378 100644
--- a/docs/html/reference/android/support/wearable/view/package-summary.html
+++ b/docs/html/reference/android/support/wearable/view/package-summary.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -502,6 +502,7 @@
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
<li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -578,7 +579,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
@@ -920,6 +921,17 @@
<tr class=" api apilevel-" >
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></td>
+ <td class="jd-descrcol" width="100%">
+ An indeterminate progress spinner designed for wearables which cycles through colors.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></td>
<td class="jd-descrcol" width="100%">
Convenience class for listening for Animator events that implements the AnimatorListener
@@ -931,7 +943,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></td>
<td class="jd-descrcol" width="100%">
A WatchViewStub allows for the use of different sub-layouts depending on the
@@ -944,7 +956,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></td>
<td class="jd-descrcol" width="100%">
WearableFrameLayout works exactly like FrameLayout, except it can have overrides for a round
@@ -956,7 +968,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.LayoutParams.html">WearableFrameLayout.LayoutParams</a></td>
<td class="jd-descrcol" width="100%">
Per-child layout information for layouts on wearable devices.
@@ -967,7 +979,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html">WearableListView</a></td>
<td class="jd-descrcol" width="100%">
An alternative version of ListView that is optimized for ease of use on small screen wearable
@@ -979,7 +991,7 @@
</tr>
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WearableListView.Adapter.html">WearableListView.Adapter</a></td>
<td class="jd-descrcol" width="100%">
Base class for adapters providing data for the WearableListView.
@@ -990,7 +1002,7 @@
</tr>
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WearableListView.ViewHolder.html">WearableListView.ViewHolder</a></td>
<td class="jd-descrcol" width="100%">
Wrapper around items displayed in the list view.
@@ -1070,6 +1082,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html b/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html
index bbae62a..1a7aa76 100644
--- a/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html
+++ b/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -466,6 +466,11 @@
<ul>
+ <li><h2>Annotations</h2>
+ <ul>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+ </ul>
+ </li>
<li><h2>Classes</h2>
@@ -631,7 +636,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -968,6 +973,29 @@
final
+ int</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#getNotificationCount()">getNotificationCount</a></span>()</nobr>
+
+ <div class="jd-descrdiv">
+ Returns the total number of notification cards in the stream.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+ final
+
+
Rect</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
@@ -984,7 +1012,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1007,7 +1035,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1030,7 +1058,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1053,7 +1081,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1069,7 +1097,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1085,7 +1113,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1101,7 +1129,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1124,6 +1152,29 @@
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onNotificationCountChanged(int)">onNotificationCountChanged</a></span>(int count)</nobr>
+
+ <div class="jd-descrdiv">
+ Called when the total number of notification cards in the stream has changed.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
<tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1180,6 +1231,29 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTapCommand(int, int, int, long)">onTapCommand</a></span>(int tapType, int x, int y, long eventTime)</nobr>
+
+ <div class="jd-descrdiv">
+ Called when a tap or touch related event occurs.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
<span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTimeTick()">onTimeTick</a></span>()</nobr>
<div class="jd-descrdiv">
@@ -1193,7 +1267,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1216,7 +1290,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1239,7 +1313,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -2201,6 +2275,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.html b/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.html
index 5dbd8ea..aee337f 100644
--- a/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.html
+++ b/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -466,6 +466,11 @@
<ul>
+ <li><h2>Annotations</h2>
+ <ul>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+ </ul>
+ </li>
<li><h2>Classes</h2>
@@ -694,7 +699,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -952,6 +957,44 @@
</tr>
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol">int</td>
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP">TAP_TYPE_TAP</a></td>
+ <td class="jd-descrcol" width="100%">
+ Used in onTapCommaned to indicate that an "up" event on the watch face has occurred that
+ has not been consumed by another activity.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol">int</td>
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH">TAP_TYPE_TOUCH</a></td>
+ <td class="jd-descrcol" width="100%">
+ Used in onTapCommand to indicate a "down" touch event on the watch face.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol">int</td>
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL">TAP_TYPE_TOUCH_CANCEL</a></td>
+ <td class="jd-descrcol" width="100%">
+ Used in onTapCaommand to indicate that a previous TAP_TYPE_TOUCH touch event has been
+ canceled.
+
+
+
+ </td>
+ </tr>
+
+
</table>
</div>
</div>
@@ -6238,6 +6281,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.Engine.html b/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.Engine.html
index 761917877..aba23a6 100644
--- a/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.Engine.html
+++ b/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.Engine.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -466,6 +466,11 @@
<ul>
+ <li><h2>Annotations</h2>
+ <ul>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+ </ul>
+ </li>
<li><h2>Classes</h2>
@@ -631,7 +636,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1138,6 +1143,29 @@
final
+ int</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#getNotificationCount()">getNotificationCount</a></span>()</nobr>
+
+ <div class="jd-descrdiv">
+ Returns the total number of notification cards in the stream.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+ final
+
+
Rect</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
@@ -1154,7 +1182,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1177,7 +1205,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1200,7 +1228,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1223,7 +1251,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1239,7 +1267,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1255,7 +1283,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1271,7 +1299,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1294,6 +1322,29 @@
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onNotificationCountChanged(int)">onNotificationCountChanged</a></span>(int count)</nobr>
+
+ <div class="jd-descrdiv">
+ Called when the total number of notification cards in the stream has changed.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
<tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1350,6 +1401,29 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTapCommand(int, int, int, long)">onTapCommand</a></span>(int tapType, int x, int y, long eventTime)</nobr>
+
+ <div class="jd-descrdiv">
+ Called when a tap or touch related event occurs.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
<span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTimeTick()">onTimeTick</a></span>()</nobr>
<div class="jd-descrdiv">
@@ -1363,7 +1437,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1386,7 +1460,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1409,7 +1483,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -2668,6 +2742,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.html b/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.html
index 6371290..1dcc7dd 100644
--- a/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.html
+++ b/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -466,6 +466,11 @@
<ul>
+ <li><h2>Annotations</h2>
+ <ul>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+ </ul>
+ </li>
<li><h2>Classes</h2>
@@ -694,7 +699,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -955,6 +960,44 @@
</tr>
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol">int</td>
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP">TAP_TYPE_TAP</a></td>
+ <td class="jd-descrcol" width="100%">
+ Used in onTapCommaned to indicate that an "up" event on the watch face has occurred that
+ has not been consumed by another activity.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol">int</td>
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH">TAP_TYPE_TOUCH</a></td>
+ <td class="jd-descrcol" width="100%">
+ Used in onTapCommand to indicate a "down" touch event on the watch face.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol">int</td>
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL">TAP_TYPE_TOUCH_CANCEL</a></td>
+ <td class="jd-descrcol" width="100%">
+ Used in onTapCaommand to indicate that a previous TAP_TYPE_TOUCH touch event has been
+ canceled.
+
+
+
+ </td>
+ </tr>
+
+
</table>
</div>
</div>
@@ -6241,6 +6284,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/WatchFaceService.Engine.html b/docs/html/reference/android/support/wearable/watchface/WatchFaceService.Engine.html
index 2326386..ad6cc2c 100644
--- a/docs/html/reference/android/support/wearable/watchface/WatchFaceService.Engine.html
+++ b/docs/html/reference/android/support/wearable/watchface/WatchFaceService.Engine.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -466,6 +466,11 @@
<ul>
+ <li><h2>Annotations</h2>
+ <ul>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+ </ul>
+ </li>
<li><h2>Classes</h2>
@@ -620,7 +625,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -831,6 +836,29 @@
final
+ int</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#getNotificationCount()">getNotificationCount</a></span>()</nobr>
+
+ <div class="jd-descrdiv">
+ Returns the total number of notification cards in the stream.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+ final
+
+
Rect</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
@@ -847,7 +875,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -870,7 +898,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -893,7 +921,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -916,7 +944,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -932,7 +960,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -948,7 +976,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -964,7 +992,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -987,6 +1015,29 @@
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onNotificationCountChanged(int)">onNotificationCountChanged</a></span>(int count)</nobr>
+
+ <div class="jd-descrdiv">
+ Called when the total number of notification cards in the stream has changed.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
<tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1043,6 +1094,29 @@
void</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTapCommand(int, int, int, long)">onTapCommand</a></span>(int tapType, int x, int y, long eventTime)</nobr>
+
+ <div class="jd-descrdiv">
+ Called when a tap or touch related event occurs.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ void</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
<span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTimeTick()">onTimeTick</a></span>()</nobr>
<div class="jd-descrdiv">
@@ -1056,7 +1130,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1079,7 +1153,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1102,7 +1176,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1805,6 +1879,39 @@
</div>
+<A NAME="getNotificationCount()"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+ final
+
+
+ int
+ </span>
+ <span class="sympad">getNotificationCount</span>
+ <span class="normal">()</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Returns the total number of notification cards in the stream.
+</p></div>
+
+ </div>
+</div>
+
+
<A NAME="getPeekCardPosition()"></A>
<div class="jd-details api apilevel-">
@@ -2075,6 +2182,48 @@
</div>
+<A NAME="onNotificationCountChanged(int)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+
+
+
+ void
+ </span>
+ <span class="sympad">onNotificationCountChanged</span>
+ <span class="normal">(int count)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Called when the total number of notification cards in the stream has changed.</p></div>
+ <div class="jd-tagdata">
+ <h5 class="jd-tagtitle">Parameters</h5>
+ <table class="jd-tagtable">
+ <tr>
+ <th>count</td>
+ <td>total number of the notification cards in the stream
+</td>
+ </tr>
+ </table>
+ </div>
+
+ </div>
+</div>
+
+
<A NAME="onPeekCardPositionUpdate(android.graphics.Rect)"></A>
<div class="jd-details api apilevel-">
@@ -2154,6 +2303,60 @@
</div>
+<A NAME="onTapCommand(int, int, int, long)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+
+
+
+ void
+ </span>
+ <span class="sympad">onTapCommand</span>
+ <span class="normal">(int tapType, int x, int y, long eventTime)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Called when a tap or touch related event occurs.</p></div>
+ <div class="jd-tagdata">
+ <h5 class="jd-tagtitle">Parameters</h5>
+ <table class="jd-tagtable">
+ <tr>
+ <th>tapType</td>
+ <td>Value representing the event sent to the wallpaper.</td>
+ </tr>
+ <tr>
+ <th>x</td>
+ <td>X coordinate of the event.</td>
+ </tr>
+ <tr>
+ <th>y</td>
+ <td>Y coordinate of the event.</td>
+ </tr>
+ <tr>
+ <th>eventTime</td>
+ <td>The time, in millis, of the event.
+</td>
+ </tr>
+ </table>
+ </div>
+
+ </div>
+</div>
+
+
<A NAME="onTimeTick()"></A>
<div class="jd-details api apilevel-">
@@ -2369,6 +2572,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/WatchFaceService.html b/docs/html/reference/android/support/wearable/watchface/WatchFaceService.html
index f566e7e..40cf0a3 100644
--- a/docs/html/reference/android/support/wearable/watchface/WatchFaceService.html
+++ b/docs/html/reference/android/support/wearable/watchface/WatchFaceService.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -466,6 +466,11 @@
<ul>
+ <li><h2>Annotations</h2>
+ <ul>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+ </ul>
+ </li>
<li><h2>Classes</h2>
@@ -684,7 +689,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -922,6 +927,23 @@
</tr>
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+ @interface</nobr></td>
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></td>
+ <td class="jd-descrcol" width="100%">
+
+
+
+
+ </td>
+ </tr>
+
+
@@ -1005,6 +1027,44 @@
</tr>
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol">int</td>
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP">TAP_TYPE_TAP</a></td>
+ <td class="jd-descrcol" width="100%">
+ Used in onTapCommaned to indicate that an "up" event on the watch face has occurred that
+ has not been consumed by another activity.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol">int</td>
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH">TAP_TYPE_TOUCH</a></td>
+ <td class="jd-descrcol" width="100%">
+ Used in onTapCommand to indicate a "down" touch event on the watch face.
+
+
+
+ </td>
+ </tr>
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol">int</td>
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL">TAP_TYPE_TOUCH_CANCEL</a></td>
+ <td class="jd-descrcol" width="100%">
+ Used in onTapCaommand to indicate that a previous TAP_TYPE_TOUCH touch event has been
+ canceled.
+
+
+
+ </td>
+ </tr>
+
+
</table>
@@ -6330,6 +6390,136 @@
+<A NAME="TAP_TYPE_TAP"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+ final
+ int
+ </span>
+ TAP_TYPE_TAP
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Used in onTapCommaned to indicate that an "up" event on the watch face has occurred that
+ has not been consumed by another activity. A TAP_TYPE_TOUCH will always occur first. This
+ event will not occur if a TAP_TYPE_TOUCH_CANCEL is sent.
+</p></div>
+
+
+ <div class="jd-tagdata">
+ <span class="jd-tagtitle">Constant Value: </span>
+ <span>
+
+ 2
+ (0x00000002)
+
+ </span>
+ </div>
+
+ </div>
+</div>
+
+
+
+<A NAME="TAP_TYPE_TOUCH"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+ final
+ int
+ </span>
+ TAP_TYPE_TOUCH
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Used in onTapCommand to indicate a "down" touch event on the watch face.
+</p></div>
+
+
+ <div class="jd-tagdata">
+ <span class="jd-tagtitle">Constant Value: </span>
+ <span>
+
+ 0
+ (0x00000000)
+
+ </span>
+ </div>
+
+ </div>
+</div>
+
+
+
+<A NAME="TAP_TYPE_TOUCH_CANCEL"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+ static
+ final
+ int
+ </span>
+ TAP_TYPE_TOUCH_CANCEL
+ </h4>
+ <div class="api-level">
+
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Used in onTapCaommand to indicate that a previous TAP_TYPE_TOUCH touch event has been
+ canceled. This generally happens when the watch face is touched but then a move or long
+ press occurs.
+</p></div>
+
+
+ <div class="jd-tagdata">
+ <span class="jd-tagtitle">Constant Value: </span>
+ <span>
+
+ 1
+ (0x00000001)
+
+ </span>
+ </div>
+
+ </div>
+</div>
+
+
+
<!-- Fields -->
@@ -6484,6 +6674,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html b/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html
index 956e3a8..a5401e5 100644
--- a/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html
+++ b/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -466,6 +466,11 @@
<ul>
+ <li><h2>Annotations</h2>
+ <ul>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+ </ul>
+ </li>
<li><h2>Classes</h2>
@@ -609,7 +614,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -758,6 +763,29 @@
<a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html">WatchFaceStyle.Builder</a></nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html#setAcceptsTapEvents(boolean)">setAcceptsTapEvents</a></span>(boolean acceptsTapEvents)</nobr>
+
+ <div class="jd-descrdiv">
+ Sets whether this watchface accepts tap events.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
+ <a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html">WatchFaceStyle.Builder</a></nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
<span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html#setAmbientPeekMode(int)">setAmbientPeekMode</a></span>(int ambientPeekMode)</nobr>
<div class="jd-descrdiv">
@@ -772,7 +800,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -795,7 +823,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -818,7 +846,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -841,7 +869,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -864,7 +892,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -887,7 +915,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -910,7 +938,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -933,7 +961,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -959,7 +987,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1312,6 +1340,53 @@
</div>
+<A NAME="setAcceptsTapEvents(boolean)"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+
+
+
+ <a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html">WatchFaceStyle.Builder</a>
+ </span>
+ <span class="sympad">setAcceptsTapEvents</span>
+ <span class="normal">(boolean acceptsTapEvents)</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Sets whether this watchface accepts tap events. The default is false.
+ <p>
+ Watchfaces that set this <code>true</code> are indicating they are prepared to receive
+ <code><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH">TAP_TYPE_TOUCH</a></code>,
+ <code><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL">TAP_TYPE_TOUCH_CANCEL</a></code>,
+ and <code><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP">TAP_TYPE_TAP</a></code></p></div>
+ <div class="jd-tagdata">
+ <h5 class="jd-tagtitle">Parameters</h5>
+ <table class="jd-tagtable">
+ <tr>
+ <th>acceptsTapEvents</td>
+ <td>whether to receive touch events.
+</td>
+ </tr>
+ </table>
+ </div>
+
+ </div>
+</div>
+
+
<A NAME="setAmbientPeekMode(int)"></A>
<div class="jd-details api apilevel-">
@@ -1825,6 +1900,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.html b/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.html
index e08608f..70c3851 100644
--- a/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.html
+++ b/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -466,6 +466,11 @@
<ul>
+ <li><h2>Annotations</h2>
+ <ul>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+ </ul>
+ </li>
<li><h2>Classes</h2>
@@ -632,7 +637,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
<table class="jd-inheritance-table">
@@ -1022,6 +1027,29 @@
+ boolean</nobr>
+ </td>
+ <td class="jd-linkcol" width="100%"><nobr>
+ <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.html#getAcceptsTapEvents()">getAcceptsTapEvents</a></span>()</nobr>
+
+ <div class="jd-descrdiv">
+ Whether the watchface accepts tap events.
+
+
+
+ </div>
+
+ </td></tr>
+
+
+
+ <tr class=" api apilevel-" >
+ <td class="jd-typecol"><nobr>
+
+
+
+
+
int</nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
@@ -1039,7 +1067,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1062,7 +1090,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1085,7 +1113,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1108,7 +1136,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1131,7 +1159,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1154,7 +1182,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1177,7 +1205,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1200,7 +1228,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1223,7 +1251,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1247,7 +1275,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1263,7 +1291,7 @@
- <tr class=" api apilevel-" >
+ <tr class="alt-color api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1279,7 +1307,7 @@
- <tr class="alt-color api apilevel-" >
+ <tr class=" api apilevel-" >
<td class="jd-typecol"><nobr>
@@ -1706,7 +1734,8 @@
<div class="jd-tagdata jd-tagdescr"><p>When this background visibility is selected, the background of the peek card should only be
- shown briefly, and only if the peek card represents an interruptive notification.
+ shown briefly, and only if the peek card represents an interruptive notification. This is the
+ default mode.
</p></div>
@@ -1749,7 +1778,7 @@
<div class="jd-tagdata jd-tagdescr"><p>When this background visibility is selected, the background of the peek card should always
- be shown. This is the default mode.
+ be shown.
Note that this will obscure your watch face whenever there is a peek card showing.
</p></div>
@@ -2191,6 +2220,39 @@
</div>
+<A NAME="getAcceptsTapEvents()"></A>
+
+<div class="jd-details api apilevel-">
+ <h4 class="jd-details-title">
+ <span class="normal">
+ public
+
+
+
+
+ boolean
+ </span>
+ <span class="sympad">getAcceptsTapEvents</span>
+ <span class="normal">()</span>
+ </h4>
+ <div class="api-level">
+ <div></div>
+
+
+
+ </div>
+ <div class="jd-details-descr">
+
+
+
+
+ <div class="jd-tagdata jd-tagdescr"><p>Whether the watchface accepts tap events. The default is false.
+</p></div>
+
+ </div>
+</div>
+
+
<A NAME="getAmbientPeekMode()"></A>
<div class="jd-details api apilevel-">
@@ -2705,6 +2767,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/package-summary.html b/docs/html/reference/android/support/wearable/watchface/package-summary.html
index 6853fc4..a654b13 100644
--- a/docs/html/reference/android/support/wearable/watchface/package-summary.html
+++ b/docs/html/reference/android/support/wearable/watchface/package-summary.html
@@ -128,7 +128,7 @@
var metaTags = [];
var devsite = false;
</script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
@@ -467,6 +467,11 @@
<ul>
+ <li><h2>Annotations</h2>
+ <ul>
+ <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+ </ul>
+ </li>
<li><h2>Classes</h2>
@@ -548,7 +553,7 @@
<div id="naMessage"></div>
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
@@ -556,6 +561,27 @@
+ <h2>Annotations</h2>
+ <div class="jd-sumtable">
+
+
+ <table class="jd-sumtable-expando">
+
+ <tr class="alt-color api apilevel-" >
+ <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></td>
+ <td class="jd-descrcol" width="100%">
+
+
+
+
+ </td>
+ </tr>
+
+
+ </table>
+
+ </div>
+
@@ -726,6 +752,7 @@
<option value="es">Español</option>
<option value="ja">日本語</option>
<option value="ko">한국어</option>
+ <option value="pt-br">Português Brasileiro</option>
<option value="ru">Русский</option>
<option value="zh-cn">中文(简体)</option>
<option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index dbc0f35..39822e5 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -5,28 +5,28 @@
header.hide=1
page.metaDescription=Download the official Android IDE and developer tools to build apps for Android phones, tablets, wearables, TVs, and more.
-studio.version=1.3.1.0
+studio.version=1.3.2.0
-studio.linux_bundle_download=android-studio-ide-141.2135290-linux.zip
-studio.linux_bundle_bytes=351992670
-studio.linux_bundle_checksum=51e5f5de2b82883d87f85ee38cf7b7b8b2e7debf
+studio.linux_bundle_download=android-studio-ide-141.2178183-linux.zip
+studio.linux_bundle_bytes=352010593
+studio.linux_bundle_checksum=cf780413f8c8223eb348bd27c19a9c04b75eaeb2
-studio.mac_bundle_download=android-studio-ide-141.2135290-mac.dmg
-studio.mac_bundle_bytes=368321249
-studio.mac_bundle_checksum=9fc12b5657ff52c761b7e7c115feade2a9728386
+studio.mac_bundle_download=android-studio-ide-141.2178183-mac.dmg
+studio.mac_bundle_bytes=368335367
+studio.mac_bundle_checksum=75b67eb15a34a152a40e7189484ab0ebc375b877
-studio.win_bundle_download=android-studio-ide-141.2135290-windows.zip
-studio.win_bundle_bytes=344406793
-studio.win_bundle_checksum=3b4c4924cb9495e56db61ca0e8c8d2bf588c4b97
+studio.win_bundle_download=android-studio-ide-141.2178183-windows.zip
+studio.win_bundle_bytes=344424713
+studio.win_bundle_checksum=3134f226b5f3c3f74d4fc2d9cff03a4458f01d69
-studio.win_bundle_exe_download=android-studio-bundle-141.2135290-windows.exe
-studio.win_bundle_exe_bytes=1008506096
-studio.win_bundle_exe_checksum=8cff590f2e08e339f8c2491b287a840ae87c7383
+studio.win_bundle_exe_download=android-studio-bundle-141.2178183-windows.exe
+studio.win_bundle_exe_bytes=1136982712
+studio.win_bundle_exe_checksum=c7d39c529dd434489da9d086ff689d34dc791526
-studio.win_notools_exe_download=android-studio-ide-141.2135290-windows.exe
-studio.win_notools_exe_bytes=321791312
-studio.win_notools_exe_checksum=d70fb49d03db9dded19c891a92452601e39272f4
+studio.win_notools_exe_download=android-studio-ide-141.2178183-windows.exe
+studio.win_notools_exe_bytes=321810248
+studio.win_notools_exe_checksum=b5d1aaa000729c03a3cf980add79d1b93121c56d
@@ -289,7 +289,7 @@
</ul>
<a class="online landing-button green download-bundle-button"
-href="#Other" >Download Android Studio</a>
+href="#Other" >Download Android Studio<br/><span class='small'></span></a>
<!-- this appears when viewing the offline docs -->
<p class="offline">
diff --git a/docs/html/tools/help/adb.jd b/docs/html/tools/help/adb.jd
index 641d463..2faff4f 100644
--- a/docs/html/tools/help/adb.jd
+++ b/docs/html/tools/help/adb.jd
@@ -420,62 +420,54 @@
<ol>
<li>
-Connect Android device and adb host computer
+<p>Connect your Android device and adb host computer
to a common Wi-Fi network accessible to both.
We have found that not all access points
are suitable; you may need to use an access point
-whose firewall is configured properly to support adb.
+whose firewall is configured properly to support adb.</p>
+
+<p class="note"><strong>Note: </strong>If you are attempting to connect
+to a Wear device, force it to connect to Wi-Fi by shutting off Bluetooth
+on the phone connected to it.</p>
</li>
<li>
-Connect the device with USB cable to host.
+Connect the device to the host computer with a USB cable.
</li>
<li>
-Make sure adb is running in USB mode on host.
-<pre>
-$ adb usb
-restarting in USB mode
-</pre>
-</li>
-
-<li>
-Connect to the device over USB.
-<pre>
-$ adb devices
-List of devices attached
-######## device
-</pre>
-</li>
-
-<li>
-Restart host adb in tcpip mode.
-<pre>
+Set the target device to listen for a TCP/IP connection on port 5555.
+<pre class="no-pretty-print">
$ adb tcpip 5555
-restarting in TCP mode port: 5555
</pre>
</li>
<li>
-Find out the IP address of the Android device:
-Settings -> About tablet -> Status -> IP address.
-Remember the IP address, of the form <code>#.#.#.#</code>.
+Disconnect the USB cable from the target device.
</li>
<li>
-Connect adb host to device:
-<pre>
-$ adb connect #.#.#.#
-connected to #.#.#.#:5555
+Find the IP address of the Android device. For example, on a Nexus device, you can find
+the IP address at <strong>Settings</strong> > <strong>About tablet</strong>
+(or <strong>About phone</strong>) > <strong>Status</strong> > <strong>IP address</strong>. Or,
+on an Android Wear device, you can find the IP address at <strong>Settings</strong> >
+<strong>Wi-Fi Settings</strong> > <strong>Advanced</strong> > <strong>IP address</strong>.
+</li>
+
+<li>
+Connect to the device, identifying it by IP address.
+<pre class="no-pretty-print">
+$ adb connect <device-ip-address>
</pre>
</li>
+
<li>
-Remove USB cable from device, and confirm you can still access device:
-<pre>
+Confirm that your host computer is connected to the target device:
+<pre class="no-pretty-print">
$ adb devices
List of devices attached
-#.#.#.#:5555 device
+<device-ip-address>:5555 device
</pre>
</ol>
@@ -500,10 +492,10 @@
<li>
Or if that doesn't work, reset your adb host:
-<pre>
+<pre class="no-pretty-print">
adb kill-server
</pre>
and then start over from the beginning.
</li>
-</ol>
\ No newline at end of file
+</ol>
diff --git a/docs/html/tools/help/desktop-head-unit.jd b/docs/html/tools/help/desktop-head-unit.jd
new file mode 100644
index 0000000..981979c
--- /dev/null
+++ b/docs/html/tools/help/desktop-head-unit.jd
@@ -0,0 +1,439 @@
+page.title=Desktop Head Unit
+page.tags="auto", "car", "testing","dhu"
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#launching-dhu">Launching the DHU</a></li>
+ <li><a href="#dhu-commands">Issuing DHU Commands</a></li>
+ </ol>
+
+ <h2>See also</h2>
+ <ol>
+ <li><a href="{@docRoot}training/auto/start/index.html#test-it-dhu">Run and Test Auto Apps</a></li>
+ </ol>
+
+</div>
+</div>
+
+
+<p>The Desktop Head Unit (DHU) enables your development machine to emulate an Android Auto
+head unit, so you can easily run and test Android Auto apps. The DHU runs on
+Windows, Mac, and Linux hosts and replaces previous Android Auto simulators,
+such as the Android Media Browser and Messaging
+simulators.</p>
+
+<p class="note"><strong>Note:</strong> For other information about testing Auto apps, see the
+training lesson
+<a href="{@docRoot}training/auto/start/index.html#test-it-dhu">Run and Test Auto Apps</a>. </p>
+
+
+<h2 id="launching-dhu">Launching the DHU</h2>
+
+<p>
+ To launch the DHU, run the <code>desktop-head-unit.exe</code> (on Windows)
+ or <code>desktop-head-unit</code> (on Mac or Linux) command, as described in
+ <a href="{@docRoot}training/auto/start/index.html#connecting-dhu">Connecting
+ the DHU to your mobile device</a>.
+</p>
+
+<p>
+ By default, the DHU emulates the most common form of Android Auto-compatible
+ head unit, which uses a touch screen user interface. You can simulate user
+ touches by clicking the DHU with a mouse. To emulate head units which use
+ a rotary controller for input, you can use the <code>-i controller</code> flag,
+ as in this example:
+</p>
+
+<pre class="no-pretty-print">$ ./desktop-head-unit -i controller</pre>
+
+<p>
+ When the DHU is in rotary-controller mode you can simulate controller
+ operations by using keyboard shortcuts, as described in <a href=
+ "#cmd-bindings">DHU commands and key bindings</a>. If the DHU is in rotary
+ controller mode, it ignores mouse clicks; you must operate Android Auto with
+ the simulated rotary controller operations.
+</p>
+
+<h2 id="dhu-commands">Issuing DHU Commands</h2>
+
+<p>
+ DHU commands allow you to test your app with Android Auto features, such as
+ playing voice input or switching between night and day display mode. You can issue commands to
+ the DHU by running commands from the terminal window where you launched DHU.
+ You can also issue commands by selecting the DHU window and
+ using keyboard shortcuts. The DHU commands
+ and key bindings for all controls are listed in <a href="#cmd-bindings">DHU
+ commands and key bindings</a>.
+</p>
+
+
+<h3 id="day-night">Switching between day and night mode</h3>
+
+<p>
+ Android Auto supports different color schemes for day and night. You should test your app in both
+ day and night mode. You can switch between night and day mode in either of the
+ following ways:
+</p>
+
+<ul>
+ <li>Run the command <code>daynight</code> in the terminal where you launched the DHU.
+ </li>
+
+ <li>Select the DHU window and press the <strong>N</strong> key.
+ </li>
+</ul>
+
+<h3>Microphone testing</h3>
+
+<p>The DHU supports using a microphone for voice input. You can also instruct the DHU to treat
+a pre-recorded voice track as input, as if the DHU had heard the track through the microphone.</p>
+
+<p>To use a pre-recorded sound file as input, enter this command: </p>
+<pre class="no-pretty-print">
+$ mic play <sound_file_path>/<sound_file>.wav
+</pre>
+
+<p>For your convenience, we have provided the following sound files for common
+voice commands. These sound files are installed in the
+<code><sdk>/extras/google/auto/voice/</code> directory.</p>
+
+<dl>
+ <dt>
+ <code>exitnav.wav</code>
+ </dt>
+
+ <dd>
+ "Exit navigation."
+ </dd>
+
+ <dt>
+ <code>navgoogle.wav</code>
+ </dt>
+
+ <dd>
+ "Navigate to 1600 Amphitheatre Parkway, Mountain View."
+ </dd>
+
+ <dt>
+ <code>navsoh.wav</code>
+ </dt>
+
+ <dd>
+ "Navigate to Sydney Opera House."
+ </dd>
+
+ <dt>
+ <code>nextturn.wav</code>
+ </dt>
+
+ <dd>
+ "When is my next turn?"
+ </dd>
+
+ <dt>
+ <code>showalternateroute.wav</code>
+ </dt>
+
+ <dd>
+ "Show alternate routes.""
+ </dd>
+
+ <dt>
+ <code>howlong.wav</code>
+ </dt>
+
+ <dd>
+ "How long until I get there?"
+ </dd>
+
+ <dt>
+ <code>navhome.wav</code>
+ </dt>
+
+ <dd>
+ "Navigate to home."
+ </dd>
+
+ <dt>
+ <code>navwork.wav</code>
+ </dt>
+
+ <dd>
+ "Navigate to work.""
+ </dd>
+
+ <dt>
+ <code>pause.wav</code>
+ </dt>
+
+ <dd>
+ "Pause music."
+ </dd>
+
+ <dt>
+ <code>showtraffic.wav</code>
+ </dt>
+
+ <dd>
+ "Show traffic."
+ </dd>
+</dl>
+<h3 id="cmd-bindings">DHU commands and key bindings</h3>
+
+<p>The DHU supports the following commands.</p>
+
+<p class="table-caption" id="table-commands"><strong>Table 1.</strong> Commands and key bindings</p>
+<table>
+<tr>
+ <th>Category</th>
+ <th>Command</th>
+ <th>Subcommand</th>
+ <th>Argument(s)</th>
+ <th>Keyboard Shortcut(s)</th>
+ <th>Description</th>
+</tr>
+
+<!--system-->
+
+<tr>
+<td rowspan="4">System</td>
+<td>help</td>
+<td></td>
+<td>[command]</td>
+<td></td>
+<td>Shows the full command set. Specifying a command name (for example, <code>help day</code>)
+ causes the system to show help for that command.</td>
+</tr>
+
+<tr>
+
+<td>quit</td>
+<td></td>
+<td></td>
+<td>Alt+q</td>
+<td>Quits the head unit.</td>
+</tr>
+
+<tr>
+
+<td>sleep</td>
+<td></td>
+<td>[seconds]</td>
+<td></td>
+<td>Sleeps for one second. Specifying an argument (for example, <code>sleep 30</code>) causes the
+system to sleep the specified number of seconds. This command
+is useful if you are writing scripts for the DHU. (You can run a script by using I/O redirection
+from the command line: <code>./desktop-head-unit < script.txt</code> loads commands from the
+file <code>script.txt</code>.)</td>
+</tr>
+
+<tr>
+
+<td>screenshot</td>
+<td></td>
+<td>filename.png</td>
+<td></td>
+<td>Saves a screenshot to <code>filename.png</code>.</td>
+</tr>
+
+
+<!--microphone-->
+
+<tr>
+<td rowspan="3">Microphone</td>
+<td rowspan="3">mic</td>
+<td>begin</td>
+<td></td>
+<td>m </td>
+<td>Activates the microphone (equivalent to clicking the steering wheel's microphone button) and
+waits for input from the computer microphone.</td>
+</tr>
+
+<tr>
+
+
+<td>play</td>
+<td>filename.wav</td>
+<td></td>
+<td>Causes the DHU to treat <code>filename.wav</code> as voice input, as if it had heard that sound
+ through the microphone. You do not hear the sound file being played, but you do hear
+ the response from Android Auto.</td>
+</tr>
+
+<tr>
+
+
+<td>repeat</td>
+<td></td>
+<td></td>
+<td>Repeats the last <code>mic play</code> command, as if you had called <code>mic play</code>
+ again with the same sound file parameter.</td>
+</tr>
+
+<!--Input-->
+
+<tr>
+<td rowspan="7">Input</td>
+<td rowspan="6">dpad</td>
+<td>up <br> down <br> left <br> right</td>
+<td></td>
+<td>Arrow keys</td>
+<td>Simulates moving the rotary controller.</td>
+</tr>
+
+<tr>
+
+
+<td>soft left <br> soft right</td>
+<td></td>
+<td>Shift+Arrow keys</td>
+<td>Simulates pressing the side buttons available on some rotary controllers.</td>
+</tr>
+
+<tr>
+
+
+<td>click</td>
+<td></td>
+<td>Return</td>
+<td>Simulates pressing the rotary controller.</td>
+</tr>
+
+<tr>
+
+
+<td>back</td>
+<td></td>
+<td>Backspace</td>
+<td>Simulates pressing the <strong>back</strong> button available below some rotary
+ controllers.</td>
+</tr>
+
+<tr>
+
+
+<td>rotate left <br> rotate right</td>
+<td></td>
+<td>1 <br> 2</td>
+<td>Simulates rotating the rotary controller left (counter-clockwise) or right (clockwise).</td>
+</tr>
+
+<tr>
+
+
+<td>flick left <br> flick right</td>
+<td></td>
+<td>Shift+1 <br> Shift+2</td>
+<td>Simulates a fast spin of the rotary controller to the left (counter-clockwise) or right
+ (clockwise).</td>
+</tr>
+
+<tr>
+
+<td>tap</td>
+<td></td>
+<td>x y</td>
+<td></td>
+<td>Simulates a touch event at the specified coordinates. For example, <code>tap 50 100</code></td>
+</tr>
+
+
+<!--Day/Night-->
+
+<tr>
+<td rowspan="3">Day/Night</td>
+<td>day</td>
+<td></td>
+<td></td>
+<td>Shift+n</td>
+<td>Activates day mode (high brightness, full color).</td>
+</tr>
+
+<tr>
+
+<td>night</td>
+<td></td>
+<td> </td>
+<td>Ctrl+n </td>
+<td>Activates night mode (low brightness, high contrast).</td>
+</tr>
+
+<tr>
+
+<td>daynight</td>
+<td></td>
+<td></td>
+<td>n </td>
+<td>Toggles current day/night mode.</td>
+</tr>
+
+</table>
+
+
+
+
+<h2 id="auto-simulators">Media Browser and Messaging Simulators</h2>
+
+<p class="caution"><strong>Important:</strong> Use of the Android Media Browser and Messaging
+Simulators for testing Android Auto apps is deprecated. Instead, we recommend using the
+Desktop Head Unit, which enables your development machine to act as if it were an Android Auto head
+unit.</p>
+
+<p>To get the simulators, open the
+<a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> and download
+them from <strong>Extras > Android Auto API Simulators</strong>.</p>
+
+<p>Before you begin testing, compile your app in your development environment.
+Install your app and the Android simulator for the features you want to test
+(that is, audio or messaging) on a physical or virtual device running Android
+5.0 (API level 21) or higher. To check the version of Android on the device, go
+to <strong>Settings > About phone</strong> (or <strong>About tablet</strong>)
+<strong>> Android Version</strong>.</p>
+
+<h3 id="testing-audio-apps">Testing audio apps</h3>
+<p>To run and test audio apps:</p>
+
+<ol>
+<li>Install the Android Media Browser simulator
+({@code <sdk>/extras/google/simulators/media-browser-simulator.apk}) on
+the test device. You can do this using
+the <a href="{@docRoot}tools/help/adb.html#move">adb</a> command line tool.</li>
+<li>Enable <a href="{@docRoot}tools/device.html#developer-device-options">
+developer options</a> on the test device.</li>
+<li>Install your app on the test device.</li>
+<li>Launch the Android Media Browser simulator to see how your audio app
+appears in Auto. If your app does not appear, stop the simulator from
+<strong>Settings > Apps</strong> and restart it.</li>
+</ol>
+
+
+<h3 id="testing-messaging-apps">Testing messaging apps</h3>
+<p>To run and test messaging apps:</p>
+
+<ol>
+<li>Install the Android Messaging simulator
+ ({@code <sdk>/extras/google/simulators/messaging-simulator.apk})
+on the test device. You can do this using the
+<a href="{@docRoot}tools/help/adb.html#move">adb</a> command line tool.</li>
+<li>Enable the simulator to read notifications posted on the system:
+<ol type="a">
+ <li>Enable <a href="{@docRoot}tools/device.html#developer-device-options">
+developer options</a> on the test device.</li>
+ <li>Click <strong>Settings > Sounds & Notifications > Notification
+ Access</strong> and check the box labeled
+ <strong>Messaging Simulator</strong>.</li>
+</ol>
+<li>Install your app on the test device.</li>
+<li>Launch the Android Messaging Simulator to see how your messaging app appears
+in Auto. If your app does not appear, stop the simulator from
+<strong>Settings > Apps</strong> and restart it.</li>
+</ol>
+
+
+
+
diff --git a/docs/html/tools/help/monkey.jd b/docs/html/tools/help/monkey.jd
index 941f5d9..7c64830 100644
--- a/docs/html/tools/help/monkey.jd
+++ b/docs/html/tools/help/monkey.jd
@@ -130,7 +130,7 @@
<td><code>--pct-majornav <percent></code></td>
<td>Adjust percentage of "major" navigation events.
(These are navigation events that will typically cause actions within your UI, such as
-the center button in a 5-way pad, the back key, or the menu key.)</td>
+the center button in a 5-way pad or the menu key.)</td>
</tr>
<tr>
diff --git a/docs/html/tools/revisions/studio.jd b/docs/html/tools/revisions/studio.jd
index c922b28..298b173 100644
--- a/docs/html/tools/revisions/studio.jd
+++ b/docs/html/tools/revisions/studio.jd
@@ -43,6 +43,29 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>Android Studio v1.3.2</a> <em>(August 2015)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+ <p>Fixes and enhancements:</p>
+ <ul>
+ <li>Added support for Android 6.0 (API level 23), including new icons and AVD Manager
+ support for creating devices with new screen densities.</li>
+ <li>Fixed an exception that was occuring during update checks.
+ <a href="http://b.android.com/183068">Issue: 183068</a></li>
+ <li>Fixed problem where unresolved view coordinates could cause the layout editor to crash.
+ <a href="http://b.android.com/178690">Issue: 178690</a></li>
+ <li>Fixed issue with invalid resource type warnings.
+ <a href="http://b.android.com/182433">Issue: 182433</a></li>
+ <li>Fixed lint check that was incorrectly flagging resources as private.
+ <a href="http://b.android.com/183120">Issue: 183120</a></li>
+ </ul>
+ </div>
+</div>
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>Android Studio v1.3.1</a> <em>(August 2015)</em>
</p>
<div class="toggle-content-toggleme">
@@ -60,8 +83,6 @@
</div>
-
-
<div class="toggle-content closed">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
@@ -100,7 +121,7 @@
<li>Added <a href="{@docRoot}tools/data-binding/guide.html">data binding</a> support to
create declarative layouts that bind your application logic to layout elements. </li>
<li>Added support for a separate
- <a href="{@docRoot}tools/studio/studio-features.html#test-module">test APK module</a>
+ <a href="{@docRoot}tools/studio/studio-features.html#test-module">test APK module</a>
to build test APKs in Android Studio. </li>
<li>Updated the <a href="{@docRoot}tools/help/avd-manager.html">AVD Manager</a> with HAXM
optimizations and improved notifications. </li>
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index 08634da..3c12a64 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -53,6 +53,39 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>ADT 23.0.7</a> <em>(August 2015)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+<dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Java 7 or higher is required if you are targeting Android 5.0 and higher.</li>
+ <li>Java 1.6 or higher is required if you are targeting other releases.</li>
+ <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li>
+ <li>This version of ADT is designed for use with
+ <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r24.1.2</a>.
+ If you haven't already installed SDK Tools r24.1.2 into your SDK, use the
+ Android SDK Manager to do so.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed issues with the rendering library for the visual layout editor.</li>
+ </ul>
+ </dd>
+</dl>
+</div>
+</div>
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>ADT 23.0.6</a> <em>(March 2015)</em>
</p>
@@ -75,7 +108,7 @@
<dt>General Notes:</dt>
<dd>
<ul>
- <li>Fixed issues with the rendering library.</li>
+ <li>Fixed issues with the rendering library for the visual layout editor.</li>
</ul>
</dd>
</dl>
diff --git a/docs/html/tools/support-library/features.jd b/docs/html/tools/support-library/features.jd
index b3af7a2..19f93e9 100644
--- a/docs/html/tools/support-library/features.jd
+++ b/docs/html/tools/support-library/features.jd
@@ -307,8 +307,8 @@
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. If you are developing in Eclipse/ADT, make sure to include
-both the <code>android-support-v7-mediarouter.jar</code> and
-<code>android-support-v7-appcompat.jar</code> files.</p>
+the <code>android-support-v7-mediarouter.jar</code>, <code>android-support-v7-appcompat.jar</code>,
+and <code>android-support-v7-palette.jar</code> files.</p>
<p>If you are using Android Studio, all you need to do is specify the Gradle build
script dependency identifier <code>com.android.support:support-v7-mediarouter:<revision></code>,
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index db19d4f..72f9f21 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -160,6 +160,7 @@
<li><a href="<?cs var:toroot ?>tools/help/avd-manager.html">AVD Manager</a></li>
<li><a href="<?cs var:toroot ?>tools/help/bmgr.html">bmgr</a>
<li><a href="<?cs var:toroot ?>tools/help/monitor.html">Device Monitor</a></li>
+ <li><a href="<?cs var:toroot ?>tools/help/desktop-head-unit.html">Desktop Head Unit</a></li>
<li><a href="<?cs var:toroot ?>tools/help/dmtracedump.html">dmtracedump</a></li>
<li><a href="<?cs var:toroot ?>tools/help/draw9patch.html">Draw 9-Patch</a></li>
<li><a href="<?cs var:toroot ?>tools/help/emulator.html">Emulator</a></li>
diff --git a/docs/html/training/auto/start/index.jd b/docs/html/training/auto/start/index.jd
index 22e7521..f6cdbd1 100644
--- a/docs/html/training/auto/start/index.jd
+++ b/docs/html/training/auto/start/index.jd
@@ -16,7 +16,7 @@
<ol>
<li><a href="#dev-project">Set Up an Auto Project</a></li>
<li><a href="#build-it">Build Auto Apps</a></li>
- <li><a href="#test-it">Run and Test Auto Apps</a></li>
+ <li><a href="#test-it-dhu">Run and Test Auto Apps </a></li>
</ol>
<h2>You should also read</h2>
@@ -149,57 +149,124 @@
more information, see
<a href="{@docRoot}distribute/essentials/quality/auto.html">Auto App Quality</a>.</p>
-<h2 id="test-it">Run and Test Auto Apps</h2>
-<p>As you prepare to publish your app, make sure that your app looks correct
-when projected on the Auto user interface. Use the Android Media Browser
-simulator and Android Messaging simulators to view and test your audio or
-messaging apps in a screen that looks similar to what is projected on Auto.</p>
-<p>To get the simulators, open the
-<a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> and download
-them from <strong>Extras > Android Auto API Simulators</strong>.</p>
+<h2 id="test-it-dhu">Run and Test Auto Apps </h2>
-<p>Before you begin testing, compile your app in your development environment.
-Install your app and the Android simulator for the features you want to test
-(that is, audio or messaging) on a physical or virtual device running Android
-5.0 (API level 21) or higher. To check the version of Android on the device, go
-to <strong>Settings > About > Android Version</strong>.</p>
+<p>
+ As you develop, you can run and test your app on your development machine
+ using the <em>Desktop Head Unit</em> (DHU). The DHU replaces the existing
+ simulators and enables your development machine to simulate a vehicle
+ dashboard system running Android Auto.
+</p>
-<h3 id="testing-audio-apps">Testing audio apps</h3>
-<p>To run and test audio apps:</p>
+<h3 id="installing-dhu">Installing the DHU</h3>
<ol>
-<li>Install the Android Media Browser simulator
-({@code <sdk>/extras/google/simulators/media-browser-simulator.apk}) on
-the test device. You can do this using
-the <a href="{@docRoot}tools/help/adb.html#move">adb</a> command line tool.</li>
-<li>Enable <a href="{@docRoot}tools/device.html#device-developer-options">
-developer options</a> on the test device.</li>
-<li>Install your app on the test device.</li>
-<li>Launch the Android Media Browser simulator to see how your audio app
-appears in Auto. If your app does not appear, stop the simulator from
-<strong>Settings > Apps</strong> then restart it.</li>
+ <li>Enable developer mode on your mobile device, as described in
+ <a href="{@docRoot}tools/device.html#developer-device-options">Enabling On-device
+ Developer Options</a>. </li>
+ <li>Compile your app in your development environment and install your app on
+ a physical mobile device running Android 5.0 (API level 21) or higher. To check the
+ version of Android on a Nexus device, go to
+ <strong>Settings > About phone</strong> (or <strong>About tablet</strong>) <strong>>
+ Android version</strong>.</li>
+
+ <li>Install the
+ <a class="external-link"
+ href="https://play.google.com/store/apps/details?id=com.google.android.projection.gearhead&hl=en"
+ >Android Auto app</a> on the mobile device.</li>
+ <li>Open the <a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> and
+ download the DHU package <strong>Android Auto Desktop Head Unit</strong> from the
+ <em>SDK Tools</em> tab. The DHU installs in the <code><sdk>/extras/google/auto/</code>
+ directory.</li>
+ <li>If you are running the DHU on Linux, you must also install
+ the portaudio, libpng, sdl2, and sdl2_ttf libraries.
+ The procedure to do this varies depending on your Linux distribution. For example, on
+ Debian-derived Linux distributions, you can install the libraries with this command:
+
+<pre class="no-pretty-print">
+$ sudo apt-get install libsdl2-2.0-0 libsdl2-ttf-2.0-0 libportaudio2 libpng12-0
+</pre>
+
+ </li>
</ol>
-<h3 id="testing-messaging-apps">Testing messaging apps</h3>
-<p>To run and test messaging apps:</p>
+<div class="figure" style="width:330px">
+ <img src="{@docRoot}images/training/auto-desktop-head-unit-server-running.png"
+ alt="" >
+ <p class="img-caption">
+ <strong>Figure 2.</strong> Notification that the head unit server is running.
+ </p>
+</div>
+<img src="{@docRoot}images/training/auto-desktop-head-unit-context-menu-enabled.png"
+ alt="" >
+<p class="img-caption">
+ <strong>Figure 1.</strong> Context menu with developer options.
+</p>
+
+<h3 id="connecting-dhu">Connecting the DHU to your mobile device</h3>
+
+<p>Run the DHU by connecting your mobile device to a development machine and setting up a connection to
+ the head unit server over <a href="{@docRoot}tools/help/adb.html">Android Debug Bridge
+ (ADB)</a>. Follow these steps to set up tunneling and start the DHU:</p>
<ol>
-<li>Install the Android Messaging simulator
- ({@code <sdk>/extras/google/simulators/messaging-simulator.apk})
-on the test device. You can do this using the
-<a href="{@docRoot}tools/help/adb.html#move">adb</a> command line tool.</li>
-<li>Enable the simulator to read notifications posted on the system:
-<ol type="a">
- <li>Enable <a href="{@docRoot}tools/device.html#device-developer-options">
-developer options</a> on the test device.</li>
- <li>Click <strong>Settings > Sounds & Notifications > Notification
- Access</strong> and check the box labeled
- <strong>Messaging Simulator</strong>.</li>
+ <li>On the mobile device, enable Android Auto developer mode by starting the Android Auto
+ companion app, and then tapping the header image 10 times.
+ This step is only required the first time you run the companion app.
+ </li>
+ <li>If the server is not already running, select <strong>Start head unit server</strong>
+ from the Android Auto menu.
+ <p>On the device, a foreground service appears in the notification area. </p>
+ </li>
+
+ <li>Connect the mobile device to the development machine via USB. Your device must be unlocked to
+ launch the DHU.
+ </li>
+ <li>On the development machine, run the following {@code adb} command to
+ forward socket connections from the
+ development machine's port 5277 to the same port number on the Android device.
+ This configuration allows the DHU to connect to the head unit server running on your phone over
+ a TCP socket.
+ <pre class="no-pretty-print">$ adb forward tcp:5277 tcp:5277</pre>
+ </li>
+
+ <li>Start the DHU by running the command <code>desktop-head-unit.exe</code> (on Windows)
+ or <code>./desktop-head-unit</code> (on Mac or Linux) from the
+ <code><sdk>/extras/google/auto/</code> directory.
+
+<pre class="no-pretty-print">$ cd <sdk>/extras/google/auto
+$ ./desktop-head-unit</pre>
+
+ <p>
+ By default, the head unit server connects over port 5277. To override the host or port
+ (for example, to forward over SSH), use the <code>--adb</code> flag.
+ </p>
+
+ </li>
</ol>
-<li>Install your app on the test device.</li>
-<li>Launch the Android Messaging Simulator to see how your messaging app appears
-in Auto. If your app does not appear, stop the simulator from
-<strong>Settings > Apps</strong> then restart it.</li>
-</ol>
+
+<div class="figure" style="width:432px">
+
+ <img src="{@docRoot}images/training/auto-desktop-head-unit-wkst-launch.png"
+ alt="" >
+ <p class="img-caption">
+ <strong>Figure 4.</strong> DHU launches on the development machine.
+ </p>
+</div>
+
+ <img src="{@docRoot}images/training/auto-desktop-head-unit-launch.png"
+ alt="" >
+ <p class="img-caption">
+ <strong>Figure 3.</strong> Android Auto launches on the mobile device.
+ </p>
+
+<p>
+ After you set up and start the DHU, you can run DHU commands from the command line to run and
+ test your app from the terminal. You can also run these commands by using keyboard shortcuts. For
+ more information about DHU configuration and commands, see <a href=
+ "{@docRoot}tools/help/desktop-head-unit.html">Desktop Head Unit</a>.
+</p>
+
+
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 5279969..7cffdd8 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -989,6 +989,9 @@
<a href="<?cs var:toroot ?>training/wearables/watch-faces/information.html">Showing Information in Watch Faces</a>
</li>
<li>
+ <a href="<?cs var:toroot ?>training/wearables/watch-faces/interacting.html">Creating Interactive Watch Faces</a>
+ </li>
+ <li>
<a href="<?cs var:toroot ?>training/wearables/watch-faces/configuration.html">Providing Configuration Activities</a>
</li>
<li>
diff --git a/docs/html/training/wearables/watch-faces/index.jd b/docs/html/training/wearables/watch-faces/index.jd
index ec428c1..a329fda 100644
--- a/docs/html/training/wearables/watch-faces/index.jd
+++ b/docs/html/training/wearables/watch-faces/index.jd
@@ -65,6 +65,9 @@
<dt><a href="{@docRoot}training/wearables/watch-faces/information.html">
Showing Information in Watch Faces</a></dt>
<dd>Learn how to incorporate contextual information into your watch face.</dd>
+<dt><a href="{@docRoot}training/wearables/watch-faces/interacting.html">
+Creating Interactive Watch Faces</a></dt>
+<dd>Learn how to enable the user to interact with your watch face.</dd>
<dt><a href="{@docRoot}training/wearables/watch-faces/configuration.html">
Providing Configuration Activities</a></dt>
<dd>Learn how to create watch faces with configurable parameters.</dd>
diff --git a/docs/html/training/wearables/watch-faces/interacting.jd b/docs/html/training/wearables/watch-faces/interacting.jd
new file mode 100644
index 0000000..5a44fde
--- /dev/null
+++ b/docs/html/training/wearables/watch-faces/interacting.jd
@@ -0,0 +1,133 @@
+page.title=Creating Interactive Watch Faces
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#Construct">Construct an Interactive Watch Face</a></li>
+ <li><a href="#Handle">Handle Gestures</a></li>
+</ol>
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}design/wear/watchfaces.html">Watch Faces for Android Wear</a></li>
+</ul>
+<h2>Related Samples</h2>
+ <ul>
+ <li><a href="{@docRoot}samples/WatchFace/index.html">WatchFace</a></li>
+ </ul>
+</div>
+</div>
+
+<p>Your watch's display is more than just a pretty face: Users can interact with it.
+For example, a user might tap the watch face to learn what song is currently playing, or
+to see the day's agenda. Android Wear allows Android Wear watch faces to accept
+the single-tap gesture at a given location on the watch face, as long as there's not another
+UI element that also responds to that gesture.
+
+<p>This lesson teaches you how to implement an interactive watch face by first constructing the
+watch face style, and then implementing gesture handling.</p>
+
+<p class="note"><strong>Note:</strong> Before beginning development work on your interactive watch
+face, you should be sure to read the <a href="{@docRoot}design/wear/watchfaces.html">Watch Faces for
+Android Wear</a> design guide.
+
+<h2 id="Construct">Handling Tap Events</h2>
+
+<p>When constructing an interactive watch-face style, the first thing the app must do is tell the
+system that the watch face receives <a href="{@docRoot}design/wear/watchfaces.html#ag">tap events</a>.
+The following example shows how to do this:
+
+<pre>
+setWatchFaceStyle(new WatchFaceStyle.Builder(mService)
+ .setAcceptsTapEvents(true)
+ // other style customizations
+ .build());
+</pre>
+
+<p>When the system detects a tap on the watch face, it triggers the
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTapCommand(int, int, int, long)">
+{@code WatchFaceService.Engine.onTapCommand()}</a> method. Override this method in your
+implementation of
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.Engine.html">
+{@code WatchFaceService.Engine}</a>to initiate the action you wish to perform, such
+as showing a detailed step count or changing the theme of the watch face. The code snippet
+in <a href="#Handle">Handle Gestures</a> shows an example of such an
+implementation.</p>
+
+<h2 id="Handle">Handle Gestures</h2>
+
+<p> To provide a consistent user experience, the system
+reserves gestures such as drag and long-press for system UI elements.
+Therefore, the system does not send raw touch events to the watch face. Instead, the system forwards specific commands to the
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTapCommand(int, int, int, long)">
+onTapCommand()</a> method.
+
+<p>The system sends the first command,
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH">
+{@code TAP_TYPE_TOUCH}</a>, when the user initially touches the
+screen. This event lets you provide visual feedback to the user on touch. Your app should not
+launch a UI when this event triggers. Launching a UI prevents drag events from opening the app
+launcher, settings shade, and notifications stream.</p>
+
+<p>Before sending the next command, the system judges whether the contact is a single tap, which is
+<a href="{@docRoot}design/wear/watchfaces.html#ag">the only gesture allowed</a>. If the user
+immediately lifts their finger, the system determines that a single tap took place, and forwards
+a
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP"</a>
+{@code TAP_TYPE_TAP}</a> event. If the user does not immediately lift their finger, the system
+forwards a
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL"</a>
+{@code TAP_TYPE_TOUCH_CANCEL}</a> event. Once the user has triggered a
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL"</a>
+{@code TAP_TYPE_TOUCH_CANCEL}</a> event, they cannot trigger a
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP"</a>
+{@code TAP_TYPE_TAP}</a> event until they
+make a new contact with the screen.</p>
+
+<p>The following example shows you how to implement tap events on a watch face:</p>
+
+
+<pre>
+@Override
+public void onTapCommand(
+ @TapType int tapType, int x, int y, long eventTime) {
+ switch (tapType) {
+ case WatchFaceService.TAP_TYPE_TAP:
+ hideTapHighlight();
+ if (withinTapRegion(x, y)) {
+ // Implement the tap action
+ // (e.g. show detailed step count)
+ onWatchFaceTap();
+ }
+ break;
+
+ case WatchFaceService.TAP_TYPE_TOUCH:
+ if (withinTapRegion(x, y)) {
+ // Provide visual feedback of touch event
+ startTapHighlight(x, y, eventTime);
+ }
+ break;
+
+ case WatchFaceService.TAP_TYPE_TOUCH_CANCEL:
+ hideTapHighlight();
+ break;
+
+ default:
+ super.onTapCommand(tapType, x, y, eventTime);
+ break;
+ }
+}
+</pre>
+
+<p>In this example, the app determines what kind of event has taken place,
+and responds accordingly. If the event is initial contact by the user's finger,
+the app displays visual feedback. If the event is an immediate lifting
+of the finger after contact, it performs the action on which the
+user tapped. If the event is prolonged contact by the finger, the app
+does nothing.</p>
+
+
+
+
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 1add3b85..b5b1a25 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -131,6 +131,13 @@
}
/**
+ * Return the pointer to the native object.
+ */
+ long getNativeInstance() {
+ return mNativePtr;
+ }
+
+ /**
* Native bitmap has been reconfigured, so set premult and cached
* width/height values
*/
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 7bcc7f9..95ae72e 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1281,7 +1281,12 @@
* @hide
*/
public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
- patch.drawSoftware(this, dst, paint);
+ Bitmap bitmap = patch.getBitmap();
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+ native_drawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint,
+ mDensity, patch.getDensity());
}
/**
@@ -1294,7 +1299,12 @@
* @hide
*/
public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
- patch.drawSoftware(this, dst, paint);
+ Bitmap bitmap = patch.getBitmap();
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+ native_drawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint,
+ mDensity, patch.getDensity());
}
/**
@@ -2062,6 +2072,9 @@
long nativePaint);
private static native void native_drawRegion(long nativeCanvas,
long nativeRegion, long nativePaint);
+ private native void native_drawNinePatch(long nativeCanvas, long nativeBitmap,
+ long ninePatch, float dstLeft, float dstTop, float dstRight, float dstBottom,
+ long nativePaintOrZero, int screenDensity, int bitmapDensity);
private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap,
float left, float top,
long nativePaintOrZero,
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 21a212a..b9a1eda 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -198,16 +198,6 @@
canvas.drawPatch(this, location, paint);
}
- void drawSoftware(Canvas canvas, RectF location, Paint paint) {
- nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap, mNativeChunk,
- paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity);
- }
-
- void drawSoftware(Canvas canvas, Rect location, Paint paint) {
- nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap, mNativeChunk,
- paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity);
- }
-
/**
* Return the underlying bitmap's density, as per
* {@link Bitmap#getDensity() Bitmap.getDensity()}.
@@ -273,9 +263,5 @@
*/
private static native long validateNinePatchChunk(byte[] chunk);
private static native void nativeFinalize(long chunk);
- private static native void nativeDraw(long canvas_instance, RectF loc, Bitmap bitmap_instance,
- long c, long paint_instance_or_null, int destDensity, int srcDensity);
- private static native void nativeDraw(long canvas_instance, Rect loc, Bitmap bitmap_instance,
- long c, long paint_instance_or_null, int destDensity, int srcDensity);
private static native long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location);
}
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 0e9823d..91e704a 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -486,9 +486,9 @@
*/
public enum Direction {
/** clockwise */
- CW (1), // must match enum in SkPath.h
+ CW (0), // must match enum in SkPath.h
/** counter-clockwise */
- CCW (2); // must match enum in SkPath.h
+ CCW (1); // must match enum in SkPath.h
Direction(int ni) {
nativeInt = ni;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 32af59a..b95c183 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1146,77 +1146,11 @@
* document, tries to create a Drawable from that tag. Returns {@code null}
* if the tag is not a valid drawable.
*/
- @SuppressWarnings("deprecation")
public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs,
Theme theme) throws XmlPullParserException, IOException {
- final Drawable drawable;
-
- final String name = parser.getName();
- switch (name) {
- case "selector":
- drawable = new StateListDrawable();
- break;
- case "animated-selector":
- drawable = new AnimatedStateListDrawable();
- break;
- case "level-list":
- drawable = new LevelListDrawable();
- break;
- case "layer-list":
- drawable = new LayerDrawable();
- break;
- case "transition":
- drawable = new TransitionDrawable();
- break;
- case "ripple":
- drawable = new RippleDrawable();
- break;
- case "color":
- drawable = new ColorDrawable();
- break;
- case "shape":
- drawable = new GradientDrawable();
- break;
- case "vector":
- drawable = new VectorDrawable();
- break;
- case "animated-vector":
- drawable = new AnimatedVectorDrawable();
- break;
- case "scale":
- drawable = new ScaleDrawable();
- break;
- case "clip":
- drawable = new ClipDrawable();
- break;
- case "rotate":
- drawable = new RotateDrawable();
- break;
- case "animated-rotate":
- drawable = new AnimatedRotateDrawable();
- break;
- case "animation-list":
- drawable = new AnimationDrawable();
- break;
- case "inset":
- drawable = new InsetDrawable();
- break;
- case "bitmap":
- drawable = new BitmapDrawable();
- break;
- case "nine-patch":
- drawable = new NinePatchDrawable();
- break;
- default:
- throw new XmlPullParserException(parser.getPositionDescription() +
- ": invalid drawable tag " + name);
-
- }
- drawable.inflate(r, parser, attrs, theme);
- return drawable;
+ return r.getDrawableInflater().inflateFromXml(parser.getName(), parser, attrs, theme);
}
-
/**
* Create a drawable from file path name.
*/
diff --git a/graphics/java/android/graphics/drawable/DrawableInflater.java b/graphics/java/android/graphics/drawable/DrawableInflater.java
new file mode 100644
index 0000000..20d54ca
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/DrawableInflater.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.annotation.DrawableRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.util.AttributeSet;
+import android.view.InflateException;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+
+/**
+ * Instantiates a drawable XML file into its corresponding
+ * {@link android.graphics.drawable.Drawable} objects.
+ * <p>
+ * For performance reasons, inflation relies heavily on pre-processing of
+ * XML files that is done at build time. Therefore, it is not currently possible
+ * to use this inflater with an XmlPullParser over a plain XML file at runtime;
+ * it only works with an XmlPullParser returned from a compiled resource (R.
+ * <em>something</em> file.)
+ *
+ * @hide Pending API finalization.
+ */
+public final class DrawableInflater {
+ private static final HashMap<String, Constructor<? extends Drawable>> CONSTRUCTOR_MAP =
+ new HashMap<>();
+
+ private final Resources mRes;
+ private final ClassLoader mClassLoader;
+
+ /**
+ * Loads the drawable resource with the specified identifier.
+ *
+ * @param context the context in which the drawable should be loaded
+ * @param id the identifier of the drawable resource
+ * @return a drawable, or {@code null} if the drawable failed to load
+ */
+ @Nullable
+ public static Drawable loadDrawable(@NonNull Context context, @DrawableRes int id) {
+ return loadDrawable(context.getResources(), context.getTheme(), id);
+ }
+
+ /**
+ * Loads the drawable resource with the specified identifier.
+ *
+ * @param resources the resources from which the drawable should be loaded
+ * @param theme the theme against which the drawable should be inflated
+ * @param id the identifier of the drawable resource
+ * @return a drawable, or {@code null} if the drawable failed to load
+ */
+ @Nullable
+ public static Drawable loadDrawable(
+ @NonNull Resources resources, @Nullable Theme theme, @DrawableRes int id) {
+ return resources.getDrawable(id, theme);
+ }
+
+ /**
+ * Constructs a new drawable inflater using the specified resources and
+ * class loader.
+ *
+ * @param res the resources used to resolve resource identifiers
+ * @param classLoader the class loader used to load custom drawables
+ * @hide
+ */
+ public DrawableInflater(@NonNull Resources res, @NonNull ClassLoader classLoader) {
+ mRes = res;
+ mClassLoader = classLoader;
+ }
+
+ /**
+ * Inflates a drawable from inside an XML document using an optional
+ * {@link Theme}.
+ * <p>
+ * This method should be called on a parser positioned at a tag in an XML
+ * document defining a drawable resource. It will attempt to create a
+ * Drawable from the tag at the current position.
+ *
+ * @param name the name of the tag at the current position
+ * @param parser an XML parser positioned at the drawable tag
+ * @param attrs an attribute set that wraps the parser
+ * @param theme the theme against which the drawable should be inflated, or
+ * {@code null} to not inflate against a theme
+ * @return a drawable
+ *
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ @NonNull
+ public Drawable inflateFromXml(@NonNull String name, @NonNull XmlPullParser parser,
+ @NonNull AttributeSet attrs, @Nullable Theme theme)
+ throws XmlPullParserException, IOException {
+ Drawable drawable = inflateFromTag(name);
+ if (drawable == null) {
+ drawable = inflateFromClass(name);
+ }
+ drawable.inflate(mRes, parser, attrs, theme);
+ return drawable;
+ }
+
+ @NonNull
+ @SuppressWarnings("deprecation")
+ private Drawable inflateFromTag(@NonNull String name) {
+ switch (name) {
+ case "selector":
+ return new StateListDrawable();
+ case "animated-selector":
+ return new AnimatedStateListDrawable();
+ case "level-list":
+ return new LevelListDrawable();
+ case "layer-list":
+ return new LayerDrawable();
+ case "transition":
+ return new TransitionDrawable();
+ case "ripple":
+ return new RippleDrawable();
+ case "color":
+ return new ColorDrawable();
+ case "shape":
+ return new GradientDrawable();
+ case "vector":
+ return new VectorDrawable();
+ case "animated-vector":
+ return new AnimatedVectorDrawable();
+ case "scale":
+ return new ScaleDrawable();
+ case "clip":
+ return new ClipDrawable();
+ case "rotate":
+ return new RotateDrawable();
+ case "animated-rotate":
+ return new AnimatedRotateDrawable();
+ case "animation-list":
+ return new AnimationDrawable();
+ case "inset":
+ return new InsetDrawable();
+ case "bitmap":
+ return new BitmapDrawable();
+ case "nine-patch":
+ return new NinePatchDrawable();
+ default:
+ return null;
+ }
+ }
+
+ @NonNull
+ private Drawable inflateFromClass(@NonNull String className) {
+ try {
+ Constructor<? extends Drawable> constructor;
+ synchronized (CONSTRUCTOR_MAP) {
+ constructor = CONSTRUCTOR_MAP.get(className);
+ if (constructor == null) {
+ final Class<? extends Drawable> clazz =
+ mClassLoader.loadClass(className).asSubclass(Drawable.class);
+ constructor = clazz.getConstructor();
+ CONSTRUCTOR_MAP.put(className, constructor);
+ }
+ }
+ return constructor.newInstance();
+ } catch (NoSuchMethodException e) {
+ final InflateException ie = new InflateException(
+ "Error inflating class " + className);
+ ie.initCause(e);
+ throw ie;
+ } catch (ClassCastException e) {
+ // If loaded class is not a Drawable subclass.
+ final InflateException ie = new InflateException(
+ "Class is not a Drawable " + className);
+ ie.initCause(e);
+ throw ie;
+ } catch (ClassNotFoundException e) {
+ // If loadClass fails, we should propagate the exception.
+ throw new InflateException("Class not found " + className);
+ } catch (Exception e) {
+ final InflateException ie = new InflateException(
+ "Error inflating class " + className);
+ ie.initCause(e);
+ throw ie;
+ }
+ }
+}
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 1c14e2f..f9474ef 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -48,8 +48,8 @@
// Software rendering properties.
private float mOpacity = 0;
- public RippleBackground(RippleDrawable owner, Rect bounds) {
- super(owner, bounds);
+ public RippleBackground(RippleDrawable owner, Rect bounds, boolean forceSoftware) {
+ super(owner, bounds, forceSoftware);
}
public boolean isVisible() {
@@ -131,15 +131,7 @@
mPropX = CanvasProperty.createFloat(0);
mPropY = CanvasProperty.createFloat(0);
- // Linear "fast" enter based on current opacity.
final int fastEnterDuration = (int) ((1 - mOpacity) * OPACITY_ENTER_DURATION_FAST);
- if (fastEnterDuration > 0) {
- final RenderNodeAnimator enter = new RenderNodeAnimator(
- mPropPaint, RenderNodeAnimator.PAINT_ALPHA, targetAlpha);
- enter.setInterpolator(LINEAR_INTERPOLATOR);
- enter.setDuration(fastEnterDuration);
- set.add(enter);
- }
// Linear exit after enter is completed.
final RenderNodeAnimator exit = new RenderNodeAnimator(
@@ -149,6 +141,15 @@
exit.setStartDelay(fastEnterDuration);
set.add(exit);
+ // Linear "fast" enter based on current opacity.
+ if (fastEnterDuration > 0) {
+ final RenderNodeAnimator enter = new RenderNodeAnimator(
+ mPropPaint, RenderNodeAnimator.PAINT_ALPHA, targetAlpha);
+ enter.setInterpolator(LINEAR_INTERPOLATOR);
+ enter.setDuration(fastEnterDuration);
+ set.add(enter);
+ }
+
return set;
}
diff --git a/graphics/java/android/graphics/drawable/RippleComponent.java b/graphics/java/android/graphics/drawable/RippleComponent.java
index 23a3ee3..2d378c6 100644
--- a/graphics/java/android/graphics/drawable/RippleComponent.java
+++ b/graphics/java/android/graphics/drawable/RippleComponent.java
@@ -52,9 +52,16 @@
/** Screen density used to adjust pixel-based constants. */
protected float mDensity;
- public RippleComponent(RippleDrawable owner, Rect bounds) {
+ /**
+ * If set, force all ripple animations to not run on RenderThread, even if it would be
+ * available.
+ */
+ private final boolean mForceSoftware;
+
+ public RippleComponent(RippleDrawable owner, Rect bounds, boolean forceSoftware) {
mOwner = owner;
mBounds = bounds;
+ mForceSoftware = forceSoftware;
}
public void onBoundsChange() {
@@ -143,7 +150,7 @@
* @return {@code true} if something was drawn, {@code false} otherwise
*/
public boolean draw(Canvas c, Paint p) {
- final boolean hasDisplayListCanvas = c.isHardwareAccelerated()
+ final boolean hasDisplayListCanvas = !mForceSoftware && c.isHardwareAccelerated()
&& c instanceof DisplayListCanvas;
if (mHasDisplayListCanvas != hasDisplayListCanvas) {
mHasDisplayListCanvas = hasDisplayListCanvas;
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 32f6a89..2690223 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -166,6 +166,12 @@
private boolean mOverrideBounds;
/**
+ * If set, force all ripple animations to not run on RenderThread, even if it would be
+ * available.
+ */
+ private boolean mForceSoftware;
+
+ /**
* Constructor used for drawable inflation.
*/
RippleDrawable() {
@@ -546,7 +552,7 @@
*/
private void tryBackgroundEnter(boolean focused) {
if (mBackground == null) {
- mBackground = new RippleBackground(this, mHotspotBounds);
+ mBackground = new RippleBackground(this, mHotspotBounds, mForceSoftware);
}
mBackground.setup(mState.mMaxRadius, mDensity);
@@ -584,7 +590,7 @@
}
final boolean isBounded = isBounded();
- mRipple = new RippleForeground(this, mHotspotBounds, x, y, isBounded);
+ mRipple = new RippleForeground(this, mHotspotBounds, x, y, isBounded, mForceSoftware);
}
mRipple.setup(mState.mMaxRadius, mDensity);
@@ -855,7 +861,8 @@
// Position the shader to account for canvas translation.
if (mMaskShader != null) {
- mMaskMatrix.setTranslate(-x, -y);
+ final Rect bounds = getBounds();
+ mMaskMatrix.setTranslate(bounds.left - x, bounds.top - y);
mMaskShader.setLocalMatrix(mMaskMatrix);
}
@@ -948,6 +955,16 @@
}
}
+ /**
+ * Sets whether to disable RenderThread animations for this ripple.
+ *
+ * @param forceSoftware true if RenderThread animations should be disabled, false otherwise
+ * @hide
+ */
+ public void setForceSoftware(boolean forceSoftware) {
+ mForceSoftware = forceSoftware;
+ }
+
@Override
public ConstantState getConstantState() {
return mState;
diff --git a/graphics/java/android/graphics/drawable/RippleForeground.java b/graphics/java/android/graphics/drawable/RippleForeground.java
index 4853b04..c660846 100644
--- a/graphics/java/android/graphics/drawable/RippleForeground.java
+++ b/graphics/java/android/graphics/drawable/RippleForeground.java
@@ -87,8 +87,8 @@
private boolean mHasFinishedExit;
public RippleForeground(RippleDrawable owner, Rect bounds, float startingX, float startingY,
- boolean isBounded) {
- super(owner, bounds);
+ boolean isBounded, boolean forceSoftware) {
+ super(owner, bounds, forceSoftware);
mIsBounded = isBounded;
mStartingX = startingX;
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 751531e..20ecda2 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -52,14 +52,14 @@
// If this is set to negative value, then all the edge will be tessellated.
#define ALPHA_THRESHOLD (0.1f / 255.0f)
-#include <math.h>
-#include <utils/Log.h>
-
#include "AmbientShadow.h"
+
#include "ShadowTessellator.h"
#include "Vertex.h"
#include "VertexBuffer.h"
-#include "utils/MathUtils.h"
+
+#include <algorithm>
+#include <utils/Log.h>
namespace android {
namespace uirenderer {
@@ -78,7 +78,7 @@
// The input z value will be converted to be non-negative inside.
// The output must be ranged from 0 to 1.
inline float getAlphaFromFactoredZ(float factoredZ) {
- return 1.0 / (1 + MathUtils::max(factoredZ, 0.0f));
+ return 1.0 / (1 + std::max(factoredZ, 0.0f));
}
// The shader is using gaussian function e^-(1-x)*(1-x)*4, therefore, we transform
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index e5bc664..b3b3479 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -23,6 +23,7 @@
utils/Blur.cpp \
utils/GLUtils.cpp \
utils/LinearAllocator.cpp \
+ utils/NinePatchImpl.cpp \
AmbientShadow.cpp \
AnimationContext.cpp \
Animator.cpp \
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 512e0e2..5ca2a2f 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -36,8 +36,8 @@
, mFinalValue(finalValue)
, mDeltaValue(0)
, mFromValue(0)
- , mStagingPlayState(NOT_STARTED)
- , mPlayState(NOT_STARTED)
+ , mStagingPlayState(PlayState::NotStarted)
+ , mPlayState(PlayState::NotStarted)
, mHasStartValue(false)
, mStartTime(0)
, mDuration(300)
@@ -50,7 +50,7 @@
void BaseRenderNodeAnimator::checkMutable() {
// Should be impossible to hit as the Java-side also has guards for this
- LOG_ALWAYS_FATAL_IF(mStagingPlayState != NOT_STARTED,
+ LOG_ALWAYS_FATAL_IF(mStagingPlayState != PlayState::NotStarted,
"Animator has already been started!");
}
@@ -92,9 +92,9 @@
if (mStagingPlayState > mPlayState) {
mPlayState = mStagingPlayState;
// Oh boy, we're starting! Man the battle stations!
- if (mPlayState == RUNNING) {
+ if (mPlayState == PlayState::Running) {
transitionToRunning(context);
- } else if (mPlayState == FINISHED) {
+ } else if (mPlayState == PlayState::Finished) {
callOnFinishedListener(context);
}
}
@@ -124,10 +124,10 @@
}
bool BaseRenderNodeAnimator::animate(AnimationContext& context) {
- if (mPlayState < RUNNING) {
+ if (mPlayState < PlayState::Running) {
return false;
}
- if (mPlayState == FINISHED) {
+ if (mPlayState == PlayState::Finished) {
return true;
}
@@ -141,18 +141,18 @@
}
float fraction = 1.0f;
- if (mPlayState == RUNNING && mDuration > 0) {
+ if (mPlayState == PlayState::Running && mDuration > 0) {
fraction = (float)(context.frameTimeMs() - mStartTime) / mDuration;
}
if (fraction >= 1.0f) {
fraction = 1.0f;
- mPlayState = FINISHED;
+ mPlayState = PlayState::Finished;
}
fraction = mInterpolator->interpolate(fraction);
setValue(mTarget, mFromValue + (mDeltaValue * fraction));
- if (mPlayState == FINISHED) {
+ if (mPlayState == PlayState::Finished) {
callOnFinishedListener(context);
return true;
}
@@ -161,8 +161,8 @@
}
void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
- if (mPlayState < FINISHED) {
- mPlayState = FINISHED;
+ if (mPlayState < PlayState::Finished) {
+ mPlayState = PlayState::Finished;
callOnFinishedListener(context);
}
}
@@ -212,9 +212,9 @@
}
void RenderPropertyAnimator::onStagingPlayStateChanged() {
- if (mStagingPlayState == RUNNING) {
+ if (mStagingPlayState == PlayState::Running) {
(mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
- } else if (mStagingPlayState == FINISHED) {
+ } else if (mStagingPlayState == PlayState::Finished) {
// We're being canceled, so make sure that whatever values the UI thread
// is observing for us is pushed over
mTarget->setPropertyFieldsDirty(dirtyMask());
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 1b3d8e7..aea95bf 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -59,8 +59,8 @@
mMayRunAsync = mayRunAsync;
}
bool mayRunAsync() { return mMayRunAsync; }
- ANDROID_API void start() { mStagingPlayState = RUNNING; onStagingPlayStateChanged(); }
- ANDROID_API void end() { mStagingPlayState = FINISHED; onStagingPlayStateChanged(); }
+ ANDROID_API void start() { mStagingPlayState = PlayState::Running; onStagingPlayStateChanged(); }
+ ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); }
void attach(RenderNode* target);
virtual void onAttached() {}
@@ -68,8 +68,8 @@
void pushStaging(AnimationContext& context);
bool animate(AnimationContext& context);
- bool isRunning() { return mPlayState == RUNNING; }
- bool isFinished() { return mPlayState == FINISHED; }
+ bool isRunning() { return mPlayState == PlayState::Running; }
+ bool isFinished() { return mPlayState == PlayState::Finished; }
float finalValue() { return mFinalValue; }
ANDROID_API virtual uint32_t dirtyMask() = 0;
@@ -77,6 +77,12 @@
void forceEndNow(AnimationContext& context);
protected:
+ enum class PlayState {
+ NotStarted,
+ Running,
+ Finished,
+ };
+
BaseRenderNodeAnimator(float finalValue);
virtual ~BaseRenderNodeAnimator();
@@ -88,12 +94,6 @@
virtual void onStagingPlayStateChanged() {}
- enum PlayState {
- NOT_STARTED,
- RUNNING,
- FINISHED,
- };
-
RenderNode* mTarget;
float mFinalValue;
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f663f07..ff71313 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -245,7 +245,7 @@
FLUSH_LOGD("Flushing caches (mode %d)", mode);
switch (mode) {
- case kFlushMode_Full:
+ case FlushMode::Full:
textureCache.clear();
patchCache.clear();
dropShadowCache.clear();
@@ -254,13 +254,13 @@
fboCache.clear();
dither.clear();
// fall through
- case kFlushMode_Moderate:
+ case FlushMode::Moderate:
fontRenderer->flush();
textureCache.flush();
pathCache.clear();
tessellationCache.clear();
// fall through
- case kFlushMode_Layers:
+ case FlushMode::Layers:
layerCache.clear();
renderBufferCache.clear();
break;
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index a02e15d..929db17 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -83,10 +83,10 @@
static Caches* sInstance;
public:
- enum FlushMode {
- kFlushMode_Layers = 0,
- kFlushMode_Moderate,
- kFlushMode_Full
+ enum class FlushMode {
+ Layers = 0,
+ Moderate,
+ Full
};
/**
@@ -103,7 +103,7 @@
/**
* Destroys all resources associated with this cache. This should
- * be called after a flush(kFlushMode_Full).
+ * be called after a flush(FlushMode::Full).
*/
void terminate();
diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h
index a0b87f9..4bd4ac8 100644
--- a/libs/hwui/Canvas.h
+++ b/libs/hwui/Canvas.h
@@ -19,6 +19,8 @@
#include <cutils/compiler.h>
+#include "utils/NinePatch.h"
+
#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkMatrix.h>
@@ -83,10 +85,6 @@
virtual void getMatrix(SkMatrix* outMatrix) const = 0;
virtual void setMatrix(const SkMatrix& matrix) = 0;
- /// Like setMatrix(), but to be translated into local / view-relative coordinates
- /// rather than executed in global / device coordinates at rendering time.
- virtual void setLocalMatrix(const SkMatrix& matrix) = 0;
-
virtual void concat(const SkMatrix& matrix) = 0;
virtual void rotate(float degrees) = 0;
virtual void scale(float sx, float sy) = 0;
@@ -144,6 +142,9 @@
float dstRight, float dstBottom, const SkPaint* paint) = 0;
virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
const float* vertices, const int* colors, const SkPaint* paint) = 0;
+ virtual void drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) = 0;
// Text
/**
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index e22b0d3..e307ad9 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -138,7 +138,7 @@
}
void CanvasState::setMatrix(const Matrix4& matrix) {
- mSnapshot->transform->load(matrix);
+ *(mSnapshot->transform) = matrix;
}
void CanvasState::concatMatrix(const SkMatrix& matrix) {
@@ -155,17 +155,20 @@
///////////////////////////////////////////////////////////////////////////////
bool CanvasState::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
- mDirtyClip |= mSnapshot->clip(left, top, right, bottom, op);
+ mSnapshot->clip(left, top, right, bottom, op);
+ mDirtyClip = true;
return !mSnapshot->clipIsEmpty();
}
bool CanvasState::clipPath(const SkPath* path, SkRegion::Op op) {
- mDirtyClip |= mSnapshot->clipPath(*path, op);
+ mSnapshot->clipPath(*path, op);
+ mDirtyClip = true;
return !mSnapshot->clipIsEmpty();
}
bool CanvasState::clipRegion(const SkRegion* region, SkRegion::Op op) {
- mDirtyClip |= mSnapshot->clipRegionTransformed(*region, op);
+ mSnapshot->clipRegionTransformed(*region, op);
+ mDirtyClip = true;
return !mSnapshot->clipIsEmpty();
}
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index b1a6844..8e7efb4 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -32,9 +32,7 @@
}
static void handlePoint(Rect& transformedBounds, const Matrix4& transform, float x, float y) {
- Vertex v;
- v.x = x;
- v.y = y;
+ Vertex v = {x, y};
transform.mapPoint(v.x, v.y);
transformedBounds.expandToCoverVertex(v.x, v.y);
}
@@ -187,7 +185,7 @@
*/
ClipArea::ClipArea()
- : mMode(kModeRectangle) {
+ : mMode(Mode::Rectangle) {
}
/*
@@ -200,45 +198,46 @@
}
void ClipArea::setEmpty() {
- mMode = kModeRectangle;
+ mMode = Mode::Rectangle;
mClipRect.setEmpty();
mClipRegion.setEmpty();
mRectangleList.setEmpty();
}
void ClipArea::setClip(float left, float top, float right, float bottom) {
- mMode = kModeRectangle;
+ mMode = Mode::Rectangle;
mClipRect.set(left, top, right, bottom);
mClipRegion.setEmpty();
}
-bool ClipArea::clipRectWithTransform(float left, float top, float right,
+void ClipArea::clipRectWithTransform(float left, float top, float right,
float bottom, const mat4* transform, SkRegion::Op op) {
Rect r(left, top, right, bottom);
- return clipRectWithTransform(r, transform, op);
+ clipRectWithTransform(r, transform, op);
}
-bool ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform,
+void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform,
SkRegion::Op op) {
switch (mMode) {
- case kModeRectangle:
- return rectangleModeClipRectWithTransform(r, transform, op);
- case kModeRectangleList:
- return rectangleListModeClipRectWithTransform(r, transform, op);
- case kModeRegion:
- return regionModeClipRectWithTransform(r, transform, op);
+ case Mode::Rectangle:
+ rectangleModeClipRectWithTransform(r, transform, op);
+ break;
+ case Mode::RectangleList:
+ rectangleListModeClipRectWithTransform(r, transform, op);
+ break;
+ case Mode::Region:
+ regionModeClipRectWithTransform(r, transform, op);
+ break;
}
- return false;
}
-bool ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
+void ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
enterRegionMode();
mClipRegion.op(region, op);
onClipRegionUpdated();
- return true;
}
-bool ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform,
+void ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform,
SkRegion::Op op) {
SkMatrix skTransform;
transform->copyTo(skTransform);
@@ -246,7 +245,7 @@
path.transform(skTransform, &transformed);
SkRegion region;
regionFromPath(transformed, region);
- return clipRegion(region, op);
+ clipRegion(region, op);
}
/*
@@ -257,19 +256,20 @@
// Entering rectangle mode discards any
// existing clipping information from the other modes.
// The only way this occurs is by a clip setting operation.
- mMode = kModeRectangle;
+ mMode = Mode::Rectangle;
}
-bool ClipArea::rectangleModeClipRectWithTransform(const Rect& r,
+void ClipArea::rectangleModeClipRectWithTransform(const Rect& r,
const mat4* transform, SkRegion::Op op) {
if (op == SkRegion::kReplace_Op && transform->rectToRect()) {
mClipRect = r;
transform->mapRect(mClipRect);
- return true;
+ return;
} else if (op != SkRegion::kIntersect_Op) {
enterRegionMode();
- return regionModeClipRectWithTransform(r, transform, op);
+ regionModeClipRectWithTransform(r, transform, op);
+ return;
}
if (transform->rectToRect()) {
@@ -279,19 +279,18 @@
if (!hasIntersection) {
mClipRect.setEmpty();
}
- return true;
+ return;
}
enterRectangleListMode();
- return rectangleListModeClipRectWithTransform(r, transform, op);
+ rectangleListModeClipRectWithTransform(r, transform, op);
}
-bool ClipArea::rectangleModeClipRectWithTransform(float left, float top,
+void ClipArea::rectangleModeClipRectWithTransform(float left, float top,
float right, float bottom, const mat4* transform, SkRegion::Op op) {
Rect r(left, top, right, bottom);
- bool result = rectangleModeClipRectWithTransform(r, transform, op);
+ rectangleModeClipRectWithTransform(r, transform, op);
mClipRect = mRectangleList.calculateBounds();
- return result;
}
/*
@@ -302,25 +301,24 @@
// Is is only legal to enter rectangle list mode from
// rectangle mode, since rectangle list mode cannot represent
// all clip areas that can be represented by a region.
- ALOG_ASSERT(mMode == kModeRectangle);
- mMode = kModeRectangleList;
+ ALOG_ASSERT(mMode == Mode::Rectangle);
+ mMode = Mode::RectangleList;
mRectangleList.set(mClipRect, Matrix4::identity());
}
-bool ClipArea::rectangleListModeClipRectWithTransform(const Rect& r,
+void ClipArea::rectangleListModeClipRectWithTransform(const Rect& r,
const mat4* transform, SkRegion::Op op) {
if (op != SkRegion::kIntersect_Op
|| !mRectangleList.intersectWith(r, *transform)) {
enterRegionMode();
- return regionModeClipRectWithTransform(r, transform, op);
+ regionModeClipRectWithTransform(r, transform, op);
}
- return true;
}
-bool ClipArea::rectangleListModeClipRectWithTransform(float left, float top,
+void ClipArea::rectangleListModeClipRectWithTransform(float left, float top,
float right, float bottom, const mat4* transform, SkRegion::Op op) {
Rect r(left, top, right, bottom);
- return rectangleListModeClipRectWithTransform(r, transform, op);
+ rectangleListModeClipRectWithTransform(r, transform, op);
}
/*
@@ -329,9 +327,9 @@
void ClipArea::enterRegionMode() {
Mode oldMode = mMode;
- mMode = kModeRegion;
- if (oldMode != kModeRegion) {
- if (oldMode == kModeRectangle) {
+ mMode = Mode::Region;
+ if (oldMode != Mode::Region) {
+ if (oldMode == Mode::Rectangle) {
mClipRegion.setRect(mClipRect.left, mClipRect.top,
mClipRect.right, mClipRect.bottom);
} else {
@@ -341,20 +339,18 @@
}
}
-bool ClipArea::regionModeClipRectWithTransform(const Rect& r,
+void ClipArea::regionModeClipRectWithTransform(const Rect& r,
const mat4* transform, SkRegion::Op op) {
SkPath transformedRect = pathFromTransformedRectangle(r, *transform);
SkRegion transformedRectRegion;
regionFromPath(transformedRect, transformedRectRegion);
mClipRegion.op(transformedRectRegion, op);
onClipRegionUpdated();
- return true;
}
-bool ClipArea::regionModeClipRectWithTransform(float left, float top,
+void ClipArea::regionModeClipRectWithTransform(float left, float top,
float right, float bottom, const mat4* transform, SkRegion::Op op) {
- return regionModeClipRectWithTransform(Rect(left, top, right, bottom),
- transform, op);
+ regionModeClipRectWithTransform(Rect(left, top, right, bottom), transform, op);
}
void ClipArea::onClipRegionUpdated() {
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index 51ef27b..38fefe5 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -80,6 +80,13 @@
};
class ClipArea {
+private:
+ enum class Mode {
+ Rectangle,
+ Region,
+ RectangleList
+ };
+
public:
ClipArea();
@@ -91,12 +98,12 @@
void setEmpty();
void setClip(float left, float top, float right, float bottom);
- bool clipRectWithTransform(float left, float top, float right, float bottom,
- const mat4* transform, SkRegion::Op op = SkRegion::kIntersect_Op);
- bool clipRectWithTransform(const Rect& r, const mat4* transform,
- SkRegion::Op op = SkRegion::kIntersect_Op);
- bool clipRegion(const SkRegion& region, SkRegion::Op op = SkRegion::kIntersect_Op);
- bool clipPathWithTransform(const SkPath& path, const mat4* transform,
+ void clipRectWithTransform(float left, float top, float right, float bottom,
+ const mat4* transform, SkRegion::Op op);
+ void clipRectWithTransform(const Rect& r, const mat4* transform,
+ SkRegion::Op op);
+ void clipRegion(const SkRegion& region, SkRegion::Op op);
+ void clipPathWithTransform(const SkPath& path, const mat4* transform,
SkRegion::Op op);
const Rect& getClipRect() const {
@@ -112,41 +119,39 @@
}
bool isRegion() const {
- return kModeRegion == mMode;
+ return Mode::Region == mMode;
}
bool isSimple() const {
- return mMode == kModeRectangle;
+ return mMode == Mode::Rectangle;
}
bool isRectangleList() const {
- return mMode == kModeRectangleList;
+ return mMode == Mode::RectangleList;
}
private:
void enterRectangleMode();
- bool rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
- bool rectangleModeClipRectWithTransform(float left, float top, float right,
+ void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
+ void rectangleModeClipRectWithTransform(float left, float top, float right,
float bottom, const mat4* transform, SkRegion::Op op);
void enterRectangleListMode();
- bool rectangleListModeClipRectWithTransform(float left, float top,
+ void rectangleListModeClipRectWithTransform(float left, float top,
float right, float bottom, const mat4* transform, SkRegion::Op op);
- bool rectangleListModeClipRectWithTransform(const Rect& r,
+ void rectangleListModeClipRectWithTransform(const Rect& r,
const mat4* transform, SkRegion::Op op);
void enterRegionModeFromRectangleMode();
void enterRegionModeFromRectangleListMode();
void enterRegionMode();
- bool regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
+ void regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
SkRegion::Op op);
- bool regionModeClipRectWithTransform(float left, float top, float right,
+ void regionModeClipRectWithTransform(float left, float top, float right,
float bottom, const mat4* transform, SkRegion::Op op);
void ensureClipRegion();
void onClipRegionUpdated();
- bool clipRegionOp(float left, float top, float right, float bottom,
- SkRegion::Op op);
SkRegion createViewportRegion() {
return SkRegion(mViewportBounds.toSkIRect());
@@ -158,12 +163,6 @@
pathAsRegion.setPath(path, createViewportRegion());
}
- enum Mode {
- kModeRectangle,
- kModeRegion,
- kModeRectangleList
- };
-
Mode mMode;
Rect mViewportBounds;
Rect mClipRect;
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index fb2b1fb..506bfad 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -168,11 +168,6 @@
mState.setMatrix(matrix);
}
-void DisplayListCanvas::setLocalMatrix(const SkMatrix& matrix) {
- addStateOp(new (alloc()) SetLocalMatrixOp(matrix));
- mState.setMatrix(matrix);
-}
-
void DisplayListCanvas::concat(const SkMatrix& matrix) {
addStateOp(new (alloc()) ConcatMatrixOp(matrix));
mState.concatMatrix(matrix);
@@ -221,11 +216,11 @@
addRenderNodeOp(op);
}
-void DisplayListCanvas::drawLayer(DeferredLayerUpdater* layerHandle, float x, float y) {
+void DisplayListCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
// We ref the DeferredLayerUpdater due to its thread-safe ref-counting
// semantics.
mDisplayListData->ref(layerHandle);
- addDrawOp(new (alloc()) DrawLayerOp(layerHandle->backingLayer(), x, y));
+ addDrawOp(new (alloc()) DrawLayerOp(layerHandle->backingLayer()));
}
void DisplayListCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
@@ -322,13 +317,14 @@
vertices, colors, paint));
}
-void DisplayListCanvas::drawPatch(const SkBitmap& bitmap, const Res_png_9patch* patch,
- float left, float top, float right, float bottom, const SkPaint* paint) {
+void DisplayListCanvas::drawNinePatch(const SkBitmap& bitmap, const Res_png_9patch& patch,
+ float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
const SkBitmap* bitmapPtr = refBitmap(bitmap);
- patch = refPatch(patch);
+ const Res_png_9patch* patchPtr = refPatch(&patch);
paint = refPaint(paint);
- addDrawOp(new (alloc()) DrawPatchOp(bitmapPtr, patch, left, top, right, bottom, paint));
+ addDrawOp(new (alloc()) DrawPatchOp(bitmapPtr, patchPtr,
+ dstLeft, dstTop, dstRight, dstBottom, paint));
}
void DisplayListCanvas::drawColor(int color, SkXfermode::Mode mode) {
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index f3f5713..392bb3e 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -79,10 +79,6 @@
// HWUI Canvas draw operations
// ----------------------------------------------------------------------------
- // TODO: move drawPatch() to Canvas.h
- void drawPatch(const SkBitmap& bitmap, const Res_png_9patch* patch,
- float left, float top, float right, float bottom, const SkPaint* paint);
-
// Shapes
void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
@@ -95,7 +91,7 @@
// ----------------------------------------------------------------------------
// HWUI Canvas draw operations - special
// ----------------------------------------------------------------------------
- void drawLayer(DeferredLayerUpdater* layerHandle, float x, float y);
+ void drawLayer(DeferredLayerUpdater* layerHandle);
void drawRenderNode(RenderNode* renderNode);
// TODO: rename for consistency
@@ -147,7 +143,6 @@
// Matrix
virtual void getMatrix(SkMatrix* outMatrix) const override { mState.getMatrix(outMatrix); }
virtual void setMatrix(const SkMatrix& matrix) override;
- virtual void setLocalMatrix(const SkMatrix& matrix) override;
virtual void concat(const SkMatrix& matrix) override;
virtual void rotate(float degrees) override;
@@ -209,6 +204,9 @@
float dstRight, float dstBottom, const SkPaint* paint) override;
virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
const float* vertices, const int* colors, const SkPaint* paint) override;
+ virtual void drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) override;
// Text
virtual void drawText(const uint16_t* glyphs, const float* positions, int count,
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 8ff58d4..14126a9 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -472,7 +472,9 @@
: mMatrix(matrix) {}
virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.setMatrix(mMatrix);
+ // Setting a matrix on a Canvas isn't equivalent to setting a total matrix on the scene.
+ // Set a canvas-relative matrix on the renderer instead.
+ renderer.setLocalMatrix(mMatrix);
}
virtual void output(int level, uint32_t logFlags) const override {
@@ -489,25 +491,6 @@
const SkMatrix mMatrix;
};
-class SetLocalMatrixOp : public StateOp {
-public:
- SetLocalMatrixOp(const SkMatrix& matrix)
- : mMatrix(matrix) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.setLocalMatrix(mMatrix);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("SetLocalMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
- }
-
- virtual const char* name() override { return "SetLocalMatrix"; }
-
-private:
- const SkMatrix mMatrix;
-};
-
class ConcatMatrixOp : public StateOp {
public:
ConcatMatrixOp(const SkMatrix& matrix)
@@ -1541,23 +1524,21 @@
class DrawLayerOp : public DrawOp {
public:
- DrawLayerOp(Layer* layer, float x, float y)
- : DrawOp(nullptr), mLayer(layer), mX(x), mY(y) {}
+ DrawLayerOp(Layer* layer)
+ : DrawOp(nullptr), mLayer(layer) {}
virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawLayer(mLayer, mX, mY);
+ renderer.drawLayer(mLayer);
}
virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
+ OP_LOG("Draw Layer %p", mLayer);
}
virtual const char* name() override { return "DrawLayer"; }
private:
Layer* mLayer;
- float mX;
- float mY;
};
}; // namespace uirenderer
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 057c231..75c3ead 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -26,14 +26,12 @@
#include "Rect.h"
#include "renderstate/RenderState.h"
#include "utils/Blur.h"
-#include "utils/MathUtils.h"
#include "utils/Timing.h"
+#include <algorithm>
+#include <cutils/properties.h>
#include <SkGlyph.h>
#include <SkUtils.h>
-
-#include <cutils/properties.h>
-
#include <utils/Log.h>
#ifdef ANDROID_ENABLE_RENDERSCRIPT
@@ -118,10 +116,10 @@
uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize;
- mSmallCacheWidth = MathUtils::min(mSmallCacheWidth, maxTextureSize);
- mSmallCacheHeight = MathUtils::min(mSmallCacheHeight, maxTextureSize);
- mLargeCacheWidth = MathUtils::min(mLargeCacheWidth, maxTextureSize);
- mLargeCacheHeight = MathUtils::min(mLargeCacheHeight, maxTextureSize);
+ mSmallCacheWidth = std::min(mSmallCacheWidth, maxTextureSize);
+ mSmallCacheHeight = std::min(mSmallCacheHeight, maxTextureSize);
+ mLargeCacheWidth = std::min(mLargeCacheWidth, maxTextureSize);
+ mLargeCacheHeight = std::min(mLargeCacheHeight, maxTextureSize);
if (sLogFontRendererCreate) {
INIT_LOGD(" Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i",
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 288fed3..e27b26b 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -274,7 +274,7 @@
SkXfermode::Mode mode;
SkScalar srcColorMatrix[20];
if (colorFilter->asColorMode(&color, &mode)) {
- mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::kColorBlend;
+ mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Blend;
mDescription.colorMode = mode;
const float alpha = SkColorGetA(color) / 255.0f;
@@ -286,7 +286,7 @@
alpha,
};
} else if (colorFilter->asColorMatrix(srcColorMatrix)) {
- mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::kColorMatrix;
+ mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Matrix;
float* colorMatrix = mOutGlop->fill.filter.matrix.matrix;
memcpy(colorMatrix, srcColorMatrix, 4 * sizeof(float));
@@ -305,7 +305,7 @@
LOG_ALWAYS_FATAL("unsupported ColorFilter");
}
} else {
- mOutGlop->fill.filterMode = ProgramDescription::kColorNone;
+ mOutGlop->fill.filterMode = ProgramDescription::ColorFilterMode::None;
}
}
@@ -467,8 +467,8 @@
const int transformFlags) {
TRIGGER_STAGE(kTransformStage);
- mOutGlop->transform.ortho.load(ortho);
- mOutGlop->transform.canvas.load(canvas);
+ mOutGlop->transform.ortho = ortho;
+ mOutGlop->transform.canvas = canvas;
mOutGlop->transform.transformFlags = transformFlags;
}
@@ -615,7 +615,7 @@
shaderMatrix.loadInverse(mOutGlop->transform.canvas);
shaderMatrix.multiply(mOutGlop->transform.modelView);
} else {
- shaderMatrix.load(mOutGlop->transform.modelView);
+ shaderMatrix = mOutGlop->transform.modelView;
}
SkiaShader::store(mCaches, *mShader, shaderMatrix,
&textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData));
diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp
index e1b0fc3..cc47f00 100644
--- a/libs/hwui/Interpolator.cpp
+++ b/libs/hwui/Interpolator.cpp
@@ -16,11 +16,11 @@
#include "Interpolator.h"
-#include <cmath>
-#include <cutils/log.h>
-
#include "utils/MathUtils.h"
+#include <algorithm>
+#include <cutils/log.h>
+
namespace android {
namespace uirenderer {
@@ -106,7 +106,7 @@
weight = modff(lutpos, &ipart);
int i1 = (int) ipart;
- int i2 = MathUtils::min(i1 + 1, (int) mSize - 1);
+ int i2 = std::min(i1 + 1, (int) mSize - 1);
LOG_ALWAYS_FATAL_IF(i1 < 0 || i2 < 0, "negatives in interpolation!"
" i1=%d, i2=%d, input=%f, lutpos=%f, size=%zu, values=%p, ipart=%f, weight=%f",
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 928f91b..e748221 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -36,7 +36,7 @@
namespace uirenderer {
Layer::Layer(Type layerType, RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
- : state(kState_Uncached)
+ : state(State::Uncached)
, caches(Caches::getInstance())
, renderState(renderState)
, texture(caches)
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index b670870..e90f055 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -56,19 +56,19 @@
*/
class Layer : public VirtualLightRefBase {
public:
- enum Type {
- kType_Texture,
- kType_DisplayList,
+ enum class Type {
+ Texture,
+ DisplayList,
};
// layer lifecycle, controlled from outside
- enum State {
- kState_Uncached = 0,
- kState_InCache = 1,
- kState_FailedToCache = 2,
- kState_RemovedFromCache = 3,
- kState_DeletedFromCache = 4,
- kState_InGarbageList = 5,
+ enum class State {
+ Uncached = 0,
+ InCache = 1,
+ FailedToCache = 2,
+ RemovedFromCache = 3,
+ DeletedFromCache = 4,
+ InGarbageList = 5,
};
State state; // public for logging/debugging purposes
@@ -241,7 +241,7 @@
}
inline bool isTextureLayer() const {
- return type == kType_Texture;
+ return type == Type::Texture;
}
inline SkColorFilter* getColorFilter() const {
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 33f40b0..39cadd1 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -81,7 +81,7 @@
LAYER_LOGD("Destroying layer %dx%d, fbo %d", layer->getWidth(), layer->getHeight(),
layer->getFbo());
mSize -= layer->getWidth() * layer->getHeight() * 4;
- layer->state = Layer::kState_DeletedFromCache;
+ layer->state = Layer::State::DeletedFromCache;
layer->decStrong(nullptr);
}
}
@@ -104,14 +104,14 @@
mCache.erase(iter);
layer = entry.mLayer;
- layer->state = Layer::kState_RemovedFromCache;
+ layer->state = Layer::State::RemovedFromCache;
mSize -= layer->getWidth() * layer->getHeight() * 4;
LAYER_LOGD("Reusing layer %dx%d", layer->getWidth(), layer->getHeight());
} else {
LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight);
- layer = new Layer(Layer::kType_DisplayList, renderState, entry.mWidth, entry.mHeight);
+ layer = new Layer(Layer::Type::DisplayList, renderState, entry.mWidth, entry.mHeight);
layer->setBlend(true);
layer->generateTexture();
layer->bindTexture();
@@ -156,11 +156,11 @@
mCache.insert(entry);
mSize += size;
- layer->state = Layer::kState_InCache;
+ layer->state = Layer::State::InCache;
return true;
}
- layer->state = Layer::kState_FailedToCache;
+ layer->state = Layer::State::FailedToCache;
return false;
}
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 00add29..d8e6392 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -272,7 +272,7 @@
Layer* LayerRenderer::createTextureLayer(RenderState& renderState) {
LAYER_RENDERER_LOGD("Creating new texture layer");
- Layer* layer = new Layer(Layer::kType_Texture, renderState, 0, 0);
+ Layer* layer = new Layer(Layer::Type::Texture, renderState, 0, 0);
layer->setCacheable(false);
layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f);
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 115e23c..73ebd1304 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -152,10 +152,6 @@
mType = kTypeUnknown;
}
-void Matrix4::load(const Matrix4& v) {
- *this = v;
-}
-
void Matrix4::load(const SkMatrix& v) {
memset(data, 0, sizeof(data));
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index ed54a25..ed517ac 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -114,7 +114,6 @@
void loadIdentity();
void load(const float* v);
- void load(const Matrix4& v);
void load(const SkMatrix& v);
void loadInverse(const Matrix4& v);
@@ -139,7 +138,7 @@
void multiply(const Matrix4& v) {
Matrix4 u;
u.loadMultiply(*this, v);
- load(u);
+ *this = u;
}
void multiply(float v);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7a56d42..5692d7e 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1141,7 +1141,7 @@
// Transform and alpha always deferred, since they are used by state operations
// (Note: saveLayer/restore use colorFilter and alpha, so we just save restore everything)
- state.mMatrix.load(*currentMatrix);
+ state.mMatrix = *currentMatrix;
state.mAlpha = currentSnapshot()->alpha;
// always store/restore, since these are just pointers
@@ -1151,7 +1151,7 @@
}
void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore) {
- setMatrix(state.mMatrix);
+ setGlobalMatrix(state.mMatrix);
writableSnapshot()->alpha = state.mAlpha;
writableSnapshot()->roundRectClipState = state.mRoundRectClipState;
writableSnapshot()->projectionPathMask = state.mProjectionPathMask;
@@ -2098,8 +2098,9 @@
mState.skew(sx, sy);
}
-void OpenGLRenderer::setMatrix(const Matrix4& matrix) {
- mState.setMatrix(matrix);
+void OpenGLRenderer::setLocalMatrix(const Matrix4& matrix) {
+ mState.setMatrix(mBaseTransform);
+ mState.concatMatrix(matrix);
}
void OpenGLRenderer::setLocalMatrix(const SkMatrix& matrix) {
@@ -2267,7 +2268,7 @@
mDirty = true;
}
-void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
+void OpenGLRenderer::drawLayer(Layer* layer) {
if (!layer) {
return;
}
@@ -2283,7 +2284,7 @@
bool clipRequired = false;
const bool rejected = mState.calculateQuickRejectForScissor(
- x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(),
+ 0, 0, layer->layer.getWidth(), layer->layer.getHeight(),
&clipRequired, nullptr, false);
if (rejected) {
@@ -2312,7 +2313,7 @@
.setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
.setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
.setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
+ .setModelViewOffsetRectSnap(0, 0, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
.build();
DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
#if DEBUG_LAYERS_AS_REGIONS
@@ -2325,7 +2326,7 @@
SkPaint paint;
paint.setColor(0x7f00ff00);
- drawColorRect(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(), &paint);
+ drawColorRect(0, 0, layer->layer.getWidth(), layer->layer.getHeight(), &paint);
}
}
layer->hasDrawnSinceUpdate = true;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 4f75482..af85e8c 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -35,6 +35,7 @@
#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkColorFilter.h>
+#include <SkDrawLooper.h>
#include <SkMatrix.h>
#include <SkPaint.h>
#include <SkRegion.h>
@@ -187,7 +188,7 @@
const SkPaint* paint, int flags);
void drawRenderNode(RenderNode* displayList, Rect& dirty, int32_t replayFlags = 1);
- void drawLayer(Layer* layer, float x, float y);
+ void drawLayer(Layer* layer);
void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
void drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entry, int bitmapCount,
TextureVertex* vertices, bool pureTranslate, const Rect& bounds, const SkPaint* paint);
@@ -367,8 +368,10 @@
void restore();
void restoreToCount(int saveCount);
- void getMatrix(SkMatrix* outMatrix) const { mState.getMatrix(outMatrix); }
- void setMatrix(const SkMatrix& matrix) { mState.setMatrix(matrix); }
+ void setGlobalMatrix(const Matrix4& matrix) {
+ mState.setMatrix(matrix);
+ }
+ void setLocalMatrix(const Matrix4& matrix);
void setLocalMatrix(const SkMatrix& matrix);
void concatMatrix(const SkMatrix& matrix) { mState.concatMatrix(matrix); }
diff --git a/libs/hwui/Outline.h b/libs/hwui/Outline.h
index 8d4d4f0..4bd4ae1 100644
--- a/libs/hwui/Outline.h
+++ b/libs/hwui/Outline.h
@@ -28,13 +28,13 @@
public:
Outline()
: mShouldClip(false)
- , mType(kOutlineType_None)
+ , mType(Type::None)
, mRadius(0)
, mAlpha(0.0f) {}
void setRoundRect(int left, int top, int right, int bottom, float radius, float alpha) {
mAlpha = alpha;
- if (mType == kOutlineType_RoundRect
+ if (mType == Type::RoundRect
&& left == mBounds.left
&& right == mBounds.right
&& top == mBounds.top
@@ -44,7 +44,7 @@
return;
}
- mType = kOutlineType_RoundRect;
+ mType = Type::RoundRect;
mBounds.set(left, top, right, bottom);
mRadius = radius;
@@ -63,26 +63,26 @@
setEmpty();
return;
}
- mType = kOutlineType_ConvexPath;
+ mType = Type::ConvexPath;
mPath = *outline;
mBounds.set(outline->getBounds());
mAlpha = alpha;
}
void setEmpty() {
- mType = kOutlineType_Empty;
+ mType = Type::Empty;
mPath.reset();
mAlpha = 0.0f;
}
void setNone() {
- mType = kOutlineType_None;
+ mType = Type::None;
mPath.reset();
mAlpha = 0.0f;
}
bool isEmpty() const {
- return mType == kOutlineType_Empty;
+ return mType == Type::Empty;
}
float getAlpha() const {
@@ -99,7 +99,7 @@
bool willClip() const {
// only round rect outlines can be used for clipping
- return mShouldClip && (mType == kOutlineType_RoundRect);
+ return mShouldClip && (mType == Type::RoundRect);
}
bool willRoundRectClip() const {
@@ -108,7 +108,7 @@
}
bool getAsRoundRect(Rect* outRect, float* outRadius) const {
- if (mType == kOutlineType_RoundRect) {
+ if (mType == Type::RoundRect) {
outRect->set(mBounds);
*outRadius = mRadius;
return true;
@@ -117,21 +117,21 @@
}
const SkPath* getPath() const {
- if (mType == kOutlineType_None || mType == kOutlineType_Empty) return nullptr;
+ if (mType == Type::None || mType == Type::Empty) return nullptr;
return &mPath;
}
private:
- enum OutlineType {
- kOutlineType_None = 0,
- kOutlineType_Empty = 1,
- kOutlineType_ConvexPath = 2,
- kOutlineType_RoundRect = 3
+ enum class Type {
+ None = 0,
+ Empty = 1,
+ ConvexPath = 2,
+ RoundRect = 3
};
bool mShouldClip;
- OutlineType mType;
+ Type mType;
Rect mBounds;
float mRadius;
float mAlpha;
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 500f9e9..b471e78 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-#include <cmath>
-
-#include <utils/Log.h>
+#include "Patch.h"
#include "Caches.h"
-#include "Patch.h"
#include "Properties.h"
#include "UvMapper.h"
#include "utils/MathUtils.h"
+#include <algorithm>
+#include <utils/Log.h>
+
namespace android {
namespace uirenderer {
@@ -189,10 +189,10 @@
const uint32_t oldQuadCount = quadCount;
quadCount++;
- x1 = MathUtils::max(x1, 0.0f);
- x2 = MathUtils::max(x2, 0.0f);
- y1 = MathUtils::max(y1, 0.0f);
- y2 = MathUtils::max(y2, 0.0f);
+ x1 = std::max(x1, 0.0f);
+ x2 = std::max(x2, 0.0f);
+ y1 = std::max(y1, 0.0f);
+ y2 = std::max(y2, 0.0f);
// Skip degenerate and transparent (empty) quads
if ((mColors[oldQuadCount] == 0) || x1 >= x2 || y1 >= y2) {
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 8fa187c..b57b8f0 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -32,6 +32,15 @@
#define DEBUG_DUMP_BUFFER()
#endif
+#include "PathTessellator.h"
+
+#include "Matrix.h"
+#include "Vector.h"
+#include "Vertex.h"
+#include "utils/MathUtils.h"
+
+#include <algorithm>
+
#include <SkPath.h>
#include <SkPaint.h>
#include <SkPoint.h>
@@ -44,12 +53,6 @@
#include <utils/Log.h>
#include <utils/Trace.h>
-#include "PathTessellator.h"
-#include "Matrix.h"
-#include "Vector.h"
-#include "Vertex.h"
-#include "utils/MathUtils.h"
-
namespace android {
namespace uirenderer {
@@ -152,7 +155,7 @@
// always use 2 points for hairline
if (halfStrokeWidth == 0.0f) return 2;
- float threshold = MathUtils::min(inverseScaleX, inverseScaleY) * ROUND_CAP_THRESH;
+ float threshold = std::min(inverseScaleX, inverseScaleY) * ROUND_CAP_THRESH;
return MathUtils::divisionsNeededToApproximateArc(halfStrokeWidth, PI, threshold);
}
return 0;
diff --git a/libs/hwui/PathTessellator.h b/libs/hwui/PathTessellator.h
index b66e832..cddfb04 100644
--- a/libs/hwui/PathTessellator.h
+++ b/libs/hwui/PathTessellator.h
@@ -22,8 +22,12 @@
#include "Vertex.h"
#include "VertexBuffer.h"
+#include <algorithm>
#include <vector>
+class SkPath;
+class SkPaint;
+
namespace android {
namespace uirenderer {
@@ -38,7 +42,7 @@
: thresholdSquared(pixelThreshold * pixelThreshold)
, sqrInvScaleX(invScaleX * invScaleX)
, sqrInvScaleY(invScaleY * invScaleY)
- , thresholdForConicQuads(pixelThreshold * MathUtils::min(invScaleX, invScaleY) / 2.0f) {
+ , thresholdForConicQuads(pixelThreshold * std::min(invScaleX, invScaleY) / 2.0f) {
};
const float thresholdSquared;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index af1e4a7..b09c207 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -103,10 +103,10 @@
* A ProgramDescription must be used in conjunction with a ProgramCache.
*/
struct ProgramDescription {
- enum ColorFilterMode {
- kColorNone = 0,
- kColorMatrix,
- kColorBlend
+ enum class ColorFilterMode {
+ None = 0,
+ Matrix,
+ Blend
};
enum Gradient {
@@ -193,7 +193,7 @@
bitmapWrapS = GL_CLAMP_TO_EDGE;
bitmapWrapT = GL_CLAMP_TO_EDGE;
- colorOp = kColorNone;
+ colorOp = ColorFilterMode::None;
colorMode = SkXfermode::kClear_Mode;
framebufferMode = SkXfermode::kClear_Mode;
@@ -249,14 +249,14 @@
key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
}
switch (colorOp) {
- case kColorMatrix:
+ case ColorFilterMode::Matrix:
key |= PROGRAM_KEY_COLOR_MATRIX;
break;
- case kColorBlend:
+ case ColorFilterMode::Blend:
key |= PROGRAM_KEY_COLOR_BLEND;
key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
break;
- case kColorNone:
+ case ColorFilterMode::None:
break;
}
key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 7f16deb..b25a4ac 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -38,7 +38,8 @@
// Vertex shaders snippets
///////////////////////////////////////////////////////////////////////////////
-const char* gVS_Header_Attributes =
+const char* gVS_Header_Start =
+ "#version 100\n"
"attribute vec4 position;\n";
const char* gVS_Header_Attributes_TexCoords =
"attribute vec2 texCoords;\n";
@@ -132,6 +133,8 @@
// Fragment shaders snippets
///////////////////////////////////////////////////////////////////////////////
+const char* gFS_Header_Start =
+ "#version 100\n";
const char* gFS_Header_Extension_FramebufferFetch =
"#extension GL_NV_shader_framebuffer_fetch : enable\n\n";
const char* gFS_Header_Extension_ExternalTexture =
@@ -457,7 +460,7 @@
String8 ProgramCache::generateVertexShader(const ProgramDescription& description) {
// Add attributes
- String8 shader(gVS_Header_Attributes);
+ String8 shader(gVS_Header_Start);
if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Header_Attributes_TexCoords);
}
@@ -543,7 +546,7 @@
}
String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) {
- String8 shader;
+ String8 shader(gFS_Header_Start);
const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode;
if (blendFramebuffer) {
@@ -604,7 +607,7 @@
if (!description.hasVertexAlpha
&& !blendFramebuffer
&& !description.hasColors
- && description.colorOp == ProgramDescription::kColorNone
+ && description.colorOp == ProgramDescription::ColorFilterMode::None
&& !description.hasDebugHighlight
&& !description.hasRoundRectClip) {
bool fast = false;
@@ -668,13 +671,13 @@
if (description.hasBitmap) {
shader.append(gFS_Uniforms_BitmapSampler);
}
- shader.append(gFS_Uniforms_ColorOp[description.colorOp]);
+ shader.append(gFS_Uniforms_ColorOp[static_cast<int>(description.colorOp)]);
// Generate required functions
if (description.hasGradient && description.hasBitmap) {
generateBlend(shader, "blendShaders", description.shadersMode);
}
- if (description.colorOp == ProgramDescription::kColorBlend) {
+ if (description.colorOp == ProgramDescription::ColorFilterMode::Blend) {
generateBlend(shader, "blendColors", description.colorMode);
}
if (blendFramebuffer) {
@@ -737,7 +740,7 @@
}
// Apply the color op if needed
- shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
+ shader.append(gFS_Main_ApplyColorOp[static_cast<int>(description.colorOp)]);
if (description.hasVertexAlpha) {
if (description.useShadowAlphaInterp) {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 48da3e8..7d09c0b 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -532,7 +532,7 @@
if (properties().getProjectBackwards()) {
// composited projectee, flag for out of order draw, save matrix, and store in proj surface
opState->mSkipInOrderDraw = true;
- opState->mTransformFromCompositingAncestor.load(localTransformFromProjectionSurface);
+ opState->mTransformFromCompositingAncestor = localTransformFromProjectionSurface;
compositedChildrenOfProjectionSurface->push_back(opState);
} else {
// standard in order draw
@@ -710,8 +710,8 @@
OpenGLRenderer& renderer, T& handler) {
const int size = zTranslatedNodes.size();
if (size == 0
- || (mode == kNegativeZChildren && zTranslatedNodes[0].key > 0.0f)
- || (mode == kPositiveZChildren && zTranslatedNodes[size - 1].key < 0.0f)) {
+ || (mode == ChildrenSelectMode::NegativeZChildren && zTranslatedNodes[0].key > 0.0f)
+ || (mode == ChildrenSelectMode::PositiveZChildren && zTranslatedNodes[size - 1].key < 0.0f)) {
// no 3d children to draw
return;
}
@@ -719,7 +719,7 @@
// Apply the base transform of the parent of the 3d children. This isolates
// 3d children of the current chunk from transformations made in previous chunks.
int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag);
- renderer.setMatrix(initialTransform);
+ renderer.setGlobalMatrix(initialTransform);
/**
* Draw shadows and (potential) casters mostly in order, but allow the shadows of casters
@@ -730,7 +730,7 @@
*/
const size_t nonNegativeIndex = findNonNegativeIndex(zTranslatedNodes);
size_t drawIndex, shadowIndex, endIndex;
- if (mode == kNegativeZChildren) {
+ if (mode == ChildrenSelectMode::NegativeZChildren) {
drawIndex = 0;
endIndex = nonNegativeIndex;
shadowIndex = endIndex; // draw no shadows
@@ -875,7 +875,7 @@
renderer.setBaseTransform(initialTransform);
if (drawLayer) {
- handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
+ handler(new (alloc) DrawLayerOp(mLayer),
renderer.getSaveCount() - 1, properties().getClipToBounds());
} else {
const int saveCountOffset = renderer.getSaveCount() - 1;
@@ -886,7 +886,7 @@
std::vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
buildZSortedChildList(chunk, zTranslatedNodes);
- issueOperationsOf3dChildren(kNegativeZChildren,
+ issueOperationsOf3dChildren(ChildrenSelectMode::NegativeZChildren,
initialTransform, zTranslatedNodes, renderer, handler);
@@ -903,7 +903,7 @@
}
}
- issueOperationsOf3dChildren(kPositiveZChildren,
+ issueOperationsOf3dChildren(ChildrenSelectMode::PositiveZChildren,
initialTransform, zTranslatedNodes, renderer, handler);
}
}
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 6d1a2b7..3bff2b3 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -184,9 +184,9 @@
return nodes.size();
}
- enum ChildrenSelectMode {
- kNegativeZChildren,
- kPositiveZChildren
+ enum class ChildrenSelectMode {
+ NegativeZChildren,
+ PositiveZChildren
};
void computeOrderingImpl(DrawRenderNodeOp* opState,
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index b2d1fec..36633b5 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -74,7 +74,6 @@
virtual void getMatrix(SkMatrix* outMatrix) const override;
virtual void setMatrix(const SkMatrix& matrix) override;
- virtual void setLocalMatrix(const SkMatrix& matrix) override { this->setMatrix(matrix); }
virtual void concat(const SkMatrix& matrix) override;
virtual void rotate(float degrees) override;
virtual void scale(float sx, float sy) override;
@@ -124,6 +123,9 @@
float dstRight, float dstBottom, const SkPaint* paint) override;
virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
const float* vertices, const int* colors, const SkPaint* paint) override;
+ virtual void drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) override;
virtual void drawText(const uint16_t* text, const float* positions, int count,
const SkPaint& paint, float x, float y,
@@ -318,7 +320,7 @@
}
if (NULL == mSaveStack.get()) {
- mSaveStack.reset(SkNEW_ARGS(SkDeque, (sizeof(struct SaveRec), 8)));
+ mSaveStack.reset(new SkDeque(sizeof(struct SaveRec), 8));
}
SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back());
@@ -484,13 +486,12 @@
SkCanvas::PointMode mode) {
// convert the floats into SkPoints
count >>= 1; // now it is the number of points
- SkAutoSTMalloc<32, SkPoint> storage(count);
- SkPoint* pts = storage.get();
+ std::unique_ptr<SkPoint[]> pts(new SkPoint[count]);
for (int i = 0; i < count; i++) {
pts[i].set(points[0], points[1]);
points += 2;
}
- mCanvas->drawPoints(mode, count, pts, paint);
+ mCanvas->drawPoints(mode, count, pts.get(), paint);
}
@@ -602,7 +603,7 @@
#ifndef SK_SCALAR_IS_FLOAT
SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
#endif
- SkAutoMalloc storage(storageSize);
+ std::unique_ptr<char[]> storage(new char[storageSize]);
SkPoint* texs = (SkPoint*)storage.get();
uint16_t* indices = (uint16_t*)(texs + ptCount);
@@ -680,6 +681,12 @@
indexCount, tmpPaint);
}
+void SkiaCanvas::drawNinePatch(const SkBitmap& bitmap, const Res_png_9patch& chunk,
+ float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
+ SkRect bounds = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
+ NinePatch::Draw(mCanvas, bounds, bitmap, chunk, paint, nullptr);
+}
+
// ----------------------------------------------------------------------------
// Canvas draw operations: Text
// ----------------------------------------------------------------------------
@@ -694,7 +701,7 @@
SkPaint paintCopy(paint);
paintCopy.setTextAlign(SkPaint::kLeft_Align);
- SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+ static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
mCanvas->drawPosText(text, count << 1, reinterpret_cast<const SkPoint*>(positions), paintCopy);
}
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 0e51325..c3f5eb2 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -24,6 +24,8 @@
#include <SkRect.h>
#include <SkRRect.h>
+#include <memory>
+
namespace android {
namespace uirenderer {
@@ -43,7 +45,7 @@
}
// convert the SkPoints into floats
- SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+ static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
const size_t floatCount = count << 1;
const float* floatArray = &pts[0].fX;
@@ -140,7 +142,7 @@
const SkPaint* paint) {
// TODO: if bitmap is a subset, do we need to add pixelRefOrigin to src?
mCanvas->save(SkCanvas::kMatrixClip_SaveFlag);
- mCanvas->setLocalMatrix(SkMatrix::I());
+ mCanvas->setMatrix(SkMatrix::I());
mCanvas->drawBitmap(bitmap, left, top, paint);
mCanvas->restore();
}
@@ -152,7 +154,7 @@
return;
}
// convert the SkPoints into floats
- SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+ static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
const int floatCount = vertexCount << 1;
const float* vArray = &vertices[0].fX;
const float* tArray = (texs) ? &texs[0].fX : NULL;
@@ -190,9 +192,7 @@
}
void SkiaCanvasProxy::didSetMatrix(const SkMatrix& matrix) {
- // SkCanvas setMatrix() is relative to the Canvas origin, but OpenGLRenderer's
- // setMatrix() is relative to device origin; call setLocalMatrix() instead.
- mCanvas->setLocalMatrix(matrix);
+ mCanvas->setMatrix(matrix);
}
void SkiaCanvasProxy::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
@@ -216,7 +216,8 @@
glyphIDs = (uint16_t*)text;
count = byteLength >> 1;
} else {
- storage.reset(byteLength); // ensures space for one glyph per ID given UTF8 encoding.
+ // ensure space for one glyph per ID given UTF8 encoding.
+ storage.reset(new uint16_t[byteLength]);
glyphIDs = storage.get();
count = paint.textToGlyphs(text, byteLength, storage.get());
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
@@ -227,7 +228,7 @@
uint16_t* glyphIDs;
int count;
private:
- SkAutoSTMalloc<32, uint16_t> storage;
+ std::unique_ptr<uint16_t[]> storage;
};
void SkiaCanvasProxy::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
@@ -236,8 +237,8 @@
GlyphIDConverter glyphs(text, byteLength, origPaint);
// compute the glyph positions
- SkAutoSTMalloc<32, SkPoint> pointStorage(glyphs.count);
- SkAutoSTMalloc<32, SkScalar> glyphWidths(glyphs.count);
+ std::unique_ptr<SkPoint[]> pointStorage(new SkPoint[glyphs.count]);
+ std::unique_ptr<SkScalar[]> glyphWidths(new SkScalar[glyphs.count]);
glyphs.paint.getTextWidths(glyphs.glyphIDs, glyphs.count << 1, glyphWidths.get());
// compute conservative bounds
@@ -283,7 +284,7 @@
}
}
- SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+ static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
mCanvas->drawText(glyphs.glyphIDs, &pointStorage[0].fX, glyphs.count, glyphs.paint,
x, y, bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
}
@@ -296,7 +297,7 @@
// convert to relative positions if necessary
int x, y;
const SkPoint* posArray;
- SkAutoSTMalloc<32, SkPoint> pointStorage;
+ std::unique_ptr<SkPoint[]> pointStorage;
if (mCanvas->drawTextAbsolutePos()) {
x = 0;
y = 0;
@@ -304,11 +305,12 @@
} else {
x = pos[0].fX;
y = pos[0].fY;
- posArray = pointStorage.reset(glyphs.count);
+ pointStorage.reset(new SkPoint[glyphs.count]);
for (int i = 0; i < glyphs.count; i++) {
- pointStorage[i].fX = pos[i].fX- x;
- pointStorage[i].fY = pos[i].fY- y;
+ pointStorage[i].fX = pos[i].fX - x;
+ pointStorage[i].fY = pos[i].fY - y;
}
+ posArray = pointStorage.get();
}
// compute conservative bounds
@@ -318,7 +320,7 @@
glyphs.paint.measureText(glyphs.glyphIDs, glyphs.count << 1, &bounds);
bounds.offset(x, y);
- SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+ static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
mCanvas->drawText(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y,
bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
}
@@ -326,12 +328,11 @@
void SkiaCanvasProxy::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
SkScalar constY, const SkPaint& paint) {
const size_t pointCount = byteLength >> 1;
- SkAutoSTMalloc<32, SkPoint> storage(pointCount);
- SkPoint* pts = storage.get();
+ std::unique_ptr<SkPoint[]> pts(new SkPoint[pointCount]);
for (size_t i = 0; i < pointCount; i++) {
pts[i].set(xpos[i], constY);
}
- this->onDrawPosText(text, byteLength, pts, paint);
+ this->onDrawPosText(text, byteLength, pts.get(), paint);
}
void SkiaCanvasProxy::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 1f95946..6c105cf 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -32,12 +32,19 @@
// Support
///////////////////////////////////////////////////////////////////////////////
-static const GLenum gTileModes[] = {
+static constexpr GLenum gTileModes[] = {
GL_CLAMP_TO_EDGE, // == SkShader::kClamp_TileMode
GL_REPEAT, // == SkShader::kRepeat_Mode
GL_MIRRORED_REPEAT // == SkShader::kMirror_TileMode
};
+static_assert(gTileModes[SkShader::kClamp_TileMode] == GL_CLAMP_TO_EDGE,
+ "SkShader TileModes have changed");
+static_assert(gTileModes[SkShader::kRepeat_TileMode] == GL_REPEAT,
+ "SkShader TileModes have changed");
+static_assert(gTileModes[SkShader::kMirror_TileMode] == GL_MIRRORED_REPEAT,
+ "SkShader TileModes have changed");
+
/**
* This function does not work for n == 0.
*/
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index fd077d9..4d60b8d 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -58,7 +58,7 @@
, mViewportData(s->mViewportData)
, mRelativeLightCenter(s->mRelativeLightCenter) {
if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
- mTransformRoot.load(*s->transform);
+ mTransformRoot = *s->transform;
transform = &mTransformRoot;
} else {
transform = s->transform;
@@ -83,24 +83,24 @@
// Clipping
///////////////////////////////////////////////////////////////////////////////
-bool Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
+void Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
flags |= Snapshot::kFlagClipSet;
- return mClipArea->clipRegion(region, op);
+ mClipArea->clipRegion(region, op);
}
-bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
+void Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
flags |= Snapshot::kFlagClipSet;
- return mClipArea->clipRectWithTransform(left, top, right, bottom, transform, op);
+ mClipArea->clipRectWithTransform(left, top, right, bottom, transform, op);
}
-bool Snapshot::clipPath(const SkPath& path, SkRegion::Op op) {
+void Snapshot::clipPath(const SkPath& path, SkRegion::Op op) {
flags |= Snapshot::kFlagClipSet;
- return mClipArea->clipPathWithTransform(path, transform, op);
+ mClipArea->clipPathWithTransform(path, transform, op);
}
void Snapshot::setClip(float left, float top, float right, float bottom) {
- mClipArea->setClip(left, top, right, bottom);
flags |= Snapshot::kFlagClipSet;
+ mClipArea->setClip(left, top, right, bottom);
}
bool Snapshot::hasPerspectiveTransform() const {
@@ -190,8 +190,7 @@
state->highPriority = highPriority;
// store the inverse drawing matrix
- Matrix4 roundRectDrawingMatrix;
- roundRectDrawingMatrix.load(getOrthoMatrix());
+ Matrix4 roundRectDrawingMatrix = getOrthoMatrix();
roundRectDrawingMatrix.multiply(*transform);
state->matrix.loadInverse(roundRectDrawingMatrix);
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index af6ad72..cf8f11c 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -124,26 +124,25 @@
* the specified operation. The specified rectangle is transformed
* by this snapshot's trasnformation.
*/
- bool clip(float left, float top, float right, float bottom,
- SkRegion::Op op = SkRegion::kIntersect_Op);
+ void clip(float left, float top, float right, float bottom, SkRegion::Op op);
/**
* Modifies the current clip with the new clip rectangle and
* the specified operation. The specified rectangle is considered
* already transformed.
*/
- bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op);
+ void clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op);
/**
* Modifies the current clip with the specified region and operation.
* The specified region is considered already transformed.
*/
- bool clipRegionTransformed(const SkRegion& region, SkRegion::Op op);
+ void clipRegionTransformed(const SkRegion& region, SkRegion::Op op);
/**
* Modifies the current clip with the specified path and operation.
*/
- bool clipPath(const SkPath& path, SkRegion::Op op);
+ void clipPath(const SkPath& path, SkRegion::Op op);
/**
* Sets the current clip.
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index eaf0303..9b0a1aa 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -46,17 +46,18 @@
#define TRANSFORMED_PENUMBRA_ALPHA 1.0f
#define TRANSFORMED_UMBRA_ALPHA 0.0f
+#include "SpotShadow.h"
+
+#include "ShadowTessellator.h"
+#include "Vertex.h"
+#include "VertexBuffer.h"
+#include "utils/MathUtils.h"
+
#include <algorithm>
#include <math.h>
#include <stdlib.h>
#include <utils/Log.h>
-#include "ShadowTessellator.h"
-#include "SpotShadow.h"
-#include "Vertex.h"
-#include "VertexBuffer.h"
-#include "utils/MathUtils.h"
-
// TODO: After we settle down the new algorithm, we can remove the old one and
// its utility functions.
// Right now, we still need to keep it for comparison purpose and future expansion.
@@ -543,7 +544,7 @@
}
float ratioVI = outlineData[i].radius / distOutline;
- minRaitoVI = MathUtils::min(minRaitoVI, ratioVI);
+ minRaitoVI = std::min(minRaitoVI, ratioVI);
if (ratioVI >= (1 - FAKE_UMBRA_SIZE_RATIO)) {
ratioVI = (1 - FAKE_UMBRA_SIZE_RATIO);
}
diff --git a/libs/hwui/VertexBuffer.h b/libs/hwui/VertexBuffer.h
index 9be4d84..c0373ac 100644
--- a/libs/hwui/VertexBuffer.h
+++ b/libs/hwui/VertexBuffer.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_HWUI_VERTEX_BUFFER_H
#define ANDROID_HWUI_VERTEX_BUFFER_H
-#include "utils/MathUtils.h"
+#include <algorithm>
namespace android {
namespace uirenderer {
@@ -129,10 +129,10 @@
unsigned int getSize() const { return mByteCount; }
unsigned int getIndexCount() const { return mIndexCount; }
void updateIndexCount(unsigned int newCount) {
- mIndexCount = MathUtils::min(newCount, mAllocatedIndexCount);
+ mIndexCount = std::min(newCount, mAllocatedIndexCount);
}
void updateVertexCount(unsigned int newCount) {
- mVertexCount = MathUtils::min(newCount, mAllocatedVertexCount);
+ mVertexCount = std::min(newCount, mAllocatedVertexCount);
}
MeshFeatureFlags getMeshFeatureFlags() const { return mMeshFeatureFlags; }
void setMeshFeatureFlags(int flags) {
diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp
index 29927ed..b21e15e 100644
--- a/libs/hwui/renderstate/Blend.cpp
+++ b/libs/hwui/renderstate/Blend.cpp
@@ -30,6 +30,26 @@
GLenum dst;
};
+// assumptions made by lookup tables in either this file or ProgramCache
+static_assert(0 == SkXfermode::kClear_Mode, "SkXfermode enums have changed");
+static_assert(1 == SkXfermode::kSrc_Mode, "SkXfermode enums have changed");
+static_assert(2 == SkXfermode::kDst_Mode, "SkXfermode enums have changed");
+static_assert(3 == SkXfermode::kSrcOver_Mode, "SkXfermode enums have changed");
+static_assert(4 == SkXfermode::kDstOver_Mode, "SkXfermode enums have changed");
+static_assert(5 == SkXfermode::kSrcIn_Mode, "SkXfermode enums have changed");
+static_assert(6 == SkXfermode::kDstIn_Mode, "SkXfermode enums have changed");
+static_assert(7 == SkXfermode::kSrcOut_Mode, "SkXfermode enums have changed");
+static_assert(8 == SkXfermode::kDstOut_Mode, "SkXfermode enums have changed");
+static_assert(9 == SkXfermode::kSrcATop_Mode, "SkXfermode enums have changed");
+static_assert(10 == SkXfermode::kDstATop_Mode, "SkXfermode enums have changed");
+static_assert(11 == SkXfermode::kXor_Mode, "SkXfermode enums have changed");
+static_assert(12 == SkXfermode::kPlus_Mode, "SkXfermode enums have changed");
+static_assert(13 == SkXfermode::kModulate_Mode, "SkXfermode enums have changed");
+static_assert(14 == SkXfermode::kScreen_Mode, "SkXfermode enums have changed");
+static_assert(15 == SkXfermode::kOverlay_Mode, "SkXfermode enums have changed");
+static_assert(16 == SkXfermode::kDarken_Mode, "SkXfermode enums have changed");
+static_assert(17 == SkXfermode::kLighten_Mode, "SkXfermode enums have changed");
+
// In this array, the index of each Blender equals the value of the first
// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
const Blender kBlends[] = {
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 1e39bfa..c5126de 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -19,6 +19,8 @@
#include "renderthread/EglManager.h"
#include "utils/GLUtils.h"
+#include <algorithm>
+
namespace android {
namespace uirenderer {
@@ -227,11 +229,11 @@
glop.transform.transformFlags & TransformFlags::OffsetByFudgeFactor);
// Color filter uniforms
- if (fill.filterMode == ProgramDescription::kColorBlend) {
+ if (fill.filterMode == ProgramDescription::ColorFilterMode::Blend) {
const FloatColor& color = fill.filter.color;
glUniform4f(mCaches->program().getUniform("colorBlend"),
color.r, color.g, color.b, color.a);
- } else if (fill.filterMode == ProgramDescription::kColorMatrix) {
+ } else if (fill.filterMode == ProgramDescription::ColorFilterMode::Matrix) {
glUniformMatrix4fv(mCaches->program().getUniform("colorMatrix"), 1, GL_FALSE,
fill.filter.matrix.matrix);
glUniform4fv(mCaches->program().getUniform("colorMatrixVector"), 1,
@@ -320,7 +322,7 @@
GLsizei elementsCount = mesh.elementCount;
const GLbyte* vertexData = static_cast<const GLbyte*>(vertices.position);
while (elementsCount > 0) {
- GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
+ GLsizei drawCount = std::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
// rebind pointers without forcing, since initial bind handled above
meshState().bindPositionVertexPointer(false, vertexData, vertices.stride);
diff --git a/libs/hwui/renderstate/Stencil.cpp b/libs/hwui/renderstate/Stencil.cpp
index 319cfe4..d25ad51 100644
--- a/libs/hwui/renderstate/Stencil.cpp
+++ b/libs/hwui/renderstate/Stencil.cpp
@@ -34,10 +34,6 @@
#define STENCIL_MASK_VALUE 0x1
#endif
-Stencil::Stencil()
- : mState(kDisabled) {
-}
-
uint8_t Stencil::getStencilSize() {
return STENCIL_BUFFER_SIZE;
}
@@ -64,14 +60,14 @@
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
- if (mState == kTest) {
+ if (mState == StencilState::Test) {
// reset to test state, with immutable stencil
glStencilMask(0);
}
}
void Stencil::enableTest(int incrementThreshold) {
- if (mState != kTest) {
+ if (mState != StencilState::Test) {
enable();
if (incrementThreshold > 0) {
glStencilFunc(GL_EQUAL, incrementThreshold, 0xff);
@@ -82,12 +78,12 @@
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilMask(0);
- mState = kTest;
+ mState = StencilState::Test;
}
}
void Stencil::enableWrite(int incrementThreshold) {
- if (mState != kWrite) {
+ if (mState != StencilState::Write) {
enable();
if (incrementThreshold > 0) {
glStencilFunc(GL_ALWAYS, 1, 0xff);
@@ -100,7 +96,7 @@
}
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glStencilMask(0xff);
- mState = kWrite;
+ mState = StencilState::Write;
}
}
@@ -109,7 +105,7 @@
glStencilFunc(greater ? GL_LESS : GL_EQUAL, value, 0xffffffff);
// We only want to test, let's keep everything
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- mState = kTest;
+ mState = StencilState::Test;
glStencilMask(0);
}
@@ -119,20 +115,20 @@
// The test always passes so the first two values are meaningless
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- mState = kWrite;
+ mState = StencilState::Write;
glStencilMask(0xff);
}
void Stencil::enable() {
- if (mState == kDisabled) {
+ if (mState == StencilState::Disabled) {
glEnable(GL_STENCIL_TEST);
}
}
void Stencil::disable() {
- if (mState != kDisabled) {
+ if (mState != StencilState::Disabled) {
glDisable(GL_STENCIL_TEST);
- mState = kDisabled;
+ mState = StencilState::Disabled;
}
}
diff --git a/libs/hwui/renderstate/Stencil.h b/libs/hwui/renderstate/Stencil.h
index 3261823..5f7d405 100644
--- a/libs/hwui/renderstate/Stencil.h
+++ b/libs/hwui/renderstate/Stencil.h
@@ -30,8 +30,6 @@
class ANDROID_API Stencil {
public:
- Stencil();
-
/**
* Returns the desired size for the stencil buffer. If the returned value
* is 0, then no stencil buffer is required.
@@ -81,32 +79,31 @@
* Indicates whether either test or write is enabled.
*/
bool isEnabled() {
- return mState != kDisabled;
+ return mState != StencilState::Disabled;
}
/**
* Indicates whether testing only is enabled.
*/
bool isTestEnabled() {
- return mState == kTest;
+ return mState == StencilState::Test;
}
bool isWriteEnabled() {
- return mState == kWrite;
+ return mState == StencilState::Write;
}
void dump();
private:
- void enable();
-
- enum StencilState {
- kDisabled,
- kTest,
- kWrite
+ enum class StencilState {
+ Disabled,
+ Test,
+ Write
};
- StencilState mState;
+ void enable();
+ StencilState mState = StencilState::Disabled;
}; // class Stencil
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 67c42f3..7cb7738 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -421,7 +421,7 @@
// Make sure to release all the textures we were owning as there won't
// be another draw
caches.textureCache.resetMarkInUse(this);
- caches.flush(Caches::kFlushMode_Layers);
+ caches.flush(Caches::FlushMode::Layers);
}
}
@@ -431,10 +431,10 @@
ATRACE_CALL();
if (level >= TRIM_MEMORY_COMPLETE) {
- Caches::getInstance().flush(Caches::kFlushMode_Full);
+ Caches::getInstance().flush(Caches::FlushMode::Full);
thread.eglManager().destroy();
} else if (level >= TRIM_MEMORY_UI_HIDDEN) {
- Caches::getInstance().flush(Caches::kFlushMode_Moderate);
+ Caches::getInstance().flush(Caches::FlushMode::Moderate);
}
}
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 9c3787c..8d20f21 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -16,6 +16,7 @@
#ifndef MATHUTILS_H
#define MATHUTILS_H
+#include <algorithm>
#include <math.h>
namespace android {
@@ -82,18 +83,8 @@
}
template<typename T>
- static inline T max(T a, T b) {
- return a > b ? a : b;
- }
-
- template<typename T>
- static inline T min(T a, T b) {
- return a < b ? a : b;
- }
-
- template<typename T>
static inline T clamp(T a, T minValue, T maxValue) {
- return min(max(a, minValue), maxValue);
+ return std::min(std::max(a, minValue), maxValue);
}
inline static float lerp(float v1, float v2, float t) {
diff --git a/libs/hwui/utils/NinePatch.h b/libs/hwui/utils/NinePatch.h
new file mode 100644
index 0000000..323e563
--- /dev/null
+++ b/libs/hwui/utils/NinePatch.h
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 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.
+*/
+
+#ifndef ANDROID_GRAPHICS_NINEPATCH_H
+#define ANDROID_GRAPHICS_NINEPATCH_H
+
+#include <androidfw/ResourceTypes.h>
+#include <cutils/compiler.h>
+
+#include "SkCanvas.h"
+#include "SkRegion.h"
+
+namespace android {
+
+class ANDROID_API NinePatch {
+public:
+ static void Draw(SkCanvas* canvas, const SkRect& bounds, const SkBitmap& bitmap,
+ const Res_png_9patch& chunk, const SkPaint* paint, SkRegion** outRegion);
+};
+
+} // namespace android
+
+#endif // ANDROID_GRAPHICS_NINEPATCH_H
diff --git a/core/jni/android/graphics/NinePatchImpl.cpp b/libs/hwui/utils/NinePatchImpl.cpp
similarity index 97%
rename from core/jni/android/graphics/NinePatchImpl.cpp
rename to libs/hwui/utils/NinePatchImpl.cpp
index 978c4a5..f51f5df 100644
--- a/core/jni/android/graphics/NinePatchImpl.cpp
+++ b/libs/hwui/utils/NinePatchImpl.cpp
@@ -15,11 +15,7 @@
** limitations under the License.
*/
-#define LOG_TAG "NinePatch"
-#define LOG_NDEBUG 1
-
-#include <androidfw/ResourceTypes.h>
-#include <utils/Log.h>
+#include "utils/NinePatch.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
@@ -30,6 +26,8 @@
#include <utils/Log.h>
+namespace android {
+
static const bool kUseTrace = true;
static bool gTrace = false;
@@ -97,9 +95,9 @@
return srcSpace * stretchySpaceRemaining / numStrechyPixelsRemaining;
}
-void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
- const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
- const SkPaint* paint, SkRegion** outRegion) {
+void NinePatch::Draw(SkCanvas* canvas, const SkRect& bounds,
+ const SkBitmap& bitmap, const Res_png_9patch& chunk,
+ const SkPaint* paint, SkRegion** outRegion) {
if (canvas && canvas->quickReject(bounds)) {
return;
}
@@ -324,3 +322,5 @@
dstRightsHaveBeenCached = true;
}
}
+
+} // namespace android
diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
index f4943d5..bc2dae1 100644
--- a/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
+++ b/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
@@ -42,6 +42,8 @@
public static final String ACTIVITY_STILL = "android.activity_recognition.still";
public static final String ACTIVITY_TILTING = "android.activity_recognition.tilting";
+ // NOTE: when adding an additional EVENT_TYPE_, EVENT_TYPE_COUNT needs to be updated in
+ // android.hardware.location.ActivityRecognitionHardware
public static final int EVENT_TYPE_FLUSH_COMPLETE = 0;
public static final int EVENT_TYPE_ENTER = 1;
public static final int EVENT_TYPE_EXIT = 2;
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 0f1be6b..e92f294 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -671,15 +671,15 @@
case USAGE_VOICE_COMMUNICATION:
return new String("USAGE_VOICE_COMMUNICATION");
case USAGE_VOICE_COMMUNICATION_SIGNALLING:
- return new String("USAGE_VOICE_COMMUNICATION");
+ return new String("USAGE_VOICE_COMMUNICATION_SIGNALLING");
case USAGE_ALARM:
return new String("USAGE_ALARM");
case USAGE_NOTIFICATION:
return new String("USAGE_NOTIFICATION");
case USAGE_NOTIFICATION_RINGTONE:
- return new String("USAGE_NOTIFICATION");
+ return new String("USAGE_NOTIFICATION_RINGTONE");
case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
- return new String("USAGE_NOTIFICATION");
+ return new String("USAGE_NOTIFICATION_COMMUNICATION_REQUEST");
case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
return new String("USAGE_NOTIFICATION_COMMUNICATION_INSTANT");
case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index e99a37a..c59d1c7 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -279,6 +279,7 @@
public static final int PERMISSION_DENIED = -4;
public static final int NO_INIT = -5;
public static final int DEAD_OBJECT = -6;
+ public static final int WOULD_BLOCK = -7;
/*
* AudioPolicyService methods
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 8880dad..bb4f7d9 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -158,6 +158,18 @@
* Denotes a failure due to the improper use of a method.
*/
public static final int ERROR_INVALID_OPERATION = AudioSystem.INVALID_OPERATION;
+ /**
+ * An error code indicating that the object reporting it is no longer valid and needs to
+ * be recreated.
+ * @hide
+ */
+ public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT;
+ /**
+ * {@link #getTimestampWithStatus(AudioTimestamp)} is called in STOPPED or FLUSHED state,
+ * or immediately after start/ACTIVE.
+ * @hide
+ */
+ public static final int ERROR_WOULD_BLOCK = AudioSystem.WOULD_BLOCK;
// Error codes:
// to keep in sync with frameworks/base/core/jni/android_media_AudioTrack.cpp
@@ -1225,6 +1237,44 @@
return true;
}
+ /**
+ * Poll for a timestamp on demand.
+ * <p>
+ * Same as {@link #getTimestamp(AudioTimestamp)} but with a more useful return code.
+ *
+ * @param timestamp a reference to a non-null AudioTimestamp instance allocated
+ * and owned by caller.
+ * @return {@link #SUCCESS} if a timestamp is available
+ * {@link #ERROR_WOULD_BLOCK} if called in STOPPED or FLUSHED state, or if called
+ * immediately after start/ACTIVE, when the number of frames consumed is less than the
+ * overall hardware latency to physical output. In WOULD_BLOCK cases, one might poll
+ * again, or use {@link #getPlaybackHeadPosition}, or use 0 position and current time
+ * for the timestamp.
+ * {@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+ * needs to be recreated.
+ * {@link #ERROR_INVALID_OPERATION} if current route does not support
+ * timestamps. In this case, the approximate frame position can be obtained
+ * using {@link #getPlaybackHeadPosition}.
+ *
+ * The AudioTimestamp instance is filled in with a position in frame units, together
+ * with the estimated time when that frame was presented or is committed to
+ * be presented.
+ * @hide
+ */
+ // Add this text when the "on new timestamp" API is added:
+ // Use if you need to get the most recent timestamp outside of the event callback handler.
+ public int getTimestampWithStatus(AudioTimestamp timestamp)
+ {
+ if (timestamp == null) {
+ throw new IllegalArgumentException();
+ }
+ // It's unfortunate, but we have to either create garbage every time or use synchronized
+ long[] longArray = new long[2];
+ int ret = native_get_timestamp(longArray);
+ timestamp.framePosition = longArray[0];
+ timestamp.nanoTime = longArray[1];
+ return ret;
+ }
//--------------------------------------------------------------------------
// Initialization / configuration
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index 7197dc0..e72bdb4 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -288,7 +288,6 @@
// fetch MidiDeviceInfo from the server
MidiDeviceInfo deviceInfo = server.getDeviceInfo();
device = new MidiDevice(deviceInfo, server, mService, mToken, deviceToken);
- sendOpenDeviceResponse(device, listenerF, handlerF);
} catch (RemoteException e) {
Log.e(TAG, "remote exception in getDeviceInfo()");
}
diff --git a/media/java/android/media/midi/package.html b/media/java/android/media/midi/package.html
index 7baa5bc..45fb579 100644
--- a/media/java/android/media/midi/package.html
+++ b/media/java/android/media/midi/package.html
@@ -202,11 +202,12 @@
<p>MIDI messages are sent as byte arrays. Here we encode a NoteOn message.</p>
<pre class=prettyprint>
-byte[] buffer = new buffer[64];
+byte[] buffer = new byte[32];
int numBytes = 0;
-buffer[numBytes++] = 0x90 + channel; // note on
-buffer[numBytes++] = pitch;
-buffer[numBytes++] = velocity;
+int channel = 3; // MIDI channels 1-16 are encoded as 0-15.
+buffer[numBytes++] = (byte)(0x90 + (channel - 1)); // note on
+buffer[numBytes++] = (byte)60; // pitch is middle C
+buffer[numBytes++] = (byte)127; // max velocity
int offset = 0;
// post is non-blocking
inputPort.send(buffer, offset, numBytes);
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index fbe047d..3cd157e 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -257,11 +257,12 @@
* on completion, and must be done by the caller.
*
* @param objectHandle handle of the target file
+ * @param size size of the file in bytes
* @param descriptor file descriptor to read the data from.
* @return true if the file transfer succeeds
*/
- public boolean sendObject(int objectHandle, ParcelFileDescriptor descriptor) {
- return native_send_object(objectHandle, descriptor.getFd());
+ public boolean sendObject(int objectHandle, int size, ParcelFileDescriptor descriptor) {
+ return native_send_object(objectHandle, size, descriptor.getFd());
}
/**
@@ -294,6 +295,6 @@
private native long native_get_storage_id(int objectHandle);
private native boolean native_import_file(int objectHandle, String destPath);
private native boolean native_import_file(int objectHandle, int fd);
- private native boolean native_send_object(int objectHandle, int fd);
+ private native boolean native_send_object(int objectHandle, int size, int fd);
private native MtpObjectInfo native_send_object_info(MtpObjectInfo info);
}
diff --git a/media/java/android/mtp/MtpObjectInfo.java b/media/java/android/mtp/MtpObjectInfo.java
index d2824b5..a080c73 100644
--- a/media/java/android/mtp/MtpObjectInfo.java
+++ b/media/java/android/mtp/MtpObjectInfo.java
@@ -256,7 +256,7 @@
/**
* Builds a new object info instance.
*/
- public class Builder {
+ public static class Builder {
private MtpObjectInfo mObjectInfo;
public Builder() {
@@ -273,25 +273,25 @@
public Builder(MtpObjectInfo objectInfo) {
mObjectInfo = new MtpObjectInfo();
mObjectInfo.mHandle = -1;
- mObjectInfo.mAssociationDesc = mObjectInfo.mAssociationDesc;
- mObjectInfo.mAssociationType = mObjectInfo.mAssociationType;
- mObjectInfo.mCompressedSize = mObjectInfo.mCompressedSize;
- mObjectInfo.mDateCreated = mObjectInfo.mDateCreated;
- mObjectInfo.mDateModified = mObjectInfo.mDateModified;
- mObjectInfo.mFormat = mObjectInfo.mFormat;
- mObjectInfo.mImagePixDepth = mObjectInfo.mImagePixDepth;
- mObjectInfo.mImagePixHeight = mObjectInfo.mImagePixHeight;
- mObjectInfo.mImagePixWidth = mObjectInfo.mImagePixWidth;
- mObjectInfo.mKeywords = mObjectInfo.mKeywords;
- mObjectInfo.mName = mObjectInfo.mName;
- mObjectInfo.mParent = mObjectInfo.mParent;
- mObjectInfo.mProtectionStatus = mObjectInfo.mProtectionStatus;
- mObjectInfo.mSequenceNumber = mObjectInfo.mSequenceNumber;
- mObjectInfo.mStorageId = mObjectInfo.mStorageId;
- mObjectInfo.mThumbCompressedSize = mObjectInfo.mThumbCompressedSize;
- mObjectInfo.mThumbFormat = mObjectInfo.mThumbFormat;
- mObjectInfo.mThumbPixHeight = mObjectInfo.mThumbPixHeight;
- mObjectInfo.mThumbPixWidth = mObjectInfo.mThumbPixWidth;
+ mObjectInfo.mAssociationDesc = objectInfo.mAssociationDesc;
+ mObjectInfo.mAssociationType = objectInfo.mAssociationType;
+ mObjectInfo.mCompressedSize = objectInfo.mCompressedSize;
+ mObjectInfo.mDateCreated = objectInfo.mDateCreated;
+ mObjectInfo.mDateModified = objectInfo.mDateModified;
+ mObjectInfo.mFormat = objectInfo.mFormat;
+ mObjectInfo.mImagePixDepth = objectInfo.mImagePixDepth;
+ mObjectInfo.mImagePixHeight = objectInfo.mImagePixHeight;
+ mObjectInfo.mImagePixWidth = objectInfo.mImagePixWidth;
+ mObjectInfo.mKeywords = objectInfo.mKeywords;
+ mObjectInfo.mName = objectInfo.mName;
+ mObjectInfo.mParent = objectInfo.mParent;
+ mObjectInfo.mProtectionStatus = objectInfo.mProtectionStatus;
+ mObjectInfo.mSequenceNumber = objectInfo.mSequenceNumber;
+ mObjectInfo.mStorageId = objectInfo.mStorageId;
+ mObjectInfo.mThumbCompressedSize = objectInfo.mThumbCompressedSize;
+ mObjectInfo.mThumbFormat = objectInfo.mThumbFormat;
+ mObjectInfo.mThumbPixHeight = objectInfo.mThumbPixHeight;
+ mObjectInfo.mThumbPixWidth = objectInfo.mThumbPixWidth;
}
public Builder setAssociationDesc(int value) {
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index ad804f3..2a46ee7 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -412,30 +412,27 @@
}
static jboolean
-android_mtp_MtpDevice_send_object(JNIEnv *env, jobject thiz, jint object_id, jint fd)
+android_mtp_MtpDevice_send_object(JNIEnv *env, jobject thiz, jint object_id, jint size, jint fd)
{
MtpDevice* device = get_device_from_object(env, thiz);
if (!device)
return JNI_FALSE;
- MtpObjectInfo* object_info = device->getObjectInfo(object_id);
- if (!object_info)
- return JNI_FALSE;
- bool result = device->sendObject(object_info, fd);
- delete object_info;
- return result;
+ return device->sendObject(object_id, size, fd);
}
static jobject
android_mtp_MtpDevice_send_object_info(JNIEnv *env, jobject thiz, jobject info)
{
MtpDevice* device = get_device_from_object(env, thiz);
- if (!device)
+ if (!device) {
return JNI_FALSE;
+ }
// Updating existing objects is not supported.
- if (env->GetIntField(info, field_objectInfo_handle) != -1)
+ if (env->GetIntField(info, field_objectInfo_handle) != -1) {
return JNI_FALSE;
+ }
MtpObjectInfo* object_info = new MtpObjectInfo(-1);
object_info->mStorageID = env->GetIntField(info, field_objectInfo_storageId);
@@ -456,17 +453,21 @@
object_info->mSequenceNumber = env->GetIntField(info, field_objectInfo_sequenceNumber);
jstring name_jstring = (jstring) env->GetObjectField(info, field_objectInfo_name);
- const char* name_string = env->GetStringUTFChars(name_jstring, NULL);
- object_info->mName = strdup(name_string);
- env->ReleaseStringUTFChars(name_jstring, name_string);
+ if (name_jstring != NULL) {
+ const char* name_string = env->GetStringUTFChars(name_jstring, NULL);
+ object_info->mName = strdup(name_string);
+ env->ReleaseStringUTFChars(name_jstring, name_string);
+ }
object_info->mDateCreated = env->GetLongField(info, field_objectInfo_dateCreated) / 1000LL;
object_info->mDateModified = env->GetLongField(info, field_objectInfo_dateModified) / 1000LL;
jstring keywords_jstring = (jstring) env->GetObjectField(info, field_objectInfo_keywords);
- const char* keywords_string = env->GetStringUTFChars(keywords_jstring, NULL);
- object_info->mKeywords = strdup(keywords_string);
- env->ReleaseStringUTFChars(keywords_jstring, keywords_string);
+ if (keywords_jstring != NULL) {
+ const char* keywords_string = env->GetStringUTFChars(keywords_jstring, NULL);
+ object_info->mKeywords = strdup(keywords_string);
+ env->ReleaseStringUTFChars(keywords_jstring, keywords_string);
+ }
int object_handle = device->sendObjectInfo(object_info);
if (object_handle == -1) {
@@ -510,7 +511,7 @@
{"native_import_file", "(ILjava/lang/String;)Z",
(void *)android_mtp_MtpDevice_import_file},
{"native_import_file", "(II)Z",(void *)android_mtp_MtpDevice_import_file_to_fd},
- {"native_send_object", "(II)Z",(void *)android_mtp_MtpDevice_send_object},
+ {"native_send_object", "(III)Z",(void *)android_mtp_MtpDevice_send_object},
{"native_send_object_info", "(Landroid/mtp/MtpObjectInfo;)Landroid/mtp/MtpObjectInfo;",
(void *)android_mtp_MtpDevice_send_object_info}
};
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiService.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiService.java
index fbde2b4..1f81a05 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiService.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiService.java
@@ -46,6 +46,7 @@
device = mDeviceServerMap.get(bluetoothDevice);
if (device == null) {
device = new BluetoothMidiDevice(this, bluetoothDevice, this);
+ mDeviceServerMap.put(bluetoothDevice, device);
}
}
return device.getBinder();
diff --git a/packages/BackupRestoreConfirmation/res/values-ro/strings.xml b/packages/BackupRestoreConfirmation/res/values-ro/strings.xml
index 1cf438b..969ec599 100644
--- a/packages/BackupRestoreConfirmation/res/values-ro/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-ro/strings.xml
@@ -18,17 +18,17 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="backup_confirm_title" msgid="827563724209303345">"Copiere de rezervă completă"</string>
<string name="restore_confirm_title" msgid="5469365809567486602">"Restabilire completă"</string>
- <string name="backup_confirm_text" msgid="1878021282758896593">"S-a solicitat crearea unei copii de rezervă complete a tuturor datelor pe un computer desktop conectat. Doriţi să permiteţi acest lucru?\n\nDacă nu aţi solicitat dvs. copierea de rezervă, nu permiteţi ca operaţiunea să continue."</string>
+ <string name="backup_confirm_text" msgid="1878021282758896593">"S-a solicitat crearea unei copii de rezervă complete a tuturor datelor pe un computer desktop conectat. Doriți să permiteți acest lucru?\n\nDacă nu aţi solicitat dvs. copierea de rezervă, nu permiteți ca operaţiunea să continue."</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"Creaţi copii de rezervă pentru datele dvs."</string>
<string name="deny_backup_button_label" msgid="6009119115581097708">"Nu creaţi copii de rezervă"</string>
- <string name="restore_confirm_text" msgid="7499866728030461776">"S-a solicitat o restabilire completă a tuturor datelor de pe un computer desktop conectat. Doriţi să permiteţi acest lucru?\n\nDacă nu dvs. aţi solicitat această restabilire, nu permiteţi continuarea operaţiunii. Acest proces va înlocui toate datele existente în prezent pe dispozitiv!"</string>
+ <string name="restore_confirm_text" msgid="7499866728030461776">"S-a solicitat o restabilire completă a tuturor datelor de pe un computer desktop conectat. Doriți să permiteți acest lucru?\n\nDacă nu dvs. aţi solicitat această restabilire, nu permiteți continuarea operaţiunii. Acest proces va înlocui toate datele existente în prezent pe dispozitiv!"</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"Restabiliţi datele dvs."</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"Nu restabiliţi"</string>
<string name="current_password_text" msgid="8268189555578298067">"Introduceţi mai jos parola actuală pentru copia de rezervă:"</string>
<string name="device_encryption_restore_text" msgid="1570864916855208992">"Introduceţi mai jos parola pentru criptarea dispozitivului."</string>
<string name="device_encryption_backup_text" msgid="5866590762672844664">"Introduceţi mai jos parola de criptare a dispozitivului. Aceasta va fi utilizată, de asemenea, pentru a cripta arhiva copiei de rezervă."</string>
<string name="backup_enc_password_text" msgid="4981585714795233099">"Introduceţi o parolă pentru a o utiliza la criptarea datelor copiei de rezervă complete. Dacă acest câmp rămâne necompletat, pentru copierea de rezervă se va utiliza parola dvs. actuală."</string>
- <string name="backup_enc_password_optional" msgid="1350137345907579306">"Dacă doriţi să criptaţi datele copiei de rezervă complete, introduceţi o parolă mai jos:"</string>
+ <string name="backup_enc_password_optional" msgid="1350137345907579306">"Dacă doriți să criptaţi datele copiei de rezervă complete, introduceţi o parolă mai jos:"</string>
<string name="backup_enc_password_required" msgid="7889652203371654149">"Întrucât dispozitivul este criptat, trebuie să criptați backupurile. Introduceți o parolă mai jos:"</string>
<string name="restore_enc_password_text" msgid="6140898525580710823">"Dacă datele pentru restabilire sunt criptate, introduceţi parola mai jos:"</string>
<string name="toast_backup_started" msgid="550354281452756121">"Se începe copierea de rezervă..."</string>
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index a0e3868..d578769 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -48,8 +48,8 @@
</activity>
<activity
- android:name=".StandaloneActivity"
- android:theme="@style/StandaloneTheme"
+ android:name=".FilesActivity"
+ android:theme="@style/FilesTheme"
android:icon="@drawable/ic_files_app"
android:label="@string/files_label"
android:enabled="@bool/productivity_device">
diff --git a/packages/DocumentsUI/res/layout/activity.xml b/packages/DocumentsUI/res/layout/drawer_layout.xml
similarity index 100%
rename from packages/DocumentsUI/res/layout/activity.xml
rename to packages/DocumentsUI/res/layout/drawer_layout.xml
diff --git a/packages/DocumentsUI/res/layout-sw720dp/activity.xml b/packages/DocumentsUI/res/layout/fixed_layout.xml
similarity index 100%
rename from packages/DocumentsUI/res/layout-sw720dp/activity.xml
rename to packages/DocumentsUI/res/layout/fixed_layout.xml
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index 1001e10..71e618b 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.documentsui.GridItem xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/grid_item_height"
android:layout_margin="@dimen/grid_item_margin"
@@ -140,4 +140,4 @@
android:contentDescription="@null"
android:duplicateParentState="true" />
-</FrameLayout>
+</com.android.documentsui.GridItem>
diff --git a/packages/DocumentsUI/res/layout/item_loading_grid.xml b/packages/DocumentsUI/res/layout/item_loading_grid.xml
index 005a111..147dfd4 100644
--- a/packages/DocumentsUI/res/layout/item_loading_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_loading_grid.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.documentsui.GridItem xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/grid_height"
android:orientation="horizontal">
@@ -26,4 +26,4 @@
android:indeterminate="true"
style="?android:attr/progressBarStyle" />
-</FrameLayout>
+</com.android.documentsui.GridItem>
diff --git a/packages/DocumentsUI/res/layout/item_message_grid.xml b/packages/DocumentsUI/res/layout/item_message_grid.xml
index 385563d..45d61a5 100644
--- a/packages/DocumentsUI/res/layout/item_message_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_message_grid.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.documentsui.GridItem xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/grid_height"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
@@ -48,4 +48,4 @@
</LinearLayout>
-</FrameLayout>
+</com.android.documentsui.GridItem>
diff --git a/packages/DocumentsUI/res/values-sw720dp-land/layouts.xml b/packages/DocumentsUI/res/values-sw720dp-land/layouts.xml
new file mode 100644
index 0000000..0e1807c
--- /dev/null
+++ b/packages/DocumentsUI/res/values-sw720dp-land/layouts.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <item name="files_activity" type="layout">@layout/fixed_layout</item>
+</resources>
diff --git a/packages/DocumentsUI/res/values-sw720dp/layouts.xml b/packages/DocumentsUI/res/values-sw720dp/layouts.xml
new file mode 100644
index 0000000..7d28f9c
--- /dev/null
+++ b/packages/DocumentsUI/res/values-sw720dp/layouts.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <item name="docs_activity" type="layout">@layout/fixed_layout</item>
+</resources>
diff --git a/packages/DocumentsUI/res/values/layouts.xml b/packages/DocumentsUI/res/values/layouts.xml
new file mode 100644
index 0000000..c73a1cb
--- /dev/null
+++ b/packages/DocumentsUI/res/values/layouts.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <item name="docs_activity" type="layout">@layout/drawer_layout</item>
+ <item name="files_activity" type="layout">@layout/drawer_layout</item>
+</resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 95c1d9c..fa94ff1 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -63,7 +63,7 @@
<item name="android:colorAccent">@color/material_blue_700</item>
</style>
- <style name="StandaloneTheme" parent="@android:style/Theme.Material.DayNight.DarkActionBar">
+ <style name="FilesTheme" parent="@android:style/Theme.Material.DayNight.DarkActionBar">
<item name="android:actionBarWidgetTheme">@null</item>
<item name="android:colorPrimaryDark">@color/status_bar_background</item>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BandSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/BandSelectManager.java
deleted file mode 100644
index 74170f5..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/BandSelectManager.java
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui;
-
-import static com.android.documentsui.Events.isMouseEvent;
-import static com.android.internal.util.Preconditions.checkState;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.util.Log;
-import android.util.SparseBooleanArray;
-import android.view.MotionEvent;
-import android.view.View;
-
-/**
- * Provides mouse driven band-select support when used in conjuction with {@link RecyclerView} and
- * {@link MultiSelectManager}. This class is responsible for rendering the band select overlay and
- * selecting overlaid items via MultiSelectManager.
- */
-public class BandSelectManager extends RecyclerView.SimpleOnItemTouchListener {
-
- private static final int NOT_SELECTED = -1;
- private static final int NOT_SET = -1;
-
- // For debugging purposes.
- private static final String TAG = "BandSelectManager";
- private static final boolean DEBUG = false;
-
- private final RecyclerView mRecyclerView;
- private final MultiSelectManager mSelectManager;
- private final Drawable mRegionSelectorDrawable;
- private final SparseBooleanArray mSelectedByBand = new SparseBooleanArray();
-
- private boolean mIsBandSelectActive = false;
- private Point mOrigin;
- private Point mPointer;
- private Rect mBounds;
-
- // Maintain the last selection made by band, so if bounds shrink back, we can deselect
- // the respective items.
- private int mCursorDeltaY = 0;
- private int mFirstSelected = NOT_SELECTED;
-
- // The time at which the current band selection-induced scroll began. If no scroll is in
- // progress, the value is NOT_SET.
- private long mScrollStartTime = NOT_SET;
- private final Runnable mScrollRunnable = new Runnable() {
- /**
- * The number of milliseconds of scrolling at which scroll speed continues to increase. At
- * first, the scroll starts slowly; then, the rate of scrolling increases until it reaches
- * its maximum value at after this many milliseconds.
- */
- private static final long SCROLL_ACCELERATION_LIMIT_TIME_MS = 2000;
-
- @Override
- public void run() {
- // Compute the number of pixels the pointer's y-coordinate is past the view. Negative
- // values mean the pointer is at or before the top of the view, and positive values mean
- // that the pointer is at or after the bottom of the view. Note that one additional
- // pixel is added here so that the view still scrolls when the pointer is exactly at the
- // top or bottom.
- int pixelsPastView = 0;
- if (mPointer.y <= 0) {
- pixelsPastView = mPointer.y - 1;
- } else if (mPointer.y >= mRecyclerView.getHeight() - 1) {
- pixelsPastView = mPointer.y - mRecyclerView.getHeight() + 1;
- }
-
- if (!mIsBandSelectActive || pixelsPastView == 0) {
- // If band selection is inactive, or if it is active but not at the edge of the
- // view, no scrolling is necessary.
- mScrollStartTime = NOT_SET;
- return;
- }
-
- if (mScrollStartTime == NOT_SET) {
- // If the pointer was previously not at the edge of the view but now is, set the
- // start time for the scroll.
- mScrollStartTime = System.currentTimeMillis();
- }
-
- // Compute the number of pixels to scroll, and scroll that many pixels.
- final int numPixels = computeNumPixelsToScroll(
- pixelsPastView, System.currentTimeMillis() - mScrollStartTime);
- mRecyclerView.scrollBy(0, numPixels);
-
- // Adjust the y-coordinate of the origin the opposite number of pixels so that the
- // origin remains in the same place relative to the view's items.
- mOrigin.y -= numPixels;
- resizeBandSelectRectangle();
-
- mRecyclerView.removeCallbacks(mScrollRunnable);
- mRecyclerView.postOnAnimation(this);
- }
-
- /**
- * Computes the number of pixels to scroll based on how far the pointer is past the end of
- * the view and how long it has been there. Roughly based on ItemTouchHelper's algorithm for
- * computing the number of pixels to scroll when an item is dragged to the end of a
- * {@link RecyclerView}.
- * @param pixelsPastView
- * @param scrollDuration
- * @return
- */
- private int computeNumPixelsToScroll(int pixelsPastView, long scrollDuration) {
- final int maxScrollStep = computeMaxScrollStep(mRecyclerView);
- final int direction = (int) Math.signum(pixelsPastView);
- final int absPastView = Math.abs(pixelsPastView);
-
- // Calculate the ratio of how far out of the view the pointer currently resides to the
- // entire height of the view.
- final float outOfBoundsRatio = Math.min(
- 1.0f, (float) absPastView / mRecyclerView.getHeight());
- // Interpolate this ratio and use it to compute the maximum scroll that should be
- // possible for this step.
- final float cappedScrollStep =
- direction * maxScrollStep * smoothOutOfBoundsRatio(outOfBoundsRatio);
-
- // Likewise, calculate the ratio of the time spent in the scroll to the limit.
- final float timeRatio = Math.min(
- 1.0f, (float) scrollDuration / SCROLL_ACCELERATION_LIMIT_TIME_MS);
- // Interpolate this ratio and use it to compute the final number of pixels to scroll.
- final int numPixels = (int) (cappedScrollStep * smoothTimeRatio(timeRatio));
-
- // If the final number of pixels to scroll ends up being 0, the view should still scroll
- // at least one pixel.
- return numPixels != 0 ? numPixels : direction;
- }
-
- /**
- * Computes the maximum scroll allowed for a given animation frame. Currently, this
- * defaults to the height of the view, but this could be tweaked if this results in scrolls
- * that are too fast or too slow.
- * @param rv
- * @return
- */
- private int computeMaxScrollStep(RecyclerView rv) {
- return rv.getHeight();
- }
-
- /**
- * Interpolates the given out of bounds ratio on a curve which starts at (0,0) and ends at
- * (1,1) and quickly approaches 1 near the start of that interval. This ensures that drags
- * that are at the edge or barely past the edge of the view still cause sufficient
- * scrolling. The equation y=(x-1)^5+1 is used, but this could also be tweaked if needed.
- * @param ratio A ratio which is in the range [0, 1].
- * @return A "smoothed" value, also in the range [0, 1].
- */
- private float smoothOutOfBoundsRatio(float ratio) {
- return (float) Math.pow(ratio - 1.0f, 5) + 1.0f;
- }
-
- /**
- * Interpolates the given time ratio on a curve which starts at (0,0) and ends at (1,1) and
- * stays close to 0 for most input values except those very close to 1. This ensures that
- * scrolls start out very slowly but speed up drastically after the scroll has been in
- * progress close to SCROLL_ACCELERATION_LIMIT_TIME_MS. The equation y=x^5 is used, but this
- * could also be tweaked if needed.
- * @param ratio A ratio which is in the range [0, 1].
- * @return A "smoothed" value, also in the range [0, 1].
- */
- private float smoothTimeRatio(float ratio) {
- return (float) Math.pow(ratio, 5);
- }
- };
-
- /**
- * @param recyclerView
- * @param multiSelectManager
- */
- public BandSelectManager(RecyclerView recyclerView, MultiSelectManager multiSelectManager) {
- mRecyclerView = recyclerView;
- mSelectManager = multiSelectManager;
- mRegionSelectorDrawable =
- mRecyclerView.getContext().getTheme().getDrawable(R.drawable.band_select_overlay);
-
- mRecyclerView.addOnItemTouchListener(this);
- }
-
- @Override
- public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
- // Only intercept the event if it was triggered by a mouse. If band select is inactive,
- // do not intercept ACTION_UP events as they will not be processed.
- return isMouseEvent(e) &&
- (mIsBandSelectActive || e.getActionMasked() != MotionEvent.ACTION_UP);
- }
-
- @Override
- public void onTouchEvent(RecyclerView rv, MotionEvent e) {
- checkState(isMouseEvent(e));
- processMotionEvent(e);
- }
-
- /**
- * Processes a MotionEvent by starting, ending, or resizing the band select overlay.
- * @param e
- */
- private void processMotionEvent(MotionEvent e) {
- if (mIsBandSelectActive && e.getActionMasked() == MotionEvent.ACTION_UP) {
- endBandSelect();
- return;
- }
-
- mPointer = new Point((int) e.getX(), (int) e.getY());
- if (!mIsBandSelectActive) {
- startBandSelect();
- }
-
- scrollViewIfNecessary();
- resizeBandSelectRectangle();
- selectChildrenCoveredBySelection();
- }
-
- /**
- * Starts band select by adding the drawable to the RecyclerView's overlay.
- */
- private void startBandSelect() {
- if (DEBUG) Log.d(TAG, "Starting band select from (" + mPointer.x + "," + mPointer.y + ").");
- mIsBandSelectActive = true;
- mOrigin = mPointer;
- mRecyclerView.getOverlay().add(mRegionSelectorDrawable);
- }
-
- /**
- * Scrolls the view if necessary.
- */
- private void scrollViewIfNecessary() {
- mRecyclerView.removeCallbacks(mScrollRunnable);
- mScrollRunnable.run();
- mRecyclerView.invalidate();
- }
-
- /**
- * Resizes the band select rectangle by using the origin and the current pointer positoin as
- * two opposite corners of the selection.
- */
- private void resizeBandSelectRectangle() {
- if (mBounds != null) {
- mCursorDeltaY = mPointer.y - mBounds.bottom;
- }
-
- mBounds = new Rect(Math.min(mOrigin.x, mPointer.x),
- Math.min(mOrigin.y, mPointer.y),
- Math.max(mOrigin.x, mPointer.x),
- Math.max(mOrigin.y, mPointer.y));
-
- mRegionSelectorDrawable.setBounds(mBounds);
- }
-
- /**
- * Selects the children covered by the band select overlay by delegating to MultiSelectManager.
- * TODO: Provide a finished implementation. This is down and dirty, proof of concept code.
- * Final optimized implementation, with support for managing offscreen selection to come.
- */
- private void selectChildrenCoveredBySelection() {
-
- // track top and bottom selections. Details on why this is useful below.
- int first = NOT_SELECTED;
- int last = NOT_SELECTED;
-
- for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
-
- View child = mRecyclerView.getChildAt(i);
- ViewHolder holder = mRecyclerView.getChildViewHolder(child);
- Rect childRect = new Rect();
- child.getHitRect(childRect);
-
- boolean shouldSelect = Rect.intersects(childRect, mBounds);
- int position = holder.getAdapterPosition();
-
- // This also allows us to clear the selection of elements
- // that only temporarily entered the bounds of the band.
- if (mSelectedByBand.get(position) && !shouldSelect) {
- mSelectManager.setItemSelected(position, false);
- mSelectedByBand.delete(position);
- }
-
- // We need to keep track of the first and last items selected.
- // We'll use this information along with cursor direction
- // to determine the starting point of the selection.
- // We provide this information to selection manager
- // to enable more natural user interaction when working
- // with Shift+Click and multiple contiguous selection ranges.
- if (shouldSelect) {
- if (first == NOT_SELECTED) {
- first = position;
- } else {
- last = position;
- }
- mSelectManager.setItemSelected(position, true);
- mSelectedByBand.put(position, true);
- }
- }
-
- // Remember which is the last selected item, so we can
- // share that with selection manager when band select ends.
- // It'll use that as it's begin selection point when
- // user SHIFT+Clicks.
- if (mCursorDeltaY < 0 && last != NOT_SELECTED) {
- mFirstSelected = last;
- } else if (mCursorDeltaY > 0 && first != NOT_SELECTED) {
- mFirstSelected = first;
- }
- }
-
- /**
- * Ends band select by removing the overlay.
- */
- private void endBandSelect() {
- if (DEBUG) Log.d(TAG, "Ending band select.");
- mIsBandSelectActive = false;
- mSelectedByBand.clear();
- mRecyclerView.getOverlay().remove(mRegionSelectorDrawable);
- if (mFirstSelected != NOT_SELECTED) {
- mSelectManager.setSelectionFocusBegin(mFirstSelected);
- }
- }
-}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 9b8d847..2835106 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -22,7 +22,6 @@
import static com.android.documentsui.DirectoryFragment.ANIM_UP;
import static com.android.internal.util.Preconditions.checkArgument;
-import android.annotation.Nullable;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
@@ -38,6 +37,8 @@
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
+import android.support.annotation.LayoutRes;
+import android.support.annotation.Nullable;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
@@ -46,6 +47,7 @@
import android.view.MenuItem.OnActionExpandListener;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStub;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
@@ -60,8 +62,6 @@
import com.android.documentsui.model.DurableUtils;
import com.android.documentsui.model.RootInfo;
-import com.google.common.collect.Maps;
-
import libcore.io.IoUtils;
import java.io.FileNotFoundException;
@@ -76,9 +76,13 @@
static final String EXTRA_STATE = "state";
+ State mState;
RootsCache mRoots;
SearchManager mSearchManager;
+ DrawerController mDrawer;
+ @LayoutRes
+ private int mLayoutId;
private final String mTag;
public abstract State getDisplayState();
@@ -89,16 +93,28 @@
abstract void onDirectoryChanged(int anim);
abstract void updateActionBar();
abstract void saveStackBlocking();
+ abstract State buildDefaultState();
- public BaseActivity(String tag) {
+ public BaseActivity(@LayoutRes int layoutId, String tag) {
+ mLayoutId = layoutId;
mTag = tag;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+
+ mState = (icicle != null)
+ ? icicle.<State>getParcelable(EXTRA_STATE)
+ : buildDefaultState();
+
+ setContentView(mLayoutId);
+
mRoots = DocumentsApplication.getRootsCache(this);
mSearchManager = new SearchManager();
+
+ // Base classes must update result in their onCreate.
+ setResult(Activity.RESULT_CANCELED);
}
@Override
@@ -371,7 +387,7 @@
public String currentSearch;
/** Instance state for every shown directory */
- public HashMap<String, SparseArray<Parcelable>> dirState = Maps.newHashMap();
+ public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>();
/** Currently copying file */
public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<DocumentInfo>();
@@ -527,6 +543,30 @@
}
}
+ @Override
+ public void onBackPressed() {
+ // While action bar is expanded, the state stack UI is hidden.
+ if (mSearchManager.cancelSearch()) {
+ return;
+ }
+
+ if (!mState.stackTouched) {
+ super.onBackPressed();
+ return;
+ }
+
+ final int size = mState.stack.size();
+
+ if (mDrawer.isOpen()) {
+ mDrawer.setOpen(false);
+ } else if (size > 1) {
+ mState.stack.pop();
+ onCurrentDirectoryChanged(ANIM_UP);
+ } else {
+ super.onBackPressed();
+ }
+ }
+
public void onStackPicked(DocumentStack stack) {
try {
// Update the restored stack to ensure we have freshest data
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
index 14155d5..8b92331 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
@@ -167,7 +167,7 @@
if (mFailedFiles.size() > 0) {
final Context context = getApplicationContext();
- final Intent navigateIntent = new Intent(context, StandaloneActivity.class);
+ final Intent navigateIntent = new Intent(context, FilesActivity.class);
navigateIntent.putExtra(EXTRA_STACK, (Parcelable) stack);
navigateIntent.putExtra(EXTRA_FAILURE, FAILURE_COPY);
navigateIntent.putParcelableArrayListExtra(EXTRA_SRC_LIST, mFailedFiles);
@@ -213,7 +213,7 @@
mIsCancelled = false;
final Context context = getApplicationContext();
- final Intent navigateIntent = new Intent(context, StandaloneActivity.class);
+ final Intent navigateIntent = new Intent(context, FilesActivity.class);
navigateIntent.putExtra(EXTRA_STACK, (Parcelable) stack);
final String contentTitle = getString(copying ? R.string.copy_notification_title
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index f927595..e408e6e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -16,7 +16,7 @@
package com.android.documentsui;
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -36,7 +36,6 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 5223d76..c28806b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -24,14 +24,13 @@
import static com.android.documentsui.BaseActivity.State.MODE_LIST;
import static com.android.documentsui.BaseActivity.State.MODE_UNKNOWN;
import static com.android.documentsui.BaseActivity.State.SORT_ORDER_UNKNOWN;
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;
-import android.annotation.NonNull;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Fragment;
@@ -98,7 +97,7 @@
import com.android.documentsui.model.RootInfo;
import com.android.internal.util.Preconditions;
-import com.google.android.collect.Lists;
+import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
@@ -235,8 +234,7 @@
public void onLayoutChange(
View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) {
- int thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width);
- mColumnCount = pickColumnCount(thumbSize);
+ mColumnCount = calculateColumnCount();
if (mGridLayout != null) {
mGridLayout.setSpanCount(mColumnCount);
}
@@ -535,8 +533,6 @@
updateLayout(state.derivedMode);
- final int thumbSize = getResources().getDimensionPixelSize(R.dimen.icon_size);
- mThumbSize = new Point(thumbSize, thumbSize);
mRecView.setAdapter(mAdapter);
}
@@ -573,13 +569,15 @@
mThumbSize = new Point(thumbSize, thumbSize);
}
- private int pickColumnCount(final int thumbSize) {
- int itemPadding =
- getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
+ private int calculateColumnCount() {
+ int cellWidth = getResources().getDimensionPixelSize(R.dimen.grid_width);
+ int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight();
+
checkState(mRecView.getWidth() > 0);
int columnCount = Math.max(1,
- (mRecView.getWidth() - viewPadding) / (thumbSize + itemPadding));
+ (mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin));
+
return columnCount;
}
@@ -740,7 +738,7 @@
new GetDocumentsTask() {
@Override
void onDocumentsReady(List<DocumentInfo> docs) {
- // TODO: Implement support in standalone for opening multiple docs.
+ // TODO: Implement support in Files activity for opening multiple docs.
BaseActivity.get(DirectoryFragment.this).onDocumentsPicked(docs);
}
}.execute(selected);
@@ -753,7 +751,7 @@
Intent intent;
// Filter out directories - those can't be shared.
- List<DocumentInfo> docsForSend = Lists.newArrayList();
+ List<DocumentInfo> docsForSend = new ArrayList<>();
for (DocumentInfo doc: docs) {
if (!Document.MIME_TYPE_DIR.equals(doc.mimeType)) {
docsForSend.add(doc);
@@ -774,8 +772,8 @@
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addCategory(Intent.CATEGORY_DEFAULT);
- final ArrayList<String> mimeTypes = Lists.newArrayList();
- final ArrayList<Uri> uris = Lists.newArrayList();
+ final ArrayList<String> mimeTypes = new ArrayList<>();
+ final ArrayList<Uri> uris = new ArrayList<>();
for (DocumentInfo doc : docsForSend) {
mimeTypes.add(doc.mimeType);
uris.add(doc.derivedUri);
@@ -956,7 +954,7 @@
private final Context mContext;
private final LayoutInflater mInflater;
// TODO: Bring back support for footers.
- private final List<Footer> mFooters = Lists.newArrayList();
+ private final List<Footer> mFooters = new ArrayList<>();
private Cursor mCursor;
private int mCursorCount;
@@ -1330,7 +1328,7 @@
return MimePredicate.mimeMatches(state.acceptMimes, docMimeType);
}
- private @NonNull List<DocumentInfo> getSelectedDocuments() {
+ private List<DocumentInfo> getSelectedDocuments() {
Selection sel = mSelectionManager.getSelection(new Selection());
return getItemsAsDocuments(sel);
}
@@ -1570,6 +1568,7 @@
final Cursor cursor = mAdapter.getItem(position);
checkNotNull(cursor, "Cursor cannot be null.");
final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
+
return Lists.newArrayList(doc);
}
@@ -1685,7 +1684,7 @@
private FragmentTuner pickFragmentTuner(final State state) {
return state.action == ACTION_BROWSE_ALL
- ? new StandaloneTuner()
+ ? new FilesTuner()
: new DefaultTuner(state);
}
@@ -1750,7 +1749,7 @@
copyTo.setVisible(manageOrBrowse && dirType != TYPE_RECENT_OPEN);
moveTo.setVisible(SystemProperties.getBoolean("debug.documentsui.enable_move", false));
- // Only shown in standalone mode.
+ // Only shown in files mode.
copyToClipboard.setVisible(false);
}
@@ -1759,9 +1758,9 @@
}
/**
- * Provides support for Standalone specific specializations of DirectoryFragment.
+ * Provides support for Files activity specific specializations of DirectoryFragment.
*/
- private static final class StandaloneTuner implements FragmentTuner {
+ private static final class FilesTuner implements FragmentTuner {
@Override
public void updateActionMenu(Menu menu, int dirType, boolean canDelete) {
menu.findItem(R.id.menu_share).setVisible(true);
@@ -1774,8 +1773,6 @@
}
@Override
- public void afterActivityCreated(DirectoryFragment fragment) {
- new BandSelectManager(fragment.mRecView, fragment.mSelectionManager);
- }
+ public void afterActivityCreated(DirectoryFragment fragment) {}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index a8a61d2..0edb241 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -16,12 +16,12 @@
package com.android.documentsui;
-import static com.android.documentsui.DocumentsActivity.TAG;
import static com.android.documentsui.BaseActivity.State.MODE_UNKNOWN;
import static com.android.documentsui.BaseActivity.State.SORT_ORDER_DISPLAY_NAME;
import static com.android.documentsui.BaseActivity.State.SORT_ORDER_LAST_MODIFIED;
import static com.android.documentsui.BaseActivity.State.SORT_ORDER_SIZE;
import static com.android.documentsui.BaseActivity.State.SORT_ORDER_UNKNOWN;
+import static com.android.documentsui.Shared.TAG;
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import android.content.AsyncTaskLoader;
@@ -31,8 +31,6 @@
import android.database.Cursor;
import android.net.Uri;
import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.Looper;
import android.os.OperationCanceledException;
import android.os.RemoteException;
import android.provider.DocumentsContract;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
index 2370575..6ba07fbb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
@@ -16,8 +16,6 @@
package com.android.documentsui;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ContentProviderClient;
@@ -26,15 +24,15 @@
import android.database.Cursor;
import android.net.Uri;
import android.provider.DocumentsContract;
+import android.support.annotation.Nullable;
import android.util.Log;
import com.android.documentsui.model.DocumentInfo;
import com.android.internal.util.Preconditions;
-import com.google.android.collect.Lists;
-
import libcore.io.IoUtils;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -78,7 +76,7 @@
* Returns a list of Documents as decoded from Clipboard primary clipdata.
* This should be run from inside an AsyncTask.
*/
- public @NonNull List<DocumentInfo> getClippedDocuments() {
+ public List<DocumentInfo> getClippedDocuments() {
return getDocumentsFromClipData(mClipboard.getPrimaryClip());
}
@@ -86,9 +84,9 @@
* Returns a list of Documents as decoded in clipData.
* This should be run from inside an AsyncTask.
*/
- public @NonNull List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) {
+ public List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) {
Preconditions.checkNotNull(clipData);
- final List<DocumentInfo> srcDocs = Lists.newArrayList();
+ final List<DocumentInfo> srcDocs = new ArrayList<>();
int count = clipData.getItemCount();
if (count == 0) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 2de7fc4..fdc4bb0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -25,8 +25,6 @@
import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_TREE;
import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
-import static com.android.documentsui.DirectoryFragment.ANIM_UP;
-import static com.android.internal.util.Preconditions.checkArgument;
import android.app.Activity;
import android.app.Fragment;
@@ -48,9 +46,6 @@
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
-import android.support.v4.app.ActionBarDrawerToggle;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v4.widget.DrawerLayout.DrawerListener;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -81,42 +76,32 @@
private Toolbar mRootsToolbar;
- private DrawerLayout mDrawerLayout;
- private ActionBarDrawerToggle mDrawerToggle;
- private View mRootsDrawer;
-
private DirectoryContainerView mDirectoryContainer;
- private State mState;
-
private ItemSelectedListener mStackListener;
private BaseAdapter mStackAdapter;
public DocumentsActivity() {
- super(TAG);
+ super(R.layout.docs_activity, TAG);
}
@Override
public void onCreate(Bundle icicle) {
- mState = (icicle != null)
- ? icicle.<State>getParcelable(EXTRA_STATE)
- : buildDefaultState();
+ super.onCreate(icicle);
final Resources res = getResources();
mShowAsDialog = res.getBoolean(R.bool.show_as_dialog) && mState.action != ACTION_MANAGE &&
mState.action != ACTION_BROWSE;
+
if (!mShowAsDialog) {
setTheme(R.style.DocumentsNonDialogTheme);
}
- super.onCreate(icicle);
-
- setResult(Activity.RESULT_CANCELED);
- setContentView(R.layout.activity);
-
final Context context = this;
if (mShowAsDialog) {
+ mDrawer = DrawerController.createDummy();
+
// Strongly define our horizontal dimension; we leave vertical as
// WRAP_CONTENT so that system resizes us when IME is showing.
final WindowManager.LayoutParams a = getWindow().getAttributes();
@@ -128,17 +113,7 @@
getWindow().setAttributes(a);
} else {
- // Non-dialog means we have a drawer
- mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
-
- if (mDrawerLayout != null) {
- mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
- R.drawable.ic_hamburger, R.string.drawer_open, R.string.drawer_close);
-
- mDrawerLayout.setDrawerListener(mDrawerListener);
-
- mRootsDrawer = findViewById(R.id.drawer_roots);
- }
+ mDrawer = DrawerController.create(this);
}
mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
@@ -162,10 +137,9 @@
// Hide roots when we're managing a specific root
if (mState.action == ACTION_MANAGE || mState.action == ACTION_BROWSE) {
- if (mShowAsDialog || mDrawerLayout == null) {
+ mDrawer.lockClosed();
+ if (mShowAsDialog) {
findViewById(R.id.container_roots).setVisibility(View.GONE);
- } else {
- mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
}
}
@@ -205,7 +179,8 @@
}
}
- private State buildDefaultState() {
+ @Override
+ State buildDefaultState() {
State state = new State();
final Intent intent = getIntent();
@@ -341,53 +316,15 @@
}
}
- private DrawerListener mDrawerListener = new DrawerListener() {
- @Override
- public void onDrawerSlide(View drawerView, float slideOffset) {
- mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
- }
-
- @Override
- public void onDrawerOpened(View drawerView) {
- mDrawerToggle.onDrawerOpened(drawerView);
- }
-
- @Override
- public void onDrawerClosed(View drawerView) {
- mDrawerToggle.onDrawerClosed(drawerView);
- }
-
- @Override
- public void onDrawerStateChanged(int newState) {
- mDrawerToggle.onDrawerStateChanged(newState);
- }
- };
-
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
- if (mDrawerToggle != null) {
- mDrawerToggle.syncState();
- }
+ mDrawer.syncState();
updateActionBar();
}
public void setRootsDrawerOpen(boolean open) {
- if (!mShowAsDialog && mDrawerLayout != null) {
- if (open) {
- mDrawerLayout.openDrawer(mRootsDrawer);
- } else {
- mDrawerLayout.closeDrawer(mRootsDrawer);
- }
- }
- }
-
- private boolean isRootsDrawerOpen() {
- if (mShowAsDialog || mDrawerLayout == null) {
- return false;
- } else {
- return mDrawerLayout.isDrawerOpen(mRootsDrawer);
- }
+ mDrawer.setOpen(open);
}
@Override
@@ -408,8 +345,7 @@
}
}
- if (!mShowAsDialog && mDrawerLayout != null &&
- mDrawerLayout.getDrawerLockMode(mRootsDrawer) == DrawerLayout.LOCK_MODE_UNLOCKED) {
+ if (!mShowAsDialog && mDrawer.isUnlocked()) {
mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
mToolbar.setNavigationContentDescription(R.string.drawer_open);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@@ -504,34 +440,7 @@
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (mDrawerToggle != null && mDrawerToggle.onOptionsItemSelected(item)) {
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public void onBackPressed() {
- // While action bar is expanded, the state stack UI is hidden.
- if (mSearchManager.cancelSearch()) {
- return;
- }
-
- if (!mState.stackTouched) {
- super.onBackPressed();
- return;
- }
-
- final int size = mState.stack.size();
- if (size > 1) {
- mState.stack.pop();
- onCurrentDirectoryChanged(ANIM_UP);
- } else if (size == 1 && !isRootsDrawerOpen()) {
- // TODO: open root drawer once we can capture back key
- super.onBackPressed();
- } else {
- super.onBackPressed();
- }
+ return mDrawer.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
new file mode 100644
index 0000000..df3ac1b
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import android.app.Activity;
+import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v4.widget.DrawerLayout.DrawerListener;
+import android.view.MenuItem;
+import android.view.View;
+
+/**
+ * A facade over the various pieces comprising "roots fragment in a Drawer".
+ *
+ * @see DrawerController#create(DrawerLayout)
+ */
+abstract class DrawerController implements DrawerListener {
+
+ abstract void setOpen(boolean open);
+ abstract void lockOpen();
+ abstract void lockClosed();
+ abstract boolean isPresent();
+ abstract boolean isOpen();
+ abstract boolean isUnlocked();
+ abstract void syncState();
+ abstract boolean onOptionsItemSelected(MenuItem item);
+
+ /**
+ * Returns a controller suitable for {@code Layout}.
+ */
+ static DrawerController create(Activity activity) {
+
+ DrawerLayout layout = (DrawerLayout) activity.findViewById(R.id.drawer_layout);
+
+ if (layout == null) {
+ return new DummyDrawerController();
+ }
+
+ View drawer = activity.findViewById(R.id.drawer_roots);
+ ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
+ activity,
+ layout,
+ R.drawable.ic_hamburger,
+ R.string.drawer_open,
+ R.string.drawer_close);
+
+ return new RuntimeDrawerController(layout, drawer, toggle);
+ }
+
+ /**
+ * Returns a controller suitable for {@code Layout}.
+ */
+ static DrawerController createDummy() {
+ return new DummyDrawerController();
+ }
+
+ /**
+ * Runtime controller that manages a real drawer.
+ */
+ private static final class RuntimeDrawerController extends DrawerController {
+
+ private final ActionBarDrawerToggle mToggle;
+ private DrawerLayout mLayout;
+ private View mDrawer;
+
+ public RuntimeDrawerController(
+ DrawerLayout layout, View drawer, ActionBarDrawerToggle toggle) {
+ checkArgument(layout != null);
+
+ mLayout = layout;
+ mDrawer = drawer;
+ mToggle = toggle;
+
+ mLayout.setDrawerListener(this);
+ }
+
+ @Override
+ void setOpen(boolean open) {
+ if (open) {
+ mLayout.openDrawer(mDrawer);
+ } else {
+ mLayout.closeDrawer(mDrawer);
+ }
+ }
+
+ @Override
+ boolean isOpen() {
+ return mLayout.isDrawerOpen(mDrawer);
+ }
+
+ @Override
+ boolean isPresent() {
+ return true;
+ }
+
+ @Override
+ void syncState() {
+ mToggle.syncState();
+ }
+
+ @Override
+ boolean isUnlocked() {
+ return mLayout.getDrawerLockMode(mDrawer) == DrawerLayout.LOCK_MODE_UNLOCKED;
+ }
+
+ @Override
+ void lockOpen() {
+ mLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
+ }
+
+ @Override
+ void lockClosed() {
+ mLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
+ }
+
+ @Override
+ boolean onOptionsItemSelected(MenuItem item) {
+ return false;
+ }
+
+ @Override
+ public void onDrawerSlide(View drawerView, float slideOffset) {
+ mToggle.onDrawerSlide(drawerView, slideOffset);
+ }
+
+ @Override
+ public void onDrawerOpened(View drawerView) {
+ mToggle.onDrawerOpened(drawerView);
+ }
+
+ @Override
+ public void onDrawerClosed(View drawerView) {
+ mToggle.onDrawerClosed(drawerView);
+ }
+
+ @Override
+ public void onDrawerStateChanged(int newState) {
+ mToggle.onDrawerStateChanged(newState);
+ }
+ }
+
+ /*
+ * Dummy controller useful with clients that don't host a real drawer.
+ */
+ private static final class DummyDrawerController extends DrawerController {
+
+ @Override
+ void setOpen(boolean open) {}
+
+ @Override
+ void syncState() {}
+
+ @Override
+ void lockOpen() {}
+
+ @Override
+ void lockClosed() {}
+
+ @Override
+ boolean isOpen() {
+ return false;
+ }
+
+ @Override
+ boolean isUnlocked() {
+ return true;
+ }
+
+ @Override
+ boolean isPresent() {
+ return false;
+ }
+
+ @Override
+ boolean onOptionsItemSelected(MenuItem item) {
+ return false;
+ }
+
+ @Override
+ public void onDrawerSlide(View drawerView, float slideOffset) {}
+
+ @Override
+ public void onDrawerOpened(View drawerView) {}
+
+ @Override
+ public void onDrawerClosed(View drawerView) {}
+
+ @Override
+ public void onDrawerStateChanged(int newState) {}
+ }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
similarity index 91%
rename from packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java
rename to packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 1ca277d..7c445bf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -18,9 +18,7 @@
import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
-import static com.android.documentsui.DirectoryFragment.ANIM_UP;
-import android.annotation.Nullable;
import android.app.Activity;
import android.app.FragmentManager;
import android.content.ActivityNotFoundException;
@@ -33,6 +31,7 @@
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
+import android.support.annotation.Nullable;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
@@ -57,7 +56,7 @@
/**
* Standalone file management activity.
*/
-public class StandaloneActivity extends BaseActivity {
+public class FilesActivity extends BaseActivity {
public static final String TAG = "StandaloneFileManagement";
static final boolean DEBUG = false;
@@ -66,30 +65,22 @@
private Spinner mToolbarStack;
private Toolbar mRootsToolbar;
private DirectoryContainerView mDirectoryContainer;
- private State mState;
private ItemSelectedListener mStackListener;
private BaseAdapter mStackAdapter;
private DocumentClipper mClipper;
- public StandaloneActivity() {
- super(TAG);
+ public FilesActivity() {
+ super(R.layout.files_activity, TAG);
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- setResult(Activity.RESULT_CANCELED);
- setContentView(R.layout.activity);
-
final Context context = this;
mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
- mState = (icicle != null)
- ? icicle.<State> getParcelable(EXTRA_STATE)
- : buildDefaultState();
-
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mToolbar.setTitleTextAppearance(context,
android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
@@ -108,6 +99,11 @@
setActionBar(mToolbar);
mClipper = new DocumentClipper(this);
+ mDrawer = DrawerController.create(this);
+ if (mDrawer.isPresent()) {
+ setTheme(R.style.DocumentsNonDialogTheme);
+ }
+
RootsFragment.show(getFragmentManager(), null);
if (!mState.restored) {
@@ -130,7 +126,8 @@
}
}
- private State buildDefaultState() {
+ @Override
+ State buildDefaultState() {
State state = new State();
final Intent intent = getIntent();
@@ -164,10 +161,23 @@
@Override
public void updateActionBar() {
final RootInfo root = getCurrentRoot();
- mToolbar.setNavigationIcon(
- root != null ? root.loadToolbarIcon(mToolbar.getContext()) : null);
- mToolbar.setNavigationContentDescription(R.string.drawer_open);
- mToolbar.setNavigationOnClickListener(null);
+
+ if (mDrawer.isPresent()) {
+ mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
+ mToolbar.setNavigationContentDescription(R.string.drawer_open);
+ mToolbar.setNavigationOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mDrawer.setOpen(true);
+ }
+ });
+ } else {
+ mToolbar.setNavigationIcon(
+ root != null ? root.loadToolbarIcon(mToolbar.getContext()) : null);
+ mToolbar.setNavigationContentDescription(R.string.drawer_open);
+ mToolbar.setNavigationOnClickListener(null);
+ }
if (mSearchManager.isExpanded()) {
mToolbar.setTitle(null);
@@ -236,22 +246,6 @@
}
@Override
- public void onBackPressed() {
- if (!mState.stackTouched) {
- super.onBackPressed();
- return;
- }
-
- final int size = mState.stack.size();
- if (size > 1) {
- mState.stack.pop();
- onCurrentDirectoryChanged(ANIM_UP);
- } else {
- super.onBackPressed();
- }
- }
-
- @Override
public State getDisplayState() {
return mState;
}
@@ -284,6 +278,12 @@
}
@Override
+ void onRootPicked(RootInfo root) {
+ super.onRootPicked(root);
+ mDrawer.setOpen(false);
+ }
+
+ @Override
public void onDocumentsPicked(List<DocumentInfo> docs) {
throw new UnsupportedOperationException();
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
index 1cbc221..17a1161 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
@@ -16,7 +16,7 @@
package com.android.documentsui;
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/GridItem.java b/packages/DocumentsUI/src/com/android/documentsui/GridItem.java
new file mode 100644
index 0000000..990dca7
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/GridItem.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/**
+ * A FrameLayout subclass used by DirectoryFragment. Ensures that the resulting grid item is always
+ * square.
+ */
+public class GridItem extends FrameLayout {
+ public GridItem(Context context) {
+ super(context);
+ }
+
+ public GridItem(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public GridItem(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Grid layout uses item width to figure out the number of columns, then dynamically fits
+ // rows into the view. The upshot of this is that changing the item width will mess up the
+ // grid layout - so to make the items square, throw out the height and use the width for
+ // both dimensions. The grid layout will correctly adjust the row height.
+ //
+ // Note that this code will need to be changed if the layout manager's orientation is
+ // changed from VERTICAL to HORIZONTAL.
+ super.onMeasure(widthMeasureSpec, widthMeasureSpec);
+ }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
index b43fedf..9959265 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
@@ -23,13 +23,11 @@
import android.provider.DocumentsContract.Document;
import android.util.TypedValue;
-import com.google.android.collect.Maps;
-
import java.util.HashMap;
public class IconUtils {
- private static HashMap<String, Integer> sMimeIcons = Maps.newHashMap();
+ private static HashMap<String, Integer> sMimeIcons = new HashMap<>();
private static void add(String mimeType, int resId) {
if (sMimeIcons.put(mimeType, resId) != null) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
index 02edd0c..e972566 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
@@ -16,24 +16,33 @@
package com.android.documentsui;
+import static com.android.documentsui.Events.isMouseEvent;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;
+import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.Adapter;
import android.support.v7.widget.RecyclerView.AdapterDataObserver;
+import android.support.v7.widget.RecyclerView.LayoutManager;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.util.Log;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
-
-import com.google.common.annotations.VisibleForTesting;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.VisibleForTesting;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -61,12 +70,13 @@
private final List<MultiSelectManager.Callback> mCallbacks = new ArrayList<>(1);
private Adapter<?> mAdapter;
- private RecyclerViewHelper mHelper;
+ private MultiSelectHelper mHelper;
private boolean mSingleSelect;
+ private BandSelectManager mBandSelectManager;
/**
* @param recyclerView
- * @param gestureDelegate Option delage gesture listener.
+ * @param gestureDelegate Option delegate gesture listener.
* @param mode Selection mode
* @template A gestureDelegate that implements both {@link OnGestureListener}
* and {@link OnDoubleTapListener}
@@ -76,17 +86,11 @@
this(
recyclerView.getAdapter(),
- new RecyclerViewHelper() {
- @Override
- public int findEventPosition(MotionEvent e) {
- View view = recyclerView.findChildViewUnder(e.getX(), e.getY());
- return view != null
- ? recyclerView.getChildAdapterPosition(view)
- : RecyclerView.NO_POSITION;
- }
- },
+ new RuntimeRecyclerViewHelper(recyclerView),
mode);
+ mBandSelectManager = new BandSelectManager((RuntimeRecyclerViewHelper) mHelper);
+
GestureDetector.SimpleOnGestureListener listener =
new GestureDetector.SimpleOnGestureListener() {
@Override
@@ -101,11 +105,8 @@
CompositeOnGestureListener<? extends Object> compositeListener =
new CompositeOnGestureListener<>(listener, gestureDelegate);
- final GestureDetector detector = new GestureDetector(
- recyclerView.getContext(),
- gestureDelegate == null
- ? listener
- : compositeListener);
+ final GestureDetector detector =
+ new GestureDetector(recyclerView.getContext(), compositeListener);
detector.setOnDoubleTapListener(compositeListener);
@@ -113,9 +114,15 @@
new RecyclerView.OnItemTouchListener() {
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
detector.onTouchEvent(e);
- return false;
+
+ // Only intercept the event if it was a mouse-based band selection.
+ return isMouseEvent(e) && (mBandSelectManager.mIsActive ||
+ e.getActionMasked() != MotionEvent.ACTION_UP);
}
- public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+ checkState(isMouseEvent(e));
+ mBandSelectManager.processMotionEvent(e);
+ }
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
});
}
@@ -125,7 +132,7 @@
* @hide
*/
@VisibleForTesting
- MultiSelectManager(Adapter<?> adapter, RecyclerViewHelper helper, int mode) {
+ MultiSelectManager(Adapter<?> adapter, MultiSelectHelper helper, int mode) {
checkNotNull(adapter, "'adapter' cannot be null.");
checkNotNull(helper, "'helper' cannot be null.");
@@ -207,6 +214,7 @@
* @param selected
* @return True if the selection state of the item changed.
*/
+ @VisibleForTesting
public boolean setItemSelected(int position, boolean selected) {
if (mSingleSelect && !mSelection.isEmpty()) {
clearSelectionQuietly();
@@ -271,7 +279,7 @@
if (DEBUG) Log.i(TAG, "View is null. Cannot handle tap event.");
}
- onLongPress(position);
+ onLongPress(position, e.getMetaState());
}
/**
@@ -279,17 +287,16 @@
* can be mocked.
*
* @param position
+ * @param metaState as returned from {@link MotionEvent#getMetaState()}.
* @hide
*/
@VisibleForTesting
- void onLongPress(int position) {
+ void onLongPress(int position, int metaState) {
if (position == RecyclerView.NO_POSITION) {
if (DEBUG) Log.i(TAG, "View is null. Cannot handle tap event.");
}
- if (toggleSelection(position)) {
- notifySelectionChanged();
- }
+ handlePositionChanged(position, metaState);
}
/**
@@ -327,17 +334,26 @@
return false;
}
+ handlePositionChanged(position, metaState);
+ return false;
+ }
+
+ /**
+ * Handles a change caused by a click on the item with the given position. If the Shift key is
+ * held down, this performs a range select; otherwise, it simply toggles the item's selection
+ * state.
+ */
+ private void handlePositionChanged(int position, int metaState) {
if (Events.hasShiftBit(metaState) && mRanger != null) {
mRanger.snapSelection(position);
- } else {
- toggleSelection(position);
- }
- // We're being lazy here notifying even when something might not have changed.
- // To make this more correct, we'd need to update the Ranger class to return
- // information about what has changed.
- notifySelectionChanged();
- return false;
+ // We're being lazy here notifying even when something might not have changed.
+ // To make this more correct, we'd need to update the Ranger class to return
+ // information about what has changed.
+ notifySelectionChanged();
+ } else if (toggleSelection(position)) {
+ notifySelectionChanged();
+ }
}
/**
@@ -588,10 +604,23 @@
*/
public static final class Selection {
- private SparseBooleanArray mSelection;
+ // This class tracks selected positions by managing two arrays: the saved selection, and
+ // the total selection. Saved selections are those which have been completed by tapping an
+ // item or by completing a band select operation. Provisional selections are selections
+ // which have been temporarily created by an in-progress band select operation (once the
+ // user releases the mouse button during a band select operation, the selected items
+ // become saved). The total selection is the combination of both the saved selection and
+ // the provisional selection. Tracking both separately is necessary to ensure that saved
+ // selections do not become deselected when they are removed from the provisional selection;
+ // for example, if item A is tapped (and selected), then an in-progress band select covers A
+ // then uncovers A, A should still be selected as it has been saved. To ensure this
+ // behavior, the saved selection must be tracked separately.
+ private SparseBooleanArray mSavedSelection;
+ private SparseBooleanArray mTotalSelection;
public Selection() {
- mSelection = new SparseBooleanArray();
+ mSavedSelection = new SparseBooleanArray();
+ mTotalSelection = new SparseBooleanArray();
}
/**
@@ -599,7 +628,7 @@
* @return true if the position is currently selected.
*/
public boolean contains(int position) {
- return mSelection.get(position);
+ return mTotalSelection.get(position);
}
/**
@@ -613,21 +642,85 @@
* @return the position value stored at specified index.
*/
public int get(int index) {
- return mSelection.keyAt(index);
+ return mTotalSelection.keyAt(index);
}
/**
* @return size of the selection.
*/
public int size() {
- return mSelection.size();
+ return mTotalSelection.size();
}
/**
* @return true if the selection is empty.
*/
public boolean isEmpty() {
- return mSelection.size() == 0;
+ return mTotalSelection.size() == 0;
+ }
+
+ /**
+ * Sets the provisional selection, which is a temporary selection that can be saved,
+ * canceled, or adjusted at a later time. When a new provision selection is applied, the old
+ * one (if it exists) is abandoned.
+ * @return Array with entry for each position added or removed. Entries which were added
+ * contain a value of true, and entries which were removed contain a value of false.
+ */
+ @VisibleForTesting
+ protected SparseBooleanArray setProvisionalSelection(
+ SparseBooleanArray provisionalSelection) {
+ SparseBooleanArray delta = new SparseBooleanArray();
+
+ for (int i = 0; i < mTotalSelection.size(); i++) {
+ int position = mTotalSelection.keyAt(i);
+ if (!provisionalSelection.get(position) && !mSavedSelection.get(position)) {
+ // Remove each item that used to be in the selection but is unsaved and not in
+ // the new provisional selection.
+ delta.put(position, false);
+ }
+ }
+
+ for (int i = 0; i < provisionalSelection.size(); i++) {
+ int position = provisionalSelection.keyAt(i);
+ if (!mTotalSelection.get(position)) {
+ // Add each item that was not previously in the selection but is in the
+ // new provisional selection.
+ delta.put(position, true);
+ }
+ }
+
+ // Now, iterate through the changes and actually add/remove them to/from
+ // mCurrentSelection. This could not be done in the previous loops because changing the
+ // size of the selection mid-iteration changes iteration order erroneously.
+ for (int i = 0; i < delta.size(); i++) {
+ int position = delta.keyAt(i);
+ if (delta.get(position)) {
+ mTotalSelection.put(position, true);
+ } else {
+ mTotalSelection.delete(position);
+ }
+ }
+
+ return delta;
+ }
+
+ /**
+ * Saves the existing provisional selection. Once the provisional selection is saved,
+ * subsequent provisional selections which are different from this existing one cannot
+ * cause items in this existing provisional selection to become deselected.
+ */
+ @VisibleForTesting
+ protected void applyProvisionalSelection() {
+ mSavedSelection = mTotalSelection.clone();
+ }
+
+ /**
+ * Abandons the existing provisional selection so that all items provisionally selected are
+ * now deselected.
+ */
+ @VisibleForTesting
+ protected void cancelProvisionalSelection() {
+ mTotalSelection = mSavedSelection.clone();
}
private boolean flip(int position) {
@@ -643,8 +736,9 @@
/** @hide */
@VisibleForTesting
boolean add(int position) {
- if (!mSelection.get(position)) {
- mSelection.put(position, true);
+ if (!mTotalSelection.get(position)) {
+ mTotalSelection.put(position, true);
+ mSavedSelection.put(position, true);
return true;
}
return false;
@@ -653,8 +747,9 @@
/** @hide */
@VisibleForTesting
boolean remove(int position) {
- if (mSelection.get(position)) {
- mSelection.delete(position);
+ if (mTotalSelection.get(position)) {
+ mTotalSelection.delete(position);
+ mSavedSelection.delete(position);
return true;
}
return false;
@@ -663,7 +758,8 @@
/**
* Adjusts the selection range to reflect the existence of newly inserted values at
* the specified positions. This has the effect of adjusting all existing selected
- * positions within the specified range accordingly.
+ * positions within the specified range accordingly. Note that this function discards any
+ * provisional selections which may have been applied.
*
* @param startPosition
* @param count
@@ -673,11 +769,13 @@
void expand(int startPosition, int count) {
checkState(startPosition >= 0);
checkState(count > 0);
+ cancelProvisionalSelection();
- for (int i = 0; i < mSelection.size(); i++) {
- int itemPosition = mSelection.keyAt(i);
+ for (int i = 0; i < mTotalSelection.size(); i++) {
+ int itemPosition = mTotalSelection.keyAt(i);
if (itemPosition >= startPosition) {
- mSelection.setKeyAt(i, itemPosition + count);
+ mTotalSelection.setKeyAt(i, itemPosition + count);
+ mSavedSelection.setKeyAt(i, itemPosition + count);
}
}
}
@@ -685,7 +783,8 @@
/**
* Adjusts the selection range to reflect the removal specified positions. This has
* the effect of adjusting all existing selected positions within the specified range
- * accordingly.
+ * accordingly. Note that this function discards any provisional selections which may have
+ * been applied.
*
* @param startPosition
* @param count The length of the range to collapse. Must be greater than 0.
@@ -699,27 +798,30 @@
int endPosition = startPosition + count - 1;
SparseBooleanArray newSelection = new SparseBooleanArray();
- for (int i = 0; i < mSelection.size(); i++) {
- int itemPosition = mSelection.keyAt(i);
+ for (int i = 0; i < mSavedSelection.size(); i++) {
+ int itemPosition = mSavedSelection.keyAt(i);
if (itemPosition < startPosition) {
newSelection.append(itemPosition, true);
} else if (itemPosition > endPosition) {
newSelection.append(itemPosition - count, true);
}
}
- mSelection = newSelection;
+ mSavedSelection = newSelection;
+ cancelProvisionalSelection();
}
/** @hide */
@VisibleForTesting
void clear() {
- mSelection.clear();
+ mSavedSelection.clear();
+ mTotalSelection.clear();
}
/** @hide */
@VisibleForTesting
void copyFrom(Selection source) {
- mSelection = source.mSelection.clone();
+ mSavedSelection = source.mSavedSelection.clone();
+ mTotalSelection = source.mTotalSelection.clone();
}
@Override
@@ -728,16 +830,16 @@
return "size=0, items=[]";
}
- StringBuilder buffer = new StringBuilder(mSelection.size() * 28);
+ StringBuilder buffer = new StringBuilder(mTotalSelection.size() * 28);
buffer.append("{size=")
- .append(mSelection.size())
+ .append(mTotalSelection.size())
.append(", ")
.append("items=[");
- for (int i=0; i < mSelection.size(); i++) {
+ for (int i=0; i < mTotalSelection.size(); i++) {
if (i > 0) {
buffer.append(", ");
}
- buffer.append(mSelection.keyAt(i));
+ buffer.append(mTotalSelection.keyAt(i));
}
buffer.append("]}");
return buffer.toString();
@@ -745,7 +847,7 @@
@Override
public int hashCode() {
- return mSelection.hashCode();
+ return mSavedSelection.hashCode() ^ mTotalSelection.hashCode();
}
@Override
@@ -758,14 +860,178 @@
return false;
}
- return mSelection.equals(((Selection) that).mSelection);
+ return mSavedSelection.equals(((Selection) that).mSavedSelection) &&
+ mTotalSelection.equals(((Selection) that).mTotalSelection);
}
}
- interface RecyclerViewHelper {
+ /**
+ * Provides functionality for MultiSelectManager. In practice, use RuntimeRecyclerViewHelper;
+ * this interface exists only for mocking in tests.
+ */
+ interface MultiSelectHelper {
int findEventPosition(MotionEvent e);
}
+ /**
+ * Provides functionality for BandSelectManager. In practice, use RuntimeRecyclerViewHelper;
+ * this interface exists only for mocking in tests.
+ */
+ interface BandManagerHelper {
+ void drawBand(Rect rect);
+ void addOnScrollListener(RecyclerView.OnScrollListener listener);
+ int findEventPosition(MotionEvent e);
+ int getHeight();
+ void hideBand();
+ void invalidateView();
+ void postRunnable(Runnable r);
+ void removeCallback(Runnable r);
+ void scrollBy(int dy);
+ }
+
+ /**
+ * Provides functionality for BandSelectModel. In practice, use RuntimeRecyclerViewHelper;
+ * this interface exists only for mocking in tests.
+ */
+ interface BandModelHelper {
+ void addOnScrollListener(RecyclerView.OnScrollListener listener);
+ Point createAbsolutePoint(Point relativePoint);
+ Rect getAbsoluteRectForChildViewAt(int index);
+ int getAdapterPositionAt(int index);
+ int getNumColumns();
+ int getNumRows();
+ int getTotalChildCount();
+ int getVisibleChildCount();
+ void removeOnScrollListener(RecyclerView.OnScrollListener listener);
+ }
+
+ /**
+ * Concrete RecyclerViewHelper implementation for use within the Files app.
+ */
+ private static final class RuntimeRecyclerViewHelper implements MultiSelectHelper,
+ BandManagerHelper, BandModelHelper {
+
+ private final RecyclerView mRecyclerView;
+ private final Drawable mBandSelectRect;
+
+ private boolean mIsOverlayShown = false;
+
+ RuntimeRecyclerViewHelper(RecyclerView rv) {
+ mRecyclerView = rv;
+ mBandSelectRect = mRecyclerView.getContext().getTheme().getDrawable(
+ R.drawable.band_select_overlay);
+ }
+
+ @Override
+ public int getAdapterPositionAt(int index) {
+ View child = mRecyclerView.getChildAt(index);
+ return mRecyclerView.getChildViewHolder(child).getAdapterPosition();
+ }
+
+ @Override
+ public void addOnScrollListener(OnScrollListener listener) {
+ mRecyclerView.addOnScrollListener(listener);
+ }
+
+ @Override
+ public void removeOnScrollListener(OnScrollListener listener) {
+ mRecyclerView.removeOnScrollListener(listener);
+ }
+
+ @Override
+ public Point createAbsolutePoint(Point relativePoint) {
+ return new Point(relativePoint.x + mRecyclerView.computeHorizontalScrollOffset(),
+ relativePoint.y + mRecyclerView.computeVerticalScrollOffset());
+ }
+
+ @Override
+ public Rect getAbsoluteRectForChildViewAt(int index) {
+ final View child = mRecyclerView.getChildAt(index);
+ final Rect childRect = new Rect();
+ child.getHitRect(childRect);
+ childRect.left += mRecyclerView.computeHorizontalScrollOffset();
+ childRect.right += mRecyclerView.computeHorizontalScrollOffset();
+ childRect.top += mRecyclerView.computeVerticalScrollOffset();
+ childRect.bottom += mRecyclerView.computeVerticalScrollOffset();
+ return childRect;
+ }
+
+ @Override
+ public int getVisibleChildCount() {
+ return mRecyclerView.getChildCount();
+ }
+
+ @Override
+ public int getTotalChildCount() {
+ return mRecyclerView.getAdapter().getItemCount();
+ }
+
+ @Override
+ public int getNumColumns() {
+ LayoutManager layoutManager = mRecyclerView.getLayoutManager();
+ if (layoutManager instanceof GridLayoutManager) {
+ return ((GridLayoutManager) layoutManager).getSpanCount();
+ }
+
+ // Otherwise, it is a list with 1 column.
+ return 1;
+ }
+
+ @Override
+ public int getNumRows() {
+ int numFullColumns = getTotalChildCount() / getNumColumns();
+ boolean hasPartiallyFullColumn = getTotalChildCount() % getNumColumns() != 0;
+ return numFullColumns + (hasPartiallyFullColumn ? 1 : 0);
+ }
+
+ @Override
+ public int findEventPosition(MotionEvent e) {
+ View view = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
+ return view != null
+ ? mRecyclerView.getChildAdapterPosition(view)
+ : RecyclerView.NO_POSITION;
+ }
+
+ @Override
+ public int getHeight() {
+ return mRecyclerView.getHeight();
+ }
+
+ @Override
+ public void invalidateView() {
+ mRecyclerView.invalidate();
+ }
+
+ @Override
+ public void postRunnable(Runnable r) {
+ mRecyclerView.postOnAnimation(r);
+ }
+
+ @Override
+ public void removeCallback(Runnable r) {
+ mRecyclerView.removeCallbacks(r);
+ }
+
+ @Override
+ public void scrollBy(int dy) {
+ mRecyclerView.scrollBy(0, dy);
+ }
+
+ @Override
+ public void drawBand(Rect rect) {
+ mBandSelectRect.setBounds(rect);
+
+ if (!mIsOverlayShown) {
+ mRecyclerView.getOverlay().add(mBandSelectRect);
+ }
+ }
+
+ @Override
+ public void hideBand() {
+ mRecyclerView.getOverlay().remove(mBandSelectRect);
+ }
+ }
+
public interface Callback {
/**
* Called when an item is selected or unselected while in selection mode.
@@ -893,4 +1159,846 @@
return false;
}
}
+
+ /**
+ * Provides mouse driven band-select support when used in conjunction with {@link RecyclerView}
+ * and {@link MultiSelectManager}. This class is responsible for rendering the band select
+ * overlay and selecting overlaid items via MultiSelectManager.
+ */
+ public class BandSelectManager extends RecyclerView.OnScrollListener
+ implements BandSelectModel.OnSelectionChangedListener {
+
+ private static final int NOT_SET = -1;
+
+ private final BandManagerHelper mHelper;
+
+ private boolean mIsActive;
+ private Point mOrigin;
+ private Point mPointer;
+ private Rect mBounds;
+ private BandSelectModel mModel;
+
+ // The time at which the current band selection-induced scroll began. If no scroll is in
+ // progress, the value is NOT_SET.
+ private long mScrollStartTime = NOT_SET;
+ private final Runnable mViewScroller = new ViewScroller();
+
+ public <T extends BandManagerHelper & BandModelHelper>
+ BandSelectManager(T helper) {
+ mHelper = helper;
+ mHelper.addOnScrollListener(this);
+ mModel = new BandSelectModel(helper);
+ mModel.addOnSelectionChangedListener(this);
+ }
+
+ /**
+ * Processes a MotionEvent by starting, ending, or resizing the band select overlay.
+ * @param e
+ */
+ private void processMotionEvent(MotionEvent e) {
+ if (!isMouseEvent(e)) {
+ return;
+ }
+
+ if (mIsActive && e.getActionMasked() == MotionEvent.ACTION_UP) {
+ endBandSelect();
+ return;
+ }
+
+ mPointer = new Point((int) e.getX(), (int) e.getY());
+ if (!mIsActive) {
+ // Only start a band select if the pointer is in margins between items, not
+ // actually within an item's bounds.
+ if (mHelper.findEventPosition(e) != RecyclerView.NO_POSITION) {
+ return;
+ }
+ startBandSelect();
+ } else {
+ mModel.resizeSelection(mPointer);
+ }
+
+ scrollViewIfNecessary();
+ resizeBandSelectRectangle();
+ }
+
+ /**
+ * Starts band select by adding the drawable to the RecyclerView's overlay.
+ */
+ private void startBandSelect() {
+ if (DEBUG) {
+ Log.d(TAG, "Starting band select from (" + mPointer.x + "," + mPointer.y + ").");
+ }
+ mIsActive = true;
+ mOrigin = new Point(mPointer.x, mPointer.y);
+ mModel.startSelection(mOrigin);
+ }
+
+ /**
+ * Scrolls the view if necessary.
+ */
+ private void scrollViewIfNecessary() {
+ mHelper.removeCallback(mViewScroller);
+ mViewScroller.run();
+ mHelper.invalidateView();
+ }
+
+ /**
+ * Resizes the band select rectangle by using the origin and the current pointer position as
+ * two opposite corners of the selection.
+ */
+ private void resizeBandSelectRectangle() {
+ mBounds = new Rect(Math.min(mOrigin.x, mPointer.x),
+ Math.min(mOrigin.y, mPointer.y),
+ Math.max(mOrigin.x, mPointer.x),
+ Math.max(mOrigin.y, mPointer.y));
+ mHelper.drawBand(mBounds);
+ }
+
+ /**
+ * Ends band select by removing the overlay.
+ */
+ private void endBandSelect() {
+ if (DEBUG) Log.d(TAG, "Ending band select.");
+ mIsActive = false;
+ mHelper.hideBand();
+ mSelection.applyProvisionalSelection();
+ mModel.endSelection();
+ int firstSelected = mModel.getPositionNearestOrigin();
+ if (firstSelected != BandSelectModel.NOT_SET) {
+ setSelectionFocusBegin(firstSelected);
+ }
+ }
+
+ @Override
+ public void onSelectionChanged(SparseBooleanArray updatedSelection) {
+ SparseBooleanArray delta = mSelection.setProvisionalSelection(updatedSelection);
+ for (int i = 0; i < delta.size(); i++) {
+ int position = delta.keyAt(i);
+ notifyItemStateChanged(position, delta.get(position));
+ }
+ notifySelectionChanged();
+ }
+
+ private class ViewScroller implements Runnable {
+ /**
+ * The number of milliseconds of scrolling at which scroll speed continues to increase.
+ * At first, the scroll starts slowly; then, the rate of scrolling increases until it
+ * reaches its maximum value at after this many milliseconds.
+ */
+ private static final long SCROLL_ACCELERATION_LIMIT_TIME_MS = 2000;
+
+ @Override
+ public void run() {
+ // Compute the number of pixels the pointer's y-coordinate is past the view.
+ // Negative values mean the pointer is at or before the top of the view, and
+ // positive values mean that the pointer is at or after the bottom of the view. Note
+ // that one additional pixel is added here so that the view still scrolls when the
+ // pointer is exactly at the top or bottom.
+ int pixelsPastView = 0;
+ if (mPointer.y <= 0) {
+ pixelsPastView = mPointer.y - 1;
+ } else if (mPointer.y >= mHelper.getHeight() - 1) {
+ pixelsPastView = mPointer.y - mHelper.getHeight() + 1;
+ }
+
+ if (!mIsActive || pixelsPastView == 0) {
+ // If band selection is inactive, or if it is active but not at the edge of the
+ // view, no scrolling is necessary.
+ mScrollStartTime = NOT_SET;
+ return;
+ }
+
+ if (mScrollStartTime == NOT_SET) {
+ // If the pointer was previously not at the edge of the view but now is, set the
+ // start time for the scroll.
+ mScrollStartTime = System.currentTimeMillis();
+ }
+
+ // Compute the number of pixels to scroll, and scroll that many pixels.
+ final int numPixels = computeScrollDistance(
+ pixelsPastView, System.currentTimeMillis() - mScrollStartTime);
+ mHelper.scrollBy(numPixels);
+
+ mHelper.removeCallback(mViewScroller);
+ mHelper.postRunnable(this);
+ }
+
+ /**
+ * Computes the number of pixels to scroll based on how far the pointer is past the end
+ * of the view and how long it has been there. Roughly based on ItemTouchHelper's
+ * algorithm for computing the number of pixels to scroll when an item is dragged to the
+ * end of a {@link RecyclerView}.
+ * @param pixelsPastView
+ * @param scrollDuration
+ * @return
+ */
+ private int computeScrollDistance(int pixelsPastView, long scrollDuration) {
+ final int maxScrollStep = mHelper.getHeight();
+ final int direction = (int) Math.signum(pixelsPastView);
+ final int absPastView = Math.abs(pixelsPastView);
+
+ // Calculate the ratio of how far out of the view the pointer currently resides to
+ // the entire height of the view.
+ final float outOfBoundsRatio = Math.min(
+ 1.0f, (float) absPastView / mHelper.getHeight());
+ // Interpolate this ratio and use it to compute the maximum scroll that should be
+ // possible for this step.
+ final float cappedScrollStep =
+ direction * maxScrollStep * smoothOutOfBoundsRatio(outOfBoundsRatio);
+
+ // Likewise, calculate the ratio of the time spent in the scroll to the limit.
+ final float timeRatio = Math.min(
+ 1.0f, (float) scrollDuration / SCROLL_ACCELERATION_LIMIT_TIME_MS);
+ // Interpolate this ratio and use it to compute the final number of pixels to
+ // scroll.
+ final int numPixels = (int) (cappedScrollStep * smoothTimeRatio(timeRatio));
+
+ // If the final number of pixels to scroll ends up being 0, the view should still
+ // scroll at least one pixel.
+ return numPixels != 0 ? numPixels : direction;
+ }
+
+ /**
+ * Interpolates the given out of bounds ratio on a curve which starts at (0,0) and ends
+ * at (1,1) and quickly approaches 1 near the start of that interval. This ensures that
+ * drags that are at the edge or barely past the edge of the view still cause sufficient
+ * scrolling. The equation y=(x-1)^5+1 is used, but this could also be tweaked if
+ * needed.
+ * @param ratio A ratio which is in the range [0, 1].
+ * @return A "smoothed" value, also in the range [0, 1].
+ */
+ private float smoothOutOfBoundsRatio(float ratio) {
+ return (float) Math.pow(ratio - 1.0f, 5) + 1.0f;
+ }
+
+ /**
+ * Interpolates the given time ratio on a curve which starts at (0,0) and ends at (1,1)
+ * and stays close to 0 for most input values except those very close to 1. This ensures
+ * that scrolls start out very slowly but speed up drastically after the scroll has been
+ * in progress close to SCROLL_ACCELERATION_LIMIT_TIME_MS. The equation y=x^5 is used,
+ * but this could also be tweaked if needed.
+ * @param ratio A ratio which is in the range [0, 1].
+ * @return A "smoothed" value, also in the range [0, 1].
+ */
+ private float smoothTimeRatio(float ratio) {
+ return (float) Math.pow(ratio, 5);
+ }
+ };
+
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ if (!mIsActive) {
+ return;
+ }
+
+ // Adjust the y-coordinate of the origin the opposite number of pixels so that the
+ // origin remains in the same place relative to the view's items.
+ mOrigin.y -= dy;
+ resizeBandSelectRectangle();
+ }
+ }
+
+ /**
+ * Provides a band selection item model for views within a RecyclerView. This class queries the
+ * RecyclerView to determine where its items are placed; then, once band selection is underway,
+ * it alerts listeners of which items are covered by the selections.
+ */
+ public static final class BandSelectModel extends RecyclerView.OnScrollListener {
+
+ public static final int NOT_SET = -1;
+
+ // Enum values used to determine the corner at which the origin is located within the
+ private static final int UPPER = 0x00;
+ private static final int LOWER = 0x01;
+ private static final int LEFT = 0x00;
+ private static final int RIGHT = 0x02;
+ private static final int UPPER_LEFT = UPPER | LEFT;
+ private static final int UPPER_RIGHT = UPPER | RIGHT;
+ private static final int LOWER_LEFT = LOWER | LEFT;
+ private static final int LOWER_RIGHT = LOWER | RIGHT;
+
+ private final BandModelHelper mHelper;
+ private final List<OnSelectionChangedListener> mOnSelectionChangedListeners = new ArrayList<>();
+
+ // Map from the x-value of the left side of a SparseBooleanArray of adapter positions, keyed
+ // by their y-offset. For example, if the first column of the view starts at an x-value of 5,
+ // mColumns.get(5) would return an array of positions in that column. Within that array, the
+ // value for key y is the adapter position for the item whose y-offset is y.
+ private final SparseArray<SparseIntArray> mColumns = new SparseArray<>();
+
+ // List of limits along the x-axis. For example, if the view has two columns, this list will
+ // have two elements, each of which lists the lower- and upper-limits of the x-values of the
+ // view items. This list is sorted from furthest left to furthest right.
+ private final List<Limits> mXLimitsList = new ArrayList<>();
+
+ // Like mXLimitsList, but for y-coordinates. Note that this list only contains items which
+ // have been in the viewport. Thus, limits which exist in an area of the view to which the
+ // view has not scrolled are not present in the list.
+ private final List<Limits> mYLimitsList = new ArrayList<>();
+
+ // The adapter positions which have been recorded so far.
+ private final SparseBooleanArray mKnownPositions = new SparseBooleanArray();
+
+ // Array passed to registered OnSelectionChangedListeners. One array is created and reused
+ // throughout the lifetime of the object.
+ private final SparseBooleanArray mSelection = new SparseBooleanArray();
+
+ // The current pointer (in absolute positioning from the top of the view).
+ private Point mPointer = null;
+
+ // The bounds of the band selection.
+ private RelativePoint mRelativeOrigin;
+ private RelativePoint mRelativePointer;
+
+ private boolean mIsActive;
+
+ // Tracks where the band select originated from. This is used to determine where selections
+ // should expand from when Shift+click is used.
+ private int mPositionNearestOrigin = NOT_SET;
+
+ BandSelectModel(BandModelHelper helper) {
+ mHelper = helper;
+ mHelper.addOnScrollListener(this);
+ }
+
+ /**
+ * Stops listening to the view's scrolls. Call this function before discarding a
+ * BandSelecModel object to prevent memory leaks.
+ */
+ void stopListening() {
+ mHelper.removeOnScrollListener(this);
+ }
+
+ /**
+ * Start a band select operation at the given point.
+ * @param relativeOrigin The origin of the band select operation, relative to the viewport.
+ * For example, if the view is scrolled to the bottom, the top-left of the viewport
+ * would have a relative origin of (0, 0), even though its absolute point has a higher
+ * y-value.
+ */
+ void startSelection(Point relativeOrigin) {
+ mIsActive = true;
+ mPointer = mHelper.createAbsolutePoint(relativeOrigin);
+
+ recordVisibleChildren();
+ mRelativeOrigin = new RelativePoint(mPointer);
+ mRelativePointer = new RelativePoint(mPointer);
+ computeCurrentSelection();
+ notifyListeners();
+ }
+
+ /**
+ * Resizes the selection by adjusting the pointer (i.e., the corner of the selection
+ * opposite the origin.
+ * @param relativePointer The pointer (opposite of the origin) of the band select operation,
+ * relative to the viewport. For example, if the view is scrolled to the bottom, the
+ * top-left of the viewport would have a relative origin of (0, 0), even though its
+ * absolute point has a higher y-value.
+ */
+ void resizeSelection(Point relativePointer) {
+ mPointer = mHelper.createAbsolutePoint(relativePointer);
+ updateModel();
+ }
+
+ /**
+ * Ends the band selection.
+ */
+ void endSelection() {
+ mIsActive = false;
+ }
+
+ /**
+ * @return The adapter position for the item nearest the origin corresponding to the latest
+ * band select operation, or NOT_SET if the selection did not cover any items.
+ */
+ int getPositionNearestOrigin() {
+ return mPositionNearestOrigin;
+ }
+
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ if (!mIsActive) {
+ return;
+ }
+
+ mPointer.x += dx;
+ mPointer.y += dy;
+ recordVisibleChildren();
+ updateModel();
+ }
+
+ /**
+ * Queries the view for all children and records their location metadata.
+ */
+ private void recordVisibleChildren() {
+ for (int i = 0; i < mHelper.getVisibleChildCount(); i++) {
+ int adapterPosition = mHelper.getAdapterPositionAt(i);
+ if (!mKnownPositions.get(adapterPosition)) {
+ mKnownPositions.put(adapterPosition, true);
+ recordItemData(
+ mHelper.getAbsoluteRectForChildViewAt(i), adapterPosition);
+ }
+ }
+ }
+
+ /**
+ * Updates the limits lists and column map with the given item metadata.
+ * @param absoluteChildRect The absolute rectangle for the child view being processed.
+ * @param adapterPosition The position of the child view being processed.
+ */
+ private void recordItemData(Rect absoluteChildRect, int adapterPosition) {
+ if (mXLimitsList.size() != mHelper.getNumColumns()) {
+ // If not all x-limits have been recorded, record this one.
+ recordLimits(
+ mXLimitsList, new Limits(absoluteChildRect.left, absoluteChildRect.right));
+ }
+
+ if (mYLimitsList.size() != mHelper.getNumRows()) {
+ // If not all y-limits have been recorded, record this one.
+ recordLimits(
+ mYLimitsList, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
+ }
+
+ SparseIntArray columnList = mColumns.get(absoluteChildRect.left);
+ if (columnList == null) {
+ columnList = new SparseIntArray();
+ mColumns.put(absoluteChildRect.left, columnList);
+ }
+ columnList.put(absoluteChildRect.top, adapterPosition);
+ }
+
+ /**
+ * Ensures limits exists within the sorted list limitsList, and adds it to the list if it
+ * does not exist.
+ */
+ private void recordLimits(List<Limits> limitsList, Limits limits) {
+ int index = Collections.binarySearch(limitsList, limits);
+ if (index < 0) {
+ limitsList.add(~index, limits);
+ }
+ }
+
+ /**
+ * Handles a moved pointer; this function determines whether the pointer movement resulted
+ * in a selection change and, if it has, notifies listeners of this change.
+ */
+ private void updateModel() {
+ RelativePoint old = mRelativePointer;
+ mRelativePointer = new RelativePoint(mPointer);
+ if (old != null && mRelativePointer.equals(old)) {
+ return;
+ }
+
+ computeCurrentSelection();
+ notifyListeners();
+ }
+
+ /**
+ * Computes the currently-selected items.
+ */
+ private void computeCurrentSelection() {
+ if (areItemsCoveredBySelection(mRelativePointer, mRelativeOrigin)) {
+ updateSelection(computeBounds());
+ } else {
+ mSelection.clear();
+ mPositionNearestOrigin = NOT_SET;
+ }
+ }
+
+ /**
+ * Notifies all listeners of a selection change. Note that this function simply passes
+ * mSelection, so computeCurrentSelection() should be called before this
+ * function.
+ */
+ private void notifyListeners() {
+ for (OnSelectionChangedListener listener : mOnSelectionChangedListeners) {
+ listener.onSelectionChanged(mSelection);
+ }
+ }
+
+ /**
+ * @param rect Rectangle including all covered items.
+ */
+ private void updateSelection(Rect rect) {
+ int columnStartIndex =
+ Collections.binarySearch(mXLimitsList, new Limits(rect.left, rect.left));
+ checkState(columnStartIndex >= 0);
+ int columnEndIndex = columnStartIndex;
+
+ for (int i = columnStartIndex;
+ i < mXLimitsList.size() && mXLimitsList.get(i).lowerLimit <= rect.right; i++) {
+ columnEndIndex = i;
+ }
+
+ SparseIntArray firstColumn =
+ mColumns.get(mXLimitsList.get(columnStartIndex).lowerLimit);
+ int rowStartIndex = firstColumn.indexOfKey(rect.top);
+ if (rowStartIndex < 0) {
+ mPositionNearestOrigin = NOT_SET;
+ return;
+ }
+
+ int rowEndIndex = rowStartIndex;
+ for (int i = rowStartIndex;
+ i < firstColumn.size() && firstColumn.keyAt(i) <= rect.bottom; i++) {
+ rowEndIndex = i;
+ }
+
+ updateSelection(columnStartIndex, columnEndIndex, rowStartIndex, rowEndIndex);
+ }
+
+ /**
+ * Computes the selection given the previously-computed start- and end-indices for each
+ * row and column.
+ */
+ private void updateSelection(
+ int columnStartIndex, int columnEndIndex, int rowStartIndex, int rowEndIndex) {
+ mSelection.clear();
+ for (int column = columnStartIndex; column <= columnEndIndex; column++) {
+ SparseIntArray items = mColumns.get(mXLimitsList.get(column).lowerLimit);
+ for (int row = rowStartIndex; row <= rowEndIndex; row++) {
+ int position = items.get(items.keyAt(row));
+ mSelection.append(position, true);
+ if (isPossiblePositionNearestOrigin(column, columnStartIndex, columnEndIndex,
+ row, rowStartIndex, rowEndIndex)) {
+ // If this is the position nearest the origin, record it now so that it
+ // can be returned by endSelection() later.
+ mPositionNearestOrigin = position;
+ }
+ }
+ }
+ }
+
+ /**
+ * @return Returns true if the position is the nearest to the origin, or, in the case of the
+ * lower-right corner, whether it is possible that the position is the nearest to the
+ * origin. See comment below for reasoning for this special case.
+ */
+ private boolean isPossiblePositionNearestOrigin(int columnIndex, int columnStartIndex,
+ int columnEndIndex, int rowIndex, int rowStartIndex, int rowEndIndex) {
+ int corner = computeCornerNearestOrigin();
+ switch (corner) {
+ case UPPER_LEFT:
+ return columnIndex == columnStartIndex && rowIndex == rowStartIndex;
+ case UPPER_RIGHT:
+ return columnIndex == columnEndIndex && rowIndex == rowStartIndex;
+ case LOWER_LEFT:
+ return columnIndex == columnStartIndex && rowIndex == rowEndIndex;
+ case LOWER_RIGHT:
+ // Note that in some cases, the last row will not have as many items as there
+ // are columns (e.g., if there are 4 items and 3 columns, the second row will
+ // only have one item in the first column). This function is invoked for each
+ // position from left to right, so return true for any position in the bottom
+ // row and only the right-most position in the bottom row will be recorded.
+ return rowIndex == rowEndIndex;
+ default:
+ throw new RuntimeException("Invalid corner type.");
+ }
+ }
+
+ /**
+ * Listener for changes in which items have been band selected.
+ */
+ static interface OnSelectionChangedListener {
+ public void onSelectionChanged(SparseBooleanArray updatedSelection);
+ }
+
+ void addOnSelectionChangedListener(OnSelectionChangedListener listener) {
+ mOnSelectionChangedListeners.add(listener);
+ }
+
+ void removeOnSelectionChangedListener(OnSelectionChangedListener listener) {
+ mOnSelectionChangedListeners.remove(listener);
+ }
+
+ /**
+ * Limits of a view item. For example, if an item's left side is at x-value 5 and its right side
+ * is at x-value 10, the limits would be from 5 to 10. Used to record the left- and right sides
+ * of item columns and the top- and bottom sides of item rows so that it can be determined
+ * whether the pointer is located within the bounds of an item.
+ */
+ private class Limits implements Comparable<Limits> {
+ int lowerLimit;
+ int upperLimit;
+
+ Limits(int lowerLimit, int upperLimit) {
+ this.lowerLimit = lowerLimit;
+ this.upperLimit = upperLimit;
+ }
+
+ @Override
+ public int compareTo(Limits other) {
+ return lowerLimit - other.lowerLimit;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Limits)) {
+ return false;
+ }
+
+ return ((Limits) other).lowerLimit == lowerLimit &&
+ ((Limits) other).upperLimit == upperLimit;
+ }
+ }
+
+ /**
+ * The location of a coordinate relative to items. This class represents a general area of the
+ * view as it relates to band selection rather than an explicit point. For example, two
+ * different points within an item are considered to have the same "location" because band
+ * selection originating within the item would select the same items no matter which point
+ * was used. Same goes for points between items as well as those at the very beginning or end
+ * of the view.
+ *
+ * Tracking a coordinate (e.g., an x-value) as a CoordinateLocation instead of as an int has the
+ * advantage of tying the value to the Limits of items along that axis. This allows easy
+ * selection of items within those Limits as opposed to a search through every item to see if a
+ * given coordinate value falls within those Limits.
+ */
+ private class RelativeCoordinate
+ implements Comparable<RelativeCoordinate> {
+ /**
+ * Location describing points after the last known item.
+ */
+ static final int AFTER_LAST_ITEM = 0;
+
+ /**
+ * Location describing points before the first known item.
+ */
+ static final int BEFORE_FIRST_ITEM = 1;
+
+ /**
+ * Location describing points between two items.
+ */
+ static final int BETWEEN_TWO_ITEMS = 2;
+
+ /**
+ * Location describing points within the limits of one item.
+ */
+ static final int WITHIN_LIMITS = 3;
+
+ /**
+ * The type of this coordinate, which is one of AFTER_LAST_ITEM, BEFORE_FIRST_ITEM,
+ * BETWEEN_TWO_ITEMS, or WITHIN_LIMITS.
+ */
+ final int type;
+
+ /**
+ * The limits before the coordinate; only populated when type == WITHIN_LIMITS or type ==
+ * BETWEEN_TWO_ITEMS.
+ */
+ Limits limitsBeforeCoordinate;
+
+ /**
+ * The limits after the coordinate; only populated when type == BETWEEN_TWO_ITEMS.
+ */
+ Limits limitsAfterCoordinate;
+
+ // Limits of the first known item; only populated when type == BEFORE_FIRST_ITEM.
+ Limits mFirstKnownItem;
+ // Limits of the last known item; only populated when type == AFTER_LAST_ITEM.
+ Limits mLastKnownItem;
+
+ /**
+ * @param limitsList The sorted limits list for the coordinate type. If this
+ * CoordinateLocation is an x-value, mXLimitsList should be passed; otherwise,
+ * mYLimitsList should be pased.
+ * @param value The coordinate value.
+ */
+ RelativeCoordinate(List<Limits> limitsList, int value) {
+ Limits dummyLimits = new Limits(value, value);
+ int index = Collections.binarySearch(limitsList, dummyLimits);
+
+ if (index >= 0) {
+ this.type = WITHIN_LIMITS;
+ this.limitsBeforeCoordinate = limitsList.get(index);
+ } else if (~index == 0) {
+ this.type = BEFORE_FIRST_ITEM;
+ this.mFirstKnownItem = limitsList.get(0);
+ } else if (~index == limitsList.size()) {
+ Limits lastLimits = limitsList.get(limitsList.size() - 1);
+ if (lastLimits.lowerLimit <= value && value <= lastLimits.upperLimit) {
+ this.type = WITHIN_LIMITS;
+ this.limitsBeforeCoordinate = lastLimits;
+ } else {
+ this.type = AFTER_LAST_ITEM;
+ this.mLastKnownItem = lastLimits;
+ }
+ } else {
+ Limits limitsBeforeIndex = limitsList.get(~index - 1);
+ if (limitsBeforeIndex.lowerLimit <= value && value <= limitsBeforeIndex.upperLimit) {
+ this.type = WITHIN_LIMITS;
+ this.limitsBeforeCoordinate = limitsList.get(~index - 1);
+ } else {
+ this.type = BETWEEN_TWO_ITEMS;
+ this.limitsBeforeCoordinate = limitsList.get(~index - 1);
+ this.limitsAfterCoordinate = limitsList.get(~index);
+ }
+ }
+ }
+
+ int toComparisonValue() {
+ if (type == BEFORE_FIRST_ITEM) {
+ return mFirstKnownItem.lowerLimit - 1;
+ } else if (type == AFTER_LAST_ITEM) {
+ return mLastKnownItem.upperLimit + 1;
+ } else if (type == BETWEEN_TWO_ITEMS) {
+ return limitsBeforeCoordinate.upperLimit + 1;
+ } else {
+ return limitsBeforeCoordinate.lowerLimit;
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof RelativeCoordinate)) {
+ return false;
+ }
+
+ RelativeCoordinate otherCoordinate = (RelativeCoordinate) other;
+ return toComparisonValue() == otherCoordinate.toComparisonValue();
+ }
+
+ @Override
+ public int compareTo(RelativeCoordinate other) {
+ return toComparisonValue() - other.toComparisonValue();
+ }
+ }
+
+ /**
+ * The location of a point relative to the Limits of nearby items; consists of both an x- and
+ * y-RelativeCoordinateLocation.
+ */
+ private class RelativePoint {
+ final RelativeCoordinate xLocation;
+ final RelativeCoordinate yLocation;
+
+ RelativePoint(Point point) {
+ this.xLocation = new RelativeCoordinate(mXLimitsList, point.x);
+ this.yLocation = new RelativeCoordinate(mYLimitsList, point.y);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof RelativePoint)) {
+ return false;
+ }
+
+ RelativePoint otherPoint = (RelativePoint) other;
+ return xLocation.equals(otherPoint.xLocation) && yLocation.equals(otherPoint.yLocation);
+ }
+ }
+
+ /**
+ * Generates a rectangle which contains the items selected by the pointer and origin.
+ * @return The rectangle, or null if no items were selected.
+ */
+ private Rect computeBounds() {
+ Rect rect = new Rect();
+ rect.left = getCoordinateValue(
+ min(mRelativeOrigin.xLocation, mRelativePointer.xLocation),
+ mXLimitsList,
+ true);
+ rect.right = getCoordinateValue(
+ max(mRelativeOrigin.xLocation, mRelativePointer.xLocation),
+ mXLimitsList,
+ false);
+ rect.top = getCoordinateValue(
+ min(mRelativeOrigin.yLocation, mRelativePointer.yLocation),
+ mYLimitsList,
+ true);
+ rect.bottom = getCoordinateValue(
+ max(mRelativeOrigin.yLocation, mRelativePointer.yLocation),
+ mYLimitsList,
+ false);
+ return rect;
+ }
+
+ /**
+ * Computes the corner of the selection nearest the origin.
+ * @return
+ */
+ private int computeCornerNearestOrigin() {
+ int cornerValue = 0;
+
+ if (mRelativeOrigin.yLocation ==
+ min(mRelativeOrigin.yLocation, mRelativePointer.yLocation)) {
+ cornerValue |= UPPER;
+ } else {
+ cornerValue |= LOWER;
+ }
+
+ if (mRelativeOrigin.xLocation ==
+ min(mRelativeOrigin.xLocation, mRelativePointer.xLocation)) {
+ cornerValue |= LEFT;
+ } else {
+ cornerValue |= RIGHT;
+ }
+
+ return cornerValue;
+ }
+
+ private RelativeCoordinate min(RelativeCoordinate first, RelativeCoordinate second) {
+ return first.compareTo(second) < 0 ? first : second;
+ }
+
+ private RelativeCoordinate max(RelativeCoordinate first, RelativeCoordinate second) {
+ return first.compareTo(second) > 0 ? first : second;
+ }
+
+ /**
+ * @return The absolute coordinate (i.e., the x- or y-value) of the given relative
+ * coordinate.
+ */
+ private int getCoordinateValue(RelativeCoordinate coordinate,
+ List<Limits> limitsList, boolean isStartOfRange) {
+ switch (coordinate.type) {
+ case RelativeCoordinate.BEFORE_FIRST_ITEM:
+ return limitsList.get(0).lowerLimit;
+ case RelativeCoordinate.AFTER_LAST_ITEM:
+ return limitsList.get(limitsList.size() - 1).upperLimit;
+ case RelativeCoordinate.BETWEEN_TWO_ITEMS:
+ if (isStartOfRange) {
+ return coordinate.limitsAfterCoordinate.lowerLimit;
+ } else {
+ return coordinate.limitsBeforeCoordinate.upperLimit;
+ }
+ case RelativeCoordinate.WITHIN_LIMITS:
+ return coordinate.limitsBeforeCoordinate.lowerLimit;
+ }
+
+ throw new RuntimeException("Invalid coordinate value.");
+ }
+
+ private boolean areItemsCoveredBySelection(
+ RelativePoint first, RelativePoint second) {
+ return doesCoordinateLocationCoverItems(first.xLocation, second.xLocation) &&
+ doesCoordinateLocationCoverItems(first.yLocation, second.yLocation);
+ }
+
+ private boolean doesCoordinateLocationCoverItems(
+ RelativeCoordinate pointerCoordinate,
+ RelativeCoordinate originCoordinate) {
+ if (pointerCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM &&
+ originCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM) {
+ return false;
+ }
+
+ if (pointerCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM &&
+ originCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM) {
+ return false;
+ }
+
+ if (pointerCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
+ originCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
+ pointerCoordinate.limitsBeforeCoordinate.equals(
+ originCoordinate.limitsBeforeCoordinate) &&
+ pointerCoordinate.limitsAfterCoordinate.equals(
+ originCoordinate.limitsAfterCoordinate)) {
+ return false;
+ }
+
+ return true;
+ }
+ }
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
index f94aebd..b0e332f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
@@ -20,8 +20,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -32,7 +30,7 @@
public class ProviderExecutor extends Thread implements Executor {
@GuardedBy("sExecutors")
- private static HashMap<String, ProviderExecutor> sExecutors = Maps.newHashMap();
+ private static HashMap<String, ProviderExecutor> sExecutors = new HashMap<>();
public static ProviderExecutor forAuthority(String authority) {
synchronized (sExecutors) {
@@ -53,7 +51,7 @@
private final LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<Runnable>();
- private final ArrayList<WeakReference<Preemptable>> mPreemptable = Lists.newArrayList();
+ private final ArrayList<WeakReference<Preemptable>> mPreemptable = new ArrayList<>();
private void preempt() {
synchronized (mPreemptable) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
index 878c4c2..4685c41 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
@@ -18,7 +18,6 @@
import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import android.annotation.Nullable;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ComponentName;
@@ -28,6 +27,7 @@
import android.net.Uri;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
+import android.support.annotation.Nullable;
import android.util.Log;
import com.android.documentsui.BaseActivity.DocumentContext;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
index f5908c5..1a7095a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
@@ -16,8 +16,8 @@
package com.android.documentsui;
-import static com.android.documentsui.DocumentsActivity.TAG;
import static com.android.documentsui.BaseActivity.State.SORT_ORDER_LAST_MODIFIED;
+import static com.android.documentsui.Shared.TAG;
import android.app.ActivityManager;
import android.content.AsyncTaskLoader;
@@ -36,14 +36,14 @@
import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.model.RootInfo;
-import com.google.android.collect.Maps;
-import com.google.common.collect.Lists;
+
import com.google.common.util.concurrent.AbstractFuture;
import libcore.io.IoUtils;
import java.io.Closeable;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -53,7 +53,7 @@
import java.util.concurrent.TimeUnit;
public class RecentLoader extends AsyncTaskLoader<DirectoryResult> {
- private static final boolean LOGD = true;
+ private static final boolean DEBUG = false;
// TODO: clean up cursor ownership so background thread doesn't traverse
// previously returned cursors for filtering/sorting; this currently races
@@ -81,7 +81,7 @@
private final RootsCache mRoots;
private final State mState;
- private final HashMap<RootInfo, RecentTask> mTasks = Maps.newHashMap();
+ private final HashMap<RootInfo, RecentTask> mTasks = new HashMap<>();
private final int mSortOrder = State.SORT_ORDER_LAST_MODIFIED;
@@ -196,7 +196,7 @@
// Collect all finished tasks
boolean allDone = true;
- List<Cursor> cursors = Lists.newArrayList();
+ List<Cursor> cursors = new ArrayList<>();
for (RecentTask task : mTasks.values()) {
if (task.isDone()) {
try {
@@ -221,7 +221,7 @@
}
}
- if (LOGD) {
+ if (DEBUG) {
Log.d(TAG, "Found " + cursors.size() + " of " + mTasks.size() + " recent queries done");
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index e11d7d9..662822e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -16,7 +16,7 @@
package com.android.documentsui;
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
import android.app.Fragment;
import android.app.FragmentManager;
@@ -50,7 +50,6 @@
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.DurableUtils;
import com.android.documentsui.model.RootInfo;
-import com.google.android.collect.Lists;
import libcore.io.IoUtils;
@@ -157,7 +156,7 @@
@Override
public List<DocumentStack> loadInBackground(Uri uri, CancellationSignal signal) {
final Collection<RootInfo> matchingRoots = mRoots.getMatchingRootsBlocking(mState);
- final ArrayList<DocumentStack> result = Lists.newArrayList();
+ final ArrayList<DocumentStack> result = new ArrayList<>();
final ContentResolver resolver = getContext().getContentResolver();
final Cursor cursor = resolver.query(
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index fbcb938..05f7d8d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -16,7 +16,7 @@
package com.android.documentsui;
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -39,14 +39,14 @@
import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.model.RootInfo;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
+import android.support.annotation.VisibleForTesting;
+
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import libcore.io.IoUtils;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@@ -74,10 +74,10 @@
@GuardedBy("mLock")
private Multimap<String, RootInfo> mRoots = ArrayListMultimap.create();
@GuardedBy("mLock")
- private HashSet<String> mStoppedAuthorities = Sets.newHashSet();
+ private HashSet<String> mStoppedAuthorities = new HashSet<>();
@GuardedBy("mObservedAuthorities")
- private final HashSet<String> mObservedAuthorities = Sets.newHashSet();
+ private final HashSet<String> mObservedAuthorities = new HashSet<>();
public RootsCache(Context context) {
mContext = context;
@@ -159,7 +159,7 @@
private final String mFilterPackage;
private final Multimap<String, RootInfo> mTaskRoots = ArrayListMultimap.create();
- private final HashSet<String> mTaskStoppedAuthorities = Sets.newHashSet();
+ private final HashSet<String> mTaskStoppedAuthorities = new HashSet<>();
/**
* Update all roots.
@@ -251,7 +251,7 @@
}
}
- final List<RootInfo> roots = Lists.newArrayList();
+ final List<RootInfo> roots = new ArrayList<>();
final Uri rootsUri = DocumentsContract.buildRootsUri(authority);
ContentProviderClient client = null;
@@ -350,7 +350,7 @@
@VisibleForTesting
static List<RootInfo> getMatchingRoots(Collection<RootInfo> roots, State state) {
- final List<RootInfo> matching = Lists.newArrayList();
+ final List<RootInfo> matching = new ArrayList<>();
for (RootInfo root : roots) {
final boolean supportsCreate = (root.flags & Root.FLAG_SUPPORTS_CREATE) != 0;
final boolean supportsIsChild = (root.flags & Root.FLAG_SUPPORTS_IS_CHILD) != 0;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index fd67a77..c02184b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -44,8 +44,8 @@
import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
-import com.google.common.collect.Lists;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -293,8 +293,8 @@
RootItem audio = null;
RootItem downloads = null;
- final List<RootInfo> clouds = Lists.newArrayList();
- final List<RootInfo> locals = Lists.newArrayList();
+ final List<RootInfo> clouds = new ArrayList<>();
+ final List<RootInfo> locals = new ArrayList<>();
for (RootInfo root : roots) {
if (root.isRecents()) {
@@ -338,7 +338,7 @@
final List<ResolveInfo> infos = pm.queryIntentActivities(
includeApps, PackageManager.MATCH_DEFAULT_ONLY);
- final List<AppItem> apps = Lists.newArrayList();
+ final List<AppItem> apps = new ArrayList<>();
// Omit ourselves from the list
for (ResolveInfo info : infos) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java
index 088e3fa..ae959f9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java
@@ -22,8 +22,6 @@
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
-import com.google.android.collect.Lists;
-
import java.util.ArrayList;
/**
@@ -31,7 +29,7 @@
* provide a header, and correctly handling item types across child adapters.
*/
public class SectionedListAdapter extends BaseAdapter {
- private ArrayList<SectionAdapter> mSections = Lists.newArrayList();
+ private ArrayList<SectionAdapter> mSections = new ArrayList<>();
public interface SectionAdapter extends ListAdapter {
public View getHeaderView(View convertView, ViewGroup parent);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
new file mode 100644
index 0000000..b414ee3
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+/**
+ * @hide
+ */
+public final class Shared {
+ public static final String TAG = "Documents";
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java b/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
index 1a5bb0c..7bb662c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
@@ -27,16 +27,16 @@
* changes while started, manages {@link CancellationSignal}, and caches
* returned results.
*/
-public abstract class UriDerivativeLoader<P, R> extends AsyncTaskLoader<R> {
+public abstract class UriDerivativeLoader<Param, Res> extends AsyncTaskLoader<Res> {
final ForceLoadContentObserver mObserver;
- private final P mParam;
+ private final Param mParam;
- private R mResult;
+ private Res mResult;
private CancellationSignal mCancellationSignal;
@Override
- public final R loadInBackground() {
+ public final Res loadInBackground() {
synchronized (this) {
if (isLoadInBackgroundCanceled()) {
throw new OperationCanceledException();
@@ -52,7 +52,7 @@
}
}
- public abstract R loadInBackground(P param, CancellationSignal signal);
+ public abstract Res loadInBackground(Param param, CancellationSignal signal);
@Override
public void cancelLoadInBackground() {
@@ -66,12 +66,12 @@
}
@Override
- public void deliverResult(R result) {
+ public void deliverResult(Res result) {
if (isReset()) {
closeQuietly(result);
return;
}
- R oldResult = mResult;
+ Res oldResult = mResult;
mResult = result;
if (isStarted()) {
@@ -83,7 +83,7 @@
}
}
- public UriDerivativeLoader(Context context, P param) {
+ public UriDerivativeLoader(Context context, Param param) {
super(context);
mObserver = new ForceLoadContentObserver();
mParam = param;
@@ -105,7 +105,7 @@
}
@Override
- public void onCanceled(R result) {
+ public void onCanceled(Res result) {
closeQuietly(result);
}
@@ -122,7 +122,7 @@
getContext().getContentResolver().unregisterContentObserver(mObserver);
}
- private void closeQuietly(R result) {
+ private void closeQuietly(Res result) {
if (result instanceof AutoCloseable) {
try {
((AutoCloseable) result).close();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
index 5d5f2eb..cc981e1e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
@@ -24,7 +24,6 @@
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
import android.text.TextUtils;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java b/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java
index 2a29cbc..e21dd49 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java
@@ -16,7 +16,7 @@
package com.android.documentsui.model;
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
import android.os.BadParcelableException;
import android.os.Parcel;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectModelTest.java
new file mode 100644
index 0000000..20c4548
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectModelTest.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static org.junit.Assert.*;
+
+import com.android.documentsui.MultiSelectManager.BandSelectModel;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
+import android.util.SparseBooleanArray;
+
+import org.junit.After;
+import org.junit.Test;
+
+public class BandSelectModelTest {
+
+ private static final int VIEW_PADDING_PX = 5;
+ private static final int CHILD_VIEW_EDGE_PX = 100;
+ private static final int VIEWPORT_HEIGHT = 500;
+
+ private static BandSelectModel model;
+ private static TestHelper helper;
+ private static SparseBooleanArray lastSelection;
+ private static int viewWidth;
+
+ private static void setUp(int numChildren, int numColumns) {
+ helper = new TestHelper(numChildren, numColumns);
+ viewWidth = VIEW_PADDING_PX + numColumns * (VIEW_PADDING_PX + CHILD_VIEW_EDGE_PX);
+ model = new BandSelectModel(helper);
+ model.addOnSelectionChangedListener(new BandSelectModel.OnSelectionChangedListener() {
+
+ @Override
+ public void onSelectionChanged(SparseBooleanArray updatedSelection) {
+ lastSelection = updatedSelection;
+ }
+ });
+ }
+
+ @After
+ public void tearDown() {
+ model = null;
+ helper = null;
+ lastSelection = null;
+ }
+
+ @Test
+ public void testSelectionLeftOfItems() {
+ setUp(20, 5);
+ model.startSelection(new Point(0, 10));
+ model.resizeSelection(new Point(1, 11));
+ assertSelected(new int[0]);
+ assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
+ }
+
+ @Test
+ public void testSelectionRightOfItems() {
+ setUp(20, 4);
+ model.startSelection(new Point(viewWidth - 1, 10));
+ model.resizeSelection(new Point(viewWidth - 2, 11));
+ assertSelected(new int[0]);
+ assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
+ }
+
+ @Test
+ public void testSelectionAboveItems() {
+ setUp(20, 4);
+ model.startSelection(new Point(10, 0));
+ model.resizeSelection(new Point(11, 1));
+ assertSelected(new int[0]);
+ assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
+ }
+
+ @Test
+ public void testSelectionBelowItems() {
+ setUp(5, 4);
+ model.startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
+ model.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
+ assertSelected(new int[0]);
+ assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
+ }
+
+ @Test
+ public void testVerticalSelectionBetweenItems() {
+ setUp(20, 4);
+ model.startSelection(new Point(106, 0));
+ model.resizeSelection(new Point(107, 200));
+ assertSelected(new int[0]);
+ assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
+ }
+
+ @Test
+ public void testHorizontalSelectionBetweenItems() {
+ setUp(20, 4);
+ model.startSelection(new Point(0, 105));
+ model.resizeSelection(new Point(200, 106));
+ assertSelected(new int[0]);
+ assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
+ }
+
+ @Test
+ public void testGrowingAndShrinkingSelection() {
+ setUp(20, 4);
+ model.startSelection(new Point(0, 0));
+ model.resizeSelection(new Point(5, 5));
+ assertSelected(new int[] {0});
+ model.resizeSelection(new Point(109, 109));
+ assertSelected(new int[] {0});
+ model.resizeSelection(new Point(110, 109));
+ assertSelected(new int[] {0, 1});
+ model.resizeSelection(new Point(110, 110));
+ assertSelected(new int[] {0, 1, 4, 5});
+ model.resizeSelection(new Point(214, 214));
+ assertSelected(new int[] {0, 1, 4, 5});
+ model.resizeSelection(new Point(215, 214));
+ assertSelected(new int[] {0, 1, 2, 4, 5, 6});
+ model.resizeSelection(new Point(214, 214));
+ assertSelected(new int[] {0, 1, 4, 5});
+ model.resizeSelection(new Point(110, 110));
+ assertSelected(new int[] {0, 1, 4, 5});
+ model.resizeSelection(new Point(110, 109));
+ assertSelected(new int[] {0, 1});
+ model.resizeSelection(new Point(109, 109));
+ assertSelected(new int[] {0});
+ model.resizeSelection(new Point(5, 5));
+ assertSelected(new int[] {0});
+ model.resizeSelection(new Point(0, 0));
+ assertSelected(new int[0]);
+ assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
+ }
+
+ @Test
+ public void testSelectionMovingAroundOrigin() {
+ setUp(16, 4);
+ model.startSelection(new Point(210, 210));
+ model.resizeSelection(new Point(viewWidth - 1, 0));
+ assertSelected(new int[] {2, 3, 6, 7});
+ model.resizeSelection(new Point(0, 0));
+ assertSelected(new int[] {0, 1, 4, 5});
+ model.resizeSelection(new Point(0, 420));
+ assertSelected(new int[] {8, 9, 12, 13});
+ model.resizeSelection(new Point(viewWidth - 1, 420));
+ assertSelected(new int[] {10, 11, 14, 15});
+ assertEquals(10, model.getPositionNearestOrigin());
+ }
+
+ @Test
+ public void testScrollingBandSelect() {
+ setUp(40, 4);
+ model.startSelection(new Point(0, 0));
+ model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+ assertSelected(new int[] {0, 4, 8, 12, 16});
+ scroll(CHILD_VIEW_EDGE_PX);
+ assertSelected(new int[] {0, 4, 8, 12, 16, 20});
+ model.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
+ assertSelected(new int[] {0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21});
+ scroll(CHILD_VIEW_EDGE_PX);
+ assertSelected(new int[] {0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25});
+ scroll(-2 * CHILD_VIEW_EDGE_PX);
+ assertSelected(new int[] {0, 1, 4, 5, 8, 9, 12, 13, 16, 17});
+ model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+ assertSelected(new int[] {0, 4, 8, 12, 16});
+ assertEquals(0, model.getPositionNearestOrigin());
+ }
+
+ private static void assertSelected(int[] selectedPositions) {
+ assertEquals(selectedPositions.length, lastSelection.size());
+ for (int position : selectedPositions) {
+ assertTrue(lastSelection.get(position));
+ }
+ }
+
+ private static void scroll(int dy) {
+ assertTrue(helper.verticalOffset + VIEWPORT_HEIGHT + dy <= helper.getTotalHeight());
+ helper.verticalOffset += dy;
+ model.onScrolled(null, 0, dy);
+ }
+
+ private static final class TestHelper implements MultiSelectManager.BandModelHelper {
+
+ public int horizontalOffset = 0;
+ public int verticalOffset = 0;
+ private final int mNumColumns;
+ private final int mNumRows;
+ private final int mNumChildren;
+
+ public TestHelper(int numChildren, int numColumns) {
+ mNumChildren = numChildren;
+ mNumColumns = numColumns;
+ mNumRows = (int) Math.ceil((double) numChildren / mNumColumns);
+ }
+
+ private int getTotalHeight() {
+ return CHILD_VIEW_EDGE_PX * mNumRows + VIEW_PADDING_PX * (mNumRows + 1);
+ }
+
+ private int getFirstVisibleRowIndex() {
+ return verticalOffset / (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
+ }
+
+ private int getLastVisibleRowIndex() {
+ int lastVisibleRowUncapped =
+ (VIEWPORT_HEIGHT + verticalOffset - 1) / (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
+ return Math.min(lastVisibleRowUncapped, mNumRows - 1);
+ }
+
+ private int getNumItemsInRow(int index) {
+ assertTrue(index >= 0 && index < mNumRows);
+ if (index == mNumRows - 1 && mNumChildren % mNumColumns != 0) {
+ return mNumChildren % mNumColumns;
+ }
+
+ return mNumColumns;
+ }
+
+ @Override
+ public void addOnScrollListener(OnScrollListener listener) {}
+
+ @Override
+ public void removeOnScrollListener(OnScrollListener listener) {}
+
+ @Override
+ public Point createAbsolutePoint(Point relativePoint) {
+ return new Point(
+ relativePoint.x + horizontalOffset, relativePoint.y + verticalOffset);
+ }
+
+ @Override
+ public int getVisibleChildCount() {
+ int childCount = 0;
+ for (int i = getFirstVisibleRowIndex(); i <= getLastVisibleRowIndex(); i++) {
+ childCount += getNumItemsInRow(i);
+ }
+ return childCount;
+ }
+
+ @Override
+ public int getAdapterPositionAt(int index) {
+ return index + mNumColumns * (getFirstVisibleRowIndex());
+ }
+
+ @Override
+ public Rect getAbsoluteRectForChildViewAt(int index) {
+ int adapterPosition = getAdapterPositionAt(index);
+ int rowIndex = adapterPosition / mNumColumns;
+ int columnIndex = adapterPosition % mNumColumns;
+
+ Rect rect = new Rect();
+ rect.top = VIEW_PADDING_PX + rowIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
+ rect.bottom = rect.top + CHILD_VIEW_EDGE_PX - 1;
+ rect.left = VIEW_PADDING_PX + columnIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
+ rect.right = rect.left + CHILD_VIEW_EDGE_PX - 1;
+ return rect;
+ }
+
+ @Override
+ public int getTotalChildCount() {
+ return mNumChildren;
+ }
+
+ @Override
+ public int getNumColumns() {
+ return mNumColumns;
+ }
+
+ @Override
+ public int getNumRows() {
+ return mNumRows;
+ }
+ }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
index 03ad3d4..b82251c 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
@@ -19,12 +19,12 @@
import static org.junit.Assert.*;
import android.support.v7.widget.RecyclerView;
+import android.util.SparseBooleanArray;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import com.android.documentsui.MultiSelectManager.RecyclerViewHelper;
import com.android.documentsui.MultiSelectManager.Selection;
import org.junit.Before;
@@ -79,7 +79,7 @@
@Test
public void mouseClick_NoPosition_ClearsSelection() {
- mManager.onLongPress(7);
+ mManager.onLongPress(7, 0);
click(11);
click(RecyclerView.NO_POSITION);
assertSelection();
@@ -95,27 +95,27 @@
@Test
public void longPress_StartsSelectionMode() {
- mManager.onLongPress(7);
+ mManager.onLongPress(7, 0);
assertSelection(7);
}
@Test
public void longPress_SecondPressExtendsSelection() {
- mManager.onLongPress(7);
- mManager.onLongPress(99);
+ mManager.onLongPress(7, 0);
+ mManager.onLongPress(99, 0);
assertSelection(7, 99);
}
@Test
public void singleTapUp_UnselectsSelectedItem() {
- mManager.onLongPress(7);
+ mManager.onLongPress(7, 0);
tap(7);
assertSelection();
}
@Test
public void singleTapUp_NoPosition_ClearsSelection() {
- mManager.onLongPress(7);
+ mManager.onLongPress(7, 0);
tap(11);
tap(RecyclerView.NO_POSITION);
assertSelection();
@@ -123,7 +123,7 @@
@Test
public void singleTapUp_ExtendsSelection() {
- mManager.onLongPress(99);
+ mManager.onLongPress(99, 0);
tap(7);
tap(13);
tap(129899);
@@ -132,21 +132,21 @@
@Test
public void singleTapUp_ShiftCreatesRangeSelection() {
- mManager.onLongPress(7);
+ mManager.onLongPress(7, 0);
shiftTap(17);
assertRangeSelection(7, 17);
}
@Test
public void singleTapUp_ShiftCreatesRangeSeletion_Backwards() {
- mManager.onLongPress(17);
+ mManager.onLongPress(17, 0);
shiftTap(7);
assertRangeSelection(7, 17);
}
@Test
public void singleTapUp_SecondShiftClickExtendsSelection() {
- mManager.onLongPress(7);
+ mManager.onLongPress(7, 0);
shiftTap(11);
shiftTap(17);
assertRangeSelection(7, 17);
@@ -154,7 +154,7 @@
@Test
public void singleTapUp_MultipleContiguousRangesSelected() {
- mManager.onLongPress(7);
+ mManager.onLongPress(7, 0);
shiftTap(11);
tap(20);
shiftTap(25);
@@ -165,7 +165,7 @@
@Test
public void singleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick() {
- mManager.onLongPress(7);
+ mManager.onLongPress(7, 0);
shiftTap(17);
shiftTap(10);
assertRangeSelection(7, 10);
@@ -173,7 +173,7 @@
@Test
public void singleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick_Backwards() {
- mManager.onLongPress(17);
+ mManager.onLongPress(17, 0);
shiftTap(7);
shiftTap(14);
assertRangeSelection(14, 17);
@@ -182,7 +182,7 @@
@Test
public void singleTapUp_ShiftReversesSelectionDirection() {
- mManager.onLongPress(7);
+ mManager.onLongPress(7, 0);
shiftTap(17);
shiftTap(0);
assertRangeSelection(0, 7);
@@ -206,6 +206,36 @@
assertSelection(20);
}
+ @Test
+ public void provisionaSelection() {
+ Selection s = mManager.getSelection();
+ assertSelection();
+
+ SparseBooleanArray provisional = new SparseBooleanArray();
+ provisional.append(1, true);
+ provisional.append(2, true);
+ s.setProvisionalSelection(provisional);
+ assertSelection(1, 2);
+
+ provisional.delete(1);
+ provisional.append(3, true);
+ s.setProvisionalSelection(provisional);
+ assertSelection(2, 3);
+
+ s.applyProvisionalSelection();
+ assertSelection(2, 3);
+
+ provisional.clear();
+ provisional.append(3, true);
+ provisional.append(4, true);
+ s.setProvisionalSelection(provisional);
+ assertSelection(2, 3, 4);
+
+ provisional.delete(3);
+ s.setProvisionalSelection(provisional);
+ assertSelection(2, 3, 4);
+ }
+
private void tap(int position) {
mManager.onSingleTapUp(position, 0, MotionEvent.TOOL_TYPE_MOUSE);
}
@@ -252,7 +282,8 @@
assertEquals(selection.toString(), expected, selection.size());
}
- private static final class EventHelper implements RecyclerViewHelper {
+ private static final class EventHelper implements MultiSelectManager.MultiSelectHelper {
+
@Override
public int findEventPosition(MotionEvent e) {
throw new UnsupportedOperationException();
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
index 8c5bac1..1325706 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
@@ -21,7 +21,8 @@
import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.model.RootInfo;
-import com.google.android.collect.Lists;
+
+import com.google.common.collect.Lists;
import java.util.List;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
index c2f1762..6a2e03a 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
@@ -36,8 +36,6 @@
import android.support.annotation.VisibleForTesting;
import android.util.Log;
-import com.google.android.collect.Maps;
-
import libcore.io.IoUtils;
import java.io.File;
@@ -101,7 +99,7 @@
});
}
// Create new roots.
- mRoots = Maps.newHashMap();
+ mRoots = new HashMap<>();
for (String rootId : rootIds) {
final RootInfo rootInfo = new RootInfo(rootId, getSize(rootId));
mRoots.put(rootId, rootInfo);
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java b/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
index 4ffe799..d90130f 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
@@ -22,6 +22,7 @@
@RunWith(Suite.class)
@SuiteClasses({
+ BandSelectModelTest.class,
MultiSelectManager_SelectionTest.class,
MultiSelectManagerTest.class
})
diff --git a/packages/Keyguard/res/values-eu-rES/strings.xml b/packages/Keyguard/res/values-eu-rES/strings.xml
index 7300584..3a740f6 100644
--- a/packages/Keyguard/res/values-eu-rES/strings.xml
+++ b/packages/Keyguard/res/values-eu-rES/strings.xml
@@ -113,9 +113,9 @@
<string name="kg_prompt_reason_restart_pattern" msgid="489430505491862444">"Gailua berrabiarazi duzunez, eredua marraztu behar duzu."</string>
<string name="kg_prompt_reason_restart_pin" msgid="994878216570694974">"Gailua berrabiarazi duzunez, PIN kodea idatzi behar duzu."</string>
<string name="kg_prompt_reason_restart_password" msgid="2375742919528461664">"Gailua berrabiarazi duzunez, pasahitza idatzi behar duzu."</string>
- <string name="kg_prompt_reason_timeout_pattern" msgid="8930047492617900785">"Segurtasun gehiago izateko, eredua behar da."</string>
- <string name="kg_prompt_reason_timeout_pin" msgid="7470468607947726377">"Segurtasun gehiago izateko, PIN kodea behar da."</string>
- <string name="kg_prompt_reason_timeout_password" msgid="1177412542773936957">"Segurtasun gehiago izateko, pasahitza behar da."</string>
+ <string name="kg_prompt_reason_timeout_pattern" msgid="8930047492617900785">"Segurtasun handiagoa izateko, eredua behar da."</string>
+ <string name="kg_prompt_reason_timeout_pin" msgid="7470468607947726377">"Segurtasun handiagoa izateko, PIN kodea behar da."</string>
+ <string name="kg_prompt_reason_timeout_password" msgid="1177412542773936957">"Segurtasun handiagoa izateko, pasahitza behar da."</string>
<string name="kg_prompt_reason_switch_profiles_pattern" msgid="3802056699323773969">"Profilez aldatu duzunez, eredua marraztu behar duzu."</string>
<string name="kg_prompt_reason_switch_profiles_pin" msgid="8108020184731052246">"Profilez aldatu duzunez, PIN kodea idatzi behar duzu."</string>
<string name="kg_prompt_reason_switch_profiles_password" msgid="6755997057852042672">"Profilez aldatu duzunez, pasahitza idatzi behar duzu."</string>
diff --git a/packages/Keyguard/res/values-fr/strings.xml b/packages/Keyguard/res/values-fr/strings.xml
index 1f4edc1..afefc9a 100644
--- a/packages/Keyguard/res/values-fr/strings.xml
+++ b/packages/Keyguard/res/values-fr/strings.xml
@@ -110,18 +110,18 @@
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Aucun service"</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
<string name="airplane_mode" msgid="3122107900897202805">"Mode Avion"</string>
- <string name="kg_prompt_reason_restart_pattern" msgid="489430505491862444">"Veuillez saisir le motif au redémarrage de l\'appareil."</string>
+ <string name="kg_prompt_reason_restart_pattern" msgid="489430505491862444">"Veuillez saisir le schéma au redémarrage de l\'appareil."</string>
<string name="kg_prompt_reason_restart_pin" msgid="994878216570694974">"Veuillez saisir le code d\'accès au redémarrage de l\'appareil."</string>
<string name="kg_prompt_reason_restart_password" msgid="2375742919528461664">"Veuillez saisir le mot de passe au redémarrage de l\'appareil."</string>
<string name="kg_prompt_reason_timeout_pattern" msgid="8930047492617900785">"Veuillez saisir le schéma pour renforcer la sécurité."</string>
<string name="kg_prompt_reason_timeout_pin" msgid="7470468607947726377">"Veuillez saisir le code d\'accès pour renforcer la sécurité."</string>
<string name="kg_prompt_reason_timeout_password" msgid="1177412542773936957">"Veuillez saisir le mot de passe pour renforcer la sécurité."</string>
- <string name="kg_prompt_reason_switch_profiles_pattern" msgid="3802056699323773969">"Veuillez saisir le motif lorsque vous changez de profil."</string>
+ <string name="kg_prompt_reason_switch_profiles_pattern" msgid="3802056699323773969">"Veuillez saisir le schéma lorsque vous changez de profil."</string>
<string name="kg_prompt_reason_switch_profiles_pin" msgid="8108020184731052246">"Veuillez saisir le code d\'accès lorsque vous changez de profil."</string>
<string name="kg_prompt_reason_switch_profiles_password" msgid="6755997057852042672">"Veuillez saisir le mot de passe lorsque vous changez de profil."</string>
<plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="2697444392228541853">
- <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le motif.</item>
- <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le motif.</item>
+ <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le schéma.</item>
+ <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le schéma.</item>
</plurals>
<plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="2118758475374354849">
<item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le code d\'accès.</item>
diff --git a/packages/Keyguard/res/values-ro/strings.xml b/packages/Keyguard/res/values-ro/strings.xml
index e4d88f7..a017564 100644
--- a/packages/Keyguard/res/values-ro/strings.xml
+++ b/packages/Keyguard/res/values-ro/strings.xml
@@ -25,7 +25,7 @@
<string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Introduceți codul PUK pentru cardul SIM și codul PIN nou"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Codul PUK pentru cardul SIM"</string>
<string name="keyguard_password_enter_pin_prompt" msgid="3201151840570492538">"Codul PIN nou pentru cardul SIM"</string>
- <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"Atingeţi și introduceţi parola"</font></string>
+ <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"Atingeți și introduceţi parola"</font></string>
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Introduceţi parola pentru a debloca"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Introduceţi codul PIN pentru a debloca"</string>
<string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Cod PIN incorect."</string>
@@ -55,7 +55,7 @@
<string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zona codului PIN al cardului SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zona codului PUK al cardului SIM"</string>
<string name="keyguard_accessibility_next_alarm" msgid="7269583073750518672">"Următoarea alarmă este setată la <xliff:g id="ALARM">%1$s</xliff:g>"</string>
- <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Ștergeţi"</string>
+ <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Ștergeți"</string>
<string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Model uitat"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Model greşit"</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index dfc31ab..b03871a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -40,6 +40,7 @@
protected SecurityMessageDisplay mSecurityMessageDisplay;
protected View mEcaView;
protected boolean mEnableHaptics;
+ private boolean mDismissing;
// To avoid accidental lockout due to events while the device in in the pocket, ignore
// any passwords with length less than or equal to this length.
@@ -67,6 +68,7 @@
@Override
public void reset() {
// start fresh
+ mDismissing = false;
resetPasswordText(false /* animate */);
// if the user is currently locked out, enforce it.
long deadline = mLockPatternUtils.getLockoutAttemptDeadline(
@@ -113,6 +115,8 @@
}
protected void verifyPasswordAndUnlock() {
+ if (mDismissing) return; // already verified but haven't been dismissed; don't do it again.
+
final String entry = getPasswordText();
setPasswordEntryInputEnabled(false);
if (mPendingLockCheck != null) {
@@ -143,6 +147,7 @@
private void onPasswordChecked(boolean matched, int timeoutMs, boolean isValidPassword) {
if (matched) {
+ mDismissing = true;
mCallback.reportUnlockAttempt(true, 0);
mCallback.dismiss(true);
} else {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 4cd4845..ce2d11a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -62,6 +62,7 @@
return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
}
+ @Override
protected void resetState() {
mPasswordEntry.setEnabled(true);
}
@@ -69,11 +70,13 @@
@Override
protected void setPasswordEntryEnabled(boolean enabled) {
mPasswordEntry.setEnabled(enabled);
+ mOkButton.setEnabled(enabled);
}
@Override
protected void setPasswordEntryInputEnabled(boolean enabled) {
mPasswordEntry.setEnabled(enabled);
+ mOkButton.setEnabled(enabled);
}
@Override
@@ -186,6 +189,7 @@
mDeleteButton = findViewById(R.id.delete_button);
mDeleteButton.setVisibility(View.VISIBLE);
mDeleteButton.setOnClickListener(new OnClickListener() {
+ @Override
public void onClick(View v) {
// check for time-based lockouts
if (mPasswordEntry.isEnabled()) {
@@ -195,6 +199,7 @@
}
});
mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
public boolean onLongClick(View v) {
// check for time-based lockouts
if (mPasswordEntry.isEnabled()) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 77215a7..f45b9bd 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -255,7 +255,6 @@
if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
- SecurityMode mode = mSecurityModel.getSecurityMode();
final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
final DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
final int failedAttemptsBeforeWipe =
@@ -264,7 +263,6 @@
final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
(failedAttemptsBeforeWipe - failedAttempts)
: Integer.MAX_VALUE; // because DPM returns 0 if no restriction
- boolean showTimeout = false;
if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
// The user has installed a DevicePolicyManager that requests a user/profile to be wiped
// N attempts. Once we get below the grace period, we post this dialog every time as a
@@ -273,7 +271,8 @@
final int expiringUser = dpm.getProfileWithMinimumFailedPasswordsForWipe(currentUser);
int userType = USER_TYPE_PRIMARY;
if (expiringUser == currentUser) {
- if (expiringUser != UserHandle.USER_OWNER) {
+ // TODO: http://b/23522538
+ if (expiringUser != UserHandle.USER_SYSTEM) {
userType = USER_TYPE_SECONDARY_USER;
}
} else if (expiringUser != UserHandle.USER_NULL) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 4eb6f88..fc6117f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -29,36 +29,19 @@
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.graphics.Bitmap;
-
-import static android.os.BatteryManager.BATTERY_STATUS_FULL;
-import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
-import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
-import static android.os.BatteryManager.EXTRA_STATUS;
-import static android.os.BatteryManager.EXTRA_PLUGGED;
-import static android.os.BatteryManager.EXTRA_LEVEL;
-import static android.os.BatteryManager.EXTRA_HEALTH;
-import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
-
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
import android.media.AudioManager;
import android.os.BatteryManager;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.Message;
-import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
-
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.TelephonyIntents;
-
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
-import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -71,6 +54,12 @@
import com.google.android.collect.Lists;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.widget.LockPatternUtils;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -79,6 +68,15 @@
import java.util.List;
import java.util.Map.Entry;
+import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
+import static android.os.BatteryManager.BATTERY_STATUS_FULL;
+import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.BatteryManager.EXTRA_HEALTH;
+import static android.os.BatteryManager.EXTRA_LEVEL;
+import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
+import static android.os.BatteryManager.EXTRA_PLUGGED;
+import static android.os.BatteryManager.EXTRA_STATUS;
+
/**
* Watches for updates that may be interesting to the keyguard, and provides
* the up to date information as well as a registration for callbacks that care
@@ -138,6 +136,24 @@
private static final int MSG_SCREEN_TURNED_ON = 331;
private static final int MSG_SCREEN_TURNED_OFF = 332;
+ /** Fingerprint state: Not listening to fingerprint. */
+ private static final int FINGERPRINT_STATE_STOPPED = 0;
+
+ /** Fingerprint state: Listening. */
+ private static final int FINGERPRINT_STATE_RUNNING = 1;
+
+ /**
+ * Fingerprint state: Cancelling and waiting for the confirmation from FingerprintService to
+ * send us the confirmation that cancellation has happened.
+ */
+ private static final int FINGERPRINT_STATE_CANCELLING = 2;
+
+ /**
+ * Fingerprint state: During cancelling we got another request to start listening, so when we
+ * receive the cancellation done signal, we should start listening again.
+ */
+ private static final int FINGERPRINT_STATE_CANCELLING_RESTARTING = 3;
+
private static KeyguardUpdateMonitor sInstance;
private final Context mContext;
@@ -147,9 +163,14 @@
private int mRingMode;
private int mPhoneState;
private boolean mKeyguardIsVisible;
+
+ /**
+ * If true, fingerprint was already authenticated and we don't need to start listening again
+ * until the Keyguard has been dismissed.
+ */
+ private boolean mFingerprintAlreadyAuthenticated;
private boolean mBouncer;
private boolean mBootCompleted;
- private boolean mUserHasAuthenticatedSinceBoot;
// Device provisioning state
private boolean mDeviceProvisioned;
@@ -161,7 +182,8 @@
private SparseIntArray mFailedAttempts = new SparseIntArray();
/** Tracks whether strong authentication hasn't been used since quite some time per user. */
- private ArraySet<Integer> mStrongAuthTimedOut = new ArraySet<>();
+ private ArraySet<Integer> mStrongAuthNotTimedOut = new ArraySet<>();
+ private final StrongAuthTracker mStrongAuthTracker = new StrongAuthTracker();
private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
mCallbacks = Lists.newArrayList();
@@ -174,8 +196,8 @@
private SubscriptionManager mSubscriptionManager;
private AlarmManager mAlarmManager;
private List<SubscriptionInfo> mSubscriptionInfo;
- private boolean mFingerprintDetectionRunning;
private TrustManager mTrustManager;
+ private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED;
private final Handler mHandler = new Handler() {
@Override
@@ -269,8 +291,6 @@
private static int sCurrentUser;
- private int mFpWakeMode;
-
public synchronized static void setCurrentUser(int currentUser) {
sCurrentUser = currentUser;
}
@@ -373,6 +393,11 @@
private void onFingerprintAuthenticated(int userId) {
mUserFingerprintAuthenticated.put(userId, true);
+
+ // If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a
+ // wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is
+ // fully gone.
+ mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -418,7 +443,7 @@
}
onFingerprintAuthenticated(userId);
} finally {
- setFingerprintRunningDetectionRunning(false);
+ setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
}
}
@@ -432,7 +457,13 @@
}
private void handleFingerprintError(int msgId, String errString) {
- setFingerprintRunningDetectionRunning(false);
+ if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED
+ && mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) {
+ setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
+ startListeningForFingerprint();
+ } else {
+ setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
+ }
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -441,9 +472,15 @@
}
}
- private void setFingerprintRunningDetectionRunning(boolean running) {
- if (running != mFingerprintDetectionRunning) {
- mFingerprintDetectionRunning = running;
+ private void setFingerprintRunningState(int fingerprintRunningState) {
+ boolean wasRunning = mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
+ boolean isRunning = fingerprintRunningState == FINGERPRINT_STATE_RUNNING;
+ mFingerprintRunningState = fingerprintRunningState;
+
+ // Clients of KeyguardUpdateMonitor don't care about the internal state about the
+ // asynchronousness of the cancel cycle. So only notify them if the actualy running state
+ // has changed.
+ if (wasRunning != isRunning) {
notifyFingerprintRunningStateChanged();
}
}
@@ -452,7 +489,7 @@
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
- cb.onFingerprintRunningStateChanged(mFingerprintDetectionRunning);
+ cb.onFingerprintRunningStateChanged(isFingerprintDetectionRunning());
}
}
}
@@ -471,7 +508,7 @@
}
public boolean isFingerprintDetectionRunning() {
- return mFingerprintDetectionRunning;
+ return mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
}
private boolean isTrustDisabled(int userId) {
@@ -486,7 +523,8 @@
final DevicePolicyManager dpm =
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId)
- & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
+ & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0
+ || isSimPinSecure();
}
public boolean getUserCanSkipBouncer(int userId) {
@@ -503,7 +541,12 @@
}
public boolean isUnlockingWithFingerprintAllowed() {
- return mUserHasAuthenticatedSinceBoot && !hasFingerprintUnlockTimedOut(sCurrentUser);
+ return mStrongAuthTracker.isUnlockingWithFingerprintAllowed()
+ && !hasFingerprintUnlockTimedOut(sCurrentUser);
+ }
+
+ public StrongAuthTracker getStrongAuthTracker() {
+ return mStrongAuthTracker;
}
/**
@@ -511,11 +554,11 @@
* while and thus can't unlock with fingerprint, false otherwise
*/
public boolean hasFingerprintUnlockTimedOut(int userId) {
- return mStrongAuthTimedOut.contains(userId);
+ return !mStrongAuthNotTimedOut.contains(userId);
}
public void reportSuccessfulStrongAuthUnlockAttempt() {
- mStrongAuthTimedOut.remove(sCurrentUser);
+ mStrongAuthNotTimedOut.add(sCurrentUser);
scheduleStrongAuthTimeout();
if (mFpm != null) {
byte[] token = null; /* TODO: pass real auth token once fp HAL supports it */
@@ -530,14 +573,14 @@
PendingIntent sender = PendingIntent.getBroadcast(mContext,
sCurrentUser, intent, PendingIntent.FLAG_CANCEL_CURRENT);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, sender);
- notifyStrongAuthTimedOutChanged(sCurrentUser);
+ notifyStrongAuthStateChanged(sCurrentUser);
}
- private void notifyStrongAuthTimedOutChanged(int userId) {
+ private void notifyStrongAuthStateChanged(int userId) {
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
- cb.onStrongAuthTimeoutExpiredChanged(userId);
+ cb.onStrongAuthStateChanged(userId);
}
}
}
@@ -632,8 +675,8 @@
public void onReceive(Context context, Intent intent) {
if (ACTION_STRONG_AUTH_TIMEOUT.equals(intent.getAction())) {
int userId = intent.getIntExtra(USER_ID, -1);
- mStrongAuthTimedOut.add(userId);
- notifyStrongAuthTimedOutChanged(userId);
+ mStrongAuthNotTimedOut.remove(userId);
+ notifyStrongAuthStateChanged(userId);
}
}
};
@@ -791,6 +834,25 @@
}
}
+ public class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
+
+ public boolean isUnlockingWithFingerprintAllowed() {
+ int userId = getCurrentUser();
+ return isFingerprintAllowedForUser(userId);
+ }
+
+ public boolean hasUserAuthenticatedSinceBoot() {
+ int userId = getCurrentUser();
+ return (getStrongAuthForUser(userId)
+ & STRONG_AUTH_REQUIRED_AFTER_BOOT) == 0;
+ }
+
+ @Override
+ public void onStrongAuthRequiredChanged(int userId) {
+ notifyStrongAuthStateChanged(userId);
+ }
+ }
+
public static KeyguardUpdateMonitor getInstance(Context context) {
if (sInstance == null) {
sInstance = new KeyguardUpdateMonitor(context);
@@ -818,6 +880,7 @@
cb.onFinishedGoingToSleep(arg1);
}
}
+ mFingerprintAlreadyAuthenticated = false;
updateFingerprintListeningState();
}
@@ -936,6 +999,7 @@
PERMISSION_SELF, null /* handler */);
mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
mTrustManager.registerTrustListener(this);
+ new LockPatternUtils(context).registerStrongAuthTracker(mStrongAuthTracker);
mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
updateFingerprintListeningState();
@@ -943,29 +1007,33 @@
private void updateFingerprintListeningState() {
boolean shouldListenForFingerprint = shouldListenForFingerprint();
- if (mFingerprintDetectionRunning && !shouldListenForFingerprint) {
+ if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) {
stopListeningForFingerprint();
- } else if (!mFingerprintDetectionRunning && shouldListenForFingerprint) {
+ } else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING
+ && shouldListenForFingerprint) {
startListeningForFingerprint();
}
}
private boolean shouldListenForFingerprint() {
- return (mKeyguardIsVisible || !mDeviceInteractive) && !mSwitchingUser;
+ return (mKeyguardIsVisible || !mDeviceInteractive) && !mSwitchingUser
+ && !mFingerprintAlreadyAuthenticated && !isFingerprintDisabled(getCurrentUser());
}
private void startListeningForFingerprint() {
+ if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) {
+ setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING);
+ return;
+ }
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
int userId = ActivityManager.getCurrentUser();
- if (!mFingerprintDetectionRunning && isUnlockWithFingerprintPossible(userId)) {
- mUserHasAuthenticatedSinceBoot = mTrustManager.hasUserAuthenticatedSinceBoot(
- ActivityManager.getCurrentUser());
+ if (isUnlockWithFingerprintPossible(userId)) {
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
}
mFingerprintCancelSignal = new CancellationSignal();
mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);
- setFingerprintRunningDetectionRunning(true);
+ setFingerprintRunningState(FINGERPRINT_STATE_RUNNING);
}
}
@@ -976,11 +1044,14 @@
private void stopListeningForFingerprint() {
if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
- if (isFingerprintDetectionRunning()) {
+ if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING) {
mFingerprintCancelSignal.cancel();
mFingerprintCancelSignal = null;
+ setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING);
}
- setFingerprintRunningDetectionRunning(false);
+ if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) {
+ setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING);
+ }
}
private boolean isDeviceProvisionedInSettingsDb() {
@@ -1020,6 +1091,7 @@
* Handle {@link #MSG_DPM_STATE_CHANGED}
*/
protected void handleDevicePolicyManagerStateChanged() {
+ updateFingerprintListeningState();
for (int i = mCallbacks.size() - 1; i >= 0; i--) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1249,6 +1321,9 @@
cb.onKeyguardVisibilityChangedRaw(isShowing);
}
}
+ if (!isShowing) {
+ mFingerprintAlreadyAuthenticated = false;
+ }
updateFingerprintListeningState();
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 7ca67b0..15ffe9f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -233,5 +233,5 @@
* Called when the state that the user hasn't used strong authentication since quite some time
* has changed.
*/
- public void onStrongAuthTimeoutExpiredChanged(int userId) { }
+ public void onStrongAuthStateChanged(int userId) { }
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 2353205..c430def 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -30,6 +30,11 @@
import java.util.Date;
import java.util.LinkedList;
+/**
+ * Loader for MTP document.
+ * At the first request, the loader returns only first NUM_INITIAL_ENTRIES. Then it launches
+ * background thread to load the rest documents and caches its result for next requests.
+ */
class DocumentLoader {
static final int NUM_INITIAL_ENTRIES = 10;
static final int NUM_LOADING_ENTRIES = 20;
@@ -37,7 +42,7 @@
private final MtpManager mMtpManager;
private final ContentResolver mResolver;
- private final LinkedList<LoaderTask> mTasks = new LinkedList<LoaderTask>();
+ private final TaskList mTaskList = new TaskList();
private boolean mHasBackgroundThread = false;
DocumentLoader(MtpManager mtpManager, ContentResolver resolver) {
@@ -56,7 +61,7 @@
synchronized Cursor queryChildDocuments(String[] columnNames, Identifier parent)
throws IOException {
- LoaderTask task = findTask(parent);
+ LoaderTask task = mTaskList.findTask(parent);
if (task == null) {
int parentHandle = parent.mObjectHandle;
// Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
@@ -70,11 +75,12 @@
mMtpManager,
parent.mDeviceId,
task.getUnloadedObjectHandles(NUM_INITIAL_ENTRIES)));
+ } else {
+ // Once remove the existing task in order to add it to the head of the list.
+ mTaskList.remove(task);
}
- // Move this task to the head of the list to prioritize it.
- mTasks.remove(task);
- mTasks.addFirst(task);
+ mTaskList.addFirst(task);
if (!task.completed() && !mHasBackgroundThread) {
mHasBackgroundThread = true;
new BackgroundLoaderThread().start();
@@ -84,41 +90,11 @@
}
synchronized void clearCache(int deviceId) {
- int i = 0;
- while (i < mTasks.size()) {
- if (mTasks.get(i).mIdentifier.mDeviceId == deviceId) {
- mTasks.remove(i);
- } else {
- i++;
- }
- }
+ mTaskList.clearTaskForDevice(deviceId);
}
synchronized void clearCache() {
- int i = 0;
- while (i < mTasks.size()) {
- if (mTasks.get(i).completed()) {
- mTasks.remove(i);
- } else {
- i++;
- }
- }
- }
-
- private LoaderTask findTask(Identifier parent) {
- for (int i = 0; i < mTasks.size(); i++) {
- if (mTasks.get(i).mIdentifier.equals(parent))
- return mTasks.get(i);
- }
- return null;
- }
-
- private LoaderTask findUncompletedTask() {
- for (int i = 0; i < mTasks.size(); i++) {
- if (!mTasks.get(i).completed())
- return mTasks.get(i);
- }
- return null;
+ mTaskList.clearCompletedTask();
}
private class BackgroundLoaderThread extends Thread {
@@ -130,7 +106,7 @@
int deviceId;
int[] handles;
synchronized (DocumentLoader.this) {
- task = findUncompletedTask();
+ task = mTaskList.findRunningTask();
if (task == null) {
mHasBackgroundThread = false;
return;
@@ -156,13 +132,53 @@
task.notify(mResolver);
}
} else {
- mTasks.remove(task);
+ mTaskList.remove(task);
}
}
}
}
}
+ private static class TaskList extends LinkedList<LoaderTask> {
+ LoaderTask findTask(Identifier parent) {
+ for (int i = 0; i < size(); i++) {
+ if (get(i).mIdentifier.equals(parent))
+ return get(i);
+ }
+ return null;
+ }
+
+ LoaderTask findRunningTask() {
+ for (int i = 0; i < size(); i++) {
+ if (!get(i).completed())
+ return get(i);
+ }
+ return null;
+ }
+
+ void clearTaskForDevice(int deviceId) {
+ int i = 0;
+ while (i < size()) {
+ if (get(i).mIdentifier.mDeviceId == deviceId) {
+ remove(i);
+ } else {
+ i++;
+ }
+ }
+ }
+
+ void clearCompletedTask() {
+ int i = 0;
+ while (i < size()) {
+ if (get(i).completed()) {
+ remove(i);
+ } else {
+ i++;
+ }
+ }
+ }
+ }
+
private static class LoaderTask {
final Identifier mIdentifier;
final int[] mObjectHandles;
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
index 98775b3..c1d9609 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
@@ -32,6 +32,7 @@
private final Date mDateModified;
private final int mSize;
private final int mThumbSize;
+ private final boolean mReadOnly;
/**
* Constructor for root document.
@@ -40,9 +41,10 @@
this(DUMMY_HANDLE_FOR_ROOT,
0x3001, // Directory.
root.mDescription,
- null, // Unknown,
+ null, // Unknown name.
(int) Math.min(root.mMaxCapacity - root.mFreeSpace, Integer.MAX_VALUE),
- 0);
+ 0, // Total size.
+ true); // Writable.
}
MtpDocument(MtpObjectInfo objectInfo) {
@@ -51,7 +53,8 @@
objectInfo.getName(),
objectInfo.getDateModified() != 0 ? new Date(objectInfo.getDateModified()) : null,
objectInfo.getCompressedSize(),
- objectInfo.getThumbCompressedSize());
+ objectInfo.getThumbCompressedSize(),
+ objectInfo.getProtectionStatus() != 0);
}
MtpDocument(int objectHandle,
@@ -59,30 +62,39 @@
String name,
Date dateModified,
int size,
- int thumbSize) {
+ int thumbSize,
+ boolean readOnly) {
this.mObjectHandle = objectHandle;
this.mFormat = format;
this.mName = name;
this.mDateModified = dateModified;
this.mSize = size;
this.mThumbSize = thumbSize;
+ this.mReadOnly = readOnly;
}
void addToCursor(Identifier rootIdentifier, MatrixCursor.RowBuilder builder) {
final Identifier identifier = new Identifier(
rootIdentifier.mDeviceId, rootIdentifier.mStorageId, mObjectHandle);
+ final String mimeType = formatTypeToMimeType(mFormat);
int flag = 0;
if (mObjectHandle != DUMMY_HANDLE_FOR_ROOT) {
- flag |= DocumentsContract.Document.FLAG_SUPPORTS_DELETE;
if (mThumbSize > 0) {
flag |= DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL;
}
+ if (!mReadOnly) {
+ flag |= DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
+ DocumentsContract.Document.FLAG_SUPPORTS_WRITE;
+ }
+ }
+ if (mimeType == DocumentsContract.Document.MIME_TYPE_DIR && !mReadOnly) {
+ flag |= DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE;
}
builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId());
builder.add(Document.COLUMN_DISPLAY_NAME, mName);
- builder.add(Document.COLUMN_MIME_TYPE, getMimeType());
+ builder.add(Document.COLUMN_MIME_TYPE, mimeType);
builder.add(
Document.COLUMN_LAST_MODIFIED,
mDateModified != null ? mDateModified.getTime() : null);
@@ -90,9 +102,9 @@
builder.add(Document.COLUMN_SIZE, mSize);
}
- private String getMimeType() {
+ static String formatTypeToMimeType(int format) {
// TODO: Add complete list of mime types.
- switch (mFormat) {
+ switch (format) {
case 0x3001:
return DocumentsContract.Document.MIME_TYPE_DIR;
case 0x3009:
@@ -100,7 +112,21 @@
case 0x3801:
return "image/jpeg";
default:
- return "";
+ return "application/octet-stream";
+ }
+ }
+
+ static int mimeTypeToFormatType(String mimeType) {
+ // TODO: Add complete list of mime types.
+ switch (mimeType.toLowerCase()) {
+ case Document.MIME_TYPE_DIR:
+ return 0x3001;
+ case "audio/mp3":
+ return 0x3009;
+ case "image/jpeg":
+ return 0x3801;
+ default:
+ return 0x3000; // Undefined object.
}
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 61b9fc5..a3cf3e2 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -96,7 +96,7 @@
final Identifier rootIdentifier = new Identifier(root.mDeviceId, root.mStorageId);
final MatrixCursor.RowBuilder builder = cursor.newRow();
builder.add(Root.COLUMN_ROOT_ID, rootIdentifier.toRootId());
- builder.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD);
+ builder.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
builder.add(Root.COLUMN_TITLE, root.mDescription);
builder.add(
Root.COLUMN_DOCUMENT_ID,
@@ -167,13 +167,18 @@
public ParcelFileDescriptor openDocument(
String documentId, String mode, CancellationSignal signal)
throws FileNotFoundException {
- if (!"r".equals(mode) && !"w".equals(mode)) {
- // TODO: Support seekable file.
- throw new UnsupportedOperationException("The provider does not support seekable file.");
- }
final Identifier identifier = Identifier.createFromDocumentId(documentId);
try {
- return mPipeManager.readDocument(mMtpManager, identifier);
+ switch (mode) {
+ case "r":
+ return mPipeManager.readDocument(mMtpManager, identifier);
+ case "w":
+ return mPipeManager.writeDocument(getContext(), mMtpManager, identifier);
+ default:
+ // TODO: Add support for seekable files.
+ throw new UnsupportedOperationException(
+ "The provider does not support seekable file.");
+ }
} catch (IOException error) {
throw new FileNotFoundException(error.getMessage());
}
@@ -214,6 +219,24 @@
mDocumentLoader.clearCache();
}
+ @Override
+ public String createDocument(String parentDocumentId, String mimeType, String displayName)
+ throws FileNotFoundException {
+ try {
+ final Identifier parentId = Identifier.createFromDocumentId(parentDocumentId);
+ final int objectHandle = mMtpManager.createDocument(
+ parentId.mDeviceId, parentId.mStorageId, parentId.mObjectHandle, mimeType,
+ displayName);
+ final String documentId = new Identifier(parentId.mDeviceId, parentId.mStorageId,
+ objectHandle).toDocumentId();
+ notifyChildDocumentsChange(parentDocumentId);
+ return documentId;
+ } catch (IOException error) {
+ Log.e(TAG, error.getMessage());
+ throw new FileNotFoundException(error.getMessage());
+ }
+ }
+
void openDevice(int deviceId) throws IOException {
mMtpManager.openDevice(deviceId);
mRootScanner.scanNow();
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 3afc173..6647009 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -21,7 +21,10 @@
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.mtp.MtpDevice;
+import android.mtp.MtpObjectInfo;
import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract;
import android.util.SparseArray;
import java.io.FileNotFoundException;
@@ -105,6 +108,11 @@
return results;
}
+ synchronized MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
+ final MtpDevice device = getDevice(deviceId);
+ return device.getObjectInfo(objectHandle);
+ }
+
synchronized MtpDocument getDocument(int deviceId, int objectHandle) throws IOException {
final MtpDevice device = getDevice(deviceId);
return new MtpDocument(device.getObjectInfo(objectHandle));
@@ -134,6 +142,27 @@
}
}
+ // TODO: Remove this method.
+ synchronized int createDocument(int deviceId, int storageId, int parentObjectHandle,
+ String mimeType, String name) throws IOException {
+ final MtpObjectInfo objectInfo = new MtpObjectInfo.Builder()
+ .setName(name)
+ .setStorageId(storageId)
+ .setParent(parentObjectHandle)
+ .setFormat(MtpDocument.mimeTypeToFormatType(mimeType))
+ .build();
+ return createDocument(deviceId, objectInfo);
+ }
+
+ synchronized int createDocument(int deviceId, MtpObjectInfo objectInfo) throws IOException {
+ final MtpDevice device = getDevice(deviceId);
+ final MtpObjectInfo result = device.sendObjectInfo(objectInfo);
+ if (result == null) {
+ throw new IOException("Failed to create a document");
+ }
+ return result.getObjectHandle();
+ }
+
synchronized int getParent(int deviceId, int objectHandle) throws IOException {
final MtpDevice device = getDevice(deviceId);
final int result = (int) device.getParent(objectHandle);
@@ -149,6 +178,13 @@
device.importFile(objectHandle, target);
}
+ synchronized void sendObject(int deviceId, int objectHandle, int size,
+ ParcelFileDescriptor source) throws IOException {
+ final MtpDevice device = getDevice(deviceId);
+ if (!device.sendObject(objectHandle, size, source))
+ throw new IOException("Failed to send a document");
+ }
+
private MtpDevice getDevice(int deviceId) throws IOException {
final MtpDevice device = mDevices.get(deviceId);
if (device == null) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
index ba13b31..53f1b65 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
@@ -16,10 +16,16 @@
package com.android.mtp;
+import android.content.Context;
+import android.mtp.MtpObjectInfo;
import android.os.ParcelFileDescriptor;
import android.util.Log;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -40,6 +46,13 @@
return task.getReadingFileDescriptor();
}
+ ParcelFileDescriptor writeDocument(Context context, MtpManager model, Identifier identifier)
+ throws IOException {
+ final Task task = new WriteDocumentTask(context, model, identifier);
+ mExecutor.execute(task);
+ return task.getWritingFileDescriptor();
+ }
+
ParcelFileDescriptor readThumbnail(MtpManager model, Identifier identifier) throws IOException {
final Task task = new GetThumbnailTask(model, identifier);
mExecutor.execute(task);
@@ -60,6 +73,10 @@
ParcelFileDescriptor getReadingFileDescriptor() {
return mDescriptors[0];
}
+
+ ParcelFileDescriptor getWritingFileDescriptor() {
+ return mDescriptors[1];
+ }
}
private static class ImportFileTask extends Task {
@@ -83,6 +100,70 @@
}
}
+ private static class WriteDocumentTask extends Task {
+ private final Context mContext;
+
+ WriteDocumentTask(Context context, MtpManager model, Identifier identifier)
+ throws IOException {
+ super(model, identifier);
+ mContext = context;
+ }
+
+ @Override
+ public void run() {
+ File tempFile = null;
+ try {
+ // Obtain a temporary file and copy the data to it.
+ tempFile = mContext.getCacheDir().createTempFile("mtp", "tmp");
+ try (
+ final FileOutputStream tempOutputStream =
+ new ParcelFileDescriptor.AutoCloseOutputStream(
+ ParcelFileDescriptor.open(
+ tempFile, ParcelFileDescriptor.MODE_WRITE_ONLY));
+ final ParcelFileDescriptor.AutoCloseInputStream inputStream =
+ new ParcelFileDescriptor.AutoCloseInputStream(mDescriptors[0])
+ ) {
+ final byte[] buffer = new byte[32 * 1024];
+ int bytes;
+ while ((bytes = inputStream.read(buffer)) != -1) {
+ mDescriptors[0].checkError();
+ tempOutputStream.write(buffer, 0, bytes);
+ }
+ tempOutputStream.flush();
+ }
+
+ // Get the placeholder object info.
+ final MtpObjectInfo placeholderObjectInfo =
+ mManager.getObjectInfo(mIdentifier.mDeviceId, mIdentifier.mObjectHandle);
+
+ // Delete the target object info if it already exists (as a placeholder).
+ mManager.deleteDocument(mIdentifier.mDeviceId, mIdentifier.mObjectHandle);
+
+ // Create the target object info with a correct file size.
+ final int targetObjectHandle =
+ mManager.createDocument(
+ mIdentifier.mDeviceId,
+ new MtpObjectInfo.Builder(placeholderObjectInfo)
+ .setCompressedSize((int) tempFile.length())
+ .build());
+
+ // Upload the object.
+ final ParcelFileDescriptor tempInputDescriptor = ParcelFileDescriptor.open(
+ tempFile, ParcelFileDescriptor.MODE_READ_ONLY);
+ mManager.sendObject(mIdentifier.mDeviceId,
+ targetObjectHandle, (int) tempFile.length(), tempInputDescriptor);
+
+ } catch (IOException error) {
+ Log.w(MtpDocumentsProvider.TAG,
+ "Failed to send a file because of: " + error.getMessage());
+ } finally {
+ if (tempFile != null) {
+ tempFile.delete();
+ }
+ }
+ }
+ }
+
private static class GetThumbnailTask extends Task {
GetThumbnailTask(MtpManager model, Identifier identifier) throws IOException {
super(model, identifier);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index 5504147..1e015bd 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
@@ -91,7 +91,8 @@
"file" + objectHandle,
new Date(),
1024,
- 0 /* thumbnail size */));
+ 0 /* thumbnail size */,
+ false /* not read only */));
}
manager.setObjectHandles(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, childDocuments);
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index c1da59f..1826bd0 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -140,7 +140,7 @@
assertEquals(1, cursor.getCount());
cursor.moveToNext();
assertEquals("0_1", cursor.getString(0));
- assertEquals(Root.FLAG_SUPPORTS_IS_CHILD, cursor.getInt(1));
+ assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
// TODO: Add storage icon for MTP devices.
assertTrue(cursor.isNull(2) /* icon */);
assertEquals("Storage A", cursor.getString(3));
@@ -156,7 +156,7 @@
cursor.moveToNext();
cursor.moveToNext();
assertEquals("1_1", cursor.getString(0));
- assertEquals(Root.FLAG_SUPPORTS_IS_CHILD, cursor.getInt(1));
+ assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
// TODO: Add storage icon for MTP devices.
assertTrue(cursor.isNull(2) /* icon */);
assertEquals("Storage B", cursor.getString(3));
@@ -194,7 +194,7 @@
assertEquals(1, cursor.getCount());
cursor.moveToNext();
assertEquals("1_1", cursor.getString(0));
- assertEquals(Root.FLAG_SUPPORTS_IS_CHILD, cursor.getInt(1));
+ assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
// TODO: Add storage icon for MTP devices.
assertTrue(cursor.isNull(2) /* icon */);
assertEquals("Storage B", cursor.getString(3));
@@ -210,7 +210,8 @@
"image.jpg" /* display name */,
new Date(1422716400000L) /* modified date */,
1024 * 1024 * 5 /* file size */,
- 1024 * 50 /* thumbnail size */));
+ 1024 * 50 /* thumbnail size */,
+ false /* read only */));
final Cursor cursor = mProvider.queryDocument("0_1_2", null);
assertEquals(1, cursor.getCount());
@@ -221,11 +222,37 @@
assertEquals(1422716400000L, cursor.getLong(3));
assertEquals(
DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
+ DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL,
cursor.getInt(4));
assertEquals(1024 * 1024 * 5, cursor.getInt(5));
}
+ public void testQueryDocument_directory() throws IOException {
+ mMtpManager.setDocument(0, 2, new MtpDocument(
+ 2 /* object handle */,
+ 0x3001 /* directory */,
+ "directory" /* display name */,
+ new Date(1422716400000L) /* modified date */,
+ 0 /* file size */,
+ 0 /* thumbnail size */,
+ false /* read only */));
+ final Cursor cursor = mProvider.queryDocument("0_1_2", null);
+ assertEquals(1, cursor.getCount());
+
+ cursor.moveToNext();
+ assertEquals("0_1_2", cursor.getString(0));
+ assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
+ assertEquals("directory", cursor.getString(2));
+ assertEquals(1422716400000L, cursor.getLong(3));
+ assertEquals(
+ DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
+ DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
+ DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE,
+ cursor.getInt(4));
+ assertEquals(0, cursor.getInt(5));
+ }
+
public void testQueryDocument_forRoot() throws IOException {
mMtpManager.setRoots(0, new MtpRoot[] {
new MtpRoot(
@@ -257,7 +284,8 @@
"image.jpg" /* display name */,
new Date(0) /* modified date */,
1024 * 1024 * 5 /* file size */,
- 1024 * 50 /* thumbnail size */));
+ 1024 * 50 /* thumbnail size */,
+ true /* read only */));
final Cursor cursor = mProvider.queryChildDocuments("0_0_0", null, null);
assertEquals(1, cursor.getCount());
@@ -267,10 +295,7 @@
assertEquals("image/jpeg", cursor.getString(1));
assertEquals("image.jpg", cursor.getString(2));
assertEquals(0, cursor.getLong(3));
- assertEquals(
- DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
- DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL,
- cursor.getInt(4));
+ assertEquals(DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL, cursor.getInt(4));
assertEquals(1024 * 1024 * 5, cursor.getInt(5));
assertFalse(cursor.moveToNext());
@@ -302,7 +327,8 @@
"image.jpg" /* display name */,
new Date(1422716400000L) /* modified date */,
1024 * 1024 * 5 /* file size */,
- 1024 * 50 /* thumbnail size */));
+ 1024 * 50 /* thumbnail size */,
+ false /* not read only */));
mMtpManager.setParent(0, 1, 2);
mProvider.deleteDocument("0_0_1");
assertEquals(1, mResolver.getChangeCount(
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index 35918e1..e2cc3ed 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -21,6 +21,7 @@
import android.test.suitebuilder.annotation.SmallTest;
import java.io.IOException;
+import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -53,6 +54,41 @@
assertDescriptorError(descriptor);
}
+ public void testWriteDocument_basic() throws Exception {
+ // Create a placeholder file which should be replaced by a real file later.
+ mtpManager.setDocument(0, 1, new MtpDocument(1, 0, "", new Date(), 0, 0, false));
+
+ // Upload testing bytes.
+ final ParcelFileDescriptor descriptor = pipeManager.writeDocument(
+ getContext(), mtpManager, new Identifier(0, 0, 1));
+ final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
+ new ParcelFileDescriptor.AutoCloseOutputStream(descriptor);
+ outputStream.write(HELLO_BYTES, 0, HELLO_BYTES.length);
+ outputStream.close();
+ executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
+
+ // Check if the placeholder file is removed.
+ try {
+ final MtpDocument placeholderDocument = mtpManager.getDocument(0, 1);
+ fail(); // The placeholder file has not been deleted.
+ } catch (IOException e) {
+ // Expected error, as the file is gone.
+ }
+
+ // Confirm that the target file is created.
+ final MtpDocument targetDocument = mtpManager.getDocument(
+ 0, TestMtpManager.CREATED_DOCUMENT_HANDLE);
+ assertTrue(targetDocument != null);
+
+ // Verify uploaded bytes.
+ final byte[] uploadedBytes = mtpManager.getImportFileBytes(
+ 0, TestMtpManager.CREATED_DOCUMENT_HANDLE);
+ assertEquals(HELLO_BYTES.length, uploadedBytes.length);
+ for (int i = 0; i < HELLO_BYTES.length; i++) {
+ assertEquals(HELLO_BYTES[i], uploadedBytes[i]);
+ }
+ }
+
public void testReadThumbnail_basic() throws Exception {
mtpManager.setThumbnail(0, 1, HELLO_BYTES);
final ParcelFileDescriptor descriptor = pipeManager.readThumbnail(
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 40de7b4..94b5ba0 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -17,10 +17,13 @@
package com.android.mtp;
import android.content.Context;
+import android.mtp.MtpObjectInfo;
+import android.mtp.MtpObjectInfo.Builder;
import android.os.ParcelFileDescriptor;
import java.io.IOException;
import java.util.Arrays;
+import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -28,6 +31,8 @@
import java.util.TreeSet;
public class TestMtpManager extends MtpManager {
+ public static final int CREATED_DOCUMENT_HANDLE = 1000;
+
protected static String pack(int... args) {
return Arrays.toString(args);
}
@@ -65,6 +70,10 @@
mImportFileBytes.put(pack(deviceId, objectHandle), bytes);
}
+ byte[] getImportFileBytes(int deviceId, int objectHandle) {
+ return mImportFileBytes.get(pack(deviceId, objectHandle));
+ }
+
void setThumbnail(int deviceId, int objectHandle, byte[] bytes) {
mThumbnailBytes.put(pack(deviceId, objectHandle), bytes);
}
@@ -109,6 +118,15 @@
}
@Override
+ MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
+ final MtpDocument document = getDocument(deviceId, objectHandle);
+ // It's impossible to set an object id of MtpObjectInfo at this stage. Also,
+ // it's hard to get any information from MtpDocument, as it's designed to return them
+ // only via cursors. Rework these.
+ return new MtpObjectInfo.Builder().build();
+ }
+
+ @Override
int[] getObjectHandles(int deviceId, int storageId, int parentObjectHandle) throws IOException {
final String key = pack(deviceId, storageId, parentObjectHandle);
if (mObjectHandles.containsKey(key)) {
@@ -119,8 +137,9 @@
}
@Override
- void importFile(int deviceId, int storageId, ParcelFileDescriptor target) throws IOException {
- final String key = pack(deviceId, storageId);
+ void importFile(int deviceId, int objectHandle, ParcelFileDescriptor target)
+ throws IOException {
+ final String key = pack(deviceId, objectHandle);
if (mImportFileBytes.containsKey(key)) {
try (final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
new ParcelFileDescriptor.AutoCloseOutputStream(target)) {
@@ -132,6 +151,44 @@
}
@Override
+ int createDocument(int deviceId, MtpObjectInfo objectInfo) throws IOException {
+ // For simplicity, it allows to create only one document, and it always has the hardcoded
+ // CREATED_DOCUMENT_HANDLE document handle.
+ final String key = pack(deviceId, CREATED_DOCUMENT_HANDLE);
+ if (!mDocuments.containsKey(key)) {
+ mDocuments.put(key, new MtpDocument(
+ CREATED_DOCUMENT_HANDLE,
+ objectInfo.getFormat(),
+ objectInfo.getName(),
+ new Date(objectInfo.getDateModified()),
+ objectInfo.getCompressedSize(),
+ objectInfo.getThumbCompressedSize(),
+ false /* Always writable for testing. */));
+ } else {
+ throw new IOException();
+ }
+ return CREATED_DOCUMENT_HANDLE;
+ }
+
+ @Override
+ void sendObject(int deviceId, int objectHandle, int size, ParcelFileDescriptor source)
+ throws IOException {
+ final String key = pack(deviceId, objectHandle);
+ if (!mDocuments.containsKey(key)) {
+ throw new IOException();
+ }
+
+ ParcelFileDescriptor.AutoCloseInputStream inputStream =
+ new ParcelFileDescriptor.AutoCloseInputStream(source);
+ byte[] buffer = new byte[size];
+ if (inputStream.read(buffer, 0, size) != size) {
+ throw new IOException();
+ }
+
+ mImportFileBytes.put(pack(deviceId, objectHandle), buffer);
+ }
+
+ @Override
byte[] getThumbnail(int deviceId, int objectHandle) throws IOException {
final String key = pack(deviceId, objectHandle);
if (mThumbnailBytes.containsKey(key)) {
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 1c4b05f..3ad8f21 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -21,4 +21,6 @@
<!-- The translation for disappearing security views after having solved them. -->
<dimen name="disappear_y_translation">-32dp</dimen>
-</resources>
\ No newline at end of file
+
+ <dimen name="circle_avatar_size">40dp</dimen>
+</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index b03f100..9b1f103 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -195,4 +195,34 @@
<!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_wifi_signal_full">Wifi signal full.</string>
+ <!-- Label for kernel threads in battery usage -->
+ <string name="process_kernel_label">Android OS</string>
+ <!-- Title of data usage item that represents all uninstalled applications. [CHAR LIMIT=48] -->
+ <string name="data_usage_uninstalled_apps">Removed apps</string>
+ <!-- Title of data usage item that represents all uninstalled applications or removed users. [CHAR LIMIT=48] -->
+ <string name="data_usage_uninstalled_apps_users">Removed apps and users</string>
+
+ <!-- Tethering controls, item title to go into the tethering settings -->
+ <!-- Tethering controls, item title to go into the tethering settings when only USB tethering is available [CHAR LIMIT=25]-->
+ <string name="tether_settings_title_usb">USB tethering</string>
+ <!-- Tethering controls, item title to go into the tethering settings when only Wifi tethering is available [CHAR LIMIT=25]-->
+ <string name="tether_settings_title_wifi">Portable hotspot</string>
+ <!-- Tethering controls, item title to go into the tethering settings when only Bluetooth tethering is available [CHAR LIMIT=25]-->
+ <string name="tether_settings_title_bluetooth">Bluetooth tethering</string>
+ <!-- Tethering controls, item title to go into the tethering settings when USB and Bluetooth tethering are available [CHAR LIMIT=25]-->
+ <string name="tether_settings_title_usb_bluetooth">Tethering</string>
+ <!-- Tethering controls, item title to go into the tethering settings when USB, Bluetooth and Wifi tethering are available [CHAR LIMIT=25]-->
+ <string name="tether_settings_title_all">Tethering & portable hotspot</string>
+
+ <!-- Title for a work profile. [CHAR LIMIT=25] -->
+ <string name="managed_user_title">Work profile</string>
+
+ <!-- Title for Guest user [CHAR LIMIT=35] -->
+ <string name="user_guest">Guest</string>
+
+ <!-- Manage apps, individual app screen, substituted for the application's label when the app's label CAN NOT be determined.-->
+ <string name="unknown">Unknown</string>
+
+ <!-- [CHAR LIMIT=NONE] Label of a running process that represents another user -->
+ <string name="running_process_item_user_label">User: <xliff:g id="user_name">%1$s</xliff:g></string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java b/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
index 096a5c4..f52d755 100644
--- a/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
@@ -54,29 +54,7 @@
public static boolean setWifiTethering(boolean enable, Context context) {
final WifiManager wifiManager =
(WifiManager) context.getSystemService(Context.WIFI_SERVICE);
- final ContentResolver cr = context.getContentResolver();
- /**
- * Disable Wifi if enabling tethering
- */
- int wifiState = wifiManager.getWifiState();
- if (enable && ((wifiState == WifiManager.WIFI_STATE_ENABLING) ||
- (wifiState == WifiManager.WIFI_STATE_ENABLED))) {
- wifiManager.setWifiEnabled(false);
- Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 1);
- }
-
- boolean success = wifiManager.setWifiApEnabled(null, enable);
- /**
- * If needed, restore Wifi on tether disable
- */
- if (!enable) {
- int wifiSavedState = Settings.Global.getInt(cr, Settings.Global.WIFI_SAVED_STATE, 0);
- if (wifiSavedState == 1) {
- wifiManager.setWifiEnabled(true);
- Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 0);
- }
- }
- return success;
+ return wifiManager.setWifiApEnabled(null, enable);
}
public static boolean isWifiTetherEnabled(Context context) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
new file mode 100644
index 0000000..621a09cd
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -0,0 +1,84 @@
+package com.android.settingslib;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.os.UserManager;
+
+import com.android.internal.util.UserIcons;
+import com.android.settingslib.drawable.CircleFramedDrawable;
+
+public final class Utils {
+
+ /**
+ * Return string resource that best describes combination of tethering
+ * options available on this device.
+ */
+ public static int getTetheringLabel(ConnectivityManager cm) {
+ String[] usbRegexs = cm.getTetherableUsbRegexs();
+ String[] wifiRegexs = cm.getTetherableWifiRegexs();
+ String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
+
+ boolean usbAvailable = usbRegexs.length != 0;
+ boolean wifiAvailable = wifiRegexs.length != 0;
+ boolean bluetoothAvailable = bluetoothRegexs.length != 0;
+
+ if (wifiAvailable && usbAvailable && bluetoothAvailable) {
+ return R.string.tether_settings_title_all;
+ } else if (wifiAvailable && usbAvailable) {
+ return R.string.tether_settings_title_all;
+ } else if (wifiAvailable && bluetoothAvailable) {
+ return R.string.tether_settings_title_all;
+ } else if (wifiAvailable) {
+ return R.string.tether_settings_title_wifi;
+ } else if (usbAvailable && bluetoothAvailable) {
+ return R.string.tether_settings_title_usb_bluetooth;
+ } else if (usbAvailable) {
+ return R.string.tether_settings_title_usb;
+ } else {
+ return R.string.tether_settings_title_bluetooth;
+ }
+ }
+
+ /**
+ * Returns a label for the user, in the form of "User: user name" or "Work profile".
+ */
+ public static String getUserLabel(Context context, UserInfo info) {
+ String name = info != null ? info.name : null;
+ if (info.isManagedProfile()) {
+ // We use predefined values for managed profiles
+ return context.getString(R.string.managed_user_title);
+ } else if (info.isGuest()) {
+ name = context.getString(R.string.user_guest);
+ }
+ if (name == null && info != null) {
+ name = Integer.toString(info.id);
+ } else if (info == null) {
+ name = context.getString(R.string.unknown);
+ }
+ return context.getResources().getString(R.string.running_process_item_user_label, name);
+ }
+
+ /**
+ * Returns a circular icon for a user.
+ */
+ public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) {
+ if (user.isManagedProfile()) {
+ // We use predefined values for managed profiles
+ Bitmap b = BitmapFactory.decodeResource(context.getResources(),
+ com.android.internal.R.drawable.ic_corp_icon);
+ return CircleFramedDrawable.getInstance(context, b);
+ }
+ if (user.iconPath != null) {
+ Bitmap icon = um.getUserIcon(user.id);
+ if (icon != null) {
+ return CircleFramedDrawable.getInstance(context, icon);
+ }
+ }
+ return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap(
+ UserIcons.getDefaultUserIcon(user.id, /* light= */ false)));
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java
new file mode 100644
index 0000000..278b57d
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2013 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.settingslib.drawable;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+
+import com.android.settingslib.R;
+
+/**
+ * Converts the user avatar icon to a circularly clipped one.
+ * TODO: Move this to an internal framework class and share with the one in Keyguard.
+ */
+public class CircleFramedDrawable extends Drawable {
+
+ private final Bitmap mBitmap;
+ private final int mSize;
+ private final Paint mPaint;
+
+ private float mScale;
+ private Rect mSrcRect;
+ private RectF mDstRect;
+
+ public static CircleFramedDrawable getInstance(Context context, Bitmap icon) {
+ Resources res = context.getResources();
+ float iconSize = res.getDimension(R.dimen.circle_avatar_size);
+
+ CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
+ return instance;
+ }
+
+ public CircleFramedDrawable(Bitmap icon, int size) {
+ super();
+ mSize = size;
+
+ mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(mBitmap);
+
+ final int width = icon.getWidth();
+ final int height = icon.getHeight();
+ final int square = Math.min(width, height);
+
+ final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, square, square);
+ final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
+
+ final Path fillPath = new Path();
+ fillPath.addArc(circleRect, 0f, 360f);
+
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+
+ // opaque circle matte
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setColor(Color.BLACK);
+ mPaint.setStyle(Paint.Style.FILL);
+ canvas.drawPath(fillPath, mPaint);
+
+ // mask in the icon where the bitmap is opaque
+ mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+ canvas.drawBitmap(icon, cropRect, circleRect, mPaint);
+
+ // prepare paint for frame drawing
+ mPaint.setXfermode(null);
+
+ mScale = 1f;
+
+ mSrcRect = new Rect(0, 0, mSize, mSize);
+ mDstRect = new RectF(0, 0, mSize, mSize);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final float inside = mScale * mSize;
+ final float pad = (mSize - inside) / 2f;
+
+ mDstRect.set(pad, pad, mSize - pad, mSize - pad);
+ canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
+ }
+
+ public void setScale(float scale) {
+ mScale = scale;
+ }
+
+ public float getScale() {
+ return mScale;
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mSize;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mSize;
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
new file mode 100644
index 0000000..572bae1
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 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.settingslib.net;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStats;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+public class SummaryForAllUidLoader extends AsyncTaskLoader<NetworkStats> {
+ private static final String KEY_TEMPLATE = "template";
+ private static final String KEY_START = "start";
+ private static final String KEY_END = "end";
+
+ private final INetworkStatsSession mSession;
+ private final Bundle mArgs;
+
+ public static Bundle buildArgs(NetworkTemplate template, long start, long end) {
+ final Bundle args = new Bundle();
+ args.putParcelable(KEY_TEMPLATE, template);
+ args.putLong(KEY_START, start);
+ args.putLong(KEY_END, end);
+ return args;
+ }
+
+ public SummaryForAllUidLoader(Context context, INetworkStatsSession session, Bundle args) {
+ super(context);
+ mSession = session;
+ mArgs = args;
+ }
+
+ @Override
+ protected void onStartLoading() {
+ super.onStartLoading();
+ forceLoad();
+ }
+
+ @Override
+ public NetworkStats loadInBackground() {
+ final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
+ final long start = mArgs.getLong(KEY_START);
+ final long end = mArgs.getLong(KEY_END);
+
+ try {
+ return mSession.getSummaryForAllUid(template, start, end, false);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ @Override
+ protected void onStopLoading() {
+ super.onStopLoading();
+ cancelLoad();
+ }
+
+ @Override
+ protected void onReset() {
+ super.onReset();
+ cancelLoad();
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java
new file mode 100644
index 0000000..5e42281
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 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.settingslib.net;
+
+import android.graphics.drawable.Drawable;
+
+public class UidDetail {
+ public CharSequence label;
+ public CharSequence contentDescription;
+ public CharSequence[] detailLabels;
+ public CharSequence[] detailContentDescriptions;
+ public Drawable icon;
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
new file mode 100644
index 0000000..224b967
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2011 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.settingslib.net;
+
+import android.app.AppGlobals;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.net.TrafficStats;
+import android.os.UserManager;
+import android.os.UserHandle;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.settingslib.R;
+import com.android.settingslib.Utils;
+
+/**
+ * Return details about a specific UID, handling special cases like
+ * {@link TrafficStats#UID_TETHERING} and {@link UserInfo}.
+ */
+public class UidDetailProvider {
+ private static final String TAG = "DataUsage";
+ private final Context mContext;
+ private final SparseArray<UidDetail> mUidDetailCache;
+
+ public static final int OTHER_USER_RANGE_START = -2000;
+
+ public static int buildKeyForUser(int userHandle) {
+ return OTHER_USER_RANGE_START - userHandle;
+ }
+
+ public static boolean isKeyForUser(int key) {
+ return key <= OTHER_USER_RANGE_START;
+ }
+
+ public static int getUserIdForKey(int key) {
+ return OTHER_USER_RANGE_START - key;
+ }
+
+ public UidDetailProvider(Context context) {
+ mContext = context.getApplicationContext();
+ mUidDetailCache = new SparseArray<UidDetail>();
+ }
+
+ public void clearCache() {
+ synchronized (mUidDetailCache) {
+ mUidDetailCache.clear();
+ }
+ }
+
+ /**
+ * Resolve best descriptive label for the given UID.
+ */
+ public UidDetail getUidDetail(int uid, boolean blocking) {
+ UidDetail detail;
+
+ synchronized (mUidDetailCache) {
+ detail = mUidDetailCache.get(uid);
+ }
+
+ if (detail != null) {
+ return detail;
+ } else if (!blocking) {
+ return null;
+ }
+
+ detail = buildUidDetail(uid);
+
+ synchronized (mUidDetailCache) {
+ mUidDetailCache.put(uid, detail);
+ }
+
+ return detail;
+ }
+
+ /**
+ * Build {@link UidDetail} object, blocking until all {@link Drawable}
+ * lookup is finished.
+ */
+ private UidDetail buildUidDetail(int uid) {
+ final Resources res = mContext.getResources();
+ final PackageManager pm = mContext.getPackageManager();
+
+ final UidDetail detail = new UidDetail();
+ detail.label = pm.getNameForUid(uid);
+ detail.icon = pm.getDefaultActivityIcon();
+
+ // handle special case labels
+ switch (uid) {
+ case android.os.Process.SYSTEM_UID:
+ detail.label = res.getString(R.string.process_kernel_label);
+ detail.icon = pm.getDefaultActivityIcon();
+ return detail;
+ case TrafficStats.UID_REMOVED:
+ detail.label = res.getString(UserManager.supportsMultipleUsers()
+ ? R.string.data_usage_uninstalled_apps_users
+ : R.string.data_usage_uninstalled_apps);
+ detail.icon = pm.getDefaultActivityIcon();
+ return detail;
+ case TrafficStats.UID_TETHERING:
+ final ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ detail.label = res.getString(Utils.getTetheringLabel(cm));
+ detail.icon = pm.getDefaultActivityIcon();
+ return detail;
+ }
+
+ final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+
+ // Handle keys that are actually user handles
+ if (isKeyForUser(uid)) {
+ final int userHandle = getUserIdForKey(uid);
+ final UserInfo info = um.getUserInfo(userHandle);
+ if (info != null) {
+ detail.label = Utils.getUserLabel(mContext, info);
+ detail.icon = Utils.getUserIcon(mContext, um, info);
+ return detail;
+ }
+ }
+
+ // otherwise fall back to using packagemanager labels
+ final String[] packageNames = pm.getPackagesForUid(uid);
+ final int length = packageNames != null ? packageNames.length : 0;
+ try {
+ final int userId = UserHandle.getUserId(uid);
+ UserHandle userHandle = new UserHandle(userId);
+ IPackageManager ipm = AppGlobals.getPackageManager();
+ if (length == 1) {
+ final ApplicationInfo info = ipm.getApplicationInfo(packageNames[0],
+ 0 /* no flags */, userId);
+ if (info != null) {
+ detail.label = info.loadLabel(pm).toString();
+ detail.icon = um.getBadgedIconForUser(info.loadIcon(pm),
+ new UserHandle(userId));
+ }
+ } else if (length > 1) {
+ detail.detailLabels = new CharSequence[length];
+ detail.detailContentDescriptions = new CharSequence[length];
+ for (int i = 0; i < length; i++) {
+ final String packageName = packageNames[i];
+ final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
+ final ApplicationInfo appInfo = ipm.getApplicationInfo(packageName,
+ 0 /* no flags */, userId);
+
+ if (appInfo != null) {
+ detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
+ detail.detailContentDescriptions[i] = um.getBadgedLabelForUser(
+ detail.detailLabels[i], userHandle);
+ if (packageInfo.sharedUserLabel != 0) {
+ detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
+ packageInfo.applicationInfo).toString();
+ detail.icon = um.getBadgedIconForUser(appInfo.loadIcon(pm), userHandle);
+ }
+ }
+ }
+ }
+ detail.contentDescription = um.getBadgedLabelForUser(detail.label, userHandle);
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Error while building UI detail for uid "+uid, e);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error while building UI detail for uid "+uid, e);
+ }
+
+ if (TextUtils.isEmpty(detail.label)) {
+ detail.label = Integer.toString(uid);
+ }
+
+ return detail;
+ }
+}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 345f682..efacd2c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -104,6 +104,7 @@
<uses-permission android:name="android.permission.REGISTER_CALL_PROVIDER" />
<uses-permission android:name="android.permission.REGISTER_CONNECTION_MANAGER" />
<uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION" />
+ <uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
<application android:label="@string/app_label">
<provider
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 51fea2a..314b3c4 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -3,13 +3,15 @@
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-proto-files-under,src) \
src/com/android/systemui/EventLogTags.logtags
LOCAL_STATIC_JAVA_LIBRARIES := Keyguard
LOCAL_JAVA_LIBRARIES := telephony-common
LOCAL_PACKAGE_NAME := SystemUI
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 8ab53b8..e4fc075 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -168,14 +168,14 @@
android:permission="android.permission.BIND_WALLPAPER"
android:exported="true" />
- <receiver android:name=".BootReceiver" androidprv:primaryUserOnly="true">
+ <receiver android:name=".BootReceiver" androidprv:systemUserOnly="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".qs.tiles.HotspotTile$APChangedReceiver"
- androidprv:primaryUserOnly="true">
+ androidprv:systemUserOnly="true">
<intent-filter>
<action android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
</intent-filter>
diff --git a/packages/SystemUI/res/anim/navbar_fade_in.xml b/packages/SystemUI/res/anim/navbar_fade_in.xml
index e3429e6..7051730 100644
--- a/packages/SystemUI/res/anim/navbar_fade_in.xml
+++ b/packages/SystemUI/res/anim/navbar_fade_in.xml
@@ -19,4 +19,5 @@
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:interpolator="@android:interpolator/linear_out_slow_in"
+ android:startDelay="32"
android:duration="200"/>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index ffdcd0e..9294a16 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"MELD GEBRUIKER AF"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Voeg nuwe gebruiker by?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Wanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul spasie opstel.\n\nEnige gebruiker kan programme vir al die ander gebruikers opdateer."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Verwyder gebruiker?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Alle programme en data van hierdie gebruiker sal uitgevee word."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Verwyder"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Batteryspaarder is aan"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Verminder werkverrigting en agtergronddata"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Skakel batterybespaarder af"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Verwyder uit Instellings"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Verwyder Stelsel-UI-ontvanger uit Instellings en staak die gebruik van al sy kenmerke?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Program is nie op jou toestel geïnstalleer nie"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Wys horlosiesekondes"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Wys horlosiesekondes op die statusbalk. Sal batterylewe dalk beïnvloed."</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 87df43b..13f768d 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ተጠቃሚን አስወጣ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"አዲስ ተጠቃሚ ይታከል?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"እርስዎ አንድ አዲስ ተጠቃሚ ሲያክሉ ያ ሰው የራሱ ቦታ ማዘጋጀት አለበት።\n\nማንኛውም ተጠቃሚ መተግበሪያዎችን ለሌሎች ተጠቃሚዎች ሁሉ ሊያዘምን ይችላል።"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"ተጠቃሚ ይወገድ?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"ሁሉም የዚህ ተጠቃሚ መተግበሪያዎች እና ውሂብ ይሰረዛሉ።"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"አስወግድ"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"የባትሪ ኃይል ቆጣቢ በርቷል"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"አፈጻጸምን እና የጀርባ ውሂብ ይቀንሳል"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ባትሪ ቆጣቢን አጥፋ"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"ከቅንብሮች አስወግድ"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"ከቅንብሮች ላይ የስርዓት በይነገጽ መቃኛ ተወግዶ ሁሉም ባህሪዎቹን መጠቀም ይቁም?"</string>
<string name="activity_not_found" msgid="348423244327799974">"መተግበሪያ በእርስዎ መሣሪያ ላይ አልተጫነም"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"የሰዓት ሰከንዶችን አሳይ"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"የሰዓት ሰከንዶችን በሁኔታ አሞሌ ውስጥ አሳይ። በባትሪ ዕድሜ ላይ ተጽዕኖ ሊኖርው ይችል ይሆናል።"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1778fad..6889a43 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -353,6 +353,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"خروج المستخدم"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"هل تريد إضافة مستخدم جديد؟"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"عند إضافة مستخدم جديد، يلزمه إعداد مساحته.\n\nعلمًا بأنه يُمكن لأي مستخدم تحديث التطبيقات لجميع المستخدمين الآخرين."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"هل تريد إزالة المستخدم؟"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"سيتم حذف جميع تطبيقات وبيانات هذا المستخدم."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"إزالة"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"وضع توفير الطاقة قيد التشغيل"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"لخفض مستوى الأداء وبيانات الخلفية"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"إيقاف توفير شحن البطارية"</string>
@@ -434,4 +437,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"إزالة من الإعدادات"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"هل تريد إزالة أداة ضبط واجهة مستخدم النظام من الإعدادات وإيقاف استخدام كل ميزاتها؟"</string>
<string name="activity_not_found" msgid="348423244327799974">"التطبيق غير مثبّت على جهازك"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"عرض ثواني الساعة"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"عرض ثواني الساعة في شريط الحالة. قد يؤثر ذلك في عمر البطارية."</string>
</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 5a43bc3..51513bd 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"İSTİFADƏÇİ ÇIXIŞI"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Yeni istifadəçi əlavə edilsin?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Yeni istifadəçi əlavə etdiyiniz zaman həmin şəxs öz yerini quraşdırmalıdır. \n\n İstənilən istifadəçi bütün digər istifadəçilərdən olan tətbiqləri güncəlləşdirə bilər."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"İstifadəçi silinsin?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Bu istifadəçinin bütün tətbiqləri və datası silinəcək."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Silin"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Enerji qənaəti aktivdir"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Performansı azaldır və arxa fon datasını məhdudlaşdırır"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Enerjiyə qənaət rejimini deaktiv edin"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Ayarlardan Silin"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"System UI Tuner Ayarlardan silinsin və onun bütün funksiyalarından istifadə dayandırılsın?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Tətbiq cihazınızda quraşdırılmayıb"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Saatın saniyəsini göstərin"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Saatın saniyəsini status panelində göstərin. Batareyaya təsir edə bilər."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 2b8660e..014d802 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ИЗЛИЗАНЕ НА ПОТРЕБИТЕЛЯ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Да се добави ли нов потреб.?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Когато добавите нов потребител, той трябва да настрои работното си пространство.\n\nВсеки потребител може да актуализира приложенията за всички останали потребители."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Да се премахне ли потребителят?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Всички приложения и данни на този потребител ще бъдат изтрити."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Премахване"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Режимът за запазване на батерията е включен"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Намалява ефективността и данните на заден план"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Изключване на режима за запазване на батерията"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Премахване от „Настройки“"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Да се премахне ли от „Настройки“ тунерът на системния потребителски интерфейс и да се спре ли използването на всичките му функции?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Приложението не е инсталирано на устройството ви"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Показване на секундите на часовника"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Показване на секундите на часовника в лентата на състоянието. Може да се отрази на живота на батерията."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 4a0a46c..0860019 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ব্যবহারকারীকে লগ-আউট করুন"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"নতুন ব্যবহারকারীকে যোগ করবেন?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"আপনি একজন নতুন ব্যবহারকারী যোগ করলে তাকে তার জায়গা সেট আপ করে নিতে হবে৷\n\nযেকোনো ব্যবহারকারী অন্য সব ব্যবহারকারীর জন্য অ্যাপ্লিকেশান আপডেট করতে পারবেন৷"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"ব্যবহারকারী সরাবেন?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"এই ব্যবহারকারীর সমস্ত অ্যাপ্লিকেশান ও ডেটা মুছে ফেলা হবে।"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"সরান"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"ব্যাটারি সেভার চালু রয়েছে"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"কার্য-সম্পাদনা ও পশ্চাদপট ডেটাকে কমিয়ে দেয়"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ব্যাটারি সঞ্চয়কারী বন্ধ করুন"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"সেটিংস থেকে সরান"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"সেটিংস থেকে সিস্টেম UI টিউনার সরাতে এবং এটির সমস্ত বৈশিষ্ট্য ব্যবহার করা বন্ধ করতে চান?"</string>
<string name="activity_not_found" msgid="348423244327799974">"আপনার ডিভাইসে অ্যাপ্লিকেশান ইনস্টল করা নেই"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"ঘড়ির সেকেন্ড দেখায়"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"স্থিতি দন্ডে ঘড়ির সেকেন্ড দেখায়৷ ব্যাটারি লাইফকে প্রভাবিত করতে পারে৷"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 2b7171a..7dd11eb 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"TANCA LA SESSIÓ DE L\'USUARI"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Vols afegir un usuari nou?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Quan s\'afegeix un usuari nou, aquest usuari ha de configurar-se l\'espai.\n\nQualsevol usuari pot actualitzar les aplicacions de la resta d\'usuaris."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Vols suprimir l\'usuari?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Totes les aplicacions i les dades d\'aquest usuari se suprimiran."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Suprimeix"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Estalvi de bateria activada"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Redueix el rendiment i l\'ús de les dades en segon pla."</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desactiva l\'estalvi de bateria"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Treu de Configuració"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vols treure el Configurador de la UI del sistema de Configuració i deixar d\'utilitzar-ne totes les funcions?"</string>
<string name="activity_not_found" msgid="348423244327799974">"L\'aplicació no està instal·lada al dispositiu"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Mostra els segons del rellotge"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra els segons del rellotge a la barra d\'estat. Això pot afectar la durada de la bateria."</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index ce1749d..4d96a01 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -353,6 +353,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ODHLÁSIT UŽIVATELE"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Přidat nového uživatele?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Když přidáte nového uživatele, musí si nastavit vlastní prostor.\n\nJakýkoli uživatel může aktualizovat aplikace všech ostatních uživatelů."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Odstranit uživatele?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Veškeré aplikace a data tohoto uživatele budou smazána."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Odstranit"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Režim Úspora baterie je zapnutý."</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Omezuje výkon a data na pozadí"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Vypnout úsporu baterie"</string>
@@ -434,4 +437,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Odstranit z Nastavení"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Chcete nástroj na ladění uživatelského rozhraní systému odstranit z Nastavení a přestat používat všechny jeho funkce?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Aplikace není v zařízení nainstalována."</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Zobrazit sekundovou ručičku"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Na stavovém řádku se bude zobrazovat sekundová ručička. Může být ovlivněna výdrž baterie."</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 6871c46..7f005a3 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"LOG BRUGEREN UD"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Vil du tilføje den nye bruger?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Når du tilføjer en ny bruger, skal personen konfigurere sit område.\n\nEnhver bruger kan opdatere apps for alle andre brugere."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Vil du fjerne brugeren?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Alle apps og data for denne bruger slettes."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Fjern"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Batterisparefunktion er slået til"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reducerer ydeevne og baggrundsdata"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Deaktiver batterisparefunktion"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Fjern fra Indstillinger"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vil du fjerne System UI Tuner fra Indstillinger og stoppe med at bruge alle dens funktioner?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Applikationen er ikke installeret på din enhed."</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Vis sekunder"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statuslinjen. Dette kan påvirke batteriets levetid."</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a9d2fd4..36f3c98 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"Nutzer abmelden"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Neuen Nutzer hinzufügen?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Wenn Sie einen neuen Nutzer hinzufügen, muss dieser seinen Bereich einrichten.\n\nJeder Nutzer kann Apps für alle anderen Nutzer aktualisieren."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Nutzer entfernen?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Alle Apps und Daten dieses Nutzers werden gelöscht."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Entfernen"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Energiesparmodus ist aktiviert"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduzierung der Leistung und Hintergrunddaten"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Energiesparmodus deaktivieren"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Aus \"Einstellungen\" entfernen"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"System UI Tuner aus \"Einstellungen\" entfernen und die Verwendung von allen zugehörigen Funktionen beenden?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Die App ist nicht auf Ihrem Gerät installiert."</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Uhrsekunden anzeigen"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Uhrsekunden in der Statusleiste anzeigen. Kann sich auf die Akkulaufzeit auswirken."</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 82ec24f..8e73b21 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ΑΠΟΣΥΝΔΕΣΗ ΧΡΗΣΤΗ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Προσθήκη νέου χρήστη;"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Κατά την προσθήκη ενός νέου χρήστη, αυτός θα πρέπει να ρυθμίσει το χώρο του.\n\nΟποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Κατάργηση χρήστη;"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Όλες οι εφαρμογές και τα δεδομένα αυτού του χρήστη θα διαγραφούν."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Κατάργηση"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Η Εξοικονόμηση μπαταρίας είναι ενεργή"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Μειώνει την απόδοση και τα δεδομένα παρασκηνίου"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Απενερ. εξοικ/σης μπαταρίας"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Κατάργηση από τις Ρυθμίσεις"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Κατάργηση System UI Tuner από τις Ρυθμίσεις και διακοπή χρήσης όλων των λειτουργιών του;"</string>
<string name="activity_not_found" msgid="348423244327799974">"Η εφαρμογή δεν έχει εγκατασταθεί στη συσκευή σας"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Εμφάνιση δευτερολέπτων ρολογιού"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Εμφάνιση δευτερολέπτων ρολογιού στη γραμμή κατάστασης. Ενδέχεται να επηρεάσει τη διάρκεια ζωής της μπαταρίας."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index b416ab3..0b49955 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"LOGOUT USER"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Add new user?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Remove user?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"All apps and data of this user will be deleted."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Remove"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Battery saver is on"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduces performance and background data"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Turn off battery saver"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Remove from settings"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Remove System UI Tuner from Settings and stop using all of its features?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Application is not installed on your device"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Show clock seconds"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index b416ab3..0b49955 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"LOGOUT USER"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Add new user?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Remove user?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"All apps and data of this user will be deleted."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Remove"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Battery saver is on"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduces performance and background data"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Turn off battery saver"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Remove from settings"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Remove System UI Tuner from Settings and stop using all of its features?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Application is not installed on your device"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Show clock seconds"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index b416ab3..0b49955 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"LOGOUT USER"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Add new user?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Remove user?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"All apps and data of this user will be deleted."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Remove"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Battery saver is on"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduces performance and background data"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Turn off battery saver"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Remove from settings"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Remove System UI Tuner from Settings and stop using all of its features?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Application is not installed on your device"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Show clock seconds"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 80d2916..c4dca9c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"SALIR DE SESIÓN DEL USUARIO"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"¿Agregar usuario nuevo?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Cuando agregas un nuevo usuario, esa persona debe configurar su espacio.\n\nCualquier usuario puede actualizar aplicaciones para todos los usuarios."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"¿Confirmas que quieres quitar el usuario?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Se borrarán todas las aplicaciones y los datos de este usuario."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Quitar"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Ahorro de batería activado"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduce el rendimiento y el uso de datos en segundo plano."</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desactivar el ahorro de batería"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Quitar de Configuración"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"¿Quieres quitar el sintonizador de IU del sistema de Configuración y dejar de utilizar todas sus funciones?"</string>
<string name="activity_not_found" msgid="348423244327799974">"La aplicación no está instalada en el dispositivo"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Mostrar los segundos del reloj"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar la duración de la batería."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index b44a1f6..e316a94 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"SALIR DE USUARIO"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"¿Añadir nuevo usuario?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Al añadir un usuario nuevo, este debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de usuarios."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"¿Quitar usuario?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Se eliminarán todas las aplicaciones y todos los datos de este usuario."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Quitar"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Ahorro de batería activado"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduce el rendimiento y el envío de datos en segundo plano"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desactivar ahorro de batería"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Eliminar de Ajustes"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"¿Eliminar el configurador de IU del sistema de Ajustes y dejar de utilizar sus funciones?"</string>
<string name="activity_not_found" msgid="348423244327799974">"La aplicación no está instalada en tu dispositivo"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Mostrar los segundos del reloj"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar a la duración de la batería."</string>
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 01dfe89..a151bce 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"LOGI KASUTAJA VÄLJA"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Kas lisada uus kasutaja?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Kui lisate uue kasutaja, siis peab ta seadistama oma ruumi.\n\nIga kasutaja saab värskendada rakendusi kõigi kasutajate jaoks."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Kas eemaldada kasutaja?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Kasutaja kõik rakendused ja andmed kustutatakse."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Eemalda"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Akusäästja on sisse lülitatud"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Vähendab jõudlust ja taustaandmeid"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Akusäästja väljalülitamine"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Eemalda seadetest"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Kas eemaldada seadetest süsteemi kasutajaliidese tuuner ja lõpetada kõikide selle funktsioonide kasutamine?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Rakendust pole teie seadmesse installitud"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Kella sekundite kuvamine"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Olekuribal kella sekundite kuvamine. See võib mõjutada aku kasutusaega."</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 7052b80..37cdee7 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"AMAITU ERABILTZAILEAREN SAIOA"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Beste erabiltzaile bat gehitu?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Erabiltzaile bat gehitzen duzunean, horrek bere eremua konfiguratu beharko du.\n\nEdozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Erabiltzailea kendu nahi duzu?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Erabiltzailearen aplikazio eta datu guztiak ezabatuko dira."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Kendu"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Bateria aurrezlea aktibatuta dago"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Errendimendua eta atzeko planoko datuak murrizten ditu"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desaktibatu bateria aurrezteko aukera"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Kendu Ezarpenak ataletik"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Sistemako erabiltzaile-interfazearen konfiguratzailea ezarpenetatik kendu nahi duzu, eta haren eginbide guztiak erabiltzeari utzi nahi diozu?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Aplikazioa ez dago gailuan instalatuta"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Erakutsi erlojuko segundoak"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Erakutsi erlojuko segundoak egoera-barran. Baliteke bateria gehiago erabiltzea."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index d4a1fa2..80d0918 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"خروج کاربر از سیستم"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"کاربر جدیدی اضافه میکنید؟"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"وقتی کاربر جدیدی را اضافه میکنید آن فرد باید فضای خودش را تنظیم کند.\n\nهر کاربری میتواند برنامهها را برای همه کاربران دیگر بهروزرسانی کند."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"کاربر حذف شود؟"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"همه برنامهها و دادههای این کاربر حذف میشود."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"حذف"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"ذخیره کننده باتری روشن است."</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"عملکرد و اطلاعات پسزمینه را کاهش میدهد"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"خاموش کردن ذخیرهکننده باتری"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"حذف از تنظیمات"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"«تنظیمکننده واسط کاربری سیستم» از تنظیمات حذف شود و همه ویژگیهای آن متوقف شوند؟"</string>
<string name="activity_not_found" msgid="348423244327799974">"برنامه در دستگاه شما نصب نیست"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"نمایش ثانیههای ساعت"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"ثانیههای ساعت را در نوار وضعیت نشان میدهد. ممکن است بر ماندگاری باتری تأثیر بگذارد."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c906e8a..b86247a 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"KIRJAA KÄYTTÄJÄ ULOS"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Lisätäänkö uusi käyttäjä?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Kun lisäät uuden käyttäjän, hänen tulee määrittää oman tilansa asetukset.\n\nKaikki käyttäjät voivat päivittää sovelluksia muille käyttäjille."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Poistetaanko käyttäjä?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Kaikki käyttäjän tiedot ja sovellukset poistetaan."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Poista"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Virransäästö on käytössä"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Rajoittaa suorituskykyä ja taustatiedonsiirtoa"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Poista virransäästö käytöstä"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Poista Asetuksista"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Haluatko poistaa System UI Tunerin Asetuksista ja lopettaa sen ominaisuuksien käytön?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Sovellusta ei ole asennettu laitteellesi."</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Näytä sekunnit kellossa"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Näytä sekunnit tilapalkin kellossa. Tämä voi vaikuttaa akun kestoon."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index eceee64..f99447c 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"DÉCONNECTER L\'UTILISATEUR"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Ajouter un utilisateur?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.\n\nN\'importe quel utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Supprimer l\'utilisateur?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Toutes les applications et les données de cet utilisateur seront supprimées."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Supprimer"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"La fonction Économie d\'énergie est activée"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Réduire les performances et de fond"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Désactiver l\'économiseur d\'énergie"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Supprimer des paramètres"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Supprimer « System UI Tuner » des paramètres et arrêter d\'utiliser toutes ses fonctionnalités?"</string>
<string name="activity_not_found" msgid="348423244327799974">"L\'application n\'est pas installée sur votre appareil"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Afficher les secondes sur l\'horloge"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes sur l\'horloge dans la barre d\'état. Cela peut réduire l\'autonomie de la pile."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index f2bc9d0..aada1eb 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"DÉCONNECTER L\'UTILISATEUR"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Ajouter un utilisateur ?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.\n\nN\'importe quel utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Supprimer l\'utilisateur ?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Toutes les applications et les données de cet utilisateur seront supprimées."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Supprimer"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"L\'économiseur de batterie est activé"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Limite les performances et les données en arrière-plan."</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Désactiver l\'économiseur de batterie"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Supprimer l\'outil des paramètres"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Supprimer System UI Tuner des paramètres et arrêter d\'utiliser toutes ses fonctionnalités ?"</string>
<string name="activity_not_found" msgid="348423244327799974">"L\'application n\'est pas installée sur votre appareil."</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Afficher les secondes sur l\'horloge"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes dans la barre d\'état. Cela risque de réduire l\'autonomie de la batterie."</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 1f80aa7..951809f 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"PECHAR SESIÓN DO USUARIO"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Engadir un usuario novo?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Cando engadas un usuario novo, este deberá configurar o seu espazo\n\nCalquera usuario pode actualizar as aplicacións para todos os demais usuarios."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Queres eliminar o usuario?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Eliminaranse todas as aplicacións e os datos deste usuario."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Eliminar"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"O aforro de batería está activado"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduce o rendemento e os datos en segundo plano"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desactivar o aforro de batería"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Eliminar da Configuración"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Queres eliminar o configurador da IU do sistema da Configuración e deixar de usar todas as súas funcións?"</string>
<string name="activity_not_found" msgid="348423244327799974">"A aplicación non está instalada no teu dispositivo"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do reloxo"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra os segundos do reloxo na barra de estado. Pode influír na duración da batería."</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 39782a2..02e4e52 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"વપરાશકર્તાને લૉગઆઉટ કરો"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"નવા વપરાશકર્તાને ઉમેરીએ?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"જ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિને તેમનું સ્થાન સેટ કરવાની જરૂર પડે છે.\n\nકોઈપણ વપરાશકર્તા બધા અન્ય વપરાશકર્તાઓ માટે એપ્લિકેશન્સને અપડેટ કરી શકે છે."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"વપરાશકર્તાને દૂર કરીએ?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"આ વપરાશકર્તાની તમામ એપ્લિકેશન્સ અને ડેટા કાઢી નાખવામાં આવશે."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"દૂર કરો"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"બેટરી સેવર ચાલુ છે"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"પ્રદર્શન અને પૃષ્ઠભૂમિ ડેટા ઘટાડે છે"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"બૅટરી સેવર બંધ કરો"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"સેટિંગ્સમાંથી દૂર કરો"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"સેટિંગ્સમાંથી સિસ્ટમ UI ટ્યૂનર દૂર કરી અને તેની તમામ સુવિધાઓનો ઉપયોગ કરવાનું બંધ કરીએ?"</string>
<string name="activity_not_found" msgid="348423244327799974">"તમારા ઉપકરણ પર એપ્લિકેશન ઇન્સ્ટોલ થયેલ નથી"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"ઘડિયાળ સેકન્ડ બતાવો"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"ઘડિયાળ સેકન્ડ સ્થિતિ બારમાં બતાવો. બૅટરીની આવરદા પર અસર કરી શકે છે."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index e2ac2b8..3ed090c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"उपयोगकर्ता को प्रस्थान करवाएं"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"नया उपयोगकर्ता जोड़ें?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं तो उस व्यक्ति को अपना स्थान सेट करना होता है.\n\nकोई भी उपयोगकर्ता अन्य सभी उपयोगकर्ताओं के लिए ऐप्स अपडेट कर सकता है."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"उपयोगकर्ता निकालें?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"इस उपयोगकर्ता के सभी ऐप्स और डेटा को हटा दिया जाएगा."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"निकालें"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"बैटरी सेवर चालू है"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"निष्पादन और पृष्ठभूमि डेटा को कम करता है"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"बैटरी बचतकर्ता को बंद करें"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"सेटिंग से निकालें"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"सेटिंग से सिस्टम UI ट्यूनर निकालें और इसकी सभी सुविधाओं का उपयोग रोक दें?"</string>
<string name="activity_not_found" msgid="348423244327799974">"ऐप्लिकेशन आपके डिवाइस पर इंस्टॉल नहीं है"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"घड़ी के सेकंड दिखाएं"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"स्थिति बार में घड़ी के सेकंड दिखाएं. इससे बैटरी के जीवनकाल पर प्रभाव पड़ सकता है."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 27b2e9c..9698aba 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -350,6 +350,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ODJAVI KORISNIKA"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Dodati novog korisnika?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Kada dodate novog korisnika, ta osoba mora postaviti vlastiti prostor.\n\nBilo koji korisnik može ažurirati aplikacije za sve ostale korisnike."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Ukloniti korisnika?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Izbrisat će se sve aplikacije i podaci ovog korisnika."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Ukloni"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Štednja baterije je uključena"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Smanjuje količinu rada i pozadinske podatke"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Isključi uštedu baterije"</string>
@@ -431,4 +434,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Ukloni iz Postavki"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Želite li ukloniti Ugađanje korisničkog sučelja sustava iz Postavki i prestati upotrebljavati njegove značajke?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Aplikacija nije instalirana na vašem uređaju"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Prikaži sekunde na satu"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikazuju se sekunde na satu na traci statusa. Može utjecati na trajanje baterije."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 634bccc..37cb0a8 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"FELHASZNÁLÓ KIJELENTKEZÉSE"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Új felhasználó hozzáadása?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Ha új felhasználót ad hozzá, az illetőnek be kell állítania saját tárterületét.\n\nBármely felhasználó frissítheti az alkalmazásokat valamennyi felhasználó számára."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Törli a felhasználót?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"A felhasználóhoz tartozó minden adat és alkalmazás törölve lesz."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Eltávolítás"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Akkumulátorkímélő mód bekapcsolva"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Csökkenti a teljesítményt és a háttéradatok használatát"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Akkumulátorkímélő mód kikapcsolása"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Eltávolítás a Beállítások közül"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Eltávolítja a Kezelőfelület-hangolót a Beállításokból, és nem használja tovább egyik funkcióját sem?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Az alkalmazás nincs telepítve eszközén."</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Másodpercek megjelenítése az órán"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Másodpercek megjelenítése az állapotsor óráján. Ez hatással lehet az akkumulátor üzemidejére."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index b6d3f35..e31cf49 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ԸՆԹԱՑԻԿ ՕԳՏՎՈՂԻ ԴՈՒՐՍ ԳՐՈՒՄ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Ավելացնե՞լ նոր պրոֆիլ:"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Երբ նոր օգտվող եք ավելացնում, նա պետք է կարգավորի իր պրոֆիլը:\n\nՑանկացած օգտվող կարող է թարմացնել հավելվածները մյուս բոլոր հաշիվների համար:"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Հեռացնե՞լ օգտվողին:"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Այս օգտվողի բոլոր հավելվածներն ու տվյալները կջնջվեն:"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Հեռացնել"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Մարտկոցի տնտեսումը միացված է"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Նվազեցնում է ծանրաբեռնվածությունը և ֆոնային տվյալները"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Անջատել մարտկոցի տնտեսումը"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Հեռացնել կարգավորումներից"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Հեռացնե՞լ Համակարգի ՕՄ-ի կարգավորիչը կարգավորումներից և չօգտվել այլևս նրա գործառույթներից:"</string>
<string name="activity_not_found" msgid="348423244327799974">"Հավելվածը տեղադրված չէ սարքի վրա"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Ցույց տալ ժամացույցի վայրկյանները"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Ցույց տալ ժամացույցի վայրկյանները կարգավիճակի տողում: Կարող է ազդել մարտկոցի աշխատանքի ժամանակի վրա:"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 832dfcf..ad8141b 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"KELUARKAN PENGGUNA"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Tambahkan pengguna baru?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Saat Anda menambahkan pengguna baru, orang tersebut perlu menyiapkan ruangnya sendiri.\n\n1Pengguna mana pun dapat memperbarui aplikasi untuk semua pengguna lain."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Hapus pengguna?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Semua aplikasi dan data pengguna ini akan dihapus."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Hapus"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Penghemat baterai aktif"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Mengurangi kinerja dan data latar belakang"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Nonaktifkan penghemat baterai"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Hapus dari Setelan"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Hapus Penyetel Antarmuka Pengguna Sistem dari Setelan dan berhenti menggunakan semua fiturnya?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Aplikasi tidak dipasang di perangkat"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Tampilkan detik jam"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Tampilkan detik jam di bilah status. Dapat memengaruhi masa pakai baterai."</string>
</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 5636e66..02caf17 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"SKRÁ NOTANDA ÚT"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Bæta nýjum notanda við?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Þegar þú bætir nýjum notanda við þarf sá notandi að setja upp svæðið sitt.\n\nHvaða notandi sem er getur uppfært forrit fyrir alla aðra notendur."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Fjarlægja notandann?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Öllum forritum og gögnum þessa notanda verður eytt."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Fjarlægja"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Kveikt er á rafhlöðusparnaði"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Dregur úr afköstum og bakgrunnsgögnum"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Slökkva á rafhlöðusparnaði"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Fjarlægja úr stillingum"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Viltu fjarlægja fínstillingar kerfisviðmóts úr stillingum og hætta að nota eiginleika þeirra?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Forritið er ekki uppsett í tækinu."</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Sýna sekúndur á klukku"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Sýna sekúndur á klukku í stöðustikunni. Getur haft áhrif á endingu rafhlöðu."</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index a98597b..ab5d8beab 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"DISCONNETTI UTENTE"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Aggiungere un nuovo utente?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Il nuovo utente, una volta aggiunto, deve impostare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Rimuovere l\'utente?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Tutte le app e i dati di questo utente verranno eliminati."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Rimuovi"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Risparmio batteria attivo"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Riduce le prestazioni e i dati in background"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Disattiva risparmio energetico"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Rimuovi dalle impostazioni"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vuoi rimuovere il sintetizzatore interfaccia utente di sistema dalle impostazioni e smettere di utilizzare tutte le sue funzioni?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Applicazione non installata sul dispositivo"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Mostra i secondi nell\'orologio"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra i secondi nell\'orologio nella barra di stato. Ciò potrebbe ridurre la durata della carica della batteria."</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index bf8a41d..9dad8aa 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"נתק משתמש"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"האם להוסיף משתמש חדש?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"בעת הוספת משתמש חדש, על משתמש זה להגדיר את השטח שלו.\n\nכל משתמש יכול לעדכן אפליקציות עבור כל המשתמשים האחרים."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"האם להסיר את המשתמש?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"כל האפליקציות והנתונים של המשתמש הזה יימחקו."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"הסר"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"תכונת \'חיסכון בסוללה\' פועלת"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"מפחית את הביצועים ונתונים ברקע"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"כבה את החיסכון בסוללה"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"הסר מההגדרות"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"האם להסיר את System UI Tuner ולהפסיק להשתמש בכל התכונות שלו?"</string>
<string name="activity_not_found" msgid="348423244327799974">"האפליקציה אינה מותקנת במכשיר"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"הצג שניות בשעון"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"הצג שניות בשעון בשורת הסטטוס. פעולה זו עשויה להשפיע על אורך חיי הסוללה."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index bd14b33..9cb2fc8 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -88,7 +88,7 @@
<string name="accessibility_voice_assist_button" msgid="487611083884852965">"音声アシスト"</string>
<string name="accessibility_unlock_button" msgid="128158454631118828">"ロック解除"</string>
<string name="accessibility_unlock_button_fingerprint" msgid="8214125623493923751">"ロック解除ボタン、指紋を待っています"</string>
- <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"指紋を使用せずにロック解除"</string>
+ <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"指紋認証を使用せずにロック解除"</string>
<string name="unlock_label" msgid="8779712358041029439">"ロック解除"</string>
<string name="phone_label" msgid="2320074140205331708">"電話を起動"</string>
<string name="voice_assist_label" msgid="3956854378310019854">"音声アシストを開く"</string>
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ユーザーをログアウト"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"新しいユーザーを追加しますか?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"新しいユーザーを追加したら、そのユーザーは自分のスペースをセットアップする必要があります。\n\nすべてのユーザーは他のユーザーに代わってアプリを更新できます。"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"ユーザーを削除しますか?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"このユーザーのアプリとデータがすべて削除されます。"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"削除"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"バッテリーセーバーがON"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"パフォーマンスとバックグラウンドデータを制限します"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"バッテリーセーバーをOFFにします"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"設定から削除"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"設定からシステムUI調整ツールを削除して、全機能の使用を停止しますか?"</string>
<string name="activity_not_found" msgid="348423244327799974">"アプリが端末にインストールされていません"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"時計の秒を表示"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"ステータスバーに時計の秒を表示します。電池使用量に影響する可能性があります。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 6d567cc..a9728b2 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"მომხმარებლის გასვლა"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"დაემატოს ახალი მომხმარებელი?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"ახალი მომხმარებლის დამატებისას, ამ მომხმარებელს საკუთარი სივრცის შექმნა მოუწევს.\n\nნებისმიერ მომხმარებელს შეუძლია აპები ყველა სხვა მომხმარებლისათვის განაახლოს."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"გსურთ მომხმარებლის წაშლა?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"ამ მომხმარებლის ყველა აპი და მონაცემი წაიშლება."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"წაშლა"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"ბატარეის დამზოგი ჩართულია"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"ამცირებს წარმადობას და უკანა ფონის მონაცემებს"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ბატარეის დაზოგვის გამორთვა"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"პარამეტრებიდან წაშლა"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"გსურთ სისტემის UI ტუნერის პარამეტრებიდან წაშლა და მისი ყველა ფუნქციის გამოყენების შეწყვეტა?"</string>
<string name="activity_not_found" msgid="348423244327799974">"აპლიკაცია თქვენს მოწყობილობაზე დაყენებული არ არის"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"საათის წამების ჩვენება"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"საათის წამების ჩვენება სტატუსის ზოლში. შეიძლება გავლენა იქონიოს ბატარეაზე."</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 6903b19..1d61372 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ПАЙДАЛАНУШЫНЫ ШЫҒАРУ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Жаңа пайд-ны қосу керек пе?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Жаңа пайдаланушыны қосқанда сол адам өз кеңістігін реттеуі керек.\n\nКез келген пайдаланушы барлық басқа пайдаланушылар үшін қолданбаларды жаңарта алады."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Пайдаланушы жойылсын ба?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Осы пайдаланушының барлық қолданбалары мен деректері жойылады."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Жою"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Батарея үнемдегіш қосулы"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Өнімділікті және фондық деректерді азайтады"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Батарея үнемдегішті өшіру"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Параметрлерден жою"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Жүйелік пайдаланушылық интерфейс тюнерін \"Параметрлер\" тармағынан жойып, оның барлық мүмкіндіктерін пайдалануды тоқтату керек пе?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Қолданба құрылғыда орнатылмаған"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Сағат секундтарын көрсету"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Күйін көрсету жолағында сағат секундтарын көрсету. Батареяның қызмет көрсету мерзіміне әсер етуі мүмкін."</string>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index d24b070..c233f83 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ចុះឈ្មោះអ្នកប្រើចេញ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"បន្ថែមអ្នកប្រើថ្មី?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"ពេលអ្នកបន្ថែមអ្នកប្រើថ្មី អ្នកប្រើនោះត្រូវកំណត់ទំហំផ្ទាល់របស់គេ។\n\nអ្នកប្រើណាមួយក៏អាចធ្វើបច្ចុប្បន្នភាពកម្មវិធីសម្រាប់អ្នកប្រើផ្សេងបានដែរ។"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"យកអ្នកប្រើចេញ?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"កម្មវិធី និងទិន្នន័យទាំងអស់របស់អ្នកប្រើនេះនឹងត្រូវបានលុប។"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"យកចេញ"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"កម្មវិធីសន្សំថ្មគឺបើក"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"ការបន្ថយការប្រតិបត្តិ និងទិន្នន័យផ្ទៃខាងក្រោយ"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"បិទធាតុរក្សាថាមពលថ្ម"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"យកចេញពីការកំណត់"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"យកកម្មវិធីសម្រួល UI ប្រព័ន្ធចេញពីការកំណត់ ហើយឈប់ប្រើលក្ខណៈពិសេសរបស់វាទាំងអស់?"</string>
<string name="activity_not_found" msgid="348423244327799974">"កម្មវិធីមិនបានដំឡើងនៅលើឧបករណ៍របស់អ្នកទេ"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"បង្ហាញវិនាទី"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"បង្ហាញវិនាទីនៅលើរបារស្ថានភាពអាចនឹងប៉ះពាល់ដល់ថាមពលថ្ម។"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index baaba3c..d486e56 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ಬಳಕೆದಾರರನ್ನು ಲಾಗ್ಔಟ್ ಮಾಡಿ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸುವುದೇ?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"ನೀವು ಒಬ್ಬ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ಅವರ ಸ್ಥಳವನ್ನು ಸ್ಥಾಪಿಸಬೇಕಾಗುತ್ತದೆ.\n\nಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ನವೀಕರಿಸಬಹುದು."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕುವುದೇ?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"ಈ ಬಳಕೆದಾರರ ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುವುದು."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"ತೆಗೆದುಹಾಕಿ"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"ಬ್ಯಾಟರಿ ರಕ್ಷಕ ಆನ್ ಆಗಿದೆ"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"ಕಾರ್ಯಕ್ಷಮತೆ ಮತ್ತು ಹಿನ್ನೆಲೆ ಡೇಟಾವನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ಬ್ಯಾಟರಿ ಉಳಿತಾಯವನ್ನು ಆಫ್ ಮಾಡಿ"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"ಸೆಟ್ಟಿಂಗ್ಗಳಿಂದ ತೆಗೆದುಹಾಕಿ"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"ಸೆಟ್ಟಿಂಗ್ಗಳಿಂದ ಸಿಸ್ಟಮ್ UI ಟ್ಯೂನರ್ ತೆಗೆದುಹಾಕುವುದೇ ಮತ್ತು ಅದರ ಎಲ್ಲಾ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಬಳಸುವುದನ್ನು ನಿಲ್ಲಿಸುವುದೇ?"</string>
<string name="activity_not_found" msgid="348423244327799974">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"ಗಡಿಯಾರದ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಗಡಿಯಾರ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು. ಇದಕ್ಕೆ ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯು ಪರಿಣಾಮಬೀರಬಹುದು."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index e8a19c8..3505754 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"사용자 로그아웃"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"새 사용자를 추가할까요?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"추가된 새로운 사용자는 자신의 공간을 설정해야 합니다.\n\n모든 사용자는 다른 사용자들을 위하여 앱을 업데이트할 수 있습니다."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"사용자를 삭제할까요?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"이 사용자의 모든 앱과 데이터가 삭제됩니다."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"삭제"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"배터리 세이버 사용 중"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"성능 및 백그라운드 데이터를 줄입니다."</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"배터리 절약 기능 사용 중지"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"설정에서 삭제"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"시스템 UI 튜너를 설정에서 삭제하고 모든 관련 기능의 사용을 중지하시겠습니까?"</string>
<string name="activity_not_found" msgid="348423244327799974">"기기에 애플리케이션이 설치되어 있지 않습니다."</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"시계 초 단위 표시"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"상태 표시줄에 시계 초 단위를 표시합니다. 배터리 수명에 영향을 줄 수도 있습니다."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 5f88549..968a65a 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"КОЛДОНУУЧУНУ ТУТУМДАН ЧЫГАРУУ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Жаңы колдонуучу кошосузбу?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Жаңы колдонуучу кошулганда, ал өз мейкиндигин түзүп алышы керек.\n\nКолдонмолорду бир колдонуучу жаңыртканда, ал калган бардык колдонуучулар үчүн да жаңырат."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Колдонуучу алынып салынсынбы?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Бул колдонуучунун бардык колдонмолору жана дайындары жок кылынат."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Алып салуу"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Батареяны үнөмдөгүч күйгүзүлдү"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Иштин майнаптуулугун начарлатып, фондук дайындарды чектейт"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Батареянын кубатын үнөмдөгүчтү өчүрүп коюу"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Жөндөөлөрдөн алып салуу"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"System UI Tuner Жөндөөлөрдөн алынып салынып, анын бардык функциялары токтотулсунбу?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Колдонмо сиздин түзмөгүңүздө орнотулган эмес"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Сааттын секунддары көрсөтүлсүн"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Абал тилкесинен сааттын секунддары көрсөтүлсүн. Батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 4a4140d..f34c70e 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ເອົາຜູ້ໃຊ້ອອກຈາກລະບົບ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"ເພີ່ມຜູ່ໃຊ້ໃໝ່ບໍ?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"ເມື່ອທ່ານເພີ່ມຜູ່ໃຊ້ໃໝ່, ຜູ່ໃຊ້ນັ້ນຈະຕ້ອງຕັ້ງຄ່າພື້ນທີ່ບ່ອນຈັດເກັບຂໍ້ມູນຂອງລາວ.\n\nຜູ່ໃຊ້ທຸກຄົນສາມາດອັບເດດແອັບຯຂອງຜູ່ໃຊ້ຄົນອື່ນທັງໝົດໄດ້."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"ລຶບຜູ້ໃຊ້ອອກບໍ?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"ທຸກແອັບ ແລະ ຂໍ້ມູນຂອງຜູ້ໃຊ້ນີ້ຈະຖືກລຶບ."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"ເອົາອອກ"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"ເປີດໃຊ້ໂຕປະຢັດແບັດເຕີຣີແລ້ວ"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"ຫຼຸດປະສິທິພາບແລະການນຳໃຊ້ຂໍ້ມູນພື້ນຫຼັງ"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ປິດໂຕປະຢັດແບັດເຕີຣີ"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"ເອົາອອກຈາກການຕັ້ງຄ່າ"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"ເອົາ System UI Tuner ອອກຈາກການຕັ້ງຄ່າ ແລະຢຸດການໃຊ້ທຸກຄຸນສົມບັດໃຊ້ງານຂອງມັນ?"</string>
<string name="activity_not_found" msgid="348423244327799974">"ແອັບພລິເຄຊັນບໍ່ຖືກຕິດຕັ້ງຢູ່ໃນອຸປະກອນຂອງທ່ານ"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"ສະແດງວິນາທີໂມງ"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"ສະແດງວິນາທີໂມງຢູ່ໃນແຖບສະຖານະ. ອາດຈະມີຜົນກະທົບຕໍ່ອາຍຸແບັດເຕີຣີ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 39b48b1..cf70d6b 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ATJUNGTI NAUDOTOJĄ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Pridėti naują naudotoją?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Kai pridedate naują naudotoją, šis asmuo turi nustatyti savo erdvę.\n\nBet kuris naudotojas gali atnaujinti visų kitų naudotojų programas."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Pašalinti naudotoją?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Bus ištrinti visi šio naudotojo duomenys ir programos."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Pašalinti"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Akumuliatoriaus tausojimo priemonė įjungta"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Sumažinamas našumas ir foninių duomenų naudojimas"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Išjungti Akumuliatoriaus tausojimo priemonę"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Pašalinti iš nustatymų"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Ar norite pašalinti sistemos naudotojo sąsajos derinimo priemonę iš nustatymų ir nebenaudoti jokių jos funkcijų?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Programa neįdiegta įrenginyje"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Rodyti laikrodžio sekundes"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Rodyti laikrodžio sekundes būsenos juostoje. Tai gali paveikti akumuliatoriaus naudojimo laiką."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index df7a292..5e2db80 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -350,6 +350,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ATTEIKT LIETOTĀJU"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Vai pievienot jaunu lietotāju?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Kad pievienosiet jaunu lietotāju, viņam būs jāizveido savs profils.\n\nIkviens lietotājs var atjaunināt lietotnes citu lietotāju vietā."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Vai noņemt lietotāju?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Tiks dzēstas visas šī lietotāja lietotnes un dati."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Noņemt"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Ieslēgts akumulatora enerģijas taupīšanas režīms"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Samazina veiktspēju un fona datus"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Izslēgt akumulatora jaudas taupīšanu"</string>
@@ -431,4 +434,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Noņemt no iestatījumiem"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vai noņemt sistēmas saskarnes regulatoru no iestatījumiem un pārtraukt izmantot visas tā funkcijas?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Lietojumprogramma nav instalēta jūsu ierīcē."</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Rādīt pulksteņa sekundes"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Statusa joslā rādīt pulksteņa sekundes. Var ietekmēt akumulatora darbības laiku."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 5743762..fe781b6 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ОДЈАВИ ГО КОРИСНИКОТ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Да се додаде нов корисник?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Кога додавате нов корисник, тоа лице треба да го постави својот простор.\n\nСекој корисник може да ажурира апликации за сите други корисници."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Да се отстрани корисникот?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Сите апликации и податоци од овој корисник ќе се избришат."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Отстрани"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Штедачот на батерија е вклучен"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Ја намалува изведбата и податоците во заднина"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Исклучете го штедачот на батерија"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Отстрани од поставки"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Да се отстрани Адаптерот на УИ на системот од Поставки и да престанат да се користат сите негови функции?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Апликацијата не е инсталирана на уредот"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Прикажи ги секундите на часовникот"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Прикажи ги секундите на часовникот на статусната лента. Може да влијае на траењето на батеријата."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index b7fdeae..6e6fc55 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ഉപയോക്താവിനെ ലോഗൗട്ട് ചെയ്യുക"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"പുതിയ ഉപയോക്താവിനെ ചേർക്കണോ?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"നിങ്ങൾ ഒരു പുതിയ ഉപയോക്താവിനെ ചേർക്കുമ്പോൾ, ആ വ്യക്തിയ്ക്ക് അവരുടെ ഇടം സജ്ജീകരിക്കേണ്ടതുണ്ട്.\n\nമറ്റ് എല്ലാ ഉപയോക്താക്കൾക്കുമായി ഏതൊരു ഉപയോക്താവിനും അപ്ലിക്കേഷനുകൾ അപ്ഡേറ്റുചെയ്യാനാവും."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"ഉപയോക്താവിനെ ഇല്ലാതാക്കണോ?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"ഈ ഉപയോക്താവിന്റെ എല്ലാ ആപ്സും ഡാറ്റയും ഇല്ലാതാക്കും."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"നീക്കംചെയ്യുക"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"ബാറ്ററി സേവർ ഓണാണ്"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"പ്രവർത്തനവും പശ്ചാത്തല ഡാറ്റയും കുറയ്ക്കുന്നു"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ബാറ്ററി സേവർ ഓഫാക്കുക"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"ക്രമീകരണത്തിൽ നിന്ന് നീക്കംചെയ്യുക"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"ക്രമീകരണത്തിൽ നിന്ന് സിസ്റ്റം UI ട്യൂണർ നീക്കംചെയ്യുകയും അതിന്റെ ഫീച്ചറുകളെല്ലാം ഉപയോഗിക്കുന്നത് നിർത്തുകയും ചെയ്യണോ?"</string>
<string name="activity_not_found" msgid="348423244327799974">"നിങ്ങളുടെ ഉപകരണത്തിൽ അപ്ലിക്കേഷൻ ഇൻസ്റ്റാൾ ചെയ്തിട്ടില്ല"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുക"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"സ്റ്റാറ്റസ് ബാറിൽ ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുന്നത് ബാറ്ററിയുടെ ലൈഫിനെ ബാധിക്കാം."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 5d61c88..65250bb 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -347,6 +347,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ХЭРЭГЛЭГЧЭЭС ГАРАХ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Шинэ хэрэглэгч нэмэх үү?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Та шинэ хэрэглэгч нэмбэл, тухайн хүн өөрийн профайлыг тохируулах шаардлагатай.\n\nАль ч хэрэглэгч бүх хэрэглэгчийн апп-уудыг шинэчлэх боломжтой."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Хэрэглэгчийг устгах уу?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Энэ хэрэглэгчийн бүх апп болон мэдээлэл устах болно."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Арилгах"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Батерей хэмнэгч асаалттай"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Ажиллагаа болон далд датаг бууруулна"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Батерей хэмнэгчийг унтраах"</string>
@@ -428,4 +431,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Тохиргооноос устгах"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Системийн UI Тохируулагчийг тохиргооноос устгаж, үүнтэй холбоотой бүх тохиргоог ашиглахаа болих уу?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Апп-ыг таны төхөөрөмжид суулгаагүй байна"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Цагийн секундыг харуулах"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Статус талбарт цагийн секундыг харуулах. Энэ нь тэжээлийн цэнэгт нөлөөлж болно."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 8f43871..0f71b4b 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"वापरकर्त्यास लॉगआउट करा"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"नवीन वापरकर्ता जोडायचा?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"आपण एक नवीन वापरकर्ता जोडता तेव्हा, त्या व्यक्तीने त्यांचे स्थान सेट करणे आवश्यक असते.\n\nकोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अॅप्स अद्यतनित करू शकतो."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"वापरकर्त्यास काढायचे?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"या वापरकर्त्याचे सर्व अॅप्स आणि डेटा काढून टाकला जाईल."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"काढा"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"बॅटरी बचतकर्ता चालू आहे"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"कार्यप्रदर्शन आणि पार्श्वभूमी डेटा कमी करते"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"बॅटरी बचतकर्ता बंद करा"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"सेटिंग्ज मधून काढा"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"सेटिंग्ज मधून सिस्टीम UI ट्यूनर काढून त्याची सर्व वैशिष्ट्ये वापरणे थांबवायचे?"</string>
<string name="activity_not_found" msgid="348423244327799974">"अनुप्रयोग आपल्या डिव्हाइसवर स्थापित केलेला नाही"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"घड्याळ सेकंद दर्शवा"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"स्टेटस बारमध्ये घड्याळ सेकंद दर्शवा. कदाचित बॅटरी आयुष्य प्रभावित होऊ शकते."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 08a4dec..596275c 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"LOG KELUAR PENGGUNA"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Tambah pengguna baharu?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Apabila anda menambah pengguna baharu, orang itu perlu menyediakan ruang mereka.\n\nMana-mana pengguna boleh mengemas kini apl untuk semua pengguna lain."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Alih keluar pengguna?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Semua apl dan data pengguna ini akan dipadamkan."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Alih keluar"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Penjimat bateri dihidupkan"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Mengurangkan prestasi dan data latar belakang"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Matikan penjimat bateri"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Alih keluar daripada Tetapan"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Alih keluar Penala UI Sistem daripada Tetapan dan berhenti menggunakan semua cirinya?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Aplikasi tidak dipasang pada peranti anda"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Tunjukkan saat jam"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Tunjukkan saat jam dalam bar status. Mungkin menjejaskan hayat bateri."</string>
</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 4551f64..3147d0c 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"အသုံးပြုသူ ထွက်လိုက်ပါ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"အသုံးပြုသူ အသစ်ကို ထည့်ရမလား?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"သင်က အသုံးပြုသူ အသစ် တစ်ဦးကို ထည့်ပေးလိုက်လျှင်၊ ထိုသူသည် ၎င်း၏ နေရာကို သတ်မှတ်စီစဉ်ရန် လိုအပ်မည်။\n\n အသုံးပြုသူ မည်သူမဆို ကျန်အသုံးပြုသူ အားလုံးတို့အတွက် appများကို မွမ်းမံပေးနိုင်သည်။"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"သုံးစွဲသူကိုဖယ်ရှားမည်လား?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"ဤအသုံးပြုသူ၏ ဒေတာနှင့် အပ်ဖ်များအားလုံး ဖျက်လိုက်ပါမည်"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"ဖယ်ရှားရန်"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"ဘက်ထရီ ချွေတာသူ ဖွင့်ထား"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"လုပ်ကိုင်မှုကို လျှော့ချလျက် နောက်ခံ ဒေတာကို ကန့်သတ်သည်"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ဘက်ထရီ ချွေတာမှုကို ပိတ်ထားရန်"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"ဆက်တင် အထဲမှ ဖယ်ရှားရန်"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"ဆက်တင် အထဲမှ စနစ် UI ဖမ်းစက်ကို ဖယ်ရှားလျက် ၎င်း၏ အင်္ဂါရပ်များ အားလုံး အသုံးပြုမှု ရပ်တန့်ရမလား?"</string>
<string name="activity_not_found" msgid="348423244327799974">"အပလီကေးရှင်းကို သင်၏ ကိရိယာထဲသို့ တပ်ဆင်မပေးရသေးပါ။"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"နာရီ စက္ကန့်များကို ပြရန်"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"အခြေအနေပြနေရာမှာ နာရီ စက္ကန့်များကို ပြပါ။ ဘက်ထရီ သက်တမ်းကို အကျိုးသက်ရောက်နိုင်တယ်။"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 70308ce..f1bfbe1 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"LOGG UT BRUKER"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Vil du legge til en ny bruker?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område.\n\nAlle brukere kan oppdatere apper for alle andre brukere."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Vil du fjerne brukeren?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Alle apper og data som tilhører denne brukeren, blir slettet."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Fjern"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Batterisparing er på"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduserer ytelsen og begrenser bakgrunnsdataene"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Slå av batterisparing"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Fjern fra Innstillinger"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vil du fjerne System UI Tuner fra Innstillinger og slutte å bruke alle de tilknyttede funksjonene?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Appen er ikke installert på enheten din"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Vis sekunder på klokken"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statusfeltet på klokken. Det kan påvirke batteritiden."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 027e2f1..461a15f 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"प्रयोगकर्ता लगआउट गर्नुहोस्"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"नयाँ प्रयोगकर्ता थप्नुहुन्छ?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"जब तपाईँले नयाँ प्रयोगकर्ता थप्नुहुन्छ, त्यस प्रयोगकर्ताले आफ्नो स्थान स्थापना गर्न पर्ने छ।\n\nकुनै पनि प्रयोगकर्ताले सबै अन्य प्रयोगकर्ताहरूका लागि अनुप्रयोगहरू अद्यावधिक गर्न सक्छन्।"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"प्रयोगकर्ता हटाउन चाहनुहुन्छ?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"यस प्रयोगकर्ताको सबै अनुप्रयोगहरू तथा डेटा हटाइनेछ।"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"हटाउनुहोस्"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"ब्याट्रि सेभर चालु छ"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"प्रदर्शन र पृष्ठभूमि डेटा घटाउँनुहोस्"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ब्याट्री बचत बन्द गर्नुहोस्"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"सेटिङहरूबाट हटाउनुहोस्"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"प्रणाली UI ट्युनर सेटिङहरूबाट हटाउने र यसका सबै सुविधाहरू प्रयोग गर्न रोक्ने हो?"</string>
<string name="activity_not_found" msgid="348423244327799974">"तपाईँको यन्त्रमा अनुप्रयोग स्थापना भएको छैन"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"घडीमा सेकेन्ड देखाउनुहोस्"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"वस्तुस्थिति पट्टीको घडीमा सेकेन्ड देखाउनुहोस्। ब्याट्री आयु प्रभावित हुन सक्छ।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index a4aa1c4..b74f91d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"GEBRUIKER UITLOGGEN"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Nieuwe gebruiker toevoegen?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Wanneer u een nieuwe gebruiker toevoegt, moet die persoon zijn eigen profiel instellen.\n\n1Elke gebruiker kan apps updaten voor alle andere gebruikers."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Gebruiker verwijderen?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Alle apps en gegevens van deze gebruiker worden verwijderd."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Verwijderen"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Accubesparing is ingeschakeld"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Vermindert de prestaties en achtergrondgegevens"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Accubesparing uitschakelen"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Verwijderen uit Instellingen"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Systeem-UI-tuner uit Instellingen verwijderen en het gebruik van alle functies daarvan stopzetten?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Deze app is niet geïnstalleerd op uw apparaat"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Klokseconden weergeven"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Klokseconden op de statusbalk weergeven. Kan van invloed zijn op de accuduur."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index fc9d600..06746cc 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ਉਪਭੋਗਤਾ ਨੂੰ ਲੌਗ ਆਉਟ ਕਰੋ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"ਕੀ ਨਵਾਂ ਉਪਭੋਗਤਾ ਜੋੜਨਾ ਹੈ?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਵਾਂ ਉਪਭੋਗਤਾ ਜੋੜਦੇ ਹੋ, ਉਸ ਵਿਅਕਤੀ ਨੂੰ ਆਪਣਾ ਸਪੇਸ ਸੈਟ ਅਪ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।\n\nਕੋਈ ਵੀ ਉਪਭੋਗਤਾ ਹੋਰ ਸਾਰੇ ਉਪਭੋਗਤਾਵਾਂ ਦੇ ਐਪਸ ਨੂੰ ਅਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"ਕੀ ਉਪਭੋਗਤਾ ਹਟਾਉਣਾ ਹੈ?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"ਇਸ ਉਪਭੋਗਤਾ ਦੇ ਸਾਰੇ ਐਪਸ ਅਤੇ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਏਗਾ।"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"ਹਟਾਓ"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"ਪ੍ਰਦਰਸ਼ਨ ਅਤੇ ਪਿਛੋਕੜ ਡਾਟਾ ਘੱਟ ਕਰਦਾ ਹੈ"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ਬੈਟਰੀ ਸੇਵਰ ਬੰਦ ਕਰੋ"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"ਸੈਟਿੰਗਜ਼ ਤੋਂ ਹਟਾਓ"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"ਕੀ ਸੈਟਿੰਗਜ਼ ਤੋਂ ਸਿਸਟਮ UI ਟਿਊਨਰ ਨੂੰ ਹਟਾਉਣਾ ਹੈ ਅਤੇ ਇਸਦੀਆਂ ਸਾਰੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਉਪਯੋਗ ਕਰਨ ਤੋਂ ਰੋਕਣਾ ਹੈ?"</string>
<string name="activity_not_found" msgid="348423244327799974">"ਐਪਲੀਕੇਸ਼ਨ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਤੇ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਬਾਰ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index b6c9964..66100c1 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"WYLOGUJ UŻYTKOWNIKA"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Dodać nowego użytkownika?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Gdy dodasz nowego użytkownika, musi on skonfigurować swój profil.\n\nKażdy użytkownik może aktualizować aplikacje wszystkich innych użytkowników."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Usunąć użytkownika?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Wszystkie aplikacje i dane tego użytkownika zostaną usunięte."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Usuń"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Oszczędzanie baterii jest włączone"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Zmniejsza wydajność i ogranicza dane w tle"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Wyłącz oszczędzanie baterii"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Usuń z Ustawień"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Usunąć Kalibrator System UI z Ustawień i przestać używać wszystkich jego funkcji?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Aplikacja nie jest zainstalowana na urządzeniu"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Pokaż sekundy na zegarku"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Pokaż sekundy na zegarku na pasku stanu. Może mieć wpływ na czas pracy baterii."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 9656de1..53cea01 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"DESCONECTAR USUÁRIO"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Adicionar novo usuário?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Quando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para os demais usuários."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Remover usuário?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Todos os apps e dados deste usuário serão excluídos."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Remover"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"A Economia de bateria está ativada"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduz o desempenho e os dados em segundo plano"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desativar a economia de bateria"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Remover das configurações"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Remover sintonizador System UI das configurações e parar de usar todos os seus recursos?"</string>
<string name="activity_not_found" msgid="348423244327799974">"O app não está instalado no seu dispositivo"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do relógio"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index cde3da9..5006413 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"TERMINAR SESSÃO DO UTILIZADOR"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Adicionar um novo utilizador?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar aplicações para todos os outros utilizadores."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Pretende remover o utilizador?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Serão eliminados todos os dados e todas as aplicações deste utilizador."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Remover"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"A poupança de bateria está ligada"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduz o desempenho e os dados de segundo plano"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desativar a poupança de bateria"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Remover das Definições"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Pretende remover o Sintonizador da interface do sistema das Definições e deixar de utilizar todas as respetivas funcionalidades?"</string>
<string name="activity_not_found" msgid="348423244327799974">"A aplicação não está instalada no dispositivo"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do relógio"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de estado. Pode afetar a autonomia da bateria."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 9656de1..53cea01 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"DESCONECTAR USUÁRIO"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Adicionar novo usuário?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Quando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para os demais usuários."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Remover usuário?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Todos os apps e dados deste usuário serão excluídos."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Remover"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"A Economia de bateria está ativada"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduz o desempenho e os dados em segundo plano"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Desativar a economia de bateria"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Remover das configurações"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Remover sintonizador System UI das configurações e parar de usar todos os seus recursos?"</string>
<string name="activity_not_found" msgid="348423244327799974">"O app não está instalado no seu dispositivo"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do relógio"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index a62dd6c..d97e16b 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -20,9 +20,9 @@
<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="7164937344850004466">"UI sistem"</string>
- <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ștergeţi"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ștergeți"</string>
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Eliminaţi din listă"</string>
- <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informaţii despre aplicație"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informații despre aplicație"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Ecranele dvs. recente apar aici"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Renunţaţi la aplicațiile recente"</string>
<plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
@@ -52,8 +52,8 @@
<string name="bluetooth_tethered" msgid="7094101612161133267">"Conectat prin tethering prin Bluetooth"</string>
<string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Setaţi metode introducere text"</string>
<string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tastatură fizică"</string>
- <string name="usb_device_permission_prompt" msgid="834698001271562057">"Permiteţi aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze dispozitivul USB?"</string>
- <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Permiteţi aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze accesoriul USB?"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"Permiteți aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze dispozitivul USB?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Permiteți aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze accesoriul USB?"</string>
<string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Deschideţi <xliff:g id="ACTIVITY">%1$s</xliff:g> la conectarea acestui dispozitiv USB?"</string>
<string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Deschideţi <xliff:g id="ACTIVITY">%1$s</xliff:g> la conectarea acestui accesoriu USB?"</string>
<string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aplic. instal. nu funcţ. cu acest acces. USB. Aflaţi despre acest accesoriu la <xliff:g id="URL">%1$s</xliff:g>"</string>
@@ -61,9 +61,9 @@
<string name="label_view" msgid="6304565553218192990">"Afişaţi"</string>
<string name="always_use_device" msgid="1450287437017315906">"Utilizaţi în mod prestabilit pt. acest dispoz. USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Utiliz. în mod prestabilit pt. acest accesoriu USB"</string>
- <string name="usb_debugging_title" msgid="4513918393387141949">"Permiteţi depanarea USB?"</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"Permiteți depanarea USB?"</string>
<string name="usb_debugging_message" msgid="2220143855912376496">"Amprenta digitală din cheia RSA a computerului este:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
- <string name="usb_debugging_always" msgid="303335496705863070">"Permiteţi întotdeauna de pe acest computer"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"Permiteți întotdeauna de pe acest computer"</string>
<string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Remedierea erorilor prin USB nu este permisă"</string>
<string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"Utilizatorul conectat momentan pe acest dispozitiv nu poate activa remedierea erorilor prin USB. Pentru a folosi această funcție, comutați la utilizatorul Administrator."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoom pt. a umple ecranul"</string>
@@ -72,13 +72,13 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"Se salvează captura de ecran..."</string>
<string name="screenshot_saving_text" msgid="2419718443411738818">"Captura de ecran este salvată."</string>
<string name="screenshot_saved_title" msgid="6461865960961414961">"Captură de ecran realizată."</string>
- <string name="screenshot_saved_text" msgid="1152839647677558815">"Atingeţi pentru a vedea captura de ecran."</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"Atingeți pentru a vedea captura de ecran."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Captura de ecran nu a putut fi realizată."</string>
<string name="screenshot_failed_text" msgid="1260203058661337274">"Captură de ecran impos. de realizat: spațiu de stoc. limitat sau nu este permisă de apl. sau de organiz."</string>
- <string name="usb_preference_title" msgid="6551050377388882787">"Opţiuni pentru transferul de fişiere prin USB"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opţiuni pentru transferul de fișiere prin USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Montaţi ca player media (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Montaţi drept cameră foto (PTP)"</string>
- <string name="installer_cd_button_title" msgid="2312667578562201583">"Instal. aplic. Transfer de fişiere Android pt. Mac"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"Instal. aplic. Transfer de fișiere Android pt. Mac"</string>
<string name="accessibility_back" msgid="567011538994429120">"Înapoi"</string>
<string name="accessibility_home" msgid="8217216074895377641">"Ecranul de pornire"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Meniu"</string>
@@ -154,7 +154,7 @@
<string name="accessibility_battery_level" msgid="7451474187113371965">"Baterie: <xliff:g id="NUMBER">%d</xliff:g> procente."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Setări de sistem."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificări."</string>
- <string name="accessibility_remove_notification" msgid="3603099514902182350">"Ștergeţi notificarea."</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"Ștergeți notificarea."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activat."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Se obţine GPS."</string>
<string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter activat."</string>
@@ -223,9 +223,9 @@
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Fără conex. internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectat"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Se caută GPS"</string>
- <string name="gps_notification_found_text" msgid="4619274244146446464">"Locaţie setată prin GPS"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"Locație setată prin GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitări locație active"</string>
- <string name="accessibility_clear_all" msgid="5235938559247164925">"Ștergeţi toate notificările."</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"Ștergeți toate notificările."</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Setări pentru notificări"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Setări <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ecranul se va roti în mod automat."</string>
@@ -263,7 +263,7 @@
<string name="quick_settings_user_new_user" msgid="9030521362023479778">"Utilizator nou"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Neconectat"</string>
- <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nicio reţea"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nicio rețea"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi deconectat"</string>
<string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Nicio rețea Wi-Fi disponibilă"</string>
<string name="quick_settings_cast_title" msgid="7709016546426454729">"Proiectați"</string>
@@ -304,7 +304,7 @@
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> până la încărcare completă"</string>
<string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Nu se încarcă"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rețeaua poate\nfi monitorizată"</string>
- <string name="description_target_search" msgid="3091587249776033139">"Căutaţi"</string>
+ <string name="description_target_search" msgid="3091587249776033139">"Căutați"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Glisaţi în sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Glisaţi spre stânga pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="zen_priority_introduction" msgid="3070506961866919502">"Nu veți fi deranjat(ă) de sunete și vibrații, exceptând alarmele, mementourile, evenimentele și apelanții pe care îi menționați."</string>
@@ -350,6 +350,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"DECONECTAȚI UTILIZATORUL"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Adăugați utilizator nou?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Când adăugați un utilizator nou, acesta trebuie să-și configureze spațiul.\n\nOrice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Eliminați utilizatorul?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Toate aplicațiile și datele acestui utilizator vor fi șterse."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Eliminați"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Economisirea bateriei este activată"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduce performanța și datele de fundal"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Dezactivați economisirea bateriei"</string>
@@ -431,4 +434,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Eliminați din Setări"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Eliminați System UI Tuner din Setări și încetați utilizarea tuturor funcțiilor sale?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Aplicația nu este instalată pe dispozitiv"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Afișează secundele pe ceas"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Afișează secundele pe ceas în bara de stare. Poate afecta autonomia bateriei."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 6ad8a67..d67ad38 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -353,6 +353,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ВЫЙТИ ОТ ИМЕНИ ПОЛЬЗОВАТЕЛЯ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Добавить пользователя?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"После создания профиля его необходимо настроить.\n\nОбновлять приложения для всех аккаунтов может любой пользователь устройства."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Удалить аккаунт?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Все приложения и данные этого пользователя будут удалены."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Удалить"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Включен режим энергосбережения"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Откл. фоновой передачи данных"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Отключить режим энергосбережения"</string>
@@ -434,4 +437,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Удалить из настроек"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Убрать функцию System UI Tuner из меню настроек и прекратить ее работу?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Приложение не установлено на вашем устройстве"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Показывать секунды"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Показывать в строке состояния время с точностью до секунды (заряд батареи может расходоваться быстрее)."</string>
</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index da41c3f..06cb626 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"පරිශීලකයා වරන්න"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"අලුත් පරිශීලකයෙක් එකතු කරන්නද?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"ඔබ අලුත් පරිශීලකයෙක් එකතු කරන විට, එම පුද්ගලයා ඔහුගේ වැඩ කරන ඉඩ සකසා ගත යුතුය.\n\nසියළුම අනෙක් පරිශීලකයින් සඳහා ඕනෑම පරිශීලකයෙකුට යාවත්කාලීන කළ හැක."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"පරිශීලකයා ඉවත් කරන්නද?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"මෙම පරිශීලකයාගේ සියලු යෙදුම් සහ දත්ත මකනු ඇත."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"ඉවත් කරන්න"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"බැටරිය සුරකින්නා සක්රීයයි"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"ක්රියාකාරිත්වය සහ පසුබිම් දත්ත අඩු කරන්න"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"බැටරි සුරැකීම අක්රිය කරන්න"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"සැකසීම් වෙතින් ඉවත් කරන්න"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"සැකසීම් වෙතින් පද්ධති UI සුසරකය ඉවත් කර සහ එහි සියලු අංග භාවිතය නවත් වන්නද?"</string>
<string name="activity_not_found" msgid="348423244327799974">"යෙදුම ඔබේ උපාංගය මත ස්ථාපනය කර නැත"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"ඔරලෝසු තත්පර පෙන්වන්න"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"තත්ත්ව තීරුවෙහි ඔරලෝසු තත්පර පෙන්වන්න. බැටරි ආයු කාලයට බලපෑමට හැකිය."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index af5d046..037074b 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -353,6 +353,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ODHLÁSIŤ POUŽÍVATEĽA"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Pridať nového používateľa?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Keď pridáte nového používateľa, musí si nastaviť vlastný priestor.\n\nAkýkoľvek používateľ môže aktualizovať aplikácie všetkých ostatných používateľov."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Odstrániť používateľa?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Všetky aplikácie a údaje tohto používateľa budú odstránené."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Odstrániť"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Šetrič batérie je zapnutý"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Obmedzí výkonnosť a prenos údajov na pozadí"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Vypnúť šetrič batérie"</string>
@@ -434,4 +437,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Odstrániť z Nastavení"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Chcete odstrániť tuner používateľského rozhrania systému z Nastavení a prestať používať všetky jeho funkcie?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Aplikácia nie je nainštalovaná na zariadení"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Zobraziť sekundy"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Zobrazí sekundy v stavovom riadku. Môže to ovplyvňovať výdrž batérie."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 1205758..31fe5d8 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ODJAVA UPORABNIKA"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Dodajanje novega uporabnika?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Ko dodate novega uporabnika, mora ta nastaviti svoj prostor.\n\nVsak uporabnik lahko posodobi aplikacije za vse druge uporabnike."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Želite odstraniti uporabnika?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Vse aplikacije in podatki tega uporabnika bodo izbrisani."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Odstrani"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Varčevanje z energijo akumulatorja je vklopljeno"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Omeji zmogljivost delovanja in prenos podatkov v ozadju"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Izklop varčevanja z energijo akumulatorja"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Odstrani iz nastavitev"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Ali želite odstraniti Uglaševalnik uporabniškega vmesnika sistema iz nastavitev in prenehati uporabljati vse njegove funkcije?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Aplikacija ni nameščena v napravi"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Prikaz sekund pri uri"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikaže sekunde pri uri v vrstici stanja. To lahko vpliva na čas delovanja pri akumulatorskem napajanju."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index baf17d1..ffb8bea 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"NXJERRJA E PËRDORUESIT NGA IDENTIFIKIMI"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Të shtohet përdorues i ri?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Kur shton një përdorues të ri, ai person duhet të konfigurojë hapësirën e vet.\n\nÇdo përdorues mund t\'i përditësojë aplikacionet për të gjithë përdoruesit e tjerë."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Të hiqet ky përdorues?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Të gjitha aplikacionet dhe të dhënat e këtij përdoruesi do të fshihen."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Hiqe"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Kursimi i baterisë është i aktivizuar"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Pakëson veprimtarinë dhe të dhënat në sfond"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Çaktivizo kursimin e baterisë"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Hiqe nga Cilësimet"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Të hiqet Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit nga Cilësimet dhe të ndërpritet përdorimi i të gjitha funksioneve të tij?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Aplikacioni nuk është instaluar në pajisjen tënde."</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Trego sekondat e orës"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Trego sekondat e orës në shiritin e statusit. Mund të ndikojë te jeta e baterisë."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 282bdcc..bae0284 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -350,6 +350,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ОДЈАВИ КОРИСНИКА"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Додајете новог корисника?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Када додате новог корисника, та особа треба да подеси сопствени простор.\n\nСваки корисник може да ажурира апликације за све остале кориснике."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Желите ли да уклоните корисника?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Све апликације и подаци овог корисника ће бити избрисани."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Уклони"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Штедња батерије је укључена"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Смањује перформансе и позадинске податке"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Искључи штедњу батерије"</string>
@@ -431,4 +434,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Уклони из Подешавања"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Желите ли да уклоните Тјунер за кориснички интерфејс система из Подешавања и да престанете да користите све његове функције?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Апликација није инсталирана на уређају"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Приказуј секунде на сату"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Секунде на сату се приказују на статусној траци. То може да утиче на трајање батерије."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index cb8cbcb..6588f10 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"LOGGA UT ANVÄNDAREN"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Lägga till ny användare?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"När du lägger till en ny användare måste den personen konfigurera sitt utrymme.\n\nAlla användare kan uppdatera appar för samtliga användares räkning."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Vill du ta bort användaren?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Alla appar och all data som tillhör den här användaren raderas."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Ta bort"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Batterisparläget har aktiverats"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Minskar prestanda och bakgrundsdata"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Inaktivera batterisparläget"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Ta bort från inställningarna"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vill du ta bort inställningar för systemgränssnitt från inställningarna och sluta använda alla tillhörande funktioner?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Appen är inte installerad på enheten"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Visa klocksekunder"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Visa klocksekunder i statusfältet. Detta kan påverka batteritiden."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index def1786..623f12c 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ONDOA MTUMIAJI"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Ungependa kuongeza mtumiaji?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Unapomwongeza mtumiaji mpya, mtu huyo anahitaji kusanidi nafasi yake.\n\nMtumiaji yoyote anaweza kusasisha programu kwa ajili ya watumiaji wengine wote."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Je, ungependa kuondoa mtumiaji?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Programu na data yote ya mtumiaji huyu itafutwa."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Ondoa"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Kiokoa betri kimewashwa"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Hupunguza utendaji na data ya chini chini"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Zima kiokoa betri"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Ondoa kwenye Mipangilio"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Je, ungependa kuondoa Kipokea ishara cha SystemUI kwenye Mipangilio na uache kutumia vipengele vyake vyote?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Programu haijasakinishwa kwenye kifaa chako"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Onyesha sekunde za saa"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Onyesha sekunde za saa katika sehemu ya arifa. Inaweza kuathiri muda wa matumizi ya betri."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index c9d0853..c6cb337 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"பயனரை வெளியேற்று"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"புதியவரைச் சேர்க்கவா?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"புதிய பயனரைச் சேர்க்கும்போது, அவர் தனக்கான இடத்தை அமைக்க வேண்டும்.\n\nஎந்தவொரு பயனரும், மற்ற எல்லா பயனர்களுக்காகவும் பயன்பாடுகளைப் புதுப்பிக்கலாம்."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"பயனரை அகற்றவா?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"இந்தப் பயனரின் எல்லா பயன்பாடுகளும் தரவும் நீக்கப்படும்."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"அகற்று"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"பேட்டரி சேமிப்பான் இயக்கத்தில் உள்ளது"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"செயல்திறனையும் பின்புலத் தரவையும் குறைக்கிறது"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"பேட்டரி சேமிப்பானை முடக்கு"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"அமைப்புகளிலிருந்து அகற்று"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"அமைப்புகளிலிருந்து System UI Tunerஐ அகற்றிவிட்டு, அதன் எல்லா அம்சங்களையும் பயன்படுத்துவதை நிறுத்தவா?"</string>
<string name="activity_not_found" msgid="348423244327799974">"சாதனத்தில் பயன்பாடு நிறுவப்படவில்லை"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"கடிகார வினாடிகளைக் காட்டு"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"நிலைப் பட்டியில் கடிகார வினாடிகளைக் காட்டும். பேட்டரியின் ஆயுளைக் குறைக்கலாம்."</string>
</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 548c021..c0717c1 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"వినియోగదారుని లాగ్ అవుట్ చేయి"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"కొత్త వినియోగదారుని జోడించాలా?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"మీరు కొత్త వినియోగదారుని జోడించినప్పుడు, ఆ వ్యక్తి తన స్థలాన్ని సెటప్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగతా అందరు వినియోగదారుల కోసం అనువర్తనాలను నవీకరించగలరు."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"వినియోగదారుని తీసివేయాలా?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"ఈ వినియోగదారుకు సంబంధించిన అన్ని అనువర్తనాలు మరియు డేటా తొలగించబడతాయి."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"తీసివేయి"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"బ్యాటర్ సేవర్ ఆన్ చేయబడింది"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"పనితీరుని మరియు నేపథ్య డేటాను తగ్గిస్తుంది"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"బ్యాటరీ సేవర్ను ఆఫ్ చేయి"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"సెట్టింగ్ల నుండి తీసివేయి"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"సిస్టమ్ UI ట్యూనర్ను సెట్టింగ్ల నుండి తీసివేసి, దాని అన్ని లక్షణాలను ఉపయోగించడం ఆపివేయాలా?"</string>
<string name="activity_not_found" msgid="348423244327799974">"అనువర్తనం మీ పరికరంలో ఇన్స్టాల్ చేయలేదు"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"గడియారం సెకన్లు చూపు"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"స్థితి పట్టీలో గడియారం సెకన్లు చూపుతుంది. బ్యాటరీ శక్తి ప్రభావితం చేయవచ్చు."</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index ddae7f6..e16fdd2 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ออกจากระบบผู้ใช้"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"ต้องการเพิ่มผู้ใช้ใหม่ใช่ไหม"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"เมื่อคุณเพิ่มผู้ใช้ใหม่ ผู้ใช้ดังกล่าวจะต้องตั้งค่าพื้นที่ของตนเอง\n\nผู้ใช้ทุกคนสามารถอัปเดตแอปสำหรับผู้ใช้รายอื่นทุกคนได้"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"นำผู้ใช้ออกใช่ไหม"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"แอปและข้อมูลทั้งหมดของผู้ใช้นี้จะถูกลบ"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"นำออก"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"เปิดโหมดประหยัดแบตเตอรี่อยู่"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"ลดการใช้แบตเตอรี่และข้อมูลแบ็กกราวด์"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ปิดโหมดประหยัดแบตเตอรี่"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"นำออกจากการตั้งค่า"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"นำตัวรับสัญญาณ UI ระบบออกจากการตั้งค่าและหยุดใช้คุณลักษณะทั้งหมดของตัวรับสัญญาณใช่ไหม"</string>
<string name="activity_not_found" msgid="348423244327799974">"ยังไม่ได้ติดตั้งแอปพลิเคชันบนอุปกรณ์ของคุณ"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"แสดงวินาทีของนาฬิกา"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"แสดงวินาทีของนาฬิกาในแถบสถานะ อาจส่งผลต่ออายุแบตเตอรี"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index d001ba9..d970084 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"I-LOGOUT ANG USER"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Magdagdag ng bagong user?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Kapag nagdagdag ka ng bagong user, kailangang i-set up ng taong iyon ang kanyang espasyo.\n\nAng sinumang user ay maaaring mag-update ng mga app para sa lahat ng iba pang user."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Gusto mo bang alisin ang user?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Made-delete ang lahat ng app at data ng user na ito."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Alisin"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Naka-on ang tagatipid ng baterya"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Binabawasan ang pagganap at data sa background"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"I-off ang pagtitipid ng baterya"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Alisin sa Mga Setting"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Alisin ang Tuner ng System UI sa Mga Setting at ihinto ang paggamit ng lahat ng feature nito?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Hindi naka-install ang application sa iyong device"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Ipakita ang mga segundo ng orasan"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Ipakita ang mga segundo ng orasan sa status bar. Maaaring makaapekto sa tagal ng baterya."</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 5f804cf..b22b4fb 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"KULLANICI OTURUMUNU KAPAT"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Yeni kullanıcı eklensin mi?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Yeni bir kullanıcı eklediğinizde, bu kişinin kendi alanını ayarlaması gerekir.\n\nHerhangi bir kullanıcı, diğer tüm kullanıcılar için uygulamaları güncelleyebilir."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Kullanıcı kaldırılsın mı?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Bu kullanıcının tüm uygulamaları ve verileri silinecek."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Kaldır"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Pil tasarrufu açık"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Performansı ve arka plan verilerini azaltır"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Pil tasarrufunu kapat"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Ayarlar\'dan kaldır"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Sistem Kullanıcı Arayüzü Ayarlayıcısı Ayarlar\'dan kaldırılsın ve tüm özelliklerinin kullanılması durdurulsun mu?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Uygulama, cihazınızda yüklü değil"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Saatin saniyelerini göster"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Durum çubuğunda saatin saniyelerini gösterir. Pil ömrünü etkileyebilir."</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 0c1d328..5c0966c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ВИЙТИ З ОБЛІКОВОГО ЗАПИСУ"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Додати нового користувача?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Користувач має налаштувати свій профіль після створення.\n\nБудь-який користувач пристрою може оновлювати додатки для решти користувачів."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Видалити користувача?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Усі додатки й дані цього користувача буде видалено."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Видалити"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Режим заощадження заряду акумулятора ввімкнено"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Знижується продуктивність і обмежуються фонові дані"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Вимкнути режим заощадження заряду акумулятора"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Видалити з додатка Налаштування"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Видалити інструмент System UI Tuner із додатка Налаштування та припинити користуватися всіма його функціями?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Додаток не встановлено на вашому пристрої"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Показувати секунди на годиннику"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Показувати секунди на годиннику в рядку стану. Акумулятор може розряджатися швидше."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index d0e2fc6..d5683e1 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"صارف لاگ آؤٹ کریں"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"نیا صارف شامل کریں؟"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"جب آپ ایک نیا صارف شامل کرتے ہیں تو اس شخص کو اپنی جگہ کو ترتیب دینے کی ضرورت ہوتی ہے۔\n\nکوئی بھی صارف دیگر سبھی صارفین کیلئے ایپس کو اپ ڈیٹ کر سکتا ہے۔"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"صارف کو ہٹائیں؟"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"اس صارف کی سبھی ایپس اور ڈیٹا حذف کر دیا جائے گا۔"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"ہٹائیں"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"بیٹری سیور آن ہے"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"کارکردگی اور پس منظر کا ڈیٹا کم کر دیتا ہے"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"بیٹری کی بچت آف کریں"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"ترتیبات سے ہٹائیں"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"ترتیبات سے سسٹم UI ٹیونر کو ہٹائیں اور اس کی سبھی خصوصیات کا استعمال بند کریں؟"</string>
<string name="activity_not_found" msgid="348423244327799974">"ایپلیکیشن آپ کے آلہ پر انسٹال نہیں ہے"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"گھڑی کے سیکنڈز دکھائیں"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"گھڑی کے سیکنڈز اسٹیٹس بار میں دکھائیں۔ اس کا بیٹری کی زندگی پر اثر پڑ سکتا ہے۔"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 8def6f42..e31af6b 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"FOYDALANUVCHI NOMIDAN CHIQISH"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Yangi foyd-chi qo‘shilsinmi?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Yangi foydalanuvchi qo‘shilgach, o‘sha shaxs o‘z hududini sozlashi lozim bo‘ladi.\n\nHar qanday foydalanuvchi ilovalarni barcha foydalanuvchilar uchun yangilashi mumkin."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Foydalanuvchi olib tashlansinmi?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Ushbu foydalanuvchining barcha ilovalari va ma’lumotlari o‘chirib tashlanadi."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Olib tashlash"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Quvvat tejash rejimi yoqildi"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Unumdorlikni pasaytiradi va fonda int-dan foyd-ni cheklaydi"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Quvvat tejash funksiyasini o‘chiring"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Sozlamalardan olib tashlash"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"System UI Tuner Sozlamalardan olib tashlanib, uning barcha funksiyalaridan foydalanish to‘xtatilsinmi?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Ilova qurilmangizga o‘rnatilmagan"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Soat soniyalari ko‘rsatilsin"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Holat panelida soat soniyalari ko‘rsatilsin. Bu batareya resursiga ta’sir qilishi mumkin."</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 0fc90d7..030bbbe 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"ĐĂNG XUẤT NGƯỜI DÙNG"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Thêm người dùng mới?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Khi bạn thêm người dùng mới, người dùng đó cần thiết lập dung lượng lưu trữ của mình.\n\nMọi người dùng đều có thể cập nhật ứng dụng cho tất cả người dùng khác."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Xóa người dùng?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Tất cả các ứng dụng và dữ liệu của người dùng này sẽ bị xóa."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Xóa"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Trình tiết kiệm pin đang bật"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Giảm hiệu suất và dữ liệu nền"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Tắt trình tiết kiệm pin"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Xóa khỏi Cài đặt"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Xóa Bộ điều hướng giao diện người dùng hệ thống khỏi Cài đặt và ngừng sử dụng tất cả tính năng của ứng dụng này?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Ứng dụng chưa được cài đặt trên thiết bị của bạn"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Hiển thị giây đồng hồ"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Hiển thị giây đồng hồ trong thanh trạng thái. Có thể ảnh hưởng đến thời lượng pin."</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 53980c1..b046415 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"退出当前用户"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"要添加新用户吗?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"当您添加新用户时,该用户必须设置自己的空间。\n\n任何用户均可为其他所有用户更新应用。"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"是否移除用户?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"此用户的所有应用和数据均将被删除。"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"移除"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"节电助手已开启"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"降低性能并限制后台流量"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"关闭节电助手"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"从“设置”中移除"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"要将系统界面调谐器从“设置”中移除,并停止使用所有相关功能吗?"</string>
<string name="activity_not_found" msgid="348423244327799974">"您的设备中未安装此应用"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"显示时钟的秒数"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"在状态栏中显示时钟的秒数。这可能会影响电池的续航时间。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 65e200b..d568dba 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"登出使用者"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"新增使用者?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"新增的使用者需要自行設定個人空間。\n\n任何使用者均可為所有其他使用者更新應用程式。"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"移除使用者?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"系統將會刪除這個使用者的所有應用程式和資料。"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"移除"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"省電模式已開啟"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"降低效能並限制背景數據傳輸"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"關閉省電模式"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"從「設定」移除"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"要從「設定」移除系統使用者介面調諧器,並停止其所有功能嗎?"</string>
<string name="activity_not_found" msgid="348423244327799974">"尚未在裝置安裝應用程式"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"顯示時鐘秒數"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數,但可能會影響電池壽命。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 04d914b..702ad53 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -351,6 +351,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"登出使用者"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"新增使用者?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"新增的使用者需要自行設定個人空間。\n\n任何使用者皆可為其他所有使用者更新應用程式。"</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"要移除使用者嗎?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"系統將刪除這個使用者的所有應用程式和資料。"</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"移除"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"節約耗電量模式已啟用"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"降低效能並限制背景數據傳輸"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"關閉節約耗電量模式"</string>
@@ -432,4 +435,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"從設定中移除"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"要將系統使用者介面調整精靈從設定中移除,並停止使用所有相關功能嗎?"</string>
<string name="activity_not_found" msgid="348423244327799974">"您的裝置未安裝這個應用程式"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"顯示時鐘秒數"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數。這可能會影響電池續航力。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 7a7e3fe..8774036 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -349,6 +349,9 @@
<string name="user_logout_notification_action" msgid="1195428991423425062">"KHIPHA UMSEBENZISI"</string>
<string name="user_add_user_title" msgid="4553596395824132638">"Engeza umsebenzisi omusha?"</string>
<string name="user_add_user_message_short" msgid="2161624834066214559">"Uma ungeza umsebenzisi omusha, loyo muntu udinga ukusetha isikhala sakhe.\n\nNoma yimuphi umsebenzisi angabuyekeza izinhlelo zokusebenza kubo bonke abasebenzisi."</string>
+ <string name="user_remove_user_title" msgid="4681256956076895559">"Susa umsebenzisi?"</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Zonke izinhlelo zokusebenza nedatha yalo msebenzisi kuzosuswa."</string>
+ <string name="user_remove_user_remove" msgid="7479275741742178297">"Susa"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Isilondolozi sebhethri sivuliwe"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Sehlisa ukusebenza nedatha yasemuva"</string>
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"Vala isilondolozi sebhethri"</string>
@@ -430,4 +433,6 @@
<string name="remove_from_settings" msgid="8389591916603406378">"Susa kusuka kuzilungiselelo"</string>
<string name="remove_from_settings_prompt" msgid="6069085993355887748">"Susa isishuni se-UI yesistimu kusuka kuzilungiselelo futhi uyeke ukusebenzisa zonke izici zakhona?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Uhlelo lokusebenza alufakiwe kudivayisi yakho"</string>
+ <string name="clock_seconds" msgid="7689554147579179507">"Bonisa amasekhondi wewashi"</string>
+ <string name="clock_seconds_desc" msgid="6282693067130470675">"Bonisa amasekhondi wewashi kubha yesimo. Ingathinta impilo yebhethri."</string>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 918d856..8b3f2d8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1140,4 +1140,9 @@
<!-- Displayed when user launches an app that was uninstalled [CHAR LIMIT=NONE] -->
<string name="activity_not_found">Application is not installed on your device</string>
+ <!-- Name of setting to show clock seconds [CHAR LIMIT=40] -->
+ <string name="clock_seconds">Show clock seconds</string>
+ <!-- Description of setting to show clock seconds [CHAR LIMIT=NONE] -->
+ <string name="clock_seconds_desc">Show clock seconds in the status bar. May impact battery life.</string>
+
</resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 3a41c3c..beb863c 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -72,10 +72,16 @@
android:summary="@string/show_battery_percentage_summary"
android:persistent="false" />
+ <com.android.systemui.tuner.TunerSwitch
+ android:key="clock_seconds"
+ android:title="@string/clock_seconds"
+ android:summary="@string/clock_seconds_desc" />
+
<Preference
android:key="demo_mode"
android:title="@string/demo_mode" />
+ <!-- Warning, this goes last. -->
<Preference
android:summary="@string/tuner_persistent_warning"
android:selectable="false" />
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/LockedPhoneAnalytics.java b/packages/SystemUI/src/com/android/systemui/analytics/LockedPhoneAnalytics.java
new file mode 100644
index 0000000..e458862
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/analytics/LockedPhoneAnalytics.java
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.analytics;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.systemui.statusbar.StatusBarState;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session;
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.PhoneEvent;
+
+/**
+ * Tracks touch, sensor and phone events when the lockscreen is on. If the phone is unlocked
+ * the data containing these events is saved to a file. This data is collected
+ * to analyze how a human interaction looks like.
+ *
+ * A session starts when the screen is turned on.
+ * A session ends when the screen is turned off or user unlocks the phone.
+ */
+public class LockedPhoneAnalytics implements SensorEventListener {
+ private static final String TAG = "LockedPhoneAnalytics";
+ private static final String ANALYTICS_ENABLE = "locked_phone_analytics_enable";
+ private static final String ENFORCE_BOUNCER = "locked_phone_analytics_enforce_bouncer";
+ private static final String COLLECT_BAD_TOCUHES = "locked_phone_analytics_collect_bad_touches";
+
+ private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
+ public static final boolean DEBUG = false;
+
+ private static final int[] SENSORS = new int[] {
+ Sensor.TYPE_ACCELEROMETER,
+ Sensor.TYPE_GYROSCOPE,
+ Sensor.TYPE_PROXIMITY,
+ Sensor.TYPE_LIGHT,
+ Sensor.TYPE_ROTATION_VECTOR,
+ };
+
+ private final Handler mHandler = new Handler();
+ protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateConfiguration();
+ }
+ };
+
+ private final SensorManager mSensorManager;
+ private final Context mContext;
+
+ // Err on the side of caution, so logging is not started after a crash even tough the screen
+ // is off.
+ private SensorLoggerSession mCurrentSession = null;
+
+ private boolean mEnableAnalytics = false;
+ private boolean mEnforceBouncer = false;
+ private boolean mTimeoutActive = false;
+ private boolean mCollectBadTouches = false;
+ private boolean mBouncerOn = false;
+ private boolean mCornerSwiping = false;
+ private boolean mTrackingStarted = false;
+
+ private int mState = StatusBarState.SHADE;
+
+ private static LockedPhoneAnalytics sInstance = null;
+
+ private LockedPhoneAnalytics(Context context) {
+ mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+ mContext = context;
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(ANALYTICS_ENABLE), false,
+ mSettingsObserver,
+ UserHandle.USER_ALL);
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(ENFORCE_BOUNCER), false,
+ mSettingsObserver,
+ UserHandle.USER_ALL);
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(COLLECT_BAD_TOCUHES), false,
+ mSettingsObserver,
+ UserHandle.USER_ALL);
+
+ updateConfiguration();
+ }
+
+ public static LockedPhoneAnalytics getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new LockedPhoneAnalytics(context);
+ }
+ return sInstance;
+ }
+
+ private void updateConfiguration() {
+ mEnableAnalytics = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
+ mContext.getContentResolver(),
+ ANALYTICS_ENABLE, 0);
+ mEnforceBouncer = mEnableAnalytics && 0 != Settings.Secure.getInt(
+ mContext.getContentResolver(),
+ ENFORCE_BOUNCER, 0);
+ mCollectBadTouches = mEnableAnalytics && 0 != Settings.Secure.getInt(
+ mContext.getContentResolver(),
+ COLLECT_BAD_TOCUHES, 0);
+ }
+
+ private boolean sessionEntrypoint() {
+ if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
+ && mEnableAnalytics && mCurrentSession == null) {
+ onSessionStart();
+ return true;
+ }
+ return false;
+ }
+
+ private void sessionExitpoint(int result) {
+ if (mEnableAnalytics && mCurrentSession != null) {
+ onSessionEnd(result);
+ }
+ }
+
+ private void onSessionStart() {
+ mBouncerOn = false;
+ mCornerSwiping = false;
+ mTrackingStarted = false;
+ mCurrentSession = new SensorLoggerSession(System.currentTimeMillis(), System.nanoTime());
+ for (int sensorType : SENSORS) {
+ Sensor s = mSensorManager.getDefaultSensor(sensorType);
+ if (s != null) {
+ mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
+ }
+ }
+ }
+
+ private void onSessionEnd(int result) {
+ SensorLoggerSession session = mCurrentSession;
+ mCurrentSession = null;
+
+ session.end(System.currentTimeMillis(), result);
+ queueSession(session);
+ }
+
+ private void queueSession(final SensorLoggerSession currentSession) {
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ byte[] b = Session.toByteArray(currentSession.toProto());
+ String dir = mContext.getFilesDir().getAbsolutePath();
+ if (currentSession.getResult() != Session.SUCCESS) {
+ if (!mCollectBadTouches) {
+ return;
+ }
+ dir += "/bad_touches";
+ } else {
+ dir += "/good_touches";
+ }
+
+ File file = new File(dir);
+ file.mkdir();
+ File touch = new File(file, "trace_" + System.currentTimeMillis());
+
+ try {
+ new FileOutputStream(touch).write(b);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+
+ @Override
+ public synchronized void onSensorChanged(SensorEvent event) {
+ if (mEnableAnalytics && mCurrentSession != null) {
+ mCurrentSession.addSensorEvent(event, System.nanoTime());
+ enforceTimeout();
+ }
+ }
+
+ private void enforceTimeout() {
+ if (mTimeoutActive) {
+ if (System.currentTimeMillis() - mCurrentSession.getStartTimestampMillis()
+ > TIMEOUT_MILLIS) {
+ onSessionEnd(Session.UNKNOWN);
+ if (DEBUG) {
+ Log.i(TAG, "Analytics timed out.");
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ public boolean shouldEnforceBouncer() {
+ return mEnforceBouncer;
+ }
+
+ public void setStatusBarState(int state) {
+ mState = state;
+ }
+
+ public void onScreenOn() {
+ if (sessionEntrypoint()) {
+ if (DEBUG) {
+ Log.d(TAG, "onScreenOn");
+ }
+ addEvent(PhoneEvent.ON_SCREEN_ON);
+ }
+ }
+
+ public void onScreenOnFromTouch() {
+ if (sessionEntrypoint()) {
+ if (DEBUG) {
+ Log.d(TAG, "onScreenOnFromTouch");
+ }
+ addEvent(PhoneEvent.ON_SCREEN_ON_FROM_TOUCH);
+ }
+ }
+
+ public void onScreenOff() {
+ if (DEBUG) {
+ Log.d(TAG, "onScreenOff");
+ }
+ addEvent(PhoneEvent.ON_SCREEN_OFF);
+ sessionExitpoint(Session.FAILURE);
+ }
+
+ public void onSucccessfulUnlock() {
+ if (DEBUG) {
+ Log.d(TAG, "onSuccessfulUnlock");
+ }
+ addEvent(PhoneEvent.ON_SUCCESSFUL_UNLOCK);
+ sessionExitpoint(Session.SUCCESS);
+ }
+
+ public void onBouncerShown() {
+ if (!mBouncerOn) {
+ if (DEBUG) {
+ Log.d(TAG, "onBouncerShown");
+ }
+ mBouncerOn = true;
+ addEvent(PhoneEvent.ON_BOUNCER_SHOWN);
+ }
+ }
+
+ public void onBouncerHidden() {
+ if (mBouncerOn) {
+ if (DEBUG) {
+ Log.d(TAG, "onBouncerHidden");
+ }
+ mBouncerOn = false;
+ addEvent(PhoneEvent.ON_BOUNCER_HIDDEN);
+ }
+ }
+
+ public void onQsDown() {
+ if (DEBUG) {
+ Log.d(TAG, "onQsDown");
+ }
+ addEvent(PhoneEvent.ON_QS_DOWN);
+ }
+
+ public void setQsExpanded(boolean expanded) {
+ if (DEBUG) {
+ Log.d(TAG, "setQsExpanded = " + expanded);
+ }
+ if (expanded) {
+ addEvent(PhoneEvent.SET_QS_EXPANDED_TRUE);
+ } else {
+ addEvent(PhoneEvent.SET_QS_EXPANDED_FALSE);
+ }
+ }
+
+ public void onTrackingStarted() {
+ if (DEBUG) {
+ Log.d(TAG, "onTrackingStarted");
+ }
+ mTrackingStarted = true;
+ addEvent(PhoneEvent.ON_TRACKING_STARTED);
+ }
+
+ public void onTrackingStopped() {
+ if (mTrackingStarted) {
+ if (DEBUG) {
+ Log.d(TAG, "onTrackingStopped");
+ }
+ mTrackingStarted = false;
+ addEvent(PhoneEvent.ON_TRACKING_STOPPED);
+ }
+ }
+
+ public void onNotificationActive() {
+ if (DEBUG) {
+ Log.d(TAG, "onNotificationActive");
+ }
+ addEvent(PhoneEvent.ON_NOTIFICATION_ACTIVE);
+ }
+
+
+ public void onNotificationDoubleTap() {
+ if (DEBUG) {
+ Log.d(TAG, "onNotificationDoubleTap");
+ }
+ addEvent(PhoneEvent.ON_NOTIFICATION_DOUBLE_TAP);
+ }
+
+ public void setNotificationExpanded() {
+ if (DEBUG) {
+ Log.d(TAG, "setNotificationExpanded");
+ }
+ addEvent(PhoneEvent.SET_NOTIFICATION_EXPANDED);
+ }
+
+ public void onNotificatonStartDraggingDown() {
+ if (DEBUG) {
+ Log.d(TAG, "onNotificationStartDraggingDown");
+ }
+ addEvent(PhoneEvent.ON_NOTIFICATION_START_DRAGGING_DOWN);
+ }
+
+ public void onNotificatonStopDraggingDown() {
+ if (DEBUG) {
+ Log.d(TAG, "onNotificationStopDraggingDown");
+ }
+ addEvent(PhoneEvent.ON_NOTIFICATION_STOP_DRAGGING_DOWN);
+ }
+
+ public void onNotificationDismissed() {
+ if (DEBUG) {
+ Log.d(TAG, "onNotificationDismissed");
+ }
+ addEvent(PhoneEvent.ON_NOTIFICATION_DISMISSED);
+ }
+
+ public void onNotificatonStartDismissing() {
+ if (DEBUG) {
+ Log.d(TAG, "onNotificationStartDismissing");
+ }
+ addEvent(PhoneEvent.ON_NOTIFICATION_START_DISMISSING);
+ }
+
+ public void onNotificatonStopDismissing() {
+ if (DEBUG) {
+ Log.d(TAG, "onNotificationStopDismissing");
+ }
+ addEvent(PhoneEvent.ON_NOTIFICATION_STOP_DISMISSING);
+ }
+
+ public void onCameraOn() {
+ if (DEBUG) {
+ Log.d(TAG, "onCameraOn");
+ }
+ addEvent(PhoneEvent.ON_CAMERA_ON);
+ }
+
+ public void onLeftAffordanceOn() {
+ if (DEBUG) {
+ Log.d(TAG, "onLeftAffordanceOn");
+ }
+ addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_ON);
+ }
+
+ public void onAffordanceSwipingStarted(boolean rightCorner) {
+ if (DEBUG) {
+ Log.d(TAG, "onAffordanceSwipingStarted");
+ }
+ mCornerSwiping = true;
+ if (rightCorner) {
+ addEvent(PhoneEvent.ON_RIGHT_AFFORDANCE_SWIPING_STARTED);
+ } else {
+ addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_SWIPING_STARTED);
+ }
+ }
+
+ public void onAffordanceSwipingAborted() {
+ if (mCornerSwiping) {
+ if (DEBUG) {
+ Log.d(TAG, "onAffordanceSwipingAborted");
+ }
+ mCornerSwiping = false;
+ addEvent(PhoneEvent.ON_AFFORDANCE_SWIPING_ABORTED);
+ }
+ }
+
+ public void onUnlockHintStarted() {
+ if (DEBUG) {
+ Log.d(TAG, "onUnlockHintStarted");
+ }
+ addEvent(PhoneEvent.ON_UNLOCK_HINT_STARTED);
+ }
+
+ public void onCameraHintStarted() {
+ if (DEBUG) {
+ Log.d(TAG, "onCameraHintStarted");
+ }
+ addEvent(PhoneEvent.ON_CAMERA_HINT_STARTED);
+ }
+
+ public void onLeftAffordanceHintStarted() {
+ if (DEBUG) {
+ Log.d(TAG, "onLeftAffordanceHintStarted");
+ }
+ addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_HINT_STARTED);
+ }
+
+ public void onTouchEvent(MotionEvent ev, int width, int height) {
+ if (!mBouncerOn && mCurrentSession != null) {
+ if (DEBUG) {
+ Log.v(TAG, "onTouchEvent(ev.action="
+ + MotionEvent.actionToString(ev.getAction()) + ")");
+ }
+ mCurrentSession.addMotionEvent(ev);
+ mCurrentSession.setTouchArea(width, height);
+ enforceTimeout();
+ }
+ }
+
+ private void addEvent(int eventType) {
+ if (mEnableAnalytics && mCurrentSession != null) {
+ mCurrentSession.addPhoneEvent(eventType, System.nanoTime());
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
new file mode 100644
index 0000000..09383f6a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.analytics;
+
+import android.os.Build;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import java.util.ArrayList;
+
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session;
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.TouchEvent;
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.SensorEvent;
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.PhoneEvent;
+
+/**
+ * Collects touch, sensor and phone events and converts the data to
+ * TouchAnalyticsProto.Session.
+ */
+public class SensorLoggerSession {
+ private static final String TAG = "SensorLoggerSession";
+
+ private final long mStartTimestampMillis;
+ private final long mStartSystemTimeNanos;
+
+ private long mEndTimestampMillis;
+ private int mType;
+
+ private ArrayList<TouchEvent> mMotionEvents = new ArrayList<>();
+ private ArrayList<SensorEvent> mSensorEvents = new ArrayList<>();
+ private ArrayList<PhoneEvent> mPhoneEvents = new ArrayList<>();
+ private int mTouchAreaHeight;
+ private int mTouchAreaWidth;
+ private int mResult = Session.UNKNOWN;
+
+ public SensorLoggerSession(long startTimestampMillis, long startSystemTimeNanos) {
+ mStartTimestampMillis = startTimestampMillis;
+ mStartSystemTimeNanos = startSystemTimeNanos;
+ mType = Session.REAL;
+ }
+
+ public void end(long endTimestampMillis, int result) {
+ mResult = result;
+ mEndTimestampMillis = endTimestampMillis;
+
+ if (LockedPhoneAnalytics.DEBUG) {
+ Log.d(TAG, "Ending session result=" + result + " it lasted for " +
+ (float) (mEndTimestampMillis - mStartTimestampMillis) / 1000f + "s");
+ }
+ }
+
+ public void addMotionEvent(MotionEvent motionEvent) {
+ TouchEvent event = motionEventToProto(motionEvent);
+ mMotionEvents.add(event);
+ }
+
+ public void addSensorEvent(android.hardware.SensorEvent eventOrig, long systemTimeNanos) {
+ SensorEvent event = sensorEventToProto(eventOrig, systemTimeNanos);
+ mSensorEvents.add(event);
+ }
+
+ public void addPhoneEvent(int eventType, long systemTimeNanos) {
+ PhoneEvent event = phoneEventToProto(eventType, systemTimeNanos);
+ mPhoneEvents.add(event);
+ }
+
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("Session{");
+ sb.append("mStartTimestampMillis=").append(mStartTimestampMillis);
+ sb.append(", mStartSystemTimeNanos=").append(mStartSystemTimeNanos);
+ sb.append(", mEndTimestampMillis=").append(mEndTimestampMillis);
+ sb.append(", mResult=").append(mResult);
+ sb.append(", mTouchAreaHeight=").append(mTouchAreaHeight);
+ sb.append(", mTouchAreaWidth=").append(mTouchAreaWidth);
+ sb.append(", mMotionEvents=[size=").append(mMotionEvents.size()).append("]");
+ sb.append(", mSensorEvents=[size=").append(mSensorEvents.size()).append("]");
+ sb.append(", mPhoneEvents=[size=").append(mPhoneEvents.size()).append("]");
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public Session toProto() {
+ Session proto = new Session();
+ proto.setStartTimestampMillis(mStartTimestampMillis);
+ proto.setDurationMillis(mEndTimestampMillis - mStartTimestampMillis);
+ proto.setBuild(Build.FINGERPRINT);
+ proto.setResult(mResult);
+ proto.setType(mType);
+ proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);
+ proto.touchEvents = mMotionEvents.toArray(proto.touchEvents);
+ proto.phoneEvents = mPhoneEvents.toArray(proto.phoneEvents);
+ proto.setTouchAreaWidth(mTouchAreaWidth);
+ proto.setTouchAreaHeight(mTouchAreaHeight);
+ return proto;
+ }
+
+ private PhoneEvent phoneEventToProto(int eventType, long sysTimeNanos) {
+ PhoneEvent proto = new PhoneEvent();
+ proto.setType(eventType);
+ proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos);
+ return proto;
+ }
+
+ private SensorEvent sensorEventToProto(android.hardware.SensorEvent ev, long sysTimeNanos) {
+ SensorEvent proto = new SensorEvent();
+ proto.setType(ev.sensor.getType());
+ proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos);
+ proto.setTimestamp(ev.timestamp);
+ proto.values = ev.values.clone();
+ return proto;
+ }
+
+ private TouchEvent motionEventToProto(MotionEvent ev) {
+ int count = ev.getPointerCount();
+ TouchEvent proto = new TouchEvent();
+ proto.setTimeOffsetNanos(ev.getEventTimeNano() - mStartSystemTimeNanos);
+ proto.setAction(ev.getActionMasked());
+ proto.setActionIndex(ev.getActionIndex());
+ proto.pointers = new TouchEvent.Pointer[count];
+ for (int i = 0; i < count; i++) {
+ TouchEvent.Pointer p = new TouchEvent.Pointer();
+ p.setX(ev.getX(i));
+ p.setY(ev.getY(i));
+ p.setSize(ev.getSize(i));
+ p.setPressure(ev.getPressure(i));
+ p.setId(ev.getPointerId(i));
+ proto.pointers[i] = p;
+ }
+ return proto;
+ }
+
+ public void setTouchArea(int width, int height) {
+ mTouchAreaWidth = width;
+ mTouchAreaHeight = height;
+ }
+
+ public int getResult() {
+ return mResult;
+ }
+
+ public long getStartTimestampMillis() {
+ return mStartTimestampMillis;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 328ee35..36efead 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -256,6 +256,8 @@
private void continuePulsing(int reason) {
if (mHost.isPulsingBlocked()) {
+ mPulsing = false;
+ mWakeLock.release();
return;
}
mHost.pulseWhileDozing(new DozeHost.PulseCallback() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index aafa991..12d5f36 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -69,6 +69,7 @@
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.FingerprintUnlockController;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -531,7 +532,7 @@
int currentUser = ActivityManager.getCurrentUser();
if ((mUpdateMonitor.getUserTrustIsManaged(currentUser)
|| mUpdateMonitor.isUnlockWithFingerprintPossible(currentUser))
- && !mTrustManager.hasUserAuthenticatedSinceBoot(currentUser)) {
+ && !mUpdateMonitor.getStrongAuthTracker().hasUserAuthenticatedSinceBoot()) {
return KeyguardSecurityView.PROMPT_REASON_RESTART;
} else if (mUpdateMonitor.isUnlockWithFingerprintPossible(currentUser)
&& mUpdateMonitor.hasFingerprintUnlockTimedOut(currentUser)) {
@@ -1240,6 +1241,7 @@
case START_KEYGUARD_EXIT_ANIM:
StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration);
+ LockedPhoneAnalytics.getInstance(mContext).onSucccessfulUnlock();
break;
case KEYGUARD_DONE_PENDING_TIMEOUT:
Log.w(TAG, "Timeout while waiting for activity drawn!");
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 2a84362..adc9b36 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.graphics.Typeface;
import android.media.projection.MediaProjectionManager;
import android.media.projection.IMediaProjectionManager;
import android.media.projection.IMediaProjection;
@@ -29,7 +30,14 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.text.BidiFormatter;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.text.style.StyleSpan;
import android.util.Log;
+import android.util.TypedValue;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
@@ -39,6 +47,8 @@
implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener,
DialogInterface.OnCancelListener {
private static final String TAG = "MediaProjectionPermissionActivity";
+ private static final float MAX_APP_NAME_SIZE_PX = 500f;
+ private static final String ELLIPSIS = "\u2026";
private boolean mPermanentGrant;
private String mPackageName;
@@ -84,11 +94,49 @@
return;
}
- String appName = aInfo.loadLabel(packageManager).toString();
+ TextPaint paint = new TextPaint();
+ paint.setTextSize(42);
+
+ String label = aInfo.loadLabel(packageManager).toString();
+
+ // If the label contains new line characters it may push the security
+ // message below the fold of the dialog. Labels shouldn't have new line
+ // characters anyways, so just truncate the message the first time one
+ // is seen.
+ final int labelLength = label.length();
+ int offset = 0;
+ while (offset < labelLength) {
+ final int codePoint = label.codePointAt(offset);
+ final int type = Character.getType(codePoint);
+ if (type == Character.LINE_SEPARATOR
+ || type == Character.CONTROL
+ || type == Character.PARAGRAPH_SEPARATOR) {
+ label = label.substring(0, offset) + ELLIPSIS;
+ break;
+ }
+ offset += Character.charCount(codePoint);
+ }
+
+ if (label.isEmpty()) {
+ label = mPackageName;
+ }
+
+ String unsanitizedAppName = TextUtils.ellipsize(label,
+ paint, MAX_APP_NAME_SIZE_PX, TextUtils.TruncateAt.END).toString();
+ String appName = BidiFormatter.getInstance().unicodeWrap(unsanitizedAppName);
+
+ String actionText = getString(R.string.media_projection_dialog_text, appName);
+ SpannableString message = new SpannableString(actionText);
+
+ int appNameIndex = actionText.indexOf(appName);
+ if (appNameIndex >= 0) {
+ message.setSpan(new StyleSpan(Typeface.BOLD),
+ appNameIndex, appNameIndex + appName.length(), 0);
+ }
mDialog = new AlertDialog.Builder(this)
.setIcon(aInfo.loadIcon(packageManager))
- .setMessage(getString(R.string.media_projection_dialog_text, appName))
+ .setMessage(message)
.setPositiveButton(R.string.media_projection_action_text, this)
.setNegativeButton(android.R.string.cancel, this)
.setView(R.layout.remember_permission_checkbox)
diff --git a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
index 803a014..728d558 100644
--- a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
@@ -21,6 +21,7 @@
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
import android.net.Uri;
import android.os.Looper;
import android.os.PowerManager;
@@ -36,7 +37,7 @@
* - whenever audio is played, audio focus is requested,
* - whenever audio playback is stopped or the playback completed, audio focus is abandoned.
*/
-public class NotificationPlayer implements OnCompletionListener {
+public class NotificationPlayer implements OnCompletionListener, OnErrorListener {
private static final int PLAY = 1;
private static final int STOP = 2;
private static final boolean mDebug = false;
@@ -112,6 +113,7 @@
// done playing. This class should be modified to use a single thread, on which
// command are issued, and on which it receives the completion callbacks.
player.setOnCompletionListener(NotificationPlayer.this);
+ player.setOnErrorListener(NotificationPlayer.this);
player.start();
if (mPlayer != null) {
mPlayer.release();
@@ -245,6 +247,13 @@
}
}
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ Log.e(mTag, "error " + what + " (extra=" + extra + ") playing notification");
+ // error happened, handle it just like a completion
+ onCompletion(mp);
+ return true;
+ }
+
private String mTag;
private CmdThread mThread;
private CreationAndCompletionThread mCompletionThread;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 947c19c..00ac5f9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents.views;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.TaskStackBuilder;
import android.content.Context;
@@ -31,6 +32,8 @@
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.SparseArray;
+import android.view.AppTransitionAnimationSpec;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowInsets;
@@ -60,6 +63,8 @@
private static final String TAG = "RecentsView";
+ private static final boolean ADD_HEADER_BITMAP = true;
+
/** The RecentsView callbacks */
public interface RecentsViewCallbacks {
public void onTaskViewClicked();
@@ -443,62 +448,158 @@
}
}
- private void postDrawHeaderThumbnailTransitionRunnable(final TaskView tv, final int offsetX,
- final int offsetY, final TaskViewTransform transform,
+ private void postDrawHeaderThumbnailTransitionRunnable(final TaskStackView view,
+ final TaskView clickedView, final int offsetX, final int offsetY,
+ final float stackScroll,
final ActivityOptions.OnAnimationStartedListener animStartedListener) {
Runnable r = new Runnable() {
@Override
public void run() {
- // Disable any focused state before we draw the header
- if (tv.isFocusedTask()) {
- tv.unsetFocusedTask();
- }
+ overrideDrawHeaderThumbnailTransition(view, clickedView, offsetX, offsetY,
+ stackScroll, animStartedListener);
- float scale = tv.getScaleX();
- int fromHeaderWidth = (int) (tv.mHeaderView.getMeasuredWidth() * scale);
- int fromHeaderHeight = (int) (tv.mHeaderView.getMeasuredHeight() * scale);
-
- Bitmap b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
- Bitmap.Config.ARGB_8888);
- if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
- b.eraseColor(0xFFff0000);
- } else {
- Canvas c = new Canvas(b);
- c.scale(tv.getScaleX(), tv.getScaleY());
- tv.mHeaderView.draw(c);
- c.setBitmap(null);
- }
- b = b.createAshmemBitmap();
- int[] pts = new int[2];
- tv.getLocationOnScreen(pts);
- try {
- WindowManagerGlobal.getWindowManagerService()
- .overridePendingAppTransitionAspectScaledThumb(b,
- pts[0] + offsetX,
- pts[1] + offsetY,
- transform.rect.width(),
- transform.rect.height(),
- new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data)
- throws RemoteException {
- post(new Runnable() {
- @Override
- public void run() {
- if (animStartedListener != null) {
- animStartedListener.onAnimationStarted();
- }
- }
- });
- }
- }, true);
- } catch (RemoteException e) {
- Log.w(TAG, "Error overriding app transition", e);
- }
}
};
+
mCb.runAfterPause(r);
}
+
+ private void overrideDrawHeaderThumbnailTransition(TaskStackView stackView,
+ TaskView clickedTask, int offsetX, int offsetY, float stackScroll,
+ final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+ List<AppTransitionAnimationSpec> specs = getAppTransitionAnimationSpecs(stackView,
+ clickedTask, offsetX, offsetY, stackScroll);
+ if (specs == null) {
+ return;
+ }
+
+ IRemoteCallback.Stub callback = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) throws RemoteException {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ if (animStartedListener != null) {
+ animStartedListener.onAnimationStarted();
+ }
+ }
+ });
+ }
+ };
+
+ AppTransitionAnimationSpec[] specsArray =
+ new AppTransitionAnimationSpec[specs.size()];
+ try {
+ WindowManagerGlobal.getWindowManagerService().overridePendingAppTransitionMultiThumb(
+ specs.toArray(specsArray), callback, true /* scaleUp */);
+
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error overriding app transition", e);
+ }
+ }
+
+ private List<AppTransitionAnimationSpec> getAppTransitionAnimationSpecs(TaskStackView stackView,
+ TaskView clickedTask, int offsetX, int offsetY, float stackScroll) {
+ final int targetStackId = clickedTask.getTask().key.stackId;
+ if (targetStackId != ActivityManager.FREEFORM_WORKSPACE_STACK_ID
+ && targetStackId != ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID) {
+ return null;
+ }
+ // If this is a full screen stack, the transition will be towards the single, full screen
+ // task. We only need the transition spec for this task.
+ List<AppTransitionAnimationSpec> specs = new ArrayList<>();
+ if (targetStackId == ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID) {
+ specs.add(createThumbnailHeaderAnimationSpec(
+ stackView, offsetX, offsetY, stackScroll, clickedTask,
+ clickedTask.getTask().key.id, ADD_HEADER_BITMAP));
+ return specs;
+ }
+ // This is a free form stack or full screen stack, so there will be multiple windows
+ // animating from thumbnails. We need transition animation specs for all of them.
+
+ // We will use top and bottom task views as a base for tasks, that aren't visible on the
+ // screen. This is necessary for cascade recents list, where some of the tasks might be
+ // hidden.
+ List<TaskView> taskViews = stackView.getTaskViews();
+ int childCount = taskViews.size();
+ TaskView topChild = taskViews.get(0);
+ TaskView bottomChild = taskViews.get(childCount - 1);
+ SparseArray<TaskView> taskViewsByTaskId = new SparseArray<>();
+ for (int i = 0; i < childCount; i++) {
+ TaskView taskView = taskViews.get(i);
+ taskViewsByTaskId.put(taskView.getTask().key.id, taskView);
+ }
+
+ TaskStack stack = stackView.getStack();
+ // We go through all tasks now and for each generate transition animation spec. If there is
+ // a view associated with a task, we use that view as a base for the animation. If there
+ // isn't, we use bottom or top view, depending on which one would be closer to the task
+ // view if it existed.
+ ArrayList<Task> tasks = stack.getTasks();
+ boolean passedClickedTask = false;
+ for (int i = 0, n = tasks.size(); i < n; i++) {
+ Task task = tasks.get(i);
+ TaskView taskView = taskViewsByTaskId.get(task.key.id);
+ if (taskView != null) {
+ specs.add(createThumbnailHeaderAnimationSpec(stackView, offsetX, offsetY,
+ stackScroll, taskView, taskView.getTask().key.id, ADD_HEADER_BITMAP));
+ if (taskView == clickedTask) {
+ passedClickedTask = true;
+ }
+ } else {
+ taskView = passedClickedTask ? bottomChild : topChild;
+ specs.add(createThumbnailHeaderAnimationSpec(stackView, offsetX, offsetY,
+ stackScroll, taskView, task.key.id, !ADD_HEADER_BITMAP));
+ }
+ }
+
+ return specs;
+ }
+
+ private AppTransitionAnimationSpec createThumbnailHeaderAnimationSpec(TaskStackView stackView,
+ int offsetX, int offsetY, float stackScroll, TaskView tv, int taskId,
+ boolean addHeaderBitmap) {
+ // Disable any focused state before we draw the header
+ // Upfront the processing of the thumbnail
+ if (tv.isFocusedTask()) {
+ tv.unsetFocusedTask();
+ }
+ TaskViewTransform transform = new TaskViewTransform();
+ transform = stackView.getStackAlgorithm().getStackTransform(tv.mTask, stackScroll,
+ transform, null);
+
+ float scale = tv.getScaleX();
+ int fromHeaderWidth = (int) (tv.mHeaderView.getMeasuredWidth() * scale);
+ int fromHeaderHeight = (int) (tv.mHeaderView.getMeasuredHeight() * scale);
+
+ Bitmap b = null;
+ if (addHeaderBitmap) {
+ b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
+ Bitmap.Config.ARGB_8888);
+
+ if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+ b.eraseColor(0xFFff0000);
+ } else {
+ Canvas c = new Canvas(b);
+ c.scale(tv.getScaleX(), tv.getScaleY());
+ tv.mHeaderView.draw(c);
+ c.setBitmap(null);
+
+ }
+ b = b.createAshmemBitmap();
+ }
+
+ int[] pts = new int[2];
+ tv.getLocationOnScreen(pts);
+
+ final int left = pts[0] + offsetX;
+ final int top = pts[1] + offsetY;
+ final Rect rect = new Rect(left, top, left + transform.rect.width(),
+ top + transform.rect.height());
+
+ return new AppTransitionAnimationSpec(taskId, b, rect);
+ }
+
/**** TaskStackView.TaskStackCallbacks Implementation ****/
@Override
@@ -521,12 +622,10 @@
// and then offset to the expected transform rect, but bound this to just
// outside the display rect (to ensure we don't animate from too far away)
sourceView = stackView;
- transform = stackView.getStackAlgorithm().getStackTransform(task, stackScroll, transform, null);
offsetX = transform.rect.left;
offsetY = mConfig.displayRect.height();
} else {
sourceView = tv.mThumbnailView;
- transform = stackView.getStackAlgorithm().getStackTransform(task, stackScroll, transform, null);
}
// Compute the thumbnail to scale up from
@@ -553,10 +652,8 @@
}
};
}
- if (tv != null) {
- postDrawHeaderThumbnailTransitionRunnable(tv, offsetX, offsetY, transform,
- animStartedListener);
- }
+ postDrawHeaderThumbnailTransitionRunnable(stackView, tv, offsetX, offsetY, stackScroll,
+ animStartedListener);
if (mConfig.multiStackEnabled) {
opts = ActivityOptions.makeCustomAnimation(sourceView.getContext(),
R.anim.recents_from_unknown_enter,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 7f17885..c1dfec3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -34,6 +34,7 @@
import android.view.animation.PathInterpolator;
import com.android.systemui.R;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
/**
* Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer}
@@ -128,6 +129,7 @@
private final int mNormalColor;
private final int mLowPriorityColor;
private boolean mIsBelowSpeedBump;
+ private LockedPhoneAnalytics mLockedPhoneAnalytics;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -151,6 +153,7 @@
R.color.notification_ripple_color_low_priority);
mNormalRippleColor = context.getColor(
R.color.notification_ripple_untinted_color);
+ mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
}
@Override
@@ -219,6 +222,7 @@
makeActive();
postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
} else {
+ mLockedPhoneAnalytics.onNotificationDoubleTap();
boolean performed = performClick();
if (performed) {
removeCallbacks(mTapTimeoutRunnable);
@@ -238,6 +242,7 @@
}
private void makeActive() {
+ mLockedPhoneAnalytics.onNotificationActive();
startActivateAnimation(false /* reverse */);
mActivated = true;
if (mOnActivatedListener != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index a55256d..de6c4b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -91,6 +91,7 @@
import com.android.internal.util.NotificationColorUtil;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.DejankUtils;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SwipeHelper;
@@ -135,6 +136,7 @@
protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024;
protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025;
+ protected static final int MSG_SHOW_KEYBOARD_SHORTCUTS_MENU = 1026;
protected static final boolean ENABLE_HEADS_UP = true;
// scores above this threshold should be displayed in heads up mode.
@@ -1066,6 +1068,13 @@
mHandler.sendEmptyMessage(msg);
}
+ @Override
+ public void showKeyboardShortcutsMenu() {
+ int msg = MSG_SHOW_KEYBOARD_SHORTCUTS_MENU;
+ mHandler.removeMessages(msg);
+ mHandler.sendEmptyMessage(msg);
+ }
+
/** Jumps to the next affiliated task in the group. */
public void showNextAffiliatedTask() {
int msg = MSG_SHOW_NEXT_AFFILIATED_TASK;
@@ -1143,6 +1152,10 @@
}
}
+ protected void showKeyboardShortcuts() {
+ Toast.makeText(mContext, "Show keyboard shortcuts screen", Toast.LENGTH_LONG).show();
+ }
+
protected void cancelPreloadingRecents() {
if (mRecents != null) {
mRecents.cancelPreloadingRecents();
@@ -1253,6 +1266,9 @@
case MSG_SHOW_PREV_AFFILIATED_TASK:
showRecentsPreviousAffiliatedTask();
break;
+ case MSG_SHOW_KEYBOARD_SHORTCUTS_MENU:
+ showKeyboardShortcuts();
+ break;
}
}
}
@@ -1609,6 +1625,15 @@
final PendingIntent intent = sbn.getNotification().contentIntent;
final String notificationKey = sbn.getKey();
+ // Mark notification for one frame.
+ row.setJustClicked(true);
+ DejankUtils.postAfterTraversal(new Runnable() {
+ @Override
+ public void run() {
+ row.setJustClicked(false);
+ }
+ });
+
if (NOTIFICATION_CLICK_DEBUG) {
Log.d(TAG, "Clicked on content of " + notificationKey);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index a1b07b5..b01a2a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -64,6 +64,8 @@
private static final int MSG_APP_TRANSITION_STARTING = 21 << MSG_SHIFT;
private static final int MSG_ASSIST_DISCLOSURE = 22 << MSG_SHIFT;
private static final int MSG_START_ASSIST = 23 << MSG_SHIFT;
+ private static final int MSG_CAMERA_LAUNCH_GESTURE = 24 << MSG_SHIFT;
+ private static final int MSG_SHOW_KEYBOARD_SHORTCUTS = 25 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -98,6 +100,7 @@
public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
public void toggleRecentApps();
public void preloadRecentApps();
+ public void showKeyboardShortcutsMenu();
public void cancelPreloadRecentApps();
public void setWindowState(int window, int state);
public void buzzBeepBlinked();
@@ -109,6 +112,7 @@
public void appTransitionStarting(long startTime, long duration);
public void showAssistDisclosure();
public void startAssist(Bundle args);
+ public void onCameraLaunchGestureDetected();
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -224,6 +228,14 @@
}
}
+ @Override
+ public void showKeyboardShortcutsMenu() {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_SHOW_KEYBOARD_SHORTCUTS);
+ mHandler.obtainMessage(MSG_SHOW_KEYBOARD_SHORTCUTS).sendToTarget();
+ }
+ }
+
public void setWindowState(int window, int state) {
synchronized (mList) {
// don't coalesce these
@@ -293,6 +305,14 @@
}
}
+ @Override
+ public void onCameraLaunchGestureDetected() {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_CAMERA_LAUNCH_GESTURE);
+ mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
@@ -360,6 +380,9 @@
case MSG_CANCEL_PRELOAD_RECENT_APPS:
mCallbacks.cancelPreloadRecentApps();
break;
+ case MSG_SHOW_KEYBOARD_SHORTCUTS:
+ mCallbacks.showKeyboardShortcutsMenu();
+ break;
case MSG_SET_WINDOW_STATE:
mCallbacks.setWindowState(msg.arg1, msg.arg2);
break;
@@ -391,6 +414,9 @@
case MSG_START_ASSIST:
mCallbacks.startAssist((Bundle) msg.obj);
break;
+ case MSG_CAMERA_LAUNCH_GESTURE:
+ mCallbacks.onCameraLaunchGestureDetected();
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 15a092c..e2304c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -29,6 +29,7 @@
import com.android.systemui.ExpandHelper;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
/**
* A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
@@ -54,6 +55,7 @@
private ExpandableView mStartingChild;
private Interpolator mInterpolator;
private float mLastHeight;
+ private LockedPhoneAnalytics mLockedPhoneAnalytics;
public DragDownHelper(Context context, View host, ExpandHelper.Callback callback,
DragDownCallback dragDownCallback) {
@@ -65,6 +67,7 @@
mCallback = callback;
mDragDownCallback = dragDownCallback;
mHost = host;
+ mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
}
@Override
@@ -84,6 +87,7 @@
case MotionEvent.ACTION_MOVE:
final float h = y - mInitialTouchY;
if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) {
+ mLockedPhoneAnalytics.onNotificatonStartDraggingDown();
mDraggingDown = true;
captureStartingChild(mInitialTouchX, mInitialTouchY);
mInitialTouchY = y;
@@ -201,6 +205,7 @@
}
private void stopDragging() {
+ mLockedPhoneAnalytics.onNotificatonStopDraggingDown();
if (mStartingChild != null) {
cancelExpansion(mStartingChild);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index b88e5ca..564a60a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -24,6 +24,7 @@
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -34,6 +35,7 @@
import android.widget.ImageView;
import com.android.systemui.R;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
@@ -109,6 +111,9 @@
!mChildrenExpanded);
}
};
+ private LockedPhoneAnalytics mLockedPhoneAnalytics;
+
+ private boolean mJustClicked;
public NotificationContentView getPrivateLayout() {
return mPrivateLayout;
@@ -301,12 +306,28 @@
return mHeadsUpHeight;
}
+ /**
+ * Mark whether this notification was just clicked, i.e. the user has just clicked this
+ * notification in this frame.
+ */
+ public void setJustClicked(boolean justClicked) {
+ mJustClicked = justClicked;
+ }
+
+ /**
+ * @return true if this notification has been clicked in this frame, false otherwise
+ */
+ public boolean wasJustClicked() {
+ return mJustClicked;
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
+ mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
}
/**
@@ -494,6 +515,7 @@
* @param userExpanded whether the user wants this notification to be expanded
*/
public void setUserExpanded(boolean userExpanded) {
+ mLockedPhoneAnalytics.setNotificationExpanded();
if (userExpanded && !mExpandable) return;
final boolean wasExpanded = isExpanded();
mHasUserChangedExpansion = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 164c496..8058933 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -36,6 +36,7 @@
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.ImageView;
+
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.KeyguardAffordanceHelper;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -79,6 +80,7 @@
private float mRestingAlpha = KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT;
private boolean mSupportHardware;
private boolean mFinishing;
+ private boolean mLaunchingAffordance;
private CanvasProperty<Float> mHwCircleRadius;
private CanvasProperty<Float> mHwCenterX;
@@ -152,7 +154,7 @@
@Override
protected void onDraw(Canvas canvas) {
- mSupportHardware = canvas.isHardwareAccelerated();
+ mSupportHardware = false;//canvas.isHardwareAccelerated();
drawBackgroundCircle(canvas);
canvas.save();
canvas.scale(mImageScale, mImageScale, getWidth() / 2, getHeight() / 2);
@@ -161,9 +163,11 @@
}
public void setPreviewView(View v) {
+ View oldPreviewView = mPreviewView;
mPreviewView = v;
if (mPreviewView != null) {
- mPreviewView.setVisibility(INVISIBLE);
+ mPreviewView.setVisibility(mLaunchingAffordance
+ ? oldPreviewView.getVisibility() : INVISIBLE);
}
}
@@ -176,7 +180,7 @@
}
private void drawBackgroundCircle(Canvas canvas) {
- if (mCircleRadius > 0) {
+ if (mCircleRadius > 0 || mFinishing) {
if (mFinishing && mSupportHardware) {
DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
displayListCanvas.drawCircle(mHwCenterX, mHwCenterY, mHwCircleRadius,
@@ -207,11 +211,12 @@
cancelAnimator(mPreviewClipper);
mFinishing = true;
mCircleStartRadius = mCircleRadius;
- float maxCircleSize = getMaxCircleSize();
+ final float maxCircleSize = getMaxCircleSize();
Animator animatorToRadius;
if (mSupportHardware) {
initHwProperties();
animatorToRadius = getRtAnimatorToRadius(maxCircleSize);
+ startRtAlphaFadeIn();
} else {
animatorToRadius = getAnimatorToRadius(maxCircleSize);
}
@@ -222,6 +227,8 @@
public void onAnimationEnd(Animator animation) {
mAnimationEndRunnable.run();
mFinishing = false;
+ mCircleRadius = maxCircleSize;
+ invalidate();
}
});
animatorToRadius.start();
@@ -241,6 +248,36 @@
}
}
+ /**
+ * Fades in the Circle on the RenderThread. It's used when finishing the circle when it had
+ * alpha 0 in the beginning.
+ */
+ private void startRtAlphaFadeIn() {
+ if (mCircleRadius == 0 && mPreviewView == null) {
+ Paint modifiedPaint = new Paint(mCirclePaint);
+ modifiedPaint.setColor(mCircleColor);
+ modifiedPaint.setAlpha(0);
+ mHwCirclePaint = CanvasProperty.createPaint(modifiedPaint);
+ RenderNodeAnimator animator = new RenderNodeAnimator(mHwCirclePaint,
+ RenderNodeAnimator.PAINT_ALPHA, 255);
+ animator.setTarget(this);
+ animator.setInterpolator(PhoneStatusBar.ALPHA_IN);
+ animator.setDuration(250);
+ animator.start();
+ }
+ }
+
+ public void instantFinishAnimation() {
+ cancelAnimator(mPreviewClipper);
+ if (mPreviewView != null) {
+ mPreviewView.setClipBounds(null);
+ mPreviewView.setVisibility(View.VISIBLE);
+ }
+ mCircleRadius = getMaxCircleSize();
+ setImageAlpha(0, false);
+ invalidate();
+ }
+
private void startRtCircleFadeOut(long duration) {
RenderNodeAnimator animator = new RenderNodeAnimator(mHwCirclePaint,
RenderNodeAnimator.PAINT_ALPHA, 0);
@@ -443,6 +480,7 @@
public void setImageAlpha(float alpha, boolean animate, long duration,
Interpolator interpolator, Runnable runnable) {
cancelAnimator(mAlphaAnimator);
+ alpha = mLaunchingAffordance ? 0 : alpha;
int endAlpha = (int) (alpha * 255);
final Drawable background = getBackground();
if (!animate) {
@@ -509,4 +547,8 @@
return false;
}
}
+
+ public void setLaunchingAffordance(boolean launchingAffordance) {
+ mLaunchingAffordance = launchingAffordance;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index 01aa8d1..8688c28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -86,6 +86,9 @@
if (mBackground != null) {
mBackground.setCallback(this);
}
+ if (mBackground instanceof RippleDrawable) {
+ ((RippleDrawable) mBackground).setForceSoftware(true);
+ }
invalidate();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java
index 5ec5147..e34c821 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java
@@ -17,24 +17,26 @@
package com.android.systemui.statusbar.phone;
import android.content.ComponentName;
+import android.os.UserHandle;
/**
* Navigation bar app information.
*/
class AppInfo {
private final ComponentName mComponentName;
- private final long mUserSerialNumber;
+ private final UserHandle mUser;
- public AppInfo(ComponentName componentName, long userSerialNumber) {
+ public AppInfo(ComponentName componentName, UserHandle user) {
+ if (componentName == null || user == null) throw new IllegalArgumentException();
mComponentName = componentName;
- mUserSerialNumber = userSerialNumber;
+ mUser = user;
}
public ComponentName getComponentName() {
return mComponentName;
}
- public long getUserSerialNumber() {
- return mUserSerialNumber;
+ public UserHandle getUser() {
+ return mUser;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 4d3e57e..3ff69c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -104,13 +104,11 @@
* Aborts pulsing immediately.
*/
public void abortPulsing() {
- mHandler.removeCallbacks(mPulseIn);
- abortAnimations();
+ cancelPulsing();
if (mDozing) {
mScrimController.setDozeBehindAlpha(1f);
mScrimController.setDozeInFrontAlpha(1f);
}
- mPulseCallback = null;
}
public void onScreenTurnedOn() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 28d4a42ef..4e69999 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -183,8 +183,11 @@
mStatusBarKeyguardViewManager.animateCollapsePanels(
FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
break;
- case MODE_WAKE_AND_UNLOCK:
case MODE_WAKE_AND_UNLOCK_PULSING:
+ mPhoneStatusBar.updateMediaMetaData(false /* metaDataChanged */);
+ // Fall through.
+ case MODE_WAKE_AND_UNLOCK:
+ mStatusBarWindowManager.setStatusBarFocusable(false);
mDozeScrimController.abortPulsing();
mKeyguardViewMediator.onWakeAndUnlocking();
mScrimController.setWakeAndUnlocking();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/GetActivityIconTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/GetActivityIconTask.java
index 076378e..f46d1a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/GetActivityIconTask.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/GetActivityIconTask.java
@@ -16,20 +16,21 @@
package com.android.systemui.statusbar.phone;
-import android.content.ComponentName;
+import android.app.AppGlobals;
+import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
+import android.os.RemoteException;
import android.util.Slog;
-import android.view.View;
import android.widget.ImageView;
/**
* Retrieves the icon for an activity and sets it as the Drawable on an ImageView. The ImageView
* is hidden if the activity isn't recognized or if there is no icon.
*/
-class GetActivityIconTask extends AsyncTask<ComponentName, Void, Drawable> {
+class GetActivityIconTask extends AsyncTask<AppInfo, Void, Drawable> {
private final static String TAG = "GetActivityIconTask";
private final PackageManager mPackageManager;
@@ -43,15 +44,27 @@
}
@Override
- protected Drawable doInBackground(ComponentName... params) {
+ protected Drawable doInBackground(AppInfo... params) {
if (params.length != 1) {
throw new IllegalArgumentException("Expected one parameter");
}
- ComponentName activityName = params[0];
+ AppInfo appInfo = params[0];
try {
- return mPackageManager.getActivityIcon(activityName);
- } catch (NameNotFoundException e) {
- Slog.w(TAG, "Icon not found for " + activityName);
+ IPackageManager mPM = AppGlobals.getPackageManager();
+ ActivityInfo ai = mPM.getActivityInfo(
+ appInfo.getComponentName(),
+ 0,
+ appInfo.getUser().getIdentifier());
+
+ if (ai == null) {
+ Slog.w(TAG, "Icon not found for " + appInfo);
+ return null;
+ }
+
+ Drawable unbadgedIcon = ai.loadIcon(mPackageManager);
+ return mPackageManager.getUserBadgedIcon(unbadgedIcon, appInfo.getUser());
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Icon not found for " + appInfo, e);
return null;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 10019f9..60ebfdf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -86,9 +86,9 @@
mContext = context;
mCallback = callback;
initIcons();
- updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true);
- updateIcon(mCenterIcon, 0.0f, mCenterIcon.getRestingAlpha(), false, false, true);
- updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true);
+ updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true, false);
+ updateIcon(mCenterIcon, 0.0f, mCenterIcon.getRestingAlpha(), false, false, true, false);
+ updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true, false);
initDimens();
}
@@ -144,9 +144,7 @@
} else {
mTouchSlopExeeded = false;
}
- mCallback.onSwipingStarted(targetView == mRightIcon);
- mSwipingInProgress = true;
- mTargetedView = targetView;
+ startSwiping(targetView);
mInitialTouchX = x;
mInitialTouchY = y;
mTranslationOnDown = mTranslation;
@@ -192,6 +190,12 @@
return true;
}
+ private void startSwiping(View targetView) {
+ mCallback.onSwipingStarted(targetView == mRightIcon);
+ mSwipingInProgress = true;
+ mTargetedView = targetView;
+ }
+
private View getIconAtPosition(float x, float y) {
if (leftSwipePossible() && isOnIcon(mLeftIcon, x, y)) {
return mLeftIcon;
@@ -324,7 +328,7 @@
boolean velIsInWrongDirection = vel * mTranslation < 0;
snapBack |= Math.abs(vel) > mMinFlingVelocity && velIsInWrongDirection;
vel = snapBack ^ velIsInWrongDirection ? 0 : vel;
- fling(vel, snapBack || forceSnapBack);
+ fling(vel, snapBack || forceSnapBack, mTranslation < 0);
}
private boolean isBelowFalsingThreshold() {
@@ -336,9 +340,8 @@
return (int) (mMinTranslationAmount * factor);
}
- private void fling(float vel, final boolean snapBack) {
- float target = mTranslation < 0
- ? -mCallback.getMaxTranslationDistance()
+ private void fling(float vel, final boolean snapBack, boolean right) {
+ float target = right ? -mCallback.getMaxTranslationDistance()
: mCallback.getMaxTranslationDistance();
target = snapBack ? 0 : target;
@@ -352,8 +355,8 @@
});
animator.addListener(mFlingEndListener);
if (!snapBack) {
- startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable);
- mCallback.onAnimationToSideStarted(mTranslation < 0, mTranslation, vel);
+ startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable, right);
+ mCallback.onAnimationToSideStarted(right, mTranslation, vel);
} else {
reset(true);
}
@@ -364,8 +367,9 @@
}
}
- private void startFinishingCircleAnimation(float velocity, Runnable mAnimationEndRunnable) {
- KeyguardAffordanceView targetView = mTranslation > 0 ? mLeftIcon : mRightIcon;
+ private void startFinishingCircleAnimation(float velocity, Runnable mAnimationEndRunnable,
+ boolean right) {
+ KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
targetView.finishAnimation(velocity, mAnimationEndRunnable);
}
@@ -383,19 +387,20 @@
fadeOutAlpha = Math.max(fadeOutAlpha, 0.0f);
boolean animateIcons = isReset && animateReset;
+ boolean forceNoCircleAnimation = isReset && !animateReset;
float radius = getRadiusFromTranslation(absTranslation);
boolean slowAnimation = isReset && isBelowFalsingThreshold();
if (!isReset) {
updateIcon(targetView, radius, alpha + fadeOutAlpha * targetView.getRestingAlpha(),
- false, false, false);
+ false, false, false, false);
} else {
updateIcon(targetView, 0.0f, fadeOutAlpha * targetView.getRestingAlpha(),
- animateIcons, slowAnimation, false);
+ animateIcons, slowAnimation, false, forceNoCircleAnimation);
}
updateIcon(otherView, 0.0f, fadeOutAlpha * otherView.getRestingAlpha(),
- animateIcons, slowAnimation, false);
+ animateIcons, slowAnimation, false, forceNoCircleAnimation);
updateIcon(mCenterIcon, 0.0f, fadeOutAlpha * mCenterIcon.getRestingAlpha(),
- animateIcons, slowAnimation, false);
+ animateIcons, slowAnimation, false, forceNoCircleAnimation);
mTranslation = translation;
}
@@ -431,16 +436,21 @@
public void animateHideLeftRightIcon() {
cancelAnimation();
- updateIcon(mRightIcon, 0f, 0f, true, false, false);
- updateIcon(mLeftIcon, 0f, 0f, true, false, false);
+ updateIcon(mRightIcon, 0f, 0f, true, false, false, false);
+ updateIcon(mLeftIcon, 0f, 0f, true, false, false, false);
}
private void updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha,
- boolean animate, boolean slowRadiusAnimation, boolean force) {
+ boolean animate, boolean slowRadiusAnimation, boolean force,
+ boolean forceNoCircleAnimation) {
if (view.getVisibility() != View.VISIBLE && !force) {
return;
}
- view.setCircleRadius(circleRadius, slowRadiusAnimation);
+ if (forceNoCircleAnimation) {
+ view.setCircleRadiusWithoutAnimation(circleRadius);
+ } else {
+ view.setCircleRadius(circleRadius, slowRadiusAnimation);
+ }
updateIconAlpha(view, alpha, animate);
}
@@ -503,8 +513,36 @@
mMotionCancelled = true;
if (mSwipingInProgress) {
mCallback.onSwipingAborted();
+ mSwipingInProgress = false;
}
- mSwipingInProgress = false;
+ }
+
+ public boolean isSwipingInProgress() {
+ return mSwipingInProgress;
+ }
+
+ public void launchAffordance(boolean animate, boolean left) {
+ if (mSwipingInProgress) {
+ // We don't want to mess with the state if the user is actually swiping already.
+ return;
+ }
+ KeyguardAffordanceView targetView = left ? mLeftIcon : mRightIcon;
+ KeyguardAffordanceView otherView = left ? mRightIcon : mLeftIcon;
+ startSwiping(targetView);
+ if (animate) {
+ fling(0, false, !left);
+ updateIcon(otherView, 0.0f, 0, true, false, true, false);
+ updateIcon(mCenterIcon, 0.0f, 0, true, false, true, false);
+ } else {
+ mCallback.onAnimationToSideStarted(!left, mTranslation, 0);
+ mTranslation = left ? mCallback.getMaxTranslationDistance()
+ : mCallback.getMaxTranslationDistance();
+ updateIcon(mCenterIcon, 0.0f, 0.0f, false, false, true, false);
+ updateIcon(otherView, 0.0f, 0.0f, false, false, true, false);
+ targetView.instantFinishAnimation();
+ mFlingEndListener.onAnimationEnd(null);
+ mAnimationEndRunnable.run();
+ }
}
public interface Callback {
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 4da9acd..d30411a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -80,7 +80,7 @@
private static final Intent SECURE_CAMERA_INTENT =
new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- private static final Intent INSECURE_CAMERA_INTENT =
+ public static final Intent INSECURE_CAMERA_INTENT =
new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
@@ -649,7 +649,7 @@
}
@Override
- public void onStrongAuthTimeoutExpiredChanged(int userId) {
+ public void onStrongAuthStateChanged(int userId) {
mLockIcon.update();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 8b96e5f..cbd23bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -31,6 +31,7 @@
import com.android.keyguard.R;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
import static com.android.keyguard.KeyguardHostView.OnDismissAction;
import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
@@ -49,10 +50,11 @@
private ViewGroup mRoot;
private boolean mShowingSoon;
private int mBouncerPromptReason;
+ private LockedPhoneAnalytics mLockedPhoneAnalytics;
private KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
- public void onStrongAuthTimeoutExpiredChanged(int userId) {
+ public void onStrongAuthStateChanged(int userId) {
mBouncerPromptReason = mCallback.getBouncerPromptReason();
}
};
@@ -66,9 +68,11 @@
mContainer = container;
mWindowManager = windowManager;
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
+ mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(mContext);
}
public void show(boolean resetSecuritySelection) {
+ mLockedPhoneAnalytics.onBouncerShown();
ensureView();
if (resetSecuritySelection) {
// showPrimarySecurityScreen() updates the current security method. This is needed in
@@ -128,6 +132,7 @@
}
public void hide(boolean destroyView) {
+ mLockedPhoneAnalytics.onBouncerHidden();
cancelShowRunnable();
if (mKeyguardView != null) {
mKeyguardView.cancelDismissAction();
@@ -157,6 +162,7 @@
public void reset() {
cancelShowRunnable();
inflateView();
+ mLockedPhoneAnalytics.onBouncerHidden();
}
public void onScreenTurnedOff() {
@@ -244,6 +250,7 @@
// We need to show it in case it is secure. If not, it will get dismissed in any case.
mRoot.setVisibility(View.VISIBLE);
+ mLockedPhoneAnalytics.onBouncerShown();
mKeyguardView.requestFocus();
mKeyguardView.onResume();
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
index d74c5b0..adcec98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
-import android.app.AppGlobals;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ClipDescription;
@@ -29,17 +28,12 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
-import android.content.pm.ActivityInfo;
-import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.Slog;
import android.view.DragEvent;
import android.view.LayoutInflater;
@@ -49,10 +43,9 @@
import android.widget.LinearLayout;
import android.widget.Toast;
+import com.android.internal.content.PackageMonitor;
import com.android.systemui.R;
-import java.util.List;
-
/**
* Container for application icons that appear in the navigation bar. Their appearance is similar
* to the launcher hotseat. Clicking an icon launches the associated activity. A long click will
@@ -75,6 +68,8 @@
private final PackageManager mPackageManager;
private final UserManager mUserManager;
private final LayoutInflater mLayoutInflater;
+ private final AppPackageMonitor mAppPackageMonitor;
+
// This view has two roles:
// 1) If the drag started outside the pinned apps list, it is a placeholder icon with a null
@@ -85,8 +80,6 @@
// When the user is not dragging this member is null.
private View mDragView;
- private long mCurrentUserSerialNumber = -1;
-
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -94,6 +87,9 @@
if (Intent.ACTION_USER_SWITCHED.equals(action)) {
int currentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
onUserSwitched(currentUserId);
+ } else if (Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
+ UserHandle removedProfile = intent.getParcelableExtra(Intent.EXTRA_USER);
+ onManagedProfileRemoved(removedProfile);
}
}
};
@@ -106,6 +102,7 @@
mPackageManager = context.getPackageManager();
mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
mLayoutInflater = LayoutInflater.from(context);
+ mAppPackageMonitor = new AppPackageMonitor();
// Dragging an icon removes and adds back the dragged icon. Use the layout transitions to
// trigger animation. By default all transitions animate, so turn off the unneeded ones.
@@ -121,6 +118,76 @@
setLayoutTransition(transition);
}
+ // Monitor that catches events like "app uninstalled".
+ private class AppPackageMonitor extends PackageMonitor {
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ postRemoveIfUnlauncheable(packageName, new UserHandle(getChangingUserId()));
+ super.onPackageRemoved(packageName, uid);
+ }
+
+ @Override
+ public void onPackageModified(String packageName) {
+ postRemoveIfUnlauncheable(packageName, new UserHandle(getChangingUserId()));
+ super.onPackageModified(packageName);
+ }
+
+ @Override
+ public void onPackagesAvailable(String[] packages) {
+ if (isReplacing()) {
+ UserHandle user = new UserHandle(getChangingUserId());
+
+ for (String packageName : packages) {
+ postRemoveIfUnlauncheable(packageName, user);
+ }
+ }
+ super.onPackagesAvailable(packages);
+ }
+
+ @Override
+ public void onPackagesUnavailable(String[] packages) {
+ if (!isReplacing()) {
+ UserHandle user = new UserHandle(getChangingUserId());
+
+ for (String packageName : packages) {
+ postRemoveIfUnlauncheable(packageName, user);
+ }
+ }
+ super.onPackagesUnavailable(packages);
+ }
+ }
+
+ private void postRemoveIfUnlauncheable(final String packageName, final UserHandle user) {
+ // This method doesn't necessarily get called in the main thread. Redirect the call into
+ // the main thread.
+ post(new Runnable() {
+ @Override
+ public void run() {
+ if (!isAttachedToWindow()) return;
+ removeIfUnlauncheable(packageName, user);
+ }
+ });
+ }
+
+ private void removeIfUnlauncheable(String packageName, UserHandle user) {
+ // Remove icons for all apps that match a package that perhaps became unlauncheable.
+ for(int i = sAppsModel.getAppCount() - 1; i >= 0; --i) {
+ AppInfo appInfo = sAppsModel.getApp(i);
+ if (!appInfo.getUser().equals(user)) continue;
+
+ ComponentName appComponentName = appInfo.getComponentName();
+ if (!appComponentName.getPackageName().equals(packageName)) continue;
+
+ if (sAppsModel.buildAppLaunchIntent(appInfo) != null) {
+ continue;
+ }
+
+ removeViewAt(i);
+ sAppsModel.removeApp(i);
+ sAppsModel.savePrefs();
+ }
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -136,21 +203,22 @@
transition.enableTransitionType(LayoutTransition.CHANGING);
parent.setLayoutTransition(transition);
- int currentUserId = ActivityManager.getCurrentUser();
- mCurrentUserSerialNumber = mUserManager.getSerialNumberForUser(
- new UserHandle(currentUserId));
- sAppsModel.setCurrentUser(currentUserId);
+ sAppsModel.setCurrentUser(ActivityManager.getCurrentUser());
recreateAppButtons();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
mContext.registerReceiver(mBroadcastReceiver, filter);
+
+ mAppPackageMonitor.register(mContext, null, UserHandle.ALL, true);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mContext.unregisterReceiver(mBroadcastReceiver);
+ mAppPackageMonitor.unregister();
}
/**
@@ -171,7 +239,7 @@
button.setContentDescription(appLabel);
// Load the icon asynchronously.
- new GetActivityIconTask(mPackageManager, button).execute(app.getComponentName());
+ new GetActivityIconTask(mPackageManager, button).execute(app);
}
}
@@ -207,7 +275,7 @@
*/
@Nullable
static CharSequence getAppLabel(PackageManager packageManager,
- ComponentName activityName) {
+ ComponentName activityName) {
String packageName = activityName.getPackageName();
ApplicationInfo info;
try {
@@ -223,7 +291,10 @@
static void startAppDrag(ImageView icon, AppInfo appInfo) {
// The drag data is an Intent to launch the activity.
Intent mainIntent = Intent.makeMainActivity(appInfo.getComponentName());
- mainIntent.putExtra(EXTRA_PROFILE, appInfo.getUserSerialNumber());
+ UserManager userManager =
+ (UserManager) icon.getContext().getSystemService(Context.USER_SERVICE);
+ long userSerialNumber = userManager.getSerialNumberForUser(appInfo.getUser());
+ mainIntent.putExtra(EXTRA_PROFILE, userSerialNumber);
ClipData dragData = ClipData.newIntent("", mainIntent);
// Use the ImageView to create the shadow.
View.DragShadowBuilder shadow = new AppIconDragShadowBuilder(icon);
@@ -389,27 +460,38 @@
if (data.getItemCount() != 1) {
return null;
}
- Intent intent = data.getItemAt(0).getIntent();
+ ClipData.Item item = data.getItemAt(0);
+ if (item == null) {
+ return null;
+ }
+ Intent intent = item.getIntent();
if (intent == null) {
return null;
}
-
long userSerialNumber = intent.getLongExtra(EXTRA_PROFILE, -1);
-
- // Validate the received user serial number.
+ if (userSerialNumber == -1) {
+ return null;
+ }
UserHandle appUser = mUserManager.getUserForSerialNumber(userSerialNumber);
if (appUser == null) {
- userSerialNumber = mCurrentUserSerialNumber;
+ return null;
}
-
- return new AppInfo(intent.getComponent(), userSerialNumber);
+ ComponentName componentName = intent.getComponent();
+ if (componentName == null) {
+ return null;
+ }
+ AppInfo appInfo = new AppInfo(componentName, appUser);
+ if (sAppsModel.buildAppLaunchIntent(appInfo) == null) {
+ return null;
+ }
+ return appInfo;
}
/** Updates the app at a given view index. */
private void updateAppAt(int index, AppInfo appInfo) {
sAppsModel.setApp(index, appInfo);
ImageView button = (ImageView) getChildAt(index);
- new GetActivityIconTask(mPackageManager, button).execute(appInfo.getComponentName());
+ new GetActivityIconTask(mPackageManager, button).execute(appInfo);
}
/** Removes the empty placeholder view and cleans up the data model. */
@@ -467,18 +549,12 @@
@Override
public void onClick(View v) {
AppInfo appInfo = sAppsModel.getApp(indexOfChild(v));
- ComponentName component = appInfo.getComponentName();
-
- long appUserSerialNumber = appInfo.getUserSerialNumber();
-
- UserHandle appUser = mUserManager.getUserForSerialNumber(appUserSerialNumber);
- if (appUser == null) {
- Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
- Log.e(TAG, "Can't start activity " + component +
- " because its user doesn't exist.");
+ Intent launchIntent = sAppsModel.buildAppLaunchIntent(appInfo);
+ if (launchIntent == null) {
+ Toast.makeText(
+ getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
return;
}
- int appUserId = appUser.getIdentifier();
// Play a scale-up animation while launching the activity.
// TODO: Consider playing a different animation, or no animation, if the activity is
@@ -489,65 +565,27 @@
ActivityOptions opts =
ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getWidth(), v.getHeight());
Bundle optsBundle = opts.toBundle();
-
- // Launch the activity. This code is based on LauncherAppsService.startActivityAsUser code.
- Intent launchIntent = new Intent(Intent.ACTION_MAIN);
- launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
launchIntent.setSourceBounds(sourceBounds);
- launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- launchIntent.setPackage(component.getPackageName());
- IPackageManager pm = AppGlobals.getPackageManager();
- try {
- ActivityInfo info = pm.getActivityInfo(component, 0, appUserId);
- if (info == null) {
- Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
- Log.e(TAG, "Can't start activity " + component + " because it's not installed.");
- return;
- }
-
- if (!info.exported) {
- Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
- Log.e(TAG, "Can't start activity " + component + " because it doesn't have 'exported' attribute.");
- return;
- }
- } catch (RemoteException e) {
- Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
- Log.e(TAG, "Failed to get activity info for " + component, e);
- return;
- }
-
- // Check that the component actually has Intent.CATEGORY_LAUCNCHER
- // as calling startActivityAsUser ignores the category and just
- // resolves based on the component if present.
- List<ResolveInfo> apps = getContext().getPackageManager().queryIntentActivitiesAsUser(launchIntent,
- 0 /* flags */, appUserId);
- final int size = apps.size();
- for (int i = 0; i < size; ++i) {
- ActivityInfo activityInfo = apps.get(i).activityInfo;
- if (activityInfo.packageName.equals(component.getPackageName()) &&
- activityInfo.name.equals(component.getClassName())) {
- // Found an activity with category launcher that matches
- // this component so ok to launch.
- launchIntent.setComponent(component);
- mContext.startActivityAsUser(launchIntent, optsBundle, appUser);
- return;
- }
- }
-
- Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
- Log.e(TAG, "Attempt to launch activity without category Intent.CATEGORY_LAUNCHER " + component);
+ mContext.startActivityAsUser(launchIntent, optsBundle, appInfo.getUser());
}
}
private void onUserSwitched(int currentUserId) {
- final long newUserSerialNumber =
- mUserManager.getSerialNumberForUser(new UserHandle(currentUserId));
+ sAppsModel.setCurrentUser(currentUserId);
+ recreateAppButtons();
+ }
- if (newUserSerialNumber != mCurrentUserSerialNumber) {
- mCurrentUserSerialNumber = newUserSerialNumber;
- sAppsModel.setCurrentUser(currentUserId);
- recreateAppButtons();
+ private void onManagedProfileRemoved(UserHandle removedProfile) {
+ boolean removedApps = false;
+ for(int i = sAppsModel.getAppCount() - 1; i >= 0; --i) {
+ AppInfo appInfo = sAppsModel.getApp(i);
+ if (!appInfo.getUser().equals(removedProfile)) continue;
+
+ removeViewAt(i);
+ sAppsModel.removeApp(i);
+ removedApps = true;
}
+ if (removedApps) sAppsModel.savePrefs();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
index b8764cf..c7b9e1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
@@ -16,16 +16,23 @@
package com.android.systemui.statusbar.phone;
+import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Log;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -94,6 +101,73 @@
}
}
+ @VisibleForTesting
+ protected IPackageManager getPackageManager() {
+ return AppGlobals.getPackageManager();
+ }
+
+ // Returns a launch intent for a given app info, or null if the app info is unlauncheable.
+ public Intent buildAppLaunchIntent(AppInfo appInfo) {
+ ComponentName component = appInfo.getComponentName();
+ int appUserId = appInfo.getUser().getIdentifier();
+
+ if (mCurrentUserId != appUserId) {
+ // Check if app user is a profile of current user and the app user is enabled.
+ UserInfo appUserInfo = mUserManager.getUserInfo(appUserId);
+ UserInfo currentUserInfo = mUserManager.getUserInfo(mCurrentUserId);
+ if (appUserInfo == null || currentUserInfo == null
+ || appUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID
+ || appUserInfo.profileGroupId != currentUserInfo.profileGroupId
+ || !appUserInfo.isEnabled()) {
+ Log.e(TAG, "User " + appUserId +
+ " is is not a profile of the current user, or is disabled.");
+ return null;
+ }
+ }
+
+ // This code is based on LauncherAppsService.startActivityAsUser code.
+ Intent launchIntent = new Intent(Intent.ACTION_MAIN);
+ launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ launchIntent.setPackage(component.getPackageName());
+
+ try {
+ ActivityInfo info = getPackageManager().getActivityInfo(component, 0, appUserId);
+ if (info == null) {
+ Log.e(TAG, "Activity " + component + " is not installed.");
+ return null;
+ }
+
+ if (!info.exported) {
+ Log.e(TAG, "Activity " + component + " doesn't have 'exported' attribute.");
+ return null;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get activity info for " + component, e);
+ return null;
+ }
+
+ // Check that the component actually has Intent.CATEGORY_LAUNCHER
+ // as calling startActivityAsUser ignores the category and just
+ // resolves based on the component if present.
+ List<ResolveInfo> apps = mContext.getPackageManager().queryIntentActivitiesAsUser(launchIntent,
+ 0 /* flags */, appUserId);
+ final int size = apps.size();
+ for (int i = 0; i < size; ++i) {
+ ActivityInfo activityInfo = apps.get(i).activityInfo;
+ if (activityInfo.packageName.equals(component.getPackageName()) &&
+ activityInfo.name.equals(component.getClassName())) {
+ // Found an activity with category launcher that matches
+ // this component so ok to launch.
+ launchIntent.setComponent(component);
+ return launchIntent;
+ }
+ }
+
+ Log.e(TAG, "Activity doesn't have category Intent.CATEGORY_LAUNCHER " + component);
+ return null;
+ }
+
/**
* Reinitializes the model for a new user.
*/
@@ -105,7 +179,7 @@
int appCount = mPrefs.getInt(userPrefixed(APP_COUNT_PREF), -1);
if (appCount >= 0) {
- loadAppsFromPrefs();
+ loadAppsFromPrefs(appCount);
} else {
// We switched to this user for the first time ever. This is a good opportunity to clean
// prefs for users deleted in the past.
@@ -191,31 +265,52 @@
final AppInfo appInfo = mApps.get(i);
String componentNameString = appInfo.getComponentName().flattenToString();
edit.putString(prefNameForApp(i), componentNameString);
- edit.putLong(prefUserForApp(i), appInfo.getUserSerialNumber());
+ long userSerialNumber = mUserManager.getSerialNumberForUser(appInfo.getUser());
+ edit.putLong(prefUserForApp(i), userSerialNumber);
}
// Start an asynchronous disk write.
edit.apply();
}
- /** Loads the list of apps from SharedPreferences. */
- private void loadAppsFromPrefs() {
- int appCount = mPrefs.getInt(userPrefixed(APP_COUNT_PREF), -1);
- for (int i = 0; i < appCount; i++) {
- String prefValue = mPrefs.getString(prefNameForApp(i), null);
- if (prefValue == null) {
- Slog.w(TAG, "Couldn't find pref " + prefNameForApp(i));
- // Couldn't find the saved state. Just skip this item.
- continue;
- }
- ComponentName componentName = ComponentName.unflattenFromString(prefValue);
- long userSerialNumber = mPrefs.getLong(prefUserForApp(i), -1);
- if (userSerialNumber == -1) {
- Slog.w(TAG, "Couldn't find pref " + prefUserForApp(i));
- // Couldn't find the saved state. Just skip this item.
- continue;
- }
- mApps.add(new AppInfo(componentName, userSerialNumber));
+ /** Loads AppInfo from prefs. Returns null if something is wrong. */
+ private AppInfo loadAppFromPrefs(int index) {
+ String prefValue = mPrefs.getString(prefNameForApp(index), null);
+ if (prefValue == null) {
+ Slog.w(TAG, "Couldn't find pref " + prefNameForApp(index));
+ return null;
}
+ ComponentName componentName = ComponentName.unflattenFromString(prefValue);
+ if (componentName == null) {
+ Slog.w(TAG, "Invalid component name " + prefValue);
+ return null;
+ }
+ long userSerialNumber = mPrefs.getLong(prefUserForApp(index), -1);
+ if (userSerialNumber == -1) {
+ Slog.w(TAG, "Couldn't find pref " + prefUserForApp(index));
+ return null;
+ }
+ UserHandle appUser = mUserManager.getUserForSerialNumber(userSerialNumber);
+ if (appUser == null) {
+ Slog.w(TAG, "No user for serial " + userSerialNumber);
+ return null;
+ }
+ AppInfo appInfo = new AppInfo(componentName, appUser);
+ if (buildAppLaunchIntent(appInfo) == null) {
+ return null;
+ }
+ return appInfo;
+ }
+
+ /** Loads the list of apps from SharedPreferences. */
+ private void loadAppsFromPrefs(int appCount) {
+ for (int i = 0; i < appCount; i++) {
+ AppInfo appInfo = loadAppFromPrefs(i);
+ if (appInfo != null) {
+ mApps.add(appInfo);
+ }
+ }
+
+ if (appCount != mApps.size()) savePrefs();
}
/** Adds the first few apps from the owner profile. Used for demo purposes. */
@@ -231,7 +326,7 @@
ResolveInfo ri = apps.get(i);
ComponentName componentName = new ComponentName(
ri.activityInfo.packageName, ri.activityInfo.name);
- mApps.add(new AppInfo(componentName, mCurrentUserSerialNumber));
+ mApps.add(new AppInfo(componentName, new UserHandle(mCurrentUserId)));
}
savePrefs();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java
index b024ec4..1f71bc0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java
@@ -25,11 +25,12 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.UserManager;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
@@ -160,7 +161,8 @@
button.setVisibility(View.VISIBLE);
// Load the activity icon on a background thread.
- new GetActivityIconTask(mPackageManager, button).execute(getRealActivityForTask(task));
+ AppInfo app = new AppInfo(activityName, new UserHandle(task.userId));
+ new GetActivityIconTask(mPackageManager, button).execute(app);
final int taskPersistentId = task.persistentId;
button.setOnClickListener(new View.OnClickListener() {
@@ -171,7 +173,9 @@
try {
manager.startActivityFromRecents(taskPersistentId, null /* options */);
} catch (RemoteException e) {
- e.printStackTrace();
+ Log.e(TAG, "Exception when activating a recent task", e);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Exception when activating a recent task", e);
}
}
});
@@ -218,6 +222,35 @@
mContext = context;
}
+ private ComponentName getLaunchComponentForPackage(String packageName, int userId) {
+ // This code is based on ApplicationPackageManager.getLaunchIntentForPackage.
+ PackageManager packageManager = mContext.getPackageManager();
+
+ // First see if the package has an INFO activity; the existence of
+ // such an activity is implied to be the desired front-door for the
+ // overall package (such as if it has multiple launcher entries).
+ Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+ intentToResolve.addCategory(Intent.CATEGORY_INFO);
+ intentToResolve.setPackage(packageName);
+ List<ResolveInfo> ris = packageManager.queryIntentActivitiesAsUser(
+ intentToResolve, 0, userId);
+
+ // Otherwise, try to find a main launcher activity.
+ if (ris == null || ris.size() <= 0) {
+ // reuse the intent instance
+ intentToResolve.removeCategory(Intent.CATEGORY_INFO);
+ intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+ intentToResolve.setPackage(packageName);
+ ris = packageManager.queryIntentActivitiesAsUser(intentToResolve, 0, userId);
+ }
+ if (ris == null || ris.size() <= 0) {
+ Log.e(TAG, "Failed to build intent for " + packageName);
+ return null;
+ }
+ return new ComponentName(ris.get(0).activityInfo.packageName,
+ ris.get(0).activityInfo.name);
+ }
+
@Override
public boolean onLongClick(View v) {
ImageView icon = (ImageView) v;
@@ -226,17 +259,15 @@
// for the task's package.
RecentTaskInfo task = (RecentTaskInfo) v.getTag();
String packageName = getRealActivityForTask(task).getPackageName();
- Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(packageName);
- if (intent == null) {
+ ComponentName component = getLaunchComponentForPackage(packageName, task.userId);
+ if (component == null) {
return false;
}
- if (DEBUG) Slog.d(TAG, "Start drag with " + intent);
+ if (DEBUG) Slog.d(TAG, "Start drag with " + component);
- UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- long userSerialNumber = userManager.getSerialNumberForUser(new UserHandle(task.userId));
NavigationBarApps.startAppDrag(
- icon, new AppInfo(intent.getComponent(), userSerialNumber));
+ icon, new AppInfo(component, new UserHandle(task.userId)));
return true;
}
}
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 1649acb..7de7a7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -91,7 +91,8 @@
private OnVerticalChangedListener mOnVerticalChangedListener;
private boolean mIsLayoutRtl;
- private boolean mLayoutTransitionsEnabled;
+ private boolean mLayoutTransitionsEnabled = true;
+ private boolean mWakeAndUnlocking;
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
@@ -371,13 +372,19 @@
}
}
- public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
- setUseFadingAnimations(wakeAndUnlocking);
- setLayoutTransitionsEnabled(!wakeAndUnlocking);
+ public void setLayoutTransitionsEnabled(boolean enabled) {
+ mLayoutTransitionsEnabled = enabled;
+ updateLayoutTransitionsEnabled();
}
- private void setLayoutTransitionsEnabled(boolean enabled) {
- mLayoutTransitionsEnabled = enabled;
+ public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
+ setUseFadingAnimations(wakeAndUnlocking);
+ mWakeAndUnlocking = wakeAndUnlocking;
+ updateLayoutTransitionsEnabled();
+ }
+
+ private void updateLayoutTransitionsEnabled() {
+ boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
ViewGroup navButtons = (ViewGroup) mCurrentView.findViewById(R.id.nav_buttons);
LayoutTransition lt = navButtons.getLayoutTransition();
if (lt != null) {
@@ -469,7 +476,7 @@
}
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
- setLayoutTransitionsEnabled(mLayoutTransitionsEnabled);
+ updateLayoutTransitionsEnabled();
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
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 710c335..3ad7246 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -56,6 +56,7 @@
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -203,6 +204,8 @@
private int mLastOrientation = -1;
private boolean mClosingWithAlphaFadeOut;
private boolean mHeadsUpAnimatingAway;
+ private boolean mLaunchingAffordance;
+ private LockedPhoneAnalytics mLockedPhoneAnalytics;
private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
@Override
@@ -219,6 +222,7 @@
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(!DEBUG);
+ mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
}
public void setStatusBar(PhoneStatusBar bar) {
@@ -488,7 +492,9 @@
mIsLaunchTransitionFinished = false;
mBlockTouches = false;
mUnlockIconActive = false;
- mAfforanceHelper.reset(true);
+ if (!mLaunchingAffordance) {
+ mAfforanceHelper.reset(false);
+ }
closeQs();
mStatusBar.dismissPopups();
mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, false /* animate */,
@@ -820,6 +826,7 @@
private void handleQsDown(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN
&& shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
+ mLockedPhoneAnalytics.onQsDown();
mQsTracking = true;
onQsExpansionStarted();
mInitialHeightOnTouch = mQsExpansionHeight;
@@ -987,6 +994,7 @@
mQsExpanded = expanded;
updateQsState();
requestPanelHeightUpdate();
+ mLockedPhoneAnalytics.setQsExpanded(expanded);
mNotificationStackScroller.setInterceptDelegateEnabled(expanded);
mStatusBar.setQsExpanded(expanded);
mQsPanel.setExpanded(expanded);
@@ -1313,6 +1321,10 @@
R.string.accessibility_desc_quick_settings));
mLastAnnouncementWasQuickSettings = true;
}
+ if (mQsFullyExpanded && mLockedPhoneAnalytics.shouldEnforceBouncer()) {
+ mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
+ false /* dismissShade */, true /* afterKeyguardGone */);
+ }
if (DEBUG) {
invalidate();
}
@@ -1840,6 +1852,7 @@
@Override
protected void onTrackingStarted() {
+ mLockedPhoneAnalytics.onTrackingStarted();
super.onTrackingStarted();
if (mQsFullyExpanded) {
mQsExpandImmediate = true;
@@ -1853,6 +1866,7 @@
@Override
protected void onTrackingStopped(boolean expand) {
+ mLockedPhoneAnalytics.onTrackingStopped();
super.onTrackingStopped(expand);
if (expand) {
mNotificationStackScroller.setOverScrolledPixels(
@@ -1951,11 +1965,35 @@
if (start) {
EventLogTags.writeSysuiLockscreenGesture(
EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER, lengthDp, velocityDp);
- mKeyguardBottomArea.launchLeftAffordance();
+
+ mLockedPhoneAnalytics.onLeftAffordanceOn();
+ if (mLockedPhoneAnalytics.shouldEnforceBouncer()) {
+ mStatusBar.executeRunnableDismissingKeyguard(new Runnable() {
+ @Override
+ public void run() {
+ mKeyguardBottomArea.launchLeftAffordance();
+ }
+ }, null, true /* dismissShade */, false /* afterKeyguardGone */);
+ }
+ else {
+ mKeyguardBottomArea.launchLeftAffordance();
+ }
} else {
EventLogTags.writeSysuiLockscreenGesture(
EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA, lengthDp, velocityDp);
- mSecureCameraLaunchManager.startSecureCameraLaunch();
+
+ mLockedPhoneAnalytics.onCameraOn();
+ if (mLockedPhoneAnalytics.shouldEnforceBouncer()) {
+ mStatusBar.executeRunnableDismissingKeyguard(new Runnable() {
+ @Override
+ public void run() {
+ mSecureCameraLaunchManager.startSecureCameraLaunch();
+ }
+ }, null, true /* dismissShade */, false /* afterKeyguardGone */);
+ }
+ else {
+ mSecureCameraLaunchManager.startSecureCameraLaunch();
+ }
}
mStatusBar.startLaunchTransitionTimeout();
mBlockTouches = true;
@@ -1999,6 +2037,7 @@
@Override
public void onSwipingStarted(boolean rightIcon) {
+ mLockedPhoneAnalytics.onAffordanceSwipingStarted(rightIcon);
boolean camera = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon
: rightIcon;
if (camera) {
@@ -2012,6 +2051,7 @@
@Override
public void onSwipingAborted() {
+ mLockedPhoneAnalytics.onAffordanceSwipingAborted();
mKeyguardBottomArea.unbindCameraPrewarmService(false /* launched */);
}
@@ -2388,4 +2428,41 @@
protected boolean isPanelVisibleBecauseOfHeadsUp() {
return mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway;
}
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return !mDozing;
+ }
+
+ public void launchCamera(boolean animate) {
+ // If we are launching it when we are occluded already we don't want it to animate,
+ // nor setting these flags, since the occluded state doesn't change anymore, hence it's
+ // never reset.
+ if (!isFullyCollapsed()) {
+ mLaunchingAffordance = true;
+ setLaunchingAffordance(true);
+ } else {
+ animate = false;
+ }
+ mAfforanceHelper.launchAffordance(animate, getLayoutDirection() == LAYOUT_DIRECTION_RTL);
+ }
+
+ public void onAffordanceLaunchEnded() {
+ mLaunchingAffordance = false;
+ setLaunchingAffordance(false);
+ }
+
+ /**
+ * Set whether we are currently launching an affordance. This is currently only set when
+ * launched via a camera gesture.
+ */
+ private void setLaunchingAffordance(boolean launchingAffordance) {
+ getLeftIcon().setLaunchingAffordance(launchingAffordance);
+ getRightIcon().setLaunchingAffordance(launchingAffordance);
+ getCenterIcon().setLaunchingAffordance(launchingAffordance);
+ }
+
+ public boolean canCameraGestureBeLaunched() {
+ return !mAfforanceHelper.isSwipingInProgress();
+ }
}
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 b794353..7b04da0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -66,6 +66,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.Vibrator;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
@@ -130,6 +131,7 @@
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.SpeedBumpView;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -155,6 +157,7 @@
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.statusbar.stack.StackViewState;
import com.android.systemui.volume.VolumeComponent;
@@ -232,7 +235,7 @@
public static final int FADE_KEYGUARD_START_DELAY = 100;
public static final int FADE_KEYGUARD_DURATION = 300;
- public static final int FADE_KEYGUARD_DURATION_PULSING = 120;
+ public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
/** Allow some time inbetween the long press for back and recents. */
private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -483,6 +486,9 @@
private Runnable mLaunchTransitionEndRunnable;
private boolean mLaunchTransitionFadingAway;
private ExpandableNotificationRow mDraggedDownRow;
+ private boolean mLaunchCameraOnScreenTurningOn;
+ private PowerManager.WakeLock mGestureWakeLock;
+ private Vibrator mVibrator;
// Fingerprint (as computed by getLoggingFingerprint() of the last logged state.
private int mLastLoggedStateFingerprint;
@@ -588,6 +594,7 @@
private HashSet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new HashSet<>();
private RankingMap mLatestRankingMap;
private boolean mNoAnimationOnNextBarModeChange;
+ private LockedPhoneAnalytics mLockedPhoneAnalytics;
@Override
public void start() {
@@ -635,6 +642,7 @@
notifyUserAboutHiddenNotifications();
mScreenPinningRequest = new ScreenPinningRequest(mContext);
+ mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(mContext);
}
// ================================================================================
@@ -915,7 +923,9 @@
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mBroadcastReceiver.onReceive(mContext,
new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));
-
+ mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
+ "GestureWakeLock");
+ mVibrator = mContext.getSystemService(Vibrator.class);
// receive broadcasts
IntentFilter filter = new IntentFilter();
@@ -1720,7 +1730,9 @@
final boolean hasArtwork = artworkBitmap != null;
- if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) && mState != StatusBarState.SHADE) {
+ if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) && mState != StatusBarState.SHADE
+ && mFingerprintUnlockController.getMode()
+ != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
// time to show some art!
if (mBackdrop.getVisibility() != View.VISIBLE) {
mBackdrop.setVisibility(View.VISIBLE);
@@ -1775,31 +1787,40 @@
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
}
- mBackdrop.animate()
- // Never let the alpha become zero - otherwise the RenderNode
- // won't draw anything and uninitialized memory will show through
- // if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in libhwui.
- .alpha(0.002f)
- .setInterpolator(mBackdropInterpolator)
- .setDuration(300)
- .setStartDelay(0)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- mBackdrop.setVisibility(View.GONE);
- mBackdropFront.animate().cancel();
- mBackdropBack.animate().cancel();
- mHandler.post(mHideBackdropFront);
- }
- });
- if (mKeyguardFadingAway) {
- mBackdrop.animate()
+ if (mFingerprintUnlockController.getMode()
+ == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
- // Make it disappear faster, as the focus should be on the activity behind.
- .setDuration(mKeyguardFadingAwayDuration / 2)
- .setStartDelay(mKeyguardFadingAwayDelay)
- .setInterpolator(mLinearInterpolator)
- .start();
+ // We are unlocking directly - no animation!
+ mBackdrop.setVisibility(View.GONE);
+ } else {
+ mBackdrop.animate()
+ // Never let the alpha become zero - otherwise the RenderNode
+ // won't draw anything and uninitialized memory will show through
+ // if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in
+ // libhwui.
+ .alpha(0.002f)
+ .setInterpolator(mBackdropInterpolator)
+ .setDuration(300)
+ .setStartDelay(0)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mBackdrop.setVisibility(View.GONE);
+ mBackdropFront.animate().cancel();
+ mBackdropBack.animate().cancel();
+ mHandler.post(mHideBackdropFront);
+ }
+ });
+ if (mKeyguardFadingAway) {
+ mBackdrop.animate()
+
+ // Make it disappear faster, as the focus should be on the activity
+ // behind.
+ .setDuration(mKeyguardFadingAwayDuration / 2)
+ .setStartDelay(mKeyguardFadingAwayDelay)
+ .setInterpolator(mLinearInterpolator)
+ .start();
+ }
}
}
}
@@ -2461,8 +2482,12 @@
|| mStatusBarMode == MODE_LIGHTS_OUT_TRANSPARENT);
boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
boolean light = (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
-
- mIconController.setIconsDark(allowLight && light);
+ boolean animate = mFingerprintUnlockController == null
+ || (mFingerprintUnlockController.getMode()
+ != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
+ && mFingerprintUnlockController.getMode()
+ != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK);
+ mIconController.setIconsDark(allowLight && light, animate);
}
// restore the recents bit
if (wasRecentsVisible) {
@@ -3406,6 +3431,8 @@
private void onLaunchTransitionFadingEnded() {
mNotificationPanel.setAlpha(1.0f);
+ mNotificationPanel.onAffordanceLaunchEnded();
+ releaseGestureWakeLock();
runLaunchTransitionEndRunnable();
mLaunchTransitionFadingAway = false;
mScrimController.forceHideScrims(false /* hide */);
@@ -3478,14 +3505,6 @@
.setStartDelay(0)
.setDuration(FADE_KEYGUARD_DURATION_PULSING)
.setInterpolator(ScrimController.KEYGUARD_FADE_OUT_INTERPOLATOR)
- .withLayer()
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- mNotificationPanel.setAlpha(1f);
- hideKeyguard();
- }
- })
.start();
}
@@ -3501,6 +3520,8 @@
private void onLaunchTransitionTimeout() {
Log.w(TAG, "Launch transition: Timeout!");
+ mNotificationPanel.onAffordanceLaunchEnded();
+ releaseGestureWakeLock();
mNotificationPanel.resetViews();
}
@@ -3523,11 +3544,24 @@
setBarState(StatusBarState.SHADE);
if (mLeaveOpenOnKeyguardHide) {
mLeaveOpenOnKeyguardHide = false;
- mNotificationPanel.animateToFullShade(calculateGoingToFullShadeDelay());
+ long delay = calculateGoingToFullShadeDelay();
+ mNotificationPanel.animateToFullShade(delay);
if (mDraggedDownRow != null) {
mDraggedDownRow.setUserLocked(false);
mDraggedDownRow = null;
}
+
+ // Disable layout transitions in navbar for this transition because the load is just
+ // too heavy for the CPU and GPU on any device.
+ if (mNavigationBarView != null) {
+ mNavigationBarView.setLayoutTransitionsEnabled(false);
+ mNavigationBarView.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mNavigationBarView.setLayoutTransitionsEnabled(true);
+ }
+ }, delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
+ }
} else {
instantCollapseNotificationPanel();
}
@@ -3539,9 +3573,18 @@
mQSPanel.refreshAllTiles();
}
mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+ releaseGestureWakeLock();
+ mNotificationPanel.onAffordanceLaunchEnded();
+ mNotificationPanel.setAlpha(1f);
return staying;
}
+ private void releaseGestureWakeLock() {
+ if (mGestureWakeLock.isHeld()) {
+ mGestureWakeLock.release();
+ }
+ }
+
public long calculateGoingToFullShadeDelay() {
return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration;
}
@@ -3679,6 +3722,11 @@
return mState == StatusBarState.KEYGUARD && mStatusBarKeyguardViewManager.onMenuPressed();
}
+ public void endAffordanceLaunch() {
+ releaseGestureWakeLock();
+ mNotificationPanel.onAffordanceLaunchEnded();
+ }
+
public boolean onBackPressed() {
if (mStatusBarKeyguardViewManager.onBackPressed()) {
return true;
@@ -3755,6 +3803,7 @@
}
mState = state;
mGroupManager.setStatusBarState(state);
+ mLockedPhoneAnalytics.setStatusBarState(state);
mStatusBarWindowManager.setStatusBarState(state);
updateDozing();
}
@@ -3776,6 +3825,7 @@
}
public void onUnlockHintStarted() {
+ mLockedPhoneAnalytics.onUnlockHintStarted();
mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock);
}
@@ -3785,14 +3835,17 @@
}
public void onCameraHintStarted() {
+ mLockedPhoneAnalytics.onCameraHintStarted();
mKeyguardIndicationController.showTransientIndication(R.string.camera_hint);
}
public void onVoiceAssistHintStarted() {
+ mLockedPhoneAnalytics.onLeftAffordanceHintStarted();
mKeyguardIndicationController.showTransientIndication(R.string.voice_hint);
}
public void onPhoneHintStarted() {
+ mLockedPhoneAnalytics.onLeftAffordanceHintStarted();
mKeyguardIndicationController.showTransientIndication(R.string.phone_hint);
}
@@ -3867,7 +3920,7 @@
row.setUserExpanded(true);
}
boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId)
- || !mShowLockscreenNotifications;
+ || !mShowLockscreenNotifications || mLockedPhoneAnalytics.shouldEnforceBouncer();
if (isLockscreenPublicMode() && fullShadeNeedsBouncer) {
mLeaveOpenOnKeyguardHide = true;
showBouncer();
@@ -3909,9 +3962,13 @@
}
public void onFinishedGoingToSleep() {
+ mNotificationPanel.onAffordanceLaunchEnded();
+ releaseGestureWakeLock();
+ mLaunchCameraOnScreenTurningOn = false;
mDeviceInteractive = false;
mWakeUpComingFromTouch = false;
mWakeUpTouchLocation = null;
+ mLockedPhoneAnalytics.onScreenOff();
mStackScroller.setAnimationsEnabled(false);
updateVisibleToUser();
}
@@ -3921,10 +3978,19 @@
mStackScroller.setAnimationsEnabled(true);
mNotificationPanel.setTouchDisabled(false);
updateVisibleToUser();
+ mLockedPhoneAnalytics.onScreenOn();
}
public void onScreenTurningOn() {
mNotificationPanel.onScreenTurningOn();
+ if (mLaunchCameraOnScreenTurningOn) {
+ mNotificationPanel.launchCamera(false);
+ mLaunchCameraOnScreenTurningOn = false;
+ }
+ }
+
+ private void vibrateForCameraGesture() {
+ mVibrator.vibrate(1000L);
}
public void onScreenTurnedOn() {
@@ -4049,6 +4115,7 @@
mWakeUpTouchLocation = new PointF(event.getX(), event.getY());
mNotificationPanel.setTouchDisabled(false);
mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
+ mLockedPhoneAnalytics.onScreenOnFromTouch();
}
}
@@ -4071,8 +4138,9 @@
public void appTransitionStarting(long startTime, long duration) {
// Use own timings when Keyguard is going away, see keyguardGoingAway and
- // setKeyguardFadingAway
- if (!mKeyguardFadingAway) {
+ // setKeyguardFadingAway. When duration is 0, skip this one because no animation is really
+ // playing.
+ if (!mKeyguardFadingAway && duration > 0) {
mIconController.appTransitionStarting(startTime, duration);
}
if (mIconPolicy != null) {
@@ -4080,6 +4148,39 @@
}
}
+ @Override
+ public void onCameraLaunchGestureDetected() {
+ if (!mNotificationPanel.canCameraGestureBeLaunched()) {
+ return;
+ }
+ if (!mDeviceInteractive) {
+ PowerManager pm = mContext.getSystemService(PowerManager.class);
+ pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE");
+ mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
+ }
+ vibrateForCameraGesture();
+ if (!mStatusBarKeyguardViewManager.isShowing()) {
+ startActivity(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT,
+ true /* dismissShade */);
+ } else {
+ if (!mDeviceInteractive) {
+ // Avoid flickering of the scrim when we instant launch the camera and the bouncer
+ // comes on.
+ mScrimController.dontAnimateBouncerChangesUntilNextFrame();
+ mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
+ }
+ if (mStatusBarKeyguardViewManager.isScreenTurnedOn()) {
+ mNotificationPanel.launchCamera(mDeviceInteractive /* animate */);
+ } else {
+ // We need to defer the camera launch until the screen comes on, since otherwise
+ // we will dismiss us too early since we are waiting on an activity to be drawn and
+ // incorrectly get notified because of the screen on event (which resumes and pauses
+ // some activities)
+ mLaunchCameraOnScreenTurningOn = true;
+ }
+ }
+ }
+
public void notifyFpAuthModeChanged() {
updateDozing();
}
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 5b009ee..b9e9292 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -22,7 +22,6 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
-import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
@@ -87,6 +86,8 @@
private float mTopHeadsUpDragAmount;
private View mDraggedHeadsUpView;
private boolean mForceHideScrims;
+ private boolean mSkipFirstFrame;
+ private boolean mDontAnimateBouncerChanges;
public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
boolean scrimSrcEnabled) {
@@ -125,7 +126,7 @@
public void setBouncerShowing(boolean showing) {
mBouncerShowing = showing;
- mAnimateChange = !mExpanding;
+ mAnimateChange = !mExpanding && !mDontAnimateBouncerChanges;
scheduleUpdate();
}
@@ -134,14 +135,20 @@
scheduleUpdate();
}
- public void animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished) {
+ public void animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished,
+ boolean skipFirstFrame) {
mWakeAndUnlocking = false;
mAnimateKeyguardFadingOut = true;
mDurationOverride = duration;
mAnimationDelay = delay;
mAnimateChange = true;
+ mSkipFirstFrame = skipFirstFrame;
mOnAnimationFinished = onAnimationFinished;
scheduleUpdate();
+
+ // No need to wait for the next frame to be drawn for this case - onPreDraw will execute
+ // the changes we just scheduled.
+ onPreDraw();
}
public void abortKeyguardFadingOut() {
@@ -339,6 +346,9 @@
}
});
anim.start();
+ if (mSkipFirstFrame) {
+ anim.setCurrentPlayTime(16);
+ }
scrim.setTag(TAG_KEY_ANIM, anim);
scrim.setTag(TAG_KEY_ANIM_TARGET, target);
}
@@ -351,9 +361,13 @@
public boolean onPreDraw() {
mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
mUpdatePending = false;
+ if (mDontAnimateBouncerChanges) {
+ mDontAnimateBouncerChanges = false;
+ }
updateScrims();
mDurationOverride = -1;
mAnimationDelay = 0;
+ mSkipFirstFrame = false;
// Make sure that we always call the listener even if we didn't start an animation.
endAnimateKeyguardFadingOut(false /* force */);
@@ -486,4 +500,8 @@
mAnimateChange = false;
scheduleUpdate();
}
+
+ public void dontAnimateBouncerChangesUntilNextFrame() {
+ mDontAnimateBouncerChanges = true;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
index a1e9ece..18db5b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
@@ -19,6 +19,7 @@
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.content.Context;
+import android.graphics.drawable.RippleDrawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 7ee47df..e9c4e49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -26,6 +26,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.util.TypedValue;
@@ -184,6 +185,12 @@
}
});
requestCaptureValues();
+
+ // RenderThread is doing more harm than good when touching the header (to expand quick
+ // settings), so disable it for this view
+ ((RippleDrawable) getBackground()).setForceSoftware(true);
+ ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
+ ((RippleDrawable) mSystemIconsSuperContainer.getBackground()).setForceSoftware(true);
}
@Override
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 067e50e..5de1c13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -335,8 +335,10 @@
}
}
- public void setIconsDark(boolean dark) {
- if (mTransitionPending) {
+ 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,
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 448f16d..d0604c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -74,7 +74,6 @@
private boolean mLastOccluded;
private boolean mLastBouncerShowing;
private boolean mLastBouncerDismissible;
- private boolean mLastDeferScrimFadeOut;
private OnDismissAction mAfterKeyguardGoneAction;
private boolean mDeviceWillWakeUp;
private boolean mDeferScrimFadeOut;
@@ -180,11 +179,16 @@
mPhoneStatusBar.onScreenTurningOn();
}
+ public boolean isScreenTurnedOn() {
+ return mScreenTurnedOn;
+ }
+
public void onScreenTurnedOn() {
mScreenTurnedOn = true;
if (mDeferScrimFadeOut) {
mDeferScrimFadeOut = false;
- animateScrimControllerKeyguardFadingOut(0, WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS);
+ animateScrimControllerKeyguardFadingOut(0, WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS,
+ true /* skipFirstFrame */);
updateStates();
}
mPhoneStatusBar.onScreenTurnedOn();
@@ -264,7 +268,8 @@
updateStates();
mScrimController.animateKeyguardFadingOut(
PhoneStatusBar.FADE_KEYGUARD_START_DELAY,
- PhoneStatusBar.FADE_KEYGUARD_DURATION, null);
+ PhoneStatusBar.FADE_KEYGUARD_DURATION, null,
+ false /* skipFirstFrame */);
}
}, new Runnable() {
@Override
@@ -279,10 +284,15 @@
if (mFingerprintUnlockController.getMode()
== FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
mFingerprintUnlockController.startKeyguardFadingAway();
- mPhoneStatusBar.setKeyguardFadingAway(startTime, 0, 250);
+ mPhoneStatusBar.setKeyguardFadingAway(startTime, 0, 240);
mStatusBarWindowManager.setKeyguardFadingAway(true);
mPhoneStatusBar.fadeKeyguardWhilePulsing();
- animateScrimControllerKeyguardFadingOut(0, 250);
+ animateScrimControllerKeyguardFadingOut(0, 240, new Runnable() {
+ @Override
+ public void run() {
+ mPhoneStatusBar.hideKeyguard();
+ }
+ }, false /* skipFirstFrame */);
} else {
mFingerprintUnlockController.startKeyguardFadingAway();
mPhoneStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
@@ -297,10 +307,12 @@
// Screen is already on, don't defer with fading out.
animateScrimControllerKeyguardFadingOut(0,
- WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS);
+ WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS,
+ true /* skipFirstFrame */);
}
} else {
- animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration);
+ animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration,
+ false /* skipFirstFrame */);
}
} else {
mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
@@ -315,11 +327,21 @@
}
}
- private void animateScrimControllerKeyguardFadingOut(long delay, long duration) {
+ private void animateScrimControllerKeyguardFadingOut(long delay, long duration,
+ boolean skipFirstFrame) {
+ animateScrimControllerKeyguardFadingOut(delay, duration, null /* endRunnable */,
+ skipFirstFrame);
+ }
+
+ private void animateScrimControllerKeyguardFadingOut(long delay, long duration,
+ final Runnable endRunnable, boolean skipFirstFrame) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "Fading out", 0);
mScrimController.animateKeyguardFadingOut(delay, duration, new Runnable() {
@Override
public void run() {
+ if (endRunnable != null) {
+ endRunnable.run();
+ }
mStatusBarWindowManager.setKeyguardFadingAway(false);
mPhoneStatusBar.finishKeyguardFadingAway();
mFingerprintUnlockController.finishKeyguardFadingAway();
@@ -327,7 +349,7 @@
ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "Fading out", 0);
}
- });
+ }, skipFirstFrame);
}
private void executeAfterKeyguardGoneAction() {
@@ -367,6 +389,7 @@
*/
public boolean onBackPressed() {
if (mBouncer.isShowing()) {
+ mPhoneStatusBar.endAffordanceLaunch();
reset();
return true;
}
@@ -401,7 +424,6 @@
boolean occluded = mOccluded;
boolean bouncerShowing = mBouncer.isShowing();
boolean bouncerDismissible = !mBouncer.isFullscreenBouncer();
- boolean deferScrimFadeOut = mDeferScrimFadeOut;
if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing)
|| mFirstUpdate) {
@@ -412,11 +434,8 @@
}
}
- // Hide navigation bar on Keyguard but not on bouncer and also if we are deferring a scrim
- // fade out, i.e. we are waiting for the screen to have turned on.
- boolean navBarVisible = !deferScrimFadeOut && (!(showing && !occluded) || bouncerShowing);
- boolean lastNavBarVisible = !mLastDeferScrimFadeOut && (!(mLastShowing && !mLastOccluded)
- || mLastBouncerShowing);
+ boolean navBarVisible = (!(showing && !occluded) || bouncerShowing);
+ boolean lastNavBarVisible = (!(mLastShowing && !mLastOccluded) || mLastBouncerShowing);
if (navBarVisible != lastNavBarVisible || mFirstUpdate) {
if (mPhoneStatusBar.getNavigationBarView() != null) {
if (navBarVisible) {
@@ -451,7 +470,6 @@
mFirstUpdate = false;
mLastShowing = showing;
mLastOccluded = occluded;
- mLastDeferScrimFadeOut = deferScrimFadeOut;
mLastBouncerShowing = bouncerShowing;
mLastBouncerDismissible = bouncerDismissible;
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 0e22aa8..bbf981f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -39,6 +39,7 @@
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -55,12 +56,14 @@
private PhoneStatusBar mService;
private final Paint mTransparentSrcPaint = new Paint();
+ private LockedPhoneAnalytics mLockedPhoneAnalytics;
public StatusBarWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
setMotionEventSplittingEnabled(false);
mTransparentSrcPaint.setColor(0);
mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+ mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
}
@Override
@@ -197,6 +200,7 @@
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
+ mLockedPhoneAnalytics.onTouchEvent(ev, getWidth(), getHeight());
if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
// Disallow new pointers while the brightness mirror is visible. This is so that you
// can't touch anything other than the brightness slider while the mirror is showing
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 091db76..a91cd51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -145,7 +145,7 @@
}
@Override
- public void onStrongAuthTimeoutExpiredChanged(int userId) {
+ public void onStrongAuthStateChanged(int userId) {
update(false /* updateAlways */);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto b/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
new file mode 100644
index 0000000..afc8f77
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
@@ -0,0 +1,136 @@
+/*
+ * 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
+ */
+
+syntax = "proto2";
+
+package systemui;
+
+option java_package = "com.android.systemui.statusbar.phone";
+option java_outer_classname = "TouchAnalyticsProto";
+
+message Session {
+ message TouchEvent {
+ message BoundingBox {
+ optional float width = 1;
+ optional float height = 2;
+ }
+
+ enum Action {
+ // Keep in sync with MotionEvent.
+ DOWN = 0;
+ UP = 1;
+ MOVE = 2;
+ CANCEL = 3;
+ OUTSIDE = 4;
+ POINTER_DOWN = 5;
+ POINTER_UP = 6;
+ }
+
+ message Pointer {
+ optional float x = 1;
+ optional float y = 2;
+ optional float size = 3;
+ optional float pressure = 4;
+ optional int32 id = 5;
+ optional float removed_length = 6;
+ optional BoundingBox removed_boundingBox = 7;
+ }
+
+ optional uint64 timeOffsetNanos = 1;
+ optional Action action = 2;
+ optional int32 actionIndex = 3;
+ repeated Pointer pointers = 4;
+ optional bool removed_redacted = 5;
+ optional BoundingBox removed_boundingBox = 6;
+ }
+
+ message SensorEvent {
+ enum Type {
+ ACCELEROMETER = 1;
+ GYROSCOPE = 4;
+ LIGHT = 5;
+ PROXIMITY = 8;
+ ROTATION_VECTOR = 11;
+ }
+
+ optional Type type = 1;
+ optional uint64 timeOffsetNanos = 2;
+ repeated float values = 3;
+ optional uint64 timestamp = 4;
+ }
+
+ message PhoneEvent {
+ enum Type {
+ ON_SCREEN_ON = 0;
+ ON_SCREEN_ON_FROM_TOUCH = 1;
+ ON_SCREEN_OFF = 2;
+ ON_SUCCESSFUL_UNLOCK = 3;
+ ON_BOUNCER_SHOWN = 4;
+ ON_BOUNCER_HIDDEN = 5;
+ ON_QS_DOWN = 6;
+ SET_QS_EXPANDED_TRUE = 7;
+ SET_QS_EXPANDED_FALSE = 8;
+ ON_TRACKING_STARTED = 9;
+ ON_TRACKING_STOPPED = 10;
+ ON_NOTIFICATION_ACTIVE = 11;
+ ON_NOTIFICATION_INACTIVE = 12;
+ ON_NOTIFICATION_DOUBLE_TAP = 13;
+ SET_NOTIFICATION_EXPANDED = 14;
+ RESET_NOTIFICATION_EXPANDED = 15;
+ ON_NOTIFICATION_START_DRAGGING_DOWN = 16;
+ ON_NOTIFICATION_STOP_DRAGGING_DOWN = 17;
+ ON_NOTIFICATION_DISMISSED = 18;
+ ON_NOTIFICATION_START_DISMISSING = 19;
+ ON_NOTIFICATION_STOP_DISMISSING = 20;
+ ON_RIGHT_AFFORDANCE_SWIPING_STARTED = 21;
+ ON_LEFT_AFFORDANCE_SWIPING_STARTED = 22;
+ ON_AFFORDANCE_SWIPING_ABORTED = 23;
+ ON_CAMERA_ON = 24;
+ ON_LEFT_AFFORDANCE_ON = 25;
+ ON_UNLOCK_HINT_STARTED = 26;
+ ON_CAMERA_HINT_STARTED = 27;
+ ON_LEFT_AFFORDANCE_HINT_STARTED = 28;
+ }
+
+ optional Type type = 1;
+ optional uint64 timeOffsetNanos = 2;
+ }
+
+ enum Result {
+ FAILURE = 0;
+ SUCCESS = 1;
+ UNKNOWN = 2;
+ }
+
+ enum Type {
+ RESERVED_1 = 0;
+ RESERVED_2 = 1;
+ RANDOM_WAKEUP = 2;
+ REAL = 3;
+ }
+
+ optional uint64 startTimestampMillis = 1;
+ optional uint64 durationMillis = 2;
+ optional string build = 3;
+ optional Result result = 4;
+ repeated TouchEvent touchEvents = 5;
+ repeated SensorEvent sensorEvents = 6;
+
+ optional int32 touchAreaWidth = 9;
+ optional int32 touchAreaHeight = 10;
+ optional Type type = 11;
+ repeated PhoneEvent phoneEvents = 12;
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 61986ad..896bd62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -23,6 +23,8 @@
import android.content.IntentFilter;
import android.content.res.TypedArray;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
@@ -30,22 +32,28 @@
import android.text.style.CharacterStyle;
import android.text.style.RelativeSizeSpan;
import android.util.AttributeSet;
+import android.view.Display;
import android.widget.TextView;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import libcore.icu.LocaleData;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
-import libcore.icu.LocaleData;
-
/**
* Digital clock for the status bar.
*/
-public class Clock extends TextView implements DemoMode {
+public class Clock extends TextView implements DemoMode, Tunable {
+
+ public static final String CLOCK_SECONDS = "clock_seconds";
+
private boolean mAttached;
private Calendar mCalendar;
private String mClockFormatString;
@@ -57,6 +65,8 @@
private static final int AM_PM_STYLE_GONE = 2;
private final int mAmPmStyle;
+ private boolean mShowSeconds;
+ private Handler mSecondsHandler;
public Clock(Context context) {
this(context, null);
@@ -77,6 +87,7 @@
} finally {
a.recycle();
}
+ TunerService.get(context).addTunable(this, CLOCK_SECONDS);
}
@Override
@@ -105,6 +116,7 @@
// Make sure we update to the current time
updateClock();
+ updateShowSeconds();
}
@Override
@@ -143,6 +155,35 @@
setText(getSmallTime());
}
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ mShowSeconds = newValue != null && Integer.parseInt(newValue) != 0;
+ updateShowSeconds();
+ }
+
+ private void updateShowSeconds() {
+ if (mShowSeconds) {
+ // Wait until we have a display to start trying to show seconds.
+ if (mSecondsHandler == null && getDisplay() != null) {
+ mSecondsHandler = new Handler();
+ if (getDisplay().getState() == Display.STATE_ON) {
+ mSecondsHandler.postAtTime(mSecondTick,
+ SystemClock.uptimeMillis() / 1000 * 1000 + 1000);
+ }
+ IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ mContext.registerReceiver(mScreenReceiver, filter);
+ }
+ } else {
+ if (mSecondsHandler != null) {
+ mContext.unregisterReceiver(mScreenReceiver);
+ mSecondsHandler.removeCallbacks(mSecondTick);
+ mSecondsHandler = null;
+ updateClock();
+ }
+ }
+ }
+
private final CharSequence getSmallTime() {
Context context = getContext();
boolean is24 = DateFormat.is24HourFormat(context, ActivityManager.getCurrentUser());
@@ -152,7 +193,9 @@
final char MAGIC2 = '\uEF01';
SimpleDateFormat sdf;
- String format = is24 ? d.timeFormat_Hm : d.timeFormat_hm;
+ String format = mShowSeconds
+ ? is24 ? d.timeFormat_Hms : d.timeFormat_hms
+ : is24 ? d.timeFormat_Hm : d.timeFormat_hm;
if (!format.equals(mClockFormatString)) {
/*
* Search for an unquoted "a" in the format string, so we can
@@ -244,5 +287,32 @@
setText(getSmallTime());
}
}
+
+ private final BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+ if (mSecondsHandler != null) {
+ mSecondsHandler.removeCallbacks(mSecondTick);
+ }
+ } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
+ if (mSecondsHandler != null) {
+ mSecondsHandler.postAtTime(mSecondTick,
+ SystemClock.uptimeMillis() / 1000 * 1000 + 1000);
+ }
+ }
+ }
+ };
+
+ private final Runnable mSecondTick = new Runnable() {
+ @Override
+ public void run() {
+ if (mCalendar != null) {
+ updateClock();
+ }
+ mSecondsHandler.postAtTime(this, SystemClock.uptimeMillis() / 1000 * 1000 + 1000);
+ }
+ };
}
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 6af9854..6d791bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -178,7 +178,8 @@
mCurrentUserId = newUserId;
if (mUserManager.getUserInfo(newUserId).isRestricted()) {
// VPN for a restricted profile is routed through its owner user
- mVpnUserId = UserHandle.USER_OWNER;
+ // TODO: http://b/22950929
+ mVpnUserId = UserHandle.USER_SYSTEM;
} else {
mVpnUserId = mCurrentUserId;
}
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 753a7f7..56f6564 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
@@ -34,6 +34,7 @@
boolean hasDelays;
boolean hasGoToFullShadeEvent;
boolean hasDarkEvent;
+ boolean hasHeadsUpDisappearClickEvent;
int darkAnimationOriginIndex;
public AnimationFilter animateAlpha() {
@@ -106,6 +107,10 @@
hasDarkEvent = true;
darkAnimationOriginIndex = ev.darkAnimationOriginIndex;
}
+ if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
+ .ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
+ hasHeadsUpDisappearClickEvent = true;
+ }
}
}
@@ -135,6 +140,7 @@
hasDelays = false;
hasGoToFullShadeEvent = false;
hasDarkEvent = false;
+ hasHeadsUpDisappearClickEvent = false;
darkAnimationOriginIndex =
NotificationStackScrollLayout.AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
}
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 82c1aa8..a1d73d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -47,6 +47,7 @@
import com.android.systemui.statusbar.SpeedBumpView;
import com.android.systemui.statusbar.StackScrollerDecorView;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -231,6 +232,7 @@
private boolean mForceNoOverlappingRendering;
private NotificationOverflowContainer mOverflowContainer;
private final ArrayList<Pair<ExpandableNotificationRow, Boolean>> mTmpList = new ArrayList<>();
+ private LockedPhoneAnalytics mLockedPhoneAnalytics;
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -264,6 +266,7 @@
mDebugPaint.setStrokeWidth(2);
mDebugPaint.setStyle(Paint.Style.STROKE);
}
+ mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
}
@Override
@@ -595,6 +598,12 @@
veto.performClick();
}
if (DEBUG) Log.v(TAG, "onChildDismissed: " + v);
+
+ mLockedPhoneAnalytics.onNotificationDismissed();
+ if (mLockedPhoneAnalytics.shouldEnforceBouncer()) {
+ mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
+ false /* dismissShade */, true /* afterKeyguardGone */);
+ }
}
@Override
@@ -622,6 +631,7 @@
}
public void onBeginDrag(View v) {
+ mLockedPhoneAnalytics.onNotificatonStartDismissing();
setSwipingInProgress(true);
mAmbientState.onBeginDrag(v);
if (mAnimationsEnabled && (mIsExpanded || !isPinnedHeadsUp(v))) {
@@ -648,6 +658,7 @@
}
public void onDragCancelled(View v) {
+ mLockedPhoneAnalytics.onNotificatonStopDismissing();
setSwipingInProgress(false);
}
@@ -1915,7 +1926,9 @@
boolean onBottom = false;
boolean pinnedAndClosed = row.isPinned() && !mIsExpanded;
if (!mIsExpanded && !isHeadsUp) {
- type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
+ type = row.wasJustClicked()
+ ? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+ : AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
} else {
StackViewState viewState = mCurrentStackScrollState.getViewStateForView(row);
if (viewState == null) {
@@ -3016,6 +3029,15 @@
.animateY()
.animateZ(),
+ // ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+ new AnimationFilter()
+ .animateAlpha()
+ .animateHeight()
+ .animateTopInset()
+ .animateY()
+ .animateZ()
+ .hasDelays(),
+
// ANIMATION_TYPE_HEADS_UP_OTHER
new AnimationFilter()
.animateAlpha()
@@ -3087,6 +3109,9 @@
// ANIMATION_TYPE_HEADS_UP_DISAPPEAR
StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
+ // ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+ StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
+
// ANIMATION_TYPE_HEADS_UP_OTHER
StackStateAnimator.ANIMATION_DURATION_STANDARD,
@@ -3110,8 +3135,9 @@
static final int ANIMATION_TYPE_GROUP_EXPANSION_CHANGED = 13;
static final int ANIMATION_TYPE_HEADS_UP_APPEAR = 14;
static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR = 15;
- static final int ANIMATION_TYPE_HEADS_UP_OTHER = 16;
- static final int ANIMATION_TYPE_EVERYTHING = 17;
+ static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK = 16;
+ static final int ANIMATION_TYPE_HEADS_UP_OTHER = 17;
+ static final int ANIMATION_TYPE_EVERYTHING = 18;
static final int DARK_ANIMATION_ORIGIN_INDEX_ABOVE = -1;
static final int DARK_ANIMATION_ORIGIN_INDEX_BELOW = -2;
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 82064a7..cf696a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -127,7 +127,7 @@
mCollapseSecondCardPadding = context.getResources().getDimensionPixelSize(
R.dimen.notification_collapse_second_card_padding);
mScaleDimmed = context.getResources().getDisplayMetrics().densityDpi
- >= DisplayMetrics.DENSITY_XXHIGH;
+ >= DisplayMetrics.DENSITY_420;
}
public boolean shouldScaleDimmed() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 97c7d30..b4ab48a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -54,6 +54,7 @@
public static final int ANIMATION_DELAY_PER_ELEMENT_DARK = 24;
public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE_CHILDREN = 3;
+ public static final int ANIMATION_DELAY_HEADS_UP = 120;
private static final int TAG_ANIMATOR_TRANSLATION_Y = R.id.translation_y_animator_tag;
private static final int TAG_ANIMATOR_TRANSLATION_Z = R.id.translation_z_animator_tag;
@@ -320,6 +321,9 @@
if (mAnimationFilter.hasGoToFullShadeEvent) {
return calculateDelayGoToFullShade(viewState);
}
+ if (mAnimationFilter.hasHeadsUpDisappearClickEvent) {
+ return ANIMATION_DELAY_HEADS_UP;
+ }
long minDelay = 0;
for (NotificationStackScrollLayout.AnimationEvent event : mNewEvents) {
long delayPerElement = ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING;
@@ -890,7 +894,9 @@
mHeadsUpAppearChildren.add(changingView);
finalState.applyState(changingView, mTmpState);
} else if (event.animationType == NotificationStackScrollLayout
- .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR) {
+ .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR ||
+ event.animationType == NotificationStackScrollLayout
+ .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
mHeadsUpDisappearChildren.add(changingView);
if (mHostLayout.indexOfChild(changingView) == -1) {
// This notification was actually removed, so we need to add it to the overlay
@@ -900,7 +906,11 @@
// We temporarily enable Y animations, the real filter will be combined
// afterwards anyway
mAnimationFilter.animateY = true;
- startViewAnimations(changingView, mTmpState, 0,
+ startViewAnimations(changingView, mTmpState,
+ event.animationType == NotificationStackScrollLayout
+ .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+ ? ANIMATION_DELAY_HEADS_UP
+ : 0,
ANIMATION_DURATION_HEADS_UP_DISAPPEAR);
mChildrenToClearFromOverlay.add(changingView);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 920b682..2587b9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -171,6 +171,10 @@
}
@Override
+ public void onCameraLaunchGestureDetected() {
+ }
+
+ @Override
protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldInterrupt,
boolean alertAgain) {
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index e5b550e..dcb0d8d 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -38,6 +38,18 @@
}
@Override
+ protected void onAttachedToActivity() {
+ super.onAttachedToActivity();
+ TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+ }
+
+ @Override
+ protected void onDetachedFromActivity() {
+ TunerService.get(getContext()).removeTunable(this);
+ super.onDetachedFromActivity();
+ }
+
+ @Override
public void onTuningChanged(String key, String newValue) {
if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 71b5de5..96ad756 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -15,8 +15,6 @@
*/
package com.android.systemui.tuner;
-import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING;
-
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.content.DialogInterface;
@@ -29,7 +27,6 @@
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceFragment;
-import android.preference.PreferenceGroup;
import android.preference.SwitchPreference;
import android.provider.Settings;
import android.provider.Settings.System;
@@ -39,8 +36,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.tuner.TunerService.Tunable;
+
+import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING;
public class TunerFragment extends PreferenceFragment {
@@ -108,7 +105,6 @@
getContext().getContentResolver().registerContentObserver(
System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
- registerPrefs(getPreferenceScreen());
MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, true);
}
@@ -117,36 +113,9 @@
super.onPause();
getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
- unregisterPrefs(getPreferenceScreen());
MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, false);
}
- private void registerPrefs(PreferenceGroup group) {
- TunerService tunerService = TunerService.get(getContext());
- final int N = group.getPreferenceCount();
- for (int i = 0; i < N; i++) {
- Preference pref = group.getPreference(i);
- if (pref instanceof StatusBarSwitch) {
- tunerService.addTunable((Tunable) pref, StatusBarIconController.ICON_BLACKLIST);
- } else if (pref instanceof PreferenceGroup) {
- registerPrefs((PreferenceGroup) pref);
- }
- }
- }
-
- private void unregisterPrefs(PreferenceGroup group) {
- TunerService tunerService = TunerService.get(getContext());
- final int N = group.getPreferenceCount();
- for (int i = 0; i < N; i++) {
- Preference pref = group.getPreference(i);
- if (pref instanceof Tunable) {
- tunerService.removeTunable((Tunable) pref);
- } else if (pref instanceof PreferenceGroup) {
- registerPrefs((PreferenceGroup) pref);
- }
- }
- }
-
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(Menu.NONE, MENU_REMOVE, Menu.NONE, R.string.remove_from_settings);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
new file mode 100644
index 0000000..0740e08
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
@@ -0,0 +1,39 @@
+package com.android.systemui.tuner;
+
+import android.content.Context;
+import android.preference.SwitchPreference;
+import android.provider.Settings;
+import android.util.AttributeSet;
+
+import com.android.systemui.tuner.TunerService.Tunable;
+
+public class TunerSwitch extends SwitchPreference implements Tunable {
+
+ public TunerSwitch(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onAttachedToActivity() {
+ super.onAttachedToActivity();
+ TunerService.get(getContext()).addTunable(this, getKey());
+ }
+
+ @Override
+ protected void onDetachedFromActivity() {
+ TunerService.get(getContext()).removeTunable(this);
+ super.onDetachedFromActivity();
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ setChecked(newValue != null && Integer.parseInt(newValue) != 0);
+ }
+
+ @Override
+ protected boolean persistBoolean(boolean value) {
+ Settings.Secure.putString(getContext().getContentResolver(), getKey(), value ? "1" : "0");
+ return true;
+ }
+
+}
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 6a7201c..d6d17cb 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -17,9 +17,14 @@
LOCAL_MODULE_TAGS := tests
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_PROTOC_FLAGS := -I$(LOCAL_PATH)/..
+LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
+
LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages com.android.systemui:com.android.keyguard
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
$(call all-java-files-under, ../src) \
+ $(call all-proto-files-under, ../src) \
src/com/android/systemui/EventLogTags.logtags
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java
index 62213ab..fce6b29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java
@@ -16,21 +16,26 @@
package com.android.systemui.statusbar.phone;
+import org.mockito.InOrder;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.test.AndroidTestCase;
@@ -45,6 +50,7 @@
/** Tests for the data model for the navigation bar app icons. */
public class NavigationBarAppsModelTest extends AndroidTestCase {
private PackageManager mMockPackageManager;
+ private IPackageManager mMockIPackageManager;
private SharedPreferences mMockPrefs;
private SharedPreferences.Editor mMockEdit;
private UserManager mMockUserManager;
@@ -61,11 +67,12 @@
final Context context = mock(Context.class);
mMockPackageManager = mock(PackageManager.class);
+ mMockIPackageManager = mock(IPackageManager.class);
mMockPrefs = mock(SharedPreferences.class);
mMockEdit = mock(SharedPreferences.Editor.class);
mMockUserManager = mock(UserManager.class);
- when (context.getSharedPreferences(
+ when(context.getSharedPreferences(
"com.android.systemui.navbarapps", Context.MODE_PRIVATE)).thenReturn(mMockPrefs);
when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager);
when(context.getPackageManager()).thenReturn(mMockPackageManager);
@@ -77,21 +84,133 @@
when(mMockPrefs.getInt("version", -1)).thenReturn(3);
when(mMockPrefs.edit()).thenReturn(mMockEdit);
- when(mMockUserManager.getSerialNumberForUser(new UserHandle(2))).thenReturn(22L);
+ when(mMockUserManager.getSerialNumberForUser(new UserHandle(2))).thenReturn(222L);
+ when(mMockUserManager.getSerialNumberForUser(new UserHandle(4))).thenReturn(444L);
+ when(mMockUserManager.getSerialNumberForUser(new UserHandle(5))).thenReturn(555L);
+ when(mMockUserManager.getUserForSerialNumber(222L)).thenReturn(new UserHandle(2));
+ when(mMockUserManager.getUserForSerialNumber(444L)).thenReturn(new UserHandle(4));
+ when(mMockUserManager.getUserForSerialNumber(555L)).thenReturn(new UserHandle(5));
- mModel = new NavigationBarAppsModel(context);
+ UserInfo ui2 = new UserInfo();
+ ui2.profileGroupId = 999;
+ UserInfo ui4 = new UserInfo();
+ ui4.profileGroupId = 999;
+ UserInfo ui5 = new UserInfo();
+ ui5.profileGroupId = 999;
+ when(mMockUserManager.getUserInfo(2)).thenReturn(ui2);
+ when(mMockUserManager.getUserInfo(4)).thenReturn(ui4);
+ when(mMockUserManager.getUserInfo(5)).thenReturn(ui5);
+
+ mModel = new NavigationBarAppsModel(context) {
+ @Override
+ protected IPackageManager getPackageManager() {
+ return mMockIPackageManager;
+ }
+ };
+ }
+
+ /** Tests buildAppLaunchIntent(). */
+ public void testBuildAppLaunchIntent() {
+ ActivityInfo mockNonExportedActivityInfo = new ActivityInfo();
+ mockNonExportedActivityInfo.exported = false;
+ ActivityInfo mockExportedActivityInfo = new ActivityInfo();
+ mockExportedActivityInfo.exported = true;
+ try {
+ when(mMockIPackageManager.getActivityInfo(
+ new ComponentName("package1", "class1"), 0, 4)).
+ thenReturn(mockNonExportedActivityInfo);
+ when(mMockIPackageManager.getActivityInfo(
+ new ComponentName("package2", "class2"), 0, 5)).
+ thenThrow(new RemoteException());
+ when(mMockIPackageManager.getActivityInfo(
+ new ComponentName("package3", "class3"), 0, 6)).
+ thenReturn(mockExportedActivityInfo);
+ when(mMockIPackageManager.getActivityInfo(
+ new ComponentName("package4", "class4"), 0, 7)).
+ thenReturn(mockExportedActivityInfo);
+ } catch (RemoteException e) {
+ fail("RemoteException can't happen in the test, but it happened.");
+ }
+
+ // Assume some installed activities.
+ ActivityInfo ai0 = new ActivityInfo();
+ ai0.packageName = "package0";
+ ai0.name = "class0";
+ ActivityInfo ai1 = new ActivityInfo();
+ ai1.packageName = "package4";
+ ai1.name = "class4";
+ ResolveInfo ri0 = new ResolveInfo();
+ ri0.activityInfo = ai0;
+ ResolveInfo ri1 = new ResolveInfo();
+ ri1.activityInfo = ai1;
+ when(mMockPackageManager
+ .queryIntentActivitiesAsUser(any(Intent.class), eq(0), any(int.class)))
+ .thenReturn(Arrays.asList(ri0, ri1));
+
+ mModel.setCurrentUser(3);
+ // Unlauncheable (for various reasons) apps.
+ assertEquals(null, mModel.buildAppLaunchIntent(
+ new AppInfo(new ComponentName("package0", "class0"), new UserHandle(3))));
+ mModel.setCurrentUser(4);
+ assertEquals(null, mModel.buildAppLaunchIntent(
+ new AppInfo(new ComponentName("package1", "class1"), new UserHandle(4))));
+ mModel.setCurrentUser(5);
+ assertEquals(null, mModel.buildAppLaunchIntent(
+ new AppInfo(new ComponentName("package2", "class2"), new UserHandle(5))));
+ mModel.setCurrentUser(6);
+ assertEquals(null, mModel.buildAppLaunchIntent(
+ new AppInfo(new ComponentName("package3", "class3"), new UserHandle(6))));
+
+ // A launcheable app.
+ mModel.setCurrentUser(7);
+ Intent intent = mModel.buildAppLaunchIntent(
+ new AppInfo(new ComponentName("package4", "class4"), new UserHandle(7)));
+ assertNotNull(intent);
+ assertEquals(new ComponentName("package4", "class4"), intent.getComponent());
+ assertEquals("package4", intent.getPackage());
}
/** Initializes the model from SharedPreferences for a few app activites. */
private void initializeModelFromPrefs() {
// Assume several apps are stored.
- when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(3);
- when(mMockPrefs.getString("22|app_0", null)).thenReturn("package0/class0");
- when(mMockPrefs.getLong("22|app_user_0", -1)).thenReturn(-1L);
- when(mMockPrefs.getString("22|app_1", null)).thenReturn("package1/class1");
- when(mMockPrefs.getLong("22|app_user_1", -1)).thenReturn(45L);
- when(mMockPrefs.getString("22|app_2", null)).thenReturn("package2/class2");
- when(mMockPrefs.getLong("22|app_user_2", -1)).thenReturn(239L);
+ when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(2);
+ when(mMockPrefs.getString("222|app_0", null)).thenReturn("package1/class1");
+ when(mMockPrefs.getLong("222|app_user_0", -1)).thenReturn(444L);
+ when(mMockPrefs.getString("222|app_1", null)).thenReturn("package2/class2");
+ when(mMockPrefs.getLong("222|app_user_1", -1)).thenReturn(555L);
+
+ ActivityInfo mockActivityInfo = new ActivityInfo();
+ mockActivityInfo.exported = true;
+ try {
+ when(mMockIPackageManager.getActivityInfo(
+ new ComponentName("package0", "class0"), 0, 5)).thenReturn(mockActivityInfo);
+ when(mMockIPackageManager.getActivityInfo(
+ new ComponentName("package1", "class1"), 0, 4)).thenReturn(mockActivityInfo);
+ when(mMockIPackageManager.getActivityInfo(
+ new ComponentName("package2", "class2"), 0, 5)).thenReturn(mockActivityInfo);
+ } catch (RemoteException e) {
+ fail("RemoteException can't happen in the test, but it happened.");
+ }
+
+ // Assume some installed activities.
+ ActivityInfo ai0 = new ActivityInfo();
+ ai0.packageName = "package0";
+ ai0.name = "class0";
+ ActivityInfo ai1 = new ActivityInfo();
+ ai1.packageName = "package1";
+ ai1.name = "class1";
+ ActivityInfo ai2 = new ActivityInfo();
+ ai2.packageName = "package2";
+ ai2.name = "class2";
+ ResolveInfo ri0 = new ResolveInfo();
+ ri0.activityInfo = ai0;
+ ResolveInfo ri1 = new ResolveInfo();
+ ri1.activityInfo = ai1;
+ ResolveInfo ri2 = new ResolveInfo();
+ ri2.activityInfo = ai2;
+ when(mMockPackageManager
+ .queryIntentActivitiesAsUser(any(Intent.class), eq(0), any(int.class)))
+ .thenReturn(Arrays.asList(ri0, ri1, ri2));
mModel.setCurrentUser(2);
}
@@ -101,15 +220,15 @@
initializeModelFromPrefs();
assertEquals(2, mModel.getAppCount());
assertEquals("package1/class1", mModel.getApp(0).getComponentName().flattenToString());
- assertEquals(45L, mModel.getApp(0).getUserSerialNumber());
+ assertEquals(new UserHandle(4), mModel.getApp(0).getUser());
assertEquals("package2/class2", mModel.getApp(1).getComponentName().flattenToString());
- assertEquals(239L, mModel.getApp(1).getUserSerialNumber());
+ assertEquals(new UserHandle(5), mModel.getApp(1).getUser());
}
/** Tests initializing the model when the SharedPreferences aren't available. */
public void testInitializeDefaultApps() {
// Assume the user's app count pref isn't available.
- when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(-1);
+ when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(-1);
// Assume some installed activities.
ActivityInfo ai1 = new ActivityInfo();
@@ -130,26 +249,101 @@
mModel.setCurrentUser(2);
assertEquals(2, mModel.getAppCount());
assertEquals("package1/class1", mModel.getApp(0).getComponentName().flattenToString());
- assertEquals(22L, mModel.getApp(0).getUserSerialNumber());
+ assertEquals(new UserHandle(2), mModel.getApp(0).getUser());
assertEquals("package2/class2", mModel.getApp(1).getComponentName().flattenToString());
- assertEquals(22L, mModel.getApp(1).getUserSerialNumber());
+ assertEquals(new UserHandle(2), mModel.getApp(1).getUser());
+ InOrder order = inOrder(mMockEdit);
+ order.verify(mMockEdit).apply();
+ order.verify(mMockEdit).putInt("222|app_count", 2);
+ order.verify(mMockEdit).putString("222|app_0", "package1/class1");
+ order.verify(mMockEdit).putLong("222|app_user_0", 222L);
+ order.verify(mMockEdit).putString("222|app_1", "package2/class2");
+ order.verify(mMockEdit).putLong("222|app_user_1", 222L);
+ order.verify(mMockEdit).apply();
+ verifyNoMoreInteractions(mMockEdit);
}
/** Tests initializing the model if one of the prefs is missing. */
public void testInitializeWithMissingPref() {
// Assume two apps are nominally stored.
- when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(2);
- when(mMockPrefs.getString("22|app_0", null)).thenReturn("package0/class0");
- when(mMockPrefs.getLong("22|app_user_0", -1)).thenReturn(239L);
+ when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(2);
+ when(mMockPrefs.getString("222|app_0", null)).thenReturn("package0/class0");
+ when(mMockPrefs.getLong("222|app_user_0", -1)).thenReturn(555L);
// But assume one pref is missing.
- when(mMockPrefs.getString("22|app_1", null)).thenReturn(null);
+ when(mMockPrefs.getString("222|app_1", null)).thenReturn(null);
+
+ ActivityInfo mockActivityInfo = new ActivityInfo();
+ mockActivityInfo.exported = true;
+ try {
+ when(mMockIPackageManager.getActivityInfo(
+ new ComponentName("package0", "class0"), 0, 5)).thenReturn(mockActivityInfo);
+ } catch (RemoteException e) {
+ fail("RemoteException can't happen in the test, but it happened.");
+ }
+
+ ActivityInfo ai0 = new ActivityInfo();
+ ai0.packageName = "package0";
+ ai0.name = "class0";
+ ResolveInfo ri0 = new ResolveInfo();
+ ri0.activityInfo = ai0;
+ when(mMockPackageManager
+ .queryIntentActivitiesAsUser(any(Intent.class), eq(0), any(int.class)))
+ .thenReturn(Arrays.asList(ri0));
// Initializing the model should load from prefs and skip the missing one.
mModel.setCurrentUser(2);
assertEquals(1, mModel.getAppCount());
assertEquals("package0/class0", mModel.getApp(0).getComponentName().flattenToString());
- assertEquals(239L, mModel.getApp(0).getUserSerialNumber());
+ assertEquals(new UserHandle(5), mModel.getApp(0).getUser());
+ InOrder order = inOrder(mMockEdit);
+ order.verify(mMockEdit).putInt("222|app_count", 1);
+ order.verify(mMockEdit).putString("222|app_0", "package0/class0");
+ order.verify(mMockEdit).putLong("222|app_user_0", 555L);
+ order.verify(mMockEdit).apply();
+ verifyNoMoreInteractions(mMockEdit);
+ }
+
+ /** Tests initializing the model if one of the apps is unlauncheable. */
+ public void testInitializeWithUnlauncheableApp() {
+ // Assume two apps are nominally stored.
+ when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(2);
+ when(mMockPrefs.getString("222|app_0", null)).thenReturn("package0/class0");
+ when(mMockPrefs.getLong("222|app_user_0", -1)).thenReturn(555L);
+ when(mMockPrefs.getString("222|app_1", null)).thenReturn("package1/class1");
+ when(mMockPrefs.getLong("222|app_user_1", -1)).thenReturn(444L);
+
+ ActivityInfo mockActivityInfo = new ActivityInfo();
+ mockActivityInfo.exported = true;
+ try {
+ when(mMockIPackageManager.getActivityInfo(
+ new ComponentName("package0", "class0"), 0, 5)).thenReturn(mockActivityInfo);
+ } catch (RemoteException e) {
+ fail("RemoteException can't happen in the test, but it happened.");
+ }
+
+ ActivityInfo ai0 = new ActivityInfo();
+ ai0.packageName = "package0";
+ ai0.name = "class0";
+ ResolveInfo ri0 = new ResolveInfo();
+ ri0.activityInfo = ai0;
+ when(mMockPackageManager
+ .queryIntentActivitiesAsUser(any(Intent.class), eq(0), any(int.class)))
+ .thenReturn(Arrays.asList(ri0));
+
+ // Initializing the model should load from prefs and skip the unlauncheable one.
+ mModel.setCurrentUser(2);
+ assertEquals(1, mModel.getAppCount());
+ assertEquals("package0/class0", mModel.getApp(0).getComponentName().flattenToString());
+ assertEquals(new UserHandle(5), mModel.getApp(0).getUser());
+
+ // Once an unlauncheable app is detected, the model should save all apps excluding the
+ // unlauncheable one.
+ verify(mMockEdit).putInt("222|app_count", 1);
+ verify(mMockEdit).putString("222|app_0", "package0/class0");
+ verify(mMockEdit).putLong("222|app_user_0", 555L);
+ verify(mMockEdit).apply();
+ verifyNoMoreInteractions(mMockEdit);
}
/** Tests saving the model to SharedPreferences. */
@@ -157,11 +351,11 @@
initializeModelFromPrefs();
mModel.savePrefs();
- verify(mMockEdit).putInt("22|app_count", 2);
- verify(mMockEdit).putString("22|app_0", "package1/class1");
- verify(mMockEdit).putLong("22|app_user_0", 45L);
- verify(mMockEdit).putString("22|app_1", "package2/class2");
- verify(mMockEdit).putLong("22|app_user_1", 239L);
+ verify(mMockEdit).putInt("222|app_count", 2);
+ verify(mMockEdit).putString("222|app_0", "package1/class1");
+ verify(mMockEdit).putLong("222|app_user_0", 444L);
+ verify(mMockEdit).putString("222|app_1", "package2/class2");
+ verify(mMockEdit).putLong("222|app_user_1", 555L);
verify(mMockEdit).apply();
verifyNoMoreInteractions(mMockEdit);
}
@@ -194,7 +388,7 @@
// Assume the user's app count pref isn't available. This will trigger clearing deleted
// users' prefs.
- when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(-1);
+ when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(-1);
final Map allPrefs = new HashMap<String, Object>();
allPrefs.put("version", null);
diff --git a/packages/WallpaperCropper/AndroidManifest.xml b/packages/WallpaperCropper/AndroidManifest.xml
index 81d1085..e558d7e 100644
--- a/packages/WallpaperCropper/AndroidManifest.xml
+++ b/packages/WallpaperCropper/AndroidManifest.xml
@@ -21,7 +21,10 @@
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
- <application android:requiredForAllUsers="true">
+ <application
+ android:requiredForAllUsers="true"
+ android:largeHeap="true">
+
<activity
android:name="WallpaperCropActivity"
android:theme="@style/Theme.WallpaperCropper"
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 34aeb60..f724749 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -401,21 +401,40 @@
public boolean isSystemRestore;
public String[] filterSet;
- // Restore a single package
+ /**
+ * Restore a single package; no kill after restore
+ */
RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
- long _token, PackageInfo _pkg, int _pmToken) {
+ long _token, PackageInfo _pkg) {
transport = _transport;
dirName = _dirName;
observer = _obs;
token = _token;
pkgInfo = _pkg;
- pmToken = _pmToken;
+ pmToken = 0;
isSystemRestore = false;
filterSet = null;
}
- // Restore everything possible. This is the form that Setup Wizard or similar
- // restore UXes use.
+ /**
+ * Restore at install: PM token needed, kill after restore
+ */
+ RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
+ long _token, String _pkgName, int _pmToken) {
+ transport = _transport;
+ dirName = _dirName;
+ observer = _obs;
+ token = _token;
+ pkgInfo = null;
+ pmToken = _pmToken;
+ isSystemRestore = false;
+ filterSet = new String[] { _pkgName };
+ }
+
+ /**
+ * Restore everything possible. This is the form that Setup Wizard or similar
+ * restore UXes use.
+ */
RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
long _token) {
transport = _transport;
@@ -428,8 +447,10 @@
filterSet = null;
}
- // Restore some set of packages. Leave this one up to the caller to specify
- // whether it's to be considered a system-level restore.
+ /**
+ * Restore some set of packages. Leave this one up to the caller to specify
+ * whether it's to be considered a system-level restore.
+ */
RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
long _token, String[] _filterSet, boolean _isSystemRestore) {
transport = _transport;
@@ -9137,19 +9158,13 @@
// This can throw and so *must* happen before the wakelock is acquired
String dirName = transport.transportDirName();
- // We can use a synthetic PackageInfo here because:
- // 1. We know it's valid, since the Package Manager supplied the name
- // 2. Only the packageName field will be used by the restore code
- PackageInfo pkg = new PackageInfo();
- pkg.packageName = packageName;
-
mWakelock.acquire();
if (MORE_DEBUG) {
Slog.d(TAG, "Restore at install of " + packageName);
}
Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
msg.obj = new RestoreParams(transport, dirName, null,
- restoreSet, pkg, token);
+ restoreSet, packageName, token);
mBackupHandler.sendMessage(msg);
} catch (RemoteException e) {
// Binding to the transport broke; back off and proceed with the installation.
@@ -9528,8 +9543,7 @@
Slog.d(TAG, "restorePackage() : " + packageName);
}
Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
- msg.obj = new RestoreParams(mRestoreTransport, dirName,
- observer, token, app, 0);
+ msg.obj = new RestoreParams(mRestoreTransport, dirName, observer, token, app);
mBackupHandler.sendMessage(msg);
} finally {
Binder.restoreCallingIdentity(oldId);
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 56ebed6..c373fb8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -1569,6 +1569,8 @@
if ("-h".equals(arg)) {
dumpHelp(pw);
return;
+ } else if ("-a".equals(arg)) {
+ // dump all data
} else if ("write-settings".equals(arg)) {
long token = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 13b3f8d..b826cfd 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -246,3 +246,8 @@
# ---------------------------
40000 volume_changed (stream|1), (prev_level|1), (level|1), (max_level|1), (caller|3)
40001 stream_devices_changed (stream|1), (prev_devices|1), (devices|1)
+
+# ---------------------------
+# GestureLauncherService.java
+# ---------------------------
+40100 camera_gesture_triggered (gesture_on_time|2|3), (sensor1_on_time|2|3), (sensor2_on_time|2|3), (event_extra|1|1)
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 1f3d61c..342a3ef 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -19,12 +19,9 @@
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.Sensor;
@@ -34,12 +31,14 @@
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Vibrator;
-import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Slog;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
/**
* The service that listens for gestures detected in sensor firmware and starts the intent
* accordingly.
@@ -55,8 +54,6 @@
private final GestureEventListener mGestureListener = new GestureEventListener();
private Sensor mCameraLaunchSensor;
- private Vibrator mVibrator;
- private KeyguardManager mKeyGuard;
private Context mContext;
/** The wake lock held when a gesture is detected. */
@@ -64,6 +61,36 @@
private boolean mRegistered;
private int mUserId;
+ // Below are fields used for event logging only.
+ /** Elapsed real time when the camera gesture is turned on. */
+ private long mCameraGestureOnTimeMs = 0L;
+
+ /** Elapsed real time when the last camera gesture was detected. */
+ private long mCameraGestureLastEventTime = 0L;
+
+ /**
+ * How long the sensor 1 has been turned on since camera launch sensor was
+ * subscribed to and when the last camera launch gesture was detected.
+ * <p>Sensor 1 is the main sensor used to detect camera launch gesture.</p>
+ */
+ private long mCameraGestureSensor1LastOnTimeMs = 0L;
+
+ /**
+ * If applicable, how long the sensor 2 has been turned on since camera
+ * launch sensor was subscribed to and when the last camera launch
+ * gesture was detected.
+ * <p>Sensor 2 is the secondary sensor used to detect camera launch gesture.
+ * This is optional and if only sensor 1 is used for detect camera launch
+ * gesture, this value would always be 0.</p>
+ */
+ private long mCameraGestureSensor2LastOnTimeMs = 0L;
+
+ /**
+ * Extra information about the event when the last camera launch gesture
+ * was detected.
+ */
+ private int mCameraLaunchLastEventExtra = 0;
+
public GestureLauncherService(Context context) {
super(context);
mContext = context;
@@ -81,12 +108,9 @@
return;
}
- mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
- mKeyGuard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
PowerManager powerManager = (PowerManager) mContext.getSystemService(
Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(
- PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
+ mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"GestureLauncherService");
updateCameraRegistered();
@@ -114,6 +138,12 @@
private void unregisterCameraLaunchGesture() {
if (mRegistered) {
mRegistered = false;
+ mCameraGestureOnTimeMs = 0L;
+ mCameraGestureLastEventTime = 0L;
+ mCameraGestureSensor1LastOnTimeMs = 0;
+ mCameraGestureSensor2LastOnTimeMs = 0;
+ mCameraLaunchLastEventExtra = 0;
+
SensorManager sensorManager = (SensorManager) mContext.getSystemService(
Context.SENSOR_SERVICE);
sensorManager.unregisterListener(mGestureListener);
@@ -127,6 +157,8 @@
if (mRegistered) {
return;
}
+ mCameraGestureOnTimeMs = SystemClock.elapsedRealtime();
+ mCameraGestureLastEventTime = mCameraGestureOnTimeMs;
SensorManager sensorManager = (SensorManager) mContext.getSystemService(
Context.SENSOR_SERVICE);
int cameraLaunchGestureId = resources.getInteger(
@@ -207,14 +239,22 @@
private final class GestureEventListener implements SensorEventListener {
@Override
public void onSensorChanged(SensorEvent event) {
+ if (!mRegistered) {
+ if (DBG) Slog.d(TAG, "Ignoring gesture event because it's unregistered.");
+ return;
+ }
if (event.sensor == mCameraLaunchSensor) {
- handleCameraLaunchGesture();
+ handleCameraLaunchGesture(event);
return;
}
}
- private void handleCameraLaunchGesture() {
- if (DBG) Slog.d(TAG, "Received a camera launch event.");
+ private void handleCameraLaunchGesture(SensorEvent event) {
+ if (DBG) {
+ float[] values = event.values;
+ Slog.d(TAG, String.format("Received a camera launch event: " +
+ "values=[%.4f, %.4f, %.4f].", values[0], values[1], values[2]));
+ }
boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
if (!userSetupComplete) {
@@ -226,28 +266,13 @@
if (DBG) Slog.d(TAG, String.format(
"userSetupComplete = %s, performing camera launch gesture.",
userSetupComplete));
- boolean locked = mKeyGuard != null && mKeyGuard.inKeyguardRestrictedInputMode();
- String action = locked
- ? MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE
- : MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA;
- Intent intent = new Intent(action);
- PackageManager pm = mContext.getPackageManager();
- ResolveInfo componentInfo = pm.resolveActivity(intent,
- PackageManager.MATCH_DEFAULT_ONLY);
- if (componentInfo == null) {
- if (DBG) Slog.d(TAG, "Couldn't find an app to process the camera intent.");
- return;
- }
- if (mVibrator != null && mVibrator.hasVibrator()) {
- mVibrator.vibrate(1000L);
- }
- // Turn on the screen before the camera launches.
+ // Make sure we don't sleep too early
mWakeLock.acquire(500L);
- intent.setComponent(new ComponentName(componentInfo.activityInfo.packageName,
- componentInfo.activityInfo.name));
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
+ StatusBarManagerInternal service = LocalServices.getService(
+ StatusBarManagerInternal.class);
+ service.onCameraLaunchGestureDetected();
+ trackCameraLaunchEvent(event);
mWakeLock.release();
}
@@ -255,5 +280,50 @@
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Ignored.
}
+
+ private void trackCameraLaunchEvent(SensorEvent event) {
+ long now = SystemClock.elapsedRealtime();
+ long totalDuration = now - mCameraGestureOnTimeMs;
+ // values[0]: ratio between total time duration when accel is turned on and time
+ // duration since camera launch gesture is subscribed.
+ // values[1]: ratio between total time duration when gyro is turned on and time duration
+ // since camera launch gesture is subscribed.
+ // values[2]: extra information
+ float[] values = event.values;
+
+ long sensor1OnTime = (long) (totalDuration * (double) values[0]);
+ long sensor2OnTime = (long) (totalDuration * (double) values[1]);
+ int extra = (int) values[2];
+
+ // We only log the difference in the event log to make aggregation easier.
+ long gestureOnTimeDiff = now - mCameraGestureLastEventTime;
+ long sensor1OnTimeDiff = sensor1OnTime - mCameraGestureSensor1LastOnTimeMs;
+ long sensor2OnTimeDiff = sensor2OnTime - mCameraGestureSensor2LastOnTimeMs;
+ int extraDiff = extra - mCameraLaunchLastEventExtra;
+
+ // Gating against negative time difference. This doesn't usually happen, but it may
+ // happen because of numeric errors.
+ if (gestureOnTimeDiff < 0 || sensor1OnTimeDiff < 0 || sensor2OnTimeDiff < 0) {
+ if (DBG) Slog.d(TAG, "Skipped event logging because negative numbers.");
+ return;
+ }
+
+ if (DBG) Slog.d(TAG, String.format("totalDuration: %d, sensor1OnTime: %s, " +
+ "sensor2OnTime: %d, extra: %d",
+ gestureOnTimeDiff,
+ sensor1OnTimeDiff,
+ sensor2OnTimeDiff,
+ extraDiff));
+ EventLogTags.writeCameraGestureTriggered(
+ gestureOnTimeDiff,
+ sensor1OnTimeDiff,
+ sensor2OnTimeDiff,
+ extraDiff);
+
+ mCameraGestureLastEventTime = now;
+ mCameraGestureSensor1LastOnTimeMs = sensor1OnTime;
+ mCameraGestureSensor2LastOnTimeMs = sensor2OnTime;
+ mCameraLaunchLastEventExtra = extra;
+ }
}
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 0a0ee3f..b418aba 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -15,8 +15,6 @@
package com.android.server;
-import android.annotation.NonNull;
-import android.content.pm.PackageManagerInternal;
import com.android.internal.content.PackageMonitor;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
@@ -27,21 +25,21 @@
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethod;
-import com.android.internal.view.IInputSessionCallback;
import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
+import com.android.internal.view.IInputSessionCallback;
import com.android.internal.view.InputBindResult;
import com.android.server.statusbar.StatusBarManagerService;
-import com.android.server.wm.WindowManagerService;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import android.annotation.NonNull;
import android.app.ActivityManagerNative;
-import android.app.AppGlobals;
import android.app.AlertDialog;
+import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.IUserSwitchObserver;
import android.app.KeyguardManager;
@@ -61,6 +59,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
@@ -80,8 +79,8 @@
import android.os.IInterface;
import android.os.IRemoteCallback;
import android.os.Message;
-import android.os.Process;
import android.os.Parcel;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -90,7 +89,6 @@
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
-import android.text.TextUtils.SimpleStringSplitter;
import android.text.style.SuggestionSpan;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -109,6 +107,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.WindowManagerInternal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputBinding;
import android.view.inputmethod.InputMethod;
@@ -182,11 +181,11 @@
final InputMethodSettings mSettings;
final SettingsObserver mSettingsObserver;
final IWindowManager mIWindowManager;
+ final WindowManagerInternal mWindowManagerInternal;
final HandlerCaller mCaller;
final boolean mHasFeature;
private InputMethodFileManager mFileManager;
private final HardKeyboardListener mHardKeyboardListener;
- private final WindowManagerService mWindowManagerService;
private final AppOpsManager mAppOpsManager;
final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1);
@@ -710,7 +709,7 @@
}
private class HardKeyboardListener
- implements WindowManagerService.OnHardKeyboardStatusChangeListener {
+ implements WindowManagerInternal.OnHardKeyboardStatusChangeListener {
@Override
public void onHardKeyboardStatusChange(boolean available) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_HARD_KEYBOARD_SWITCH_CHANGED,
@@ -732,7 +731,7 @@
}
}
- public InputMethodManagerService(Context context, WindowManagerService windowManager) {
+ public InputMethodManagerService(Context context) {
mIPackageManager = AppGlobals.getPackageManager();
mContext = context;
mRes = context.getResources();
@@ -741,13 +740,13 @@
mSettingsObserver = new SettingsObserver(mHandler);
mIWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
+ mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
@Override
public void executeMessage(Message msg) {
handleMessage(msg);
}
}, true /*asyncHandler*/);
- mWindowManagerService = windowManager;
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mHardKeyboardListener = new HardKeyboardListener();
mHasFeature = context.getPackageManager().hasSystemFeature(
@@ -1045,7 +1044,7 @@
mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
com.android.internal.R.bool.show_ongoing_ime_switcher);
if (mShowOngoingImeSwitcherForPhones) {
- mWindowManagerService.setOnHardKeyboardStatusChangeListener(
+ mWindowManagerInternal.setOnHardKeyboardStatusChangeListener(
mHardKeyboardListener);
}
buildInputMethodListLocked(mMethodList, mMethodMap,
@@ -1507,7 +1506,7 @@
if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
// The current IME is shown. Hence an IME switch (transition) is happening.
- mWindowManagerService.saveLastInputMethodWindowForTransition();
+ mWindowManagerInternal.saveLastInputMethodWindowForTransition();
}
mIWindowManager.removeWindowToken(mCurToken);
} catch (RemoteException e) {
@@ -1641,7 +1640,7 @@
if (mSwitchingDialog != null) return false;
if (isScreenLocked()) return false;
if ((visibility & InputMethodService.IME_ACTIVE) == 0) return false;
- if (mWindowManagerService.isHardKeyboardAvailable()) {
+ if (mWindowManagerInternal.isHardKeyboardAvailable()) {
// When physical keyboard is attached, we show the ime switcher (or notification if
// NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently
// exists in the IME switcher dialog. Might be OK to remove this condition once
@@ -1753,15 +1752,18 @@
mImeSwitcherNotification.setContentTitle(title)
.setContentText(summary)
.setContentIntent(mImeSwitchPendingIntent);
- if ((mNotificationManager != null)
- && !mWindowManagerService.hasNavigationBar()) {
- if (DEBUG) {
- Slog.d(TAG, "--- show notification: label = " + summary);
+ try {
+ if ((mNotificationManager != null)
+ && !mIWindowManager.hasNavigationBar()) {
+ if (DEBUG) {
+ Slog.d(TAG, "--- show notification: label = " + summary);
+ }
+ mNotificationManager.notifyAsUser(null,
+ com.android.internal.R.string.select_input_method,
+ mImeSwitcherNotification.build(), UserHandle.ALL);
+ mNotificationShown = true;
}
- mNotificationManager.notifyAsUser(null,
- com.android.internal.R.string.select_input_method,
- mImeSwitcherNotification.build(), UserHandle.ALL);
- mNotificationShown = true;
+ } catch (RemoteException e) {
}
} else {
if (mNotificationShown && mNotificationManager != null) {
@@ -2527,7 +2529,7 @@
@Override
public int getInputMethodWindowVisibleHeight() {
- return mWindowManagerService.getInputMethodWindowVisibleHeight();
+ return mWindowManagerInternal.getInputMethodWindowVisibleHeight();
}
@Override
@@ -3041,7 +3043,7 @@
mSwitchingDialogTitleView = tv;
mSwitchingDialogTitleView
.findViewById(com.android.internal.R.id.hard_keyboard_section)
- .setVisibility(mWindowManagerService.isHardKeyboardAvailable()
+ .setVisibility(mWindowManagerInternal.isHardKeyboardAvailable()
? View.VISIBLE : View.GONE);
final Switch hardKeySwitch = (Switch) mSwitchingDialogTitleView.findViewById(
com.android.internal.R.id.hard_keyboard_switch);
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 9427b61..c7e0c98 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -18,6 +18,7 @@
import android.app.admin.DevicePolicyManager;
import android.app.backup.BackupManager;
+import android.app.trust.IStrongAuthTracker;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -28,6 +29,8 @@
import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
import static android.content.Context.USER_SERVICE;
import static android.Manifest.permission.READ_CONTACTS;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
+
import android.database.sqlite.SQLiteDatabase;
import android.os.Binder;
import android.os.IBinder;
@@ -70,6 +73,7 @@
private final Context mContext;
private final LockSettingsStorage mStorage;
+ private final LockSettingsStrongAuth mStrongAuth = new LockSettingsStrongAuth();
private LockPatternUtils mLockPatternUtils;
private boolean mFirstCallToVold;
@@ -93,6 +97,7 @@
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_STARTING);
filter.addAction(Intent.ACTION_USER_REMOVED);
+ filter.addAction(Intent.ACTION_USER_PRESENT);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() {
@@ -122,6 +127,8 @@
} else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
mStorage.prefetchUser(userHandle);
+ } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+ mStrongAuth.reportUnlock(getSendingUserId());
} else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
if (userHandle > 0) {
@@ -659,6 +666,10 @@
if (shouldReEnroll) {
credentialUtil.setCredential(credential, credential, userId);
}
+ } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
+ if (response.getTimeout() > 0) {
+ requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
+ }
}
return response;
@@ -713,6 +724,7 @@
private void removeUser(int userId) {
mStorage.removeUser(userId);
+ mStrongAuth.removeUser(userId);
final KeyStore ks = KeyStore.getInstance();
ks.onUserRemoved(userId);
@@ -727,6 +739,24 @@
}
}
+ @Override
+ public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
+ checkPasswordReadPermission(UserHandle.USER_ALL);
+ mStrongAuth.registerStrongAuthTracker(tracker);
+ }
+
+ @Override
+ public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
+ checkPasswordReadPermission(UserHandle.USER_ALL);
+ mStrongAuth.unregisterStrongAuthTracker(tracker);
+ }
+
+ @Override
+ public void requireStrongAuth(int strongAuthReason, int userId) {
+ checkWritePermission(userId);
+ mStrongAuth.requireStrongAuth(strongAuthReason, userId);
+ }
+
private static final String[] VALID_SETTINGS = new String[] {
LockPatternUtils.LOCKOUT_PERMANENT_KEY,
LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
@@ -797,5 +827,4 @@
Slog.e(TAG, "Unable to acquire GateKeeperService");
return null;
}
-
}
diff --git a/services/core/java/com/android/server/LockSettingsStrongAuth.java b/services/core/java/com/android/server/LockSettingsStrongAuth.java
new file mode 100644
index 0000000..c023f4a
--- /dev/null
+++ b/services/core/java/com/android/server/LockSettingsStrongAuth.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
+
+import android.app.trust.IStrongAuthTracker;
+import android.os.DeadObjectException;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Slog;
+import android.util.SparseIntArray;
+
+import java.util.ArrayList;
+
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
+
+/**
+ * Keeps track of requests for strong authentication.
+ */
+public class LockSettingsStrongAuth {
+
+ private static final String TAG = "LockSettings";
+
+ private static final int MSG_REQUIRE_STRONG_AUTH = 1;
+ private static final int MSG_REGISTER_TRACKER = 2;
+ private static final int MSG_UNREGISTER_TRACKER = 3;
+ private static final int MSG_REMOVE_USER = 4;
+
+ private final ArrayList<IStrongAuthTracker> mStrongAuthTrackers = new ArrayList<>();
+ private final SparseIntArray mStrongAuthForUser = new SparseIntArray();
+
+ private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) {
+ for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
+ if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) {
+ return;
+ }
+ }
+ mStrongAuthTrackers.add(tracker);
+
+ for (int i = 0; i < mStrongAuthForUser.size(); i++) {
+ int key = mStrongAuthForUser.keyAt(i);
+ int value = mStrongAuthForUser.valueAt(i);
+ try {
+ tracker.onStrongAuthRequiredChanged(value, key);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception while adding StrongAuthTracker.", e);
+ }
+ }
+ }
+
+ private void handleRemoveStrongAuthTracker(IStrongAuthTracker tracker) {
+ for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
+ if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) {
+ mStrongAuthTrackers.remove(i);
+ return;
+ }
+ }
+ }
+
+ private void handleRequireStrongAuth(int strongAuthReason, int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ for (int i = 0; i < mStrongAuthForUser.size(); i++) {
+ int key = mStrongAuthForUser.keyAt(i);
+ handleRequireStrongAuthOneUser(strongAuthReason, key);
+ }
+ } else {
+ handleRequireStrongAuthOneUser(strongAuthReason, userId);
+ }
+ }
+
+ private void handleRequireStrongAuthOneUser(int strongAuthReason, int userId) {
+ int oldValue = mStrongAuthForUser.get(userId, LockPatternUtils.StrongAuthTracker.DEFAULT);
+ int newValue = strongAuthReason == STRONG_AUTH_NOT_REQUIRED
+ ? STRONG_AUTH_NOT_REQUIRED
+ : (oldValue | strongAuthReason);
+ if (oldValue != newValue) {
+ mStrongAuthForUser.put(userId, newValue);
+ notifyStrongAuthTrackers(newValue, userId);
+ }
+ }
+
+ private void handleRemoveUser(int userId) {
+ int index = mStrongAuthForUser.indexOfKey(userId);
+ if (index >= 0) {
+ mStrongAuthForUser.removeAt(index);
+ notifyStrongAuthTrackers(StrongAuthTracker.DEFAULT, userId);
+ }
+ }
+
+ private void notifyStrongAuthTrackers(int strongAuthReason, int userId) {
+ for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
+ try {
+ mStrongAuthTrackers.get(i).onStrongAuthRequiredChanged(strongAuthReason, userId);
+ } catch (DeadObjectException e) {
+ Slog.d(TAG, "Removing dead StrongAuthTracker.");
+ mStrongAuthTrackers.remove(i);
+ i--;
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception while notifying StrongAuthTracker.", e);
+ }
+ }
+ }
+
+ public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
+ mHandler.obtainMessage(MSG_REGISTER_TRACKER, tracker).sendToTarget();
+ }
+
+ public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
+ mHandler.obtainMessage(MSG_UNREGISTER_TRACKER, tracker).sendToTarget();
+ }
+
+ public void removeUser(int userId) {
+ mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
+ }
+
+ public void requireStrongAuth(int strongAuthReason, int userId) {
+ if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) {
+ mHandler.obtainMessage(MSG_REQUIRE_STRONG_AUTH, strongAuthReason,
+ userId).sendToTarget();
+ } else {
+ throw new IllegalArgumentException(
+ "userId must be an explicit user id or USER_ALL");
+ }
+ }
+
+ public void reportUnlock(int userId) {
+ requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId);
+ }
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_REGISTER_TRACKER:
+ handleAddStrongAuthTracker((IStrongAuthTracker) msg.obj);
+ break;
+ case MSG_UNREGISTER_TRACKER:
+ handleRemoveStrongAuthTracker((IStrongAuthTracker) msg.obj);
+ break;
+ case MSG_REQUIRE_STRONG_AUTH:
+ handleRequireStrongAuth(msg.arg1, msg.arg2);
+ break;
+ case MSG_REMOVE_USER:
+ handleRemoveUser(msg.arg1);
+ break;
+ }
+ }
+ };
+}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 0d64540..72cece3 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -165,6 +165,8 @@
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
mMountService.systemReady();
+ } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+ mMountService.bootCompleted();
}
}
@@ -405,6 +407,7 @@
private final NativeDaemonConnector mCryptConnector;
private volatile boolean mSystemReady = false;
+ private volatile boolean mBootCompleted = false;
private volatile boolean mDaemonConnected = false;
private PackageManagerService mPms;
@@ -1244,7 +1247,9 @@
mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
- if (isBroadcastWorthy(vol)) {
+ // Do not broadcast before boot has completed to avoid launching the
+ // processes that receive the intent unnecessarily.
+ if (mBootCompleted && isBroadcastWorthy(vol)) {
final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
@@ -1429,6 +1434,10 @@
mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
}
+ private void bootCompleted() {
+ mBootCompleted = true;
+ }
+
private String getDefaultPrimaryStorageUuid() {
if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
return StorageManager.UUID_PRIMARY_PHYSICAL;
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index cd61347..86183af 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -99,6 +99,12 @@
// URL-handling state upon factory reset.
final ArraySet<String> mLinkedApps = new ArraySet<>();
+ // These are the packages that are whitelisted to be able to run as system user
+ final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
+
+ // These are the packages that should not run under system user
+ final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
+
public static SystemConfig getInstance() {
synchronized (SystemConfig.class) {
if (sInstance == null) {
@@ -144,6 +150,14 @@
return mLinkedApps;
}
+ public ArraySet<String> getSystemUserWhitelistedApps() {
+ return mSystemUserWhitelistedApps;
+ }
+
+ public ArraySet<String> getSystemUserBlacklistedApps() {
+ return mSystemUserBlacklistedApps;
+ }
+
SystemConfig() {
// Read configuration from system
readPermissions(Environment.buildPath(
@@ -380,7 +394,24 @@
mLinkedApps.add(pkgname);
}
XmlUtils.skipCurrentTag(parser);
-
+ } else if ("system-user-whitelisted-app".equals(name)) {
+ String pkgname = parser.getAttributeValue(null, "package");
+ if (pkgname == null) {
+ Slog.w(TAG, "<system-user-whitelisted-app> without package in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else {
+ mSystemUserWhitelistedApps.add(pkgname);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ } else if ("system-user-blacklisted-app".equals(name)) {
+ String pkgname = parser.getAttributeValue(null, "package");
+ if (pkgname == null) {
+ Slog.w(TAG, "<system-user-blacklisted-app without package in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else {
+ mSystemUserBlacklistedApps.add(pkgname);
+ }
+ XmlUtils.skipCurrentTag(parser);
} else {
XmlUtils.skipCurrentTag(parser);
continue;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f3ea1c4..8e24127 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -21,6 +21,7 @@
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.app.ActivityManager.HOME_STACK_ID;
+import static android.app.ActivityManager.INVALID_STACK_ID;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -53,6 +54,7 @@
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
+import android.content.pm.AppsQueryHelper;
import android.content.pm.PermissionInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -100,6 +102,7 @@
import com.android.server.IntentResolver;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
+import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
import com.android.server.Watchdog;
@@ -207,7 +210,6 @@
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.os.SELinux;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemClock;
@@ -9005,8 +9007,7 @@
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack == null) {
- throw new IllegalArgumentException(
- "getActivityStackId: No stack for token=" + token);
+ return INVALID_STACK_ID;
}
return stack.mStackId;
}
@@ -9028,7 +9029,7 @@
}
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveActivityToStack: moving r=" + r
+ " to stackId=" + stackId);
- mStackSupervisor.moveTaskToStackLocked(r.task.taskId, stackId, ON_TOP, FORCE_FOCUS);
+ mStackSupervisor.moveTaskToStackLocked(r.task.taskId, stackId, ON_TOP, !FORCE_FOCUS);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -10906,7 +10907,7 @@
synchronized (this) {
buildAssistBundleLocked(pae, pae.result);
mPendingAssistExtras.remove(pae);
- mHandler.removeCallbacks(pae);
+ mUiHandler.removeCallbacks(pae);
}
return pae.extras;
}
@@ -10994,7 +10995,7 @@
activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
requestType);
mPendingAssistExtras.add(pae);
- mHandler.postDelayed(pae, timeout);
+ mUiHandler.postDelayed(pae, timeout);
} catch (RemoteException e) {
Slog.w(TAG, "getAssistContextExtras failed: crash calling " + activity);
return null;
@@ -11051,7 +11052,7 @@
synchronized (this) {
buildAssistBundleLocked(pae, extras);
boolean exists = mPendingAssistExtras.remove(pae);
- mHandler.removeCallbacks(pae);
+ mUiHandler.removeCallbacks(pae);
if (!exists) {
// Timed out.
return;
@@ -11983,6 +11984,8 @@
}
}
+ enableSystemUserApps();
+
// Start up initial activity.
mBooting = true;
startHomeActivityLocked(mCurrentUserId, "systemReady");
@@ -12033,6 +12036,42 @@
}
}
+ private void enableSystemUserApps() {
+ // For system user, enable apps based on the following conditions:
+ // - app is whitelisted; or has no launcher icons; or has INTERACT_ACROSS_USERS permission
+ // - app is not in the blacklist
+ if (UserManager.isSplitSystemUser()) {
+ AppsQueryHelper queryHelper = new AppsQueryHelper(mContext);
+ Set<String> enableApps = new HashSet<>();
+ enableApps.addAll(queryHelper.queryApps(AppsQueryHelper.GET_NON_LAUNCHABLE_APPS
+ | AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM,
+ /* systemAppsOnly */ true, UserHandle.SYSTEM));
+ ArraySet<String> wlApps = SystemConfig.getInstance().getSystemUserWhitelistedApps();
+ enableApps.addAll(wlApps);
+ ArraySet<String> blApps = SystemConfig.getInstance().getSystemUserBlacklistedApps();
+ enableApps.removeAll(blApps);
+
+ List<String> systemApps = queryHelper.queryApps(0, /* systemAppsOnly */ true,
+ UserHandle.SYSTEM);
+ final int systemAppsSize = systemApps.size();
+ for (int i = 0; i < systemAppsSize; i++) {
+ String pName = systemApps.get(i);
+ boolean enable = enableApps.contains(pName);
+ try {
+ if (enable) {
+ AppGlobals.getPackageManager().installExistingPackageAsUser(pName,
+ UserHandle.USER_SYSTEM);
+ } else {
+ AppGlobals.getPackageManager().deletePackageAsUser(pName, null,
+ UserHandle.USER_SYSTEM, PackageManager.DELETE_SYSTEM_APP);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error occured when processing package " + pName, e);
+ }
+ }
+ }
+ }
+
private boolean makeAppCrashingLocked(ProcessRecord app,
String shortMsg, String longMsg, String stackTrace) {
app.crashing = true;
@@ -16022,7 +16061,7 @@
"Call does not support special user #" + targetUserId);
}
// Check shell permission
- if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_OWNER) {
+ if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_SYSTEM) {
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES,
targetUserId)) {
throw new SecurityException("Shell does not have permission to access user "
@@ -16541,12 +16580,12 @@
}
List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
.queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);
- if (user != UserHandle.USER_OWNER && newReceivers != null) {
- // If this is not the primary user, we need to check for
+ if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
+ // If this is not the system user, we need to check for
// any receivers that should be filtered out.
for (int i=0; i<newReceivers.size(); i++) {
ResolveInfo ri = newReceivers.get(i);
- if ((ri.activityInfo.flags&ActivityInfo.FLAG_PRIMARY_USER_ONLY) != 0) {
+ if ((ri.activityInfo.flags&ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
newReceivers.remove(i);
i--;
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 8eea00f..24b90d8 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -513,7 +513,7 @@
configDestroy = false;
keysPaused = false;
inHistory = false;
- visible = true;
+ visible = false;
nowVisible = false;
idle = false;
hasBeenLaunched = false;
@@ -1278,7 +1278,7 @@
int event;
while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
- (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
+ (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
if (event == XmlPullParser.START_TAG) {
final String name = in.getName();
if (TaskPersister.DEBUG)
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 356565f..f50df3a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -248,6 +248,8 @@
/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;
+ private final LaunchingTaskPositioner mTaskPositioner;
+
static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
@@ -363,6 +365,33 @@
mStackId = activityContainer.mStackId;
mCurrentUser = mService.mCurrentUserId;
mRecentTasks = recentTasks;
+ mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID
+ ? new LaunchingTaskPositioner() : null;
+ }
+
+ void attachDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) {
+ mDisplayId = activityDisplay.mDisplayId;
+ mStacks = activityDisplay.mStacks;
+ mBounds = mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId, onTop);
+ mFullscreen = mBounds == null;
+ if (mTaskPositioner != null) {
+ mTaskPositioner.setDisplay(activityDisplay.mDisplay);
+ mTaskPositioner.configure(mBounds);
+ }
+ }
+
+ void detachDisplay() {
+ mDisplayId = Display.INVALID_DISPLAY;
+ mStacks = null;
+ if (mTaskPositioner != null) {
+ mTaskPositioner.reset();
+ }
+ mWindowManager.detachStack(mStackId);
+ }
+
+ void setBounds(Rect bounds) {
+ mBounds = mFullscreen ? null : new Rect(bounds);
+ mTaskPositioner.configure(bounds);
}
boolean okToShowLocked(ActivityRecord r) {
@@ -873,7 +902,14 @@
prev.task.touchActiveTime();
clearLaunchTime(prev);
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
- if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
+ // In freeform mode we only update the thumbnail when there is no thumbnail yet since every
+ // focus change will request a thumbnail to be taken.
+ // Note furthermore that since windows can change their content in freeform mode all the
+ // time a thumbnail is possibly constantly outdated.
+ if (mService.mHasRecents &&
+ (next == null || next.noDisplay || next.task != prev.task || uiSleeping) &&
+ (!prev.task.hasThumbnail() ||
+ prev.task.stack.mStackId != FREEFORM_WORKSPACE_STACK_ID)) {
prev.updateThumbnailLocked(screenshotActivities(prev), null);
}
stopFullyDrawnTraceIfNeeded();
@@ -2223,7 +2259,7 @@
+ task, new RuntimeException("here").fillInStackTrace());
task.addActivityToTop(r);
r.putInHistory();
- addAppToken(r, task);
+ addConfigOverride(r, task);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
@@ -2283,7 +2319,7 @@
: AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
}
- addAppToken(r, task);
+ addConfigOverride(r, task);
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
@@ -2332,7 +2368,7 @@
} else {
// If this is the first activity, don't do any fancy animations,
// because there is nothing for it to animate on top of.
- addAppToken(r, task);
+ addConfigOverride(r, task);
ActivityOptions.abort(options);
options = null;
}
@@ -4513,6 +4549,9 @@
boolean toTop) {
TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
voiceInteractor);
+ if (mTaskPositioner != null) {
+ mTaskPositioner.updateDefaultBounds(task, mTaskHistory, info.initialLayout);
+ }
addTask(task, toTop, false);
return task;
}
@@ -4548,7 +4587,7 @@
}
}
- void addAppToken(ActivityRecord r, TaskRecord task) {
+ void addConfigOverride(ActivityRecord r, TaskRecord task) {
final Rect bounds = task.getLaunchBounds();
final Configuration config =
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 12b848b..c86056b 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2977,7 +2977,7 @@
}
}
- stack.mBounds = stack.mFullscreen ? null : new Rect(bounds);
+ stack.setBounds(bounds);
if (r != null) {
final boolean updated = stack.ensureActivityConfigurationLocked(r, 0);
@@ -3017,7 +3017,6 @@
// Place the task in the right stack if it isn't there already based on the requested
// bounds.
int stackId = task.stack.mStackId;
- final boolean wasFrontStack = isFrontStack(task.stack);
if (bounds == null && stackId != FULLSCREEN_WORKSPACE_STACK_ID) {
stackId = FULLSCREEN_WORKSPACE_STACK_ID;
} else if (bounds != null
@@ -3027,12 +3026,7 @@
if (stackId != task.stack.mStackId) {
final String reason = "resizeTask";
final ActivityStack stack =
- moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, reason);
- if (wasFrontStack) {
- // Since the stack was previously in front,
- // move the stack in which we are placing the task to the front.
- stack.moveToFront(reason);
- }
+ moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason);
}
final Configuration overrideConfig = mWindowManager.resizeTask(task.taskId, bounds);
@@ -3112,7 +3106,7 @@
"Added restored task=" + task + " to stack=" + stack);
final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- stack.addAppToken(activities.get(activityNdx), task);
+ stack.addConfigOverride(activities.get(activityNdx), task);
}
return true;
}
@@ -3126,17 +3120,36 @@
* @param task Task to move.
* @param stackId Id of stack to move task to.
* @param toTop True if the task should be placed at the top of the stack.
+ * @param forceFocus if focus should be moved to the new stack
* @param reason Reason the task is been moved.
* @return The stack the task was moved to.
*/
private ActivityStack moveTaskToStackUncheckedLocked(
- TaskRecord task, int stackId, boolean toTop, String reason) {
+ TaskRecord task, int stackId, boolean toTop, boolean forceFocus, String reason) {
+ final ActivityRecord r = task.getTopActivity();
+ final boolean wasFocused = isFrontStack(task.stack) && (topRunningActivityLocked() == r);
+ final boolean wasResumed = wasFocused && (task.stack.mResumedActivity == r);
+
final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, toTop);
mWindowManager.moveTaskToStack(task.taskId, stack.mStackId, toTop);
if (task.stack != null) {
task.stack.removeTask(task, reason, MOVING);
}
stack.addTask(task, toTop, MOVING);
+
+ // If the task had focus before (or we're requested to move focus),
+ // move focus to the new stack.
+ if (forceFocus || wasFocused) {
+ // If the task owns the last resumed activity, transfer that together,
+ // so that we don't resume the same activity again in the new stack.
+ // Apps may depend on onResume()/onPause() being called in pairs.
+ if (wasResumed) {
+ stack.mResumedActivity = r;
+ }
+ // move the stack in which we are placing the task to the front.
+ stack.moveToFront(reason);
+ }
+
return stack;
}
@@ -3147,10 +3160,8 @@
return;
}
final String reason = "moveTaskToStack";
- final ActivityRecord top = task.topRunningActivityLocked(null);
- final boolean adjustFocus = forceFocus || mService.mFocusedActivity == top;
final ActivityStack stack =
- moveTaskToStackUncheckedLocked(task, stackId, toTop, reason);
+ moveTaskToStackUncheckedLocked(task, stackId, toTop, forceFocus, reason);
// Make sure the task has the appropriate bounds/size for the stack it is in.
if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
@@ -3162,14 +3173,6 @@
resizeTaskLocked(task, stack.mBounds);
}
- if (top != null && adjustFocus) {
- if (mService.mFocusedActivity != top) {
- mService.setFocusedActivityLocked(top, reason);
- } else {
- setFocusedStack(top, reason);
- }
- }
-
// The task might have already been running and its visibility needs to be synchronized with
// the visibility of the stack / windows.
ensureActivitiesVisibleLocked(null, 0);
@@ -4387,13 +4390,8 @@
if (DEBUG_STACK) Slog.d(TAG_STACK, "attachToDisplayLocked: " + this
+ " to display=" + activityDisplay + " onTop=" + onTop);
mActivityDisplay = activityDisplay;
- mStack.mDisplayId = activityDisplay.mDisplayId;
- mStack.mStacks = activityDisplay.mStacks;
-
+ mStack.attachDisplay(activityDisplay, onTop);
activityDisplay.attachActivities(mStack, onTop);
- mStack.mBounds =
- mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId, onTop);
- mStack.mFullscreen = mStack.mBounds == null;
}
@Override
@@ -4465,9 +4463,7 @@
if (mActivityDisplay != null) {
mActivityDisplay.detachActivitiesLocked(mStack);
mActivityDisplay = null;
- mStack.mDisplayId = -1;
- mStack.mStacks = null;
- mWindowManager.detachStack(mStackId);
+ mStack.detachDisplay();
}
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index d0f68f0..335288d 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -975,7 +975,9 @@
pw.println("Battery stats (batterystats) dump options:");
pw.println(" [--checkin] [--history] [--history-start] [--charged] [-c]");
pw.println(" [--daily] [--reset] [--write] [--new-daily] [--read-daily] [-h] [<package.name>]");
- pw.println(" --checkin: format output for a checkin report.");
+ pw.println(" --checkin: generate output for a checkin report; will write (and clear) the");
+ pw.println(" last old completed stats when they had been reset.");
+ pw.println(" --c: write the current stats in checkin format.");
pw.println(" --history: show only history data.");
pw.println(" --history-start <num>: show only history data starting at given time offset.");
pw.println(" --charged: only output data since last charged.");
@@ -1261,8 +1263,8 @@
Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + result);
}
- // There is some accuracy error in reports so allow 30 milliseconds of error.
- final long SAMPLE_ERROR_MILLIS = 30;
+ // There is some accuracy error in reports so allow some slop in the results.
+ final long SAMPLE_ERROR_MILLIS = 750;
final long totalTimeMs = result.mControllerIdleTimeMs + result.mControllerRxTimeMs +
result.mControllerTxTimeMs;
if (totalTimeMs > timePeriodMs + SAMPLE_ERROR_MILLIS) {
diff --git a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
new file mode 100644
index 0000000..5c4fd13
--- /dev/null
+++ b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.annotation.Nullable;
+import android.content.pm.ActivityInfo;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.Slog;
+import android.view.Display;
+import android.view.Gravity;
+
+import java.util.ArrayList;
+
+/**
+ * Determines where a launching task should be positioned and sized on the display.
+ *
+ * The positioner is fairly simple. For the new task it tries default position based on the gravity
+ * and compares corners of the task with corners of existing tasks. If some two pairs of corners are
+ * sufficiently close enough, it shifts the bounds of the new task and tries again. When it exhausts
+ * all possible shifts, it gives up and puts the task in the original position.
+ */
+class LaunchingTaskPositioner {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "LaunchingTaskPositioner" : TAG_AM;
+
+ // Determines how close window frames/corners have to be to call them colliding.
+ private static final int BOUNDS_CONFLICT_MIN_DISTANCE = 4;
+
+ // Task will receive dimensions based on available dimensions divided by this.
+ private static final int WINDOW_SIZE_DENOMINATOR = 2;
+
+ // Task will receive margins based on available dimensions divided by this.
+ private static final int MARGIN_SIZE_DENOMINATOR = 4;
+
+ // If task bounds collide with some other, we will step and try again until we find a good
+ // position. The step will be determined by using dimensions and dividing it by this.
+ private static final int STEP_DENOMINATOR = 16;
+
+ // We always want to step by at least this.
+ private static final int MINIMAL_STEP = 1;
+
+ // Used to indicate if positioning algorithm is allowed to restart from the beginning, when it
+ // reaches the end of stack bounds.
+ private static final boolean ALLOW_RESTART = true;
+
+ private static final int SHIFT_POLICY_DIAGONAL_DOWN = 1;
+ private static final int SHIFT_POLICY_HORIZONTAL_RIGHT = 2;
+ private static final int SHIFT_POLICY_HORIZONTAL_LEFT = 3;
+
+ private boolean mDefaultStartBoundsConfigurationSet = false;
+ private final Rect mAvailableRect = new Rect();
+ private final Rect mTmpProposal = new Rect();
+ private final Rect mTmpOriginal = new Rect();
+
+ private int mDefaultFreeformStartX;
+ private int mDefaultFreeformStartY;
+ private int mDefaultFreeformWidth;
+ private int mDefaultFreeformHeight;
+ private int mDefaultFreeformStepHorizontal;
+ private int mDefaultFreeformStepVertical;
+ private int mDisplayWidth;
+ private int mDisplayHeight;
+
+ void setDisplay(Display display) {
+ Point size = new Point();
+ display.getSize(size);
+ mDisplayWidth = size.x;
+ mDisplayHeight = size.y;
+ }
+
+ void configure(Rect stackBounds) {
+ if (stackBounds == null) {
+ mAvailableRect.set(0, 0, mDisplayWidth, mDisplayHeight);
+ } else {
+ mAvailableRect.set(stackBounds);
+ }
+ int width = mAvailableRect.width();
+ int height = mAvailableRect.height();
+ mDefaultFreeformStartX = mAvailableRect.left + width / MARGIN_SIZE_DENOMINATOR;
+ mDefaultFreeformStartY = mAvailableRect.top + height / MARGIN_SIZE_DENOMINATOR;
+ mDefaultFreeformWidth = width / WINDOW_SIZE_DENOMINATOR;
+ mDefaultFreeformHeight = height / WINDOW_SIZE_DENOMINATOR;
+ mDefaultFreeformStepHorizontal = Math.max(width / STEP_DENOMINATOR, MINIMAL_STEP);
+ mDefaultFreeformStepVertical = Math.max(height / STEP_DENOMINATOR, MINIMAL_STEP);
+ mDefaultStartBoundsConfigurationSet = true;
+ }
+
+ /**
+ * Tries to set task's bound in a way that it won't collide with any other task. By colliding
+ * we mean that two tasks have left-top corner very close to each other, so one might get
+ * obfuscated by the other one.
+ *
+ * @param task Task for which we want to find bounds that won't collide with other.
+ * @param tasks Existing tasks with which we don't want to collide.
+ * @param initialLayout Optional information from the client about how it would like to be sized
+ * and positioned.
+ */
+ void updateDefaultBounds(TaskRecord task, ArrayList<TaskRecord> tasks,
+ @Nullable ActivityInfo.InitialLayout initialLayout) {
+ if (!mDefaultStartBoundsConfigurationSet) {
+ return;
+ }
+ if (initialLayout == null) {
+ positionCenter(task, tasks, mDefaultFreeformWidth, mDefaultFreeformHeight);
+ return;
+ }
+ int width = getFinalWidth(initialLayout);
+ int height = getFinalHeight(initialLayout);
+ int verticalGravity = initialLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
+ int horizontalGravity = initialLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ if (verticalGravity == Gravity.TOP) {
+ if (horizontalGravity == Gravity.RIGHT) {
+ positionTopRight(task, tasks, width, height);
+ } else {
+ positionTopLeft(task, tasks, width, height);
+ }
+ } else if (verticalGravity == Gravity.BOTTOM) {
+ if (horizontalGravity == Gravity.RIGHT) {
+ positionBottomRight(task, tasks, width, height);
+ } else {
+ positionBottomLeft(task, tasks, width, height);
+ }
+ } else {
+ // Some fancy gravity setting that we don't support yet. We just put the activity in the
+ // center.
+ Slog.w(TAG, "Received unsupported gravity: " + initialLayout.gravity
+ + ", positioning in the center instead.");
+ positionCenter(task, tasks, width, height);
+ }
+ }
+
+ private int getFinalWidth(ActivityInfo.InitialLayout initialLayout) {
+ int width = mDefaultFreeformWidth;
+ if (initialLayout.width > 0) {
+ width = initialLayout.width;
+ }
+ if (initialLayout.widthFraction > 0) {
+ width = (int) (mAvailableRect.width() * initialLayout.widthFraction);
+ }
+ return width;
+ }
+
+ private int getFinalHeight(ActivityInfo.InitialLayout initialLayout) {
+ int height = mDefaultFreeformHeight;
+ if (initialLayout.height > 0) {
+ height = initialLayout.height;
+ }
+ if (initialLayout.heightFraction > 0) {
+ height = (int) (mAvailableRect.height() * initialLayout.heightFraction);
+ }
+ return height;
+ }
+
+ private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+ int height) {
+ mTmpProposal.set(mAvailableRect.left, mAvailableRect.bottom - height,
+ mAvailableRect.left + width, mAvailableRect.bottom);
+ position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT);
+ }
+
+ private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+ int height) {
+ mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.bottom - height,
+ mAvailableRect.right, mAvailableRect.bottom);
+ position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT);
+ }
+
+ private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+ int height) {
+ mTmpProposal.set(mAvailableRect.left, mAvailableRect.top,
+ mAvailableRect.left + width, mAvailableRect.top + height);
+ position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT);
+ }
+
+ private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+ int height) {
+ mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.top,
+ mAvailableRect.right, mAvailableRect.top + height);
+ position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT);
+ }
+
+ private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+ int height) {
+ mTmpProposal.set(mDefaultFreeformStartX, mDefaultFreeformStartY,
+ mDefaultFreeformStartX + width, mDefaultFreeformStartY + height);
+ position(task, tasks, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN);
+ }
+
+ private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect proposal,
+ boolean allowRestart, int shiftPolicy) {
+ mTmpOriginal.set(proposal);
+ boolean restarted = false;
+ while (boundsConflict(proposal, tasks)) {
+ // Unfortunately there is already a task at that spot, so we need to look for some
+ // other place.
+ shiftStartingPoint(proposal, shiftPolicy);
+ if (shiftedToFar(proposal, shiftPolicy)) {
+ // We don't want the task to go outside of the stack, because it won't look
+ // nice. Depending on the starting point we either restart, or immediately give up.
+ if (!allowRestart) {
+ proposal.set(mTmpOriginal);
+ break;
+ }
+ // We must have started not from the top. Let's restart from there because there
+ // might be some space there.
+ proposal.set(mAvailableRect.left, mAvailableRect.top,
+ mAvailableRect.left + proposal.width(),
+ mAvailableRect.top + proposal.height());
+ restarted = true;
+ }
+ if (restarted && (proposal.left > mDefaultFreeformStartX
+ || proposal.top > mDefaultFreeformStartY)) {
+ // If we restarted and crossed the initial position, let's not struggle anymore.
+ // The user already must have ton of tasks visible, we can just smack the new
+ // one in the center.
+ proposal.set(mTmpOriginal);
+ break;
+ }
+ }
+ task.setInitialBounds(proposal);
+ }
+
+ private boolean shiftedToFar(Rect start, int shiftPolicy) {
+ switch (shiftPolicy) {
+ case SHIFT_POLICY_HORIZONTAL_LEFT:
+ return start.left < mAvailableRect.left;
+ case SHIFT_POLICY_HORIZONTAL_RIGHT:
+ return start.right > mAvailableRect.right;
+ default: // SHIFT_POLICY_DIAGONAL_DOWN
+ return start.right > mAvailableRect.right || start.bottom > mAvailableRect.bottom;
+ }
+ }
+
+ private void shiftStartingPoint(Rect posposal, int shiftPolicy) {
+ switch (shiftPolicy) {
+ case SHIFT_POLICY_HORIZONTAL_LEFT:
+ posposal.offset(-mDefaultFreeformStepHorizontal, 0);
+ break;
+ case SHIFT_POLICY_HORIZONTAL_RIGHT:
+ posposal.offset(mDefaultFreeformStepHorizontal, 0);
+ break;
+ default: // SHIFT_POLICY_DIAGONAL_DOWN:
+ posposal.offset(mDefaultFreeformStepHorizontal, mDefaultFreeformStepVertical);
+ break;
+ }
+ }
+
+ private static boolean boundsConflict(Rect proposal, ArrayList<TaskRecord> tasks) {
+ for (int i = tasks.size() - 1; i >= 0; i--) {
+ TaskRecord task = tasks.get(i);
+ if (!task.mActivities.isEmpty() && task.mBounds != null) {
+ Rect bounds = task.mBounds;
+ if (closeLeftTopCorner(proposal, bounds) || closeRightTopCorner(proposal, bounds)
+ || closeLeftBottomCorner(proposal, bounds)
+ || closeRightBottomCorner(proposal, bounds)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static final boolean closeLeftTopCorner(Rect first, Rect second) {
+ return Math.abs(first.left - second.left) < BOUNDS_CONFLICT_MIN_DISTANCE
+ && Math.abs(first.top - second.top) < BOUNDS_CONFLICT_MIN_DISTANCE;
+ }
+
+ private static final boolean closeRightTopCorner(Rect first, Rect second) {
+ return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
+ && Math.abs(first.top - second.top) < BOUNDS_CONFLICT_MIN_DISTANCE;
+ }
+
+ private static final boolean closeLeftBottomCorner(Rect first, Rect second) {
+ return Math.abs(first.left - second.left) < BOUNDS_CONFLICT_MIN_DISTANCE
+ && Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
+ }
+
+ private static final boolean closeRightBottomCorner(Rect first, Rect second) {
+ return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
+ && Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
+ }
+
+ void reset() {
+ mDefaultStartBoundsConfigurationSet = false;
+ }
+}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 8fa0ae6..9cbaec5 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -478,6 +478,14 @@
}
/**
+ * Returns true when we have a thumbnail.
+ * @return Returns true if there is a thumbnail.
+ */
+ boolean hasThumbnail() {
+ return mLastThumbnail != null;
+ }
+
+ /**
* Sets the last thumbnail.
* @return whether the thumbnail was set
*/
@@ -1103,7 +1111,7 @@
int event;
while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
- (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
+ (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
if (event == XmlPullParser.START_TAG) {
final String name = in.getName();
if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" +
@@ -1217,6 +1225,14 @@
return mLastNonFullscreenBounds;
}
+ void setInitialBounds(Rect rect) {
+ if (mBounds == null) {
+ mBounds = new Rect();
+ }
+ mBounds.set(rect);
+ mLastNonFullscreenBounds = mBounds;
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("userId="); pw.print(userId);
pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java
index 0be24f4..f82454a 100644
--- a/services/core/java/com/android/server/camera/CameraService.java
+++ b/services/core/java/com/android/server/camera/CameraService.java
@@ -23,13 +23,17 @@
import android.content.pm.UserInfo;
import android.hardware.ICameraService;
import android.hardware.ICameraServiceProxy;
+import android.nfc.INfcAdapter;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Binder;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserManager;
+import android.os.SystemProperties;
import android.util.Slog;
+import android.util.ArraySet;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
@@ -44,8 +48,10 @@
*
* @hide
*/
-public class CameraService extends SystemService implements Handler.Callback {
+public class CameraService extends SystemService
+ implements Handler.Callback, IBinder.DeathRecipient {
private static final String TAG = "CameraService_proxy";
+ private static final boolean DEBUG = false;
/**
* This must match the ICameraService.aidl definition
@@ -58,6 +64,16 @@
public static final int NO_EVENT = 0; // NOOP
public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle
+ // State arguments to use with the notifyCameraState call from camera service:
+ public static final int CAMERA_STATE_OPEN = 0;
+ public static final int CAMERA_STATE_ACTIVE = 1;
+ public static final int CAMERA_STATE_IDLE = 2;
+ public static final int CAMERA_STATE_CLOSED = 3;
+
+ // Flags arguments to NFC adapter to enable/disable NFC
+ public static final int DISABLE_POLLING_FLAGS = 0x1000;
+ public static final int ENABLE_POLLING_FLAGS = 0x0000;
+
// Handler message codes
private static final int MSG_SWITCH_USER = 1;
@@ -72,6 +88,17 @@
private Set<Integer> mEnabledCameraUsers;
private int mLastUser;
+ private ICameraService mCameraServiceRaw;
+
+ private final ArraySet<String> mActiveCameraIds = new ArraySet<>();
+
+ private static final String NFC_NOTIFICATION_PROP = "ro.camera.notify_nfc";
+ private static final String NFC_SERVICE_BINDER_NAME = "nfc";
+ private static final IBinder nfcInterfaceToken = new Binder();
+
+ private final boolean mNotifyNfc;
+ private int mActiveCameraCount = 0;
+
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -102,6 +129,14 @@
public void pingForUserUpdate() {
notifySwitchWithRetries(30);
}
+
+ @Override
+ public void notifyCameraState(String cameraId, int newCameraState) {
+ String state = cameraStateToString(newCameraState);
+ if (DEBUG) Slog.v(TAG, "Camera " + cameraId + " state now " + state);
+
+ updateActivityCount(cameraId, newCameraState);
+ }
};
public CameraService(Context context) {
@@ -110,6 +145,9 @@
mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, /*allowTo*/false);
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper(), this);
+
+ mNotifyNfc = SystemProperties.getInt(NFC_NOTIFICATION_PROP, 0) > 0;
+ if (DEBUG) Slog.v(TAG, "Notify NFC behavior is " + (mNotifyNfc ? "active" : "disabled"));
}
@Override
@@ -161,13 +199,32 @@
}
}
+ /**
+ * Handle the death of the native camera service
+ */
+ @Override
+ public void binderDied() {
+ if (DEBUG) Slog.w(TAG, "Native camera service has died");
+ synchronized(mLock) {
+ mCameraServiceRaw = null;
+
+ // All cameras reset to idle on camera service death
+ boolean wasEmpty = mActiveCameraIds.isEmpty();
+ mActiveCameraIds.clear();
+
+ if ( mNotifyNfc && !wasEmpty ) {
+ notifyNfcService(/*enablePolling*/ true);
+ }
+ }
+ }
+
private void switchUserLocked(int userHandle) {
Set<Integer> currentUserHandles = getEnabledUserHandles(userHandle);
mLastUser = userHandle;
if (mEnabledCameraUsers == null || !mEnabledCameraUsers.equals(currentUserHandles)) {
// Some user handles have been added or removed, update mediaserver.
mEnabledCameraUsers = currentUserHandles;
- notifyMediaserver(USER_SWITCHED, currentUserHandles);
+ notifyMediaserverLocked(USER_SWITCHED, currentUserHandles);
}
}
@@ -187,7 +244,7 @@
if (mEnabledCameraUsers == null) {
return;
}
- if (notifyMediaserver(USER_SWITCHED, mEnabledCameraUsers)) {
+ if (notifyMediaserverLocked(USER_SWITCHED, mEnabledCameraUsers)) {
retries = 0;
}
}
@@ -199,19 +256,27 @@
RETRY_DELAY_TIME);
}
- private boolean notifyMediaserver(int eventType, Set<Integer> updatedUserHandles) {
+ private boolean notifyMediaserverLocked(int eventType, Set<Integer> updatedUserHandles) {
// Forward the user switch event to the native camera service running in the mediaserver
// process.
- IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
- if (cameraServiceBinder == null) {
- Slog.w(TAG, "Could not notify mediaserver, camera service not available.");
- return false; // Camera service not active, cannot evict user clients.
+ if (mCameraServiceRaw == null) {
+ IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
+ if (cameraServiceBinder == null) {
+ Slog.w(TAG, "Could not notify mediaserver, camera service not available.");
+ return false; // Camera service not active, cannot evict user clients.
+ }
+ try {
+ cameraServiceBinder.linkToDeath(this, /*flags*/ 0);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Could not link to death of native camera service");
+ return false;
+ }
+
+ mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
}
- ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
-
try {
- cameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles));
+ mCameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles));
} catch (RemoteException e) {
Slog.w(TAG, "Could not notify mediaserver, remote exception: " + e);
// Not much we can do if camera service is dead.
@@ -220,6 +285,44 @@
return true;
}
+ private void updateActivityCount(String cameraId, int newCameraState) {
+ synchronized(mLock) {
+ boolean wasEmpty = mActiveCameraIds.isEmpty();
+ switch (newCameraState) {
+ case CAMERA_STATE_OPEN:
+ break;
+ case CAMERA_STATE_ACTIVE:
+ mActiveCameraIds.add(cameraId);
+ break;
+ case CAMERA_STATE_IDLE:
+ case CAMERA_STATE_CLOSED:
+ mActiveCameraIds.remove(cameraId);
+ break;
+ }
+ boolean isEmpty = mActiveCameraIds.isEmpty();
+ if ( mNotifyNfc && (wasEmpty != isEmpty) ) {
+ notifyNfcService(isEmpty);
+ }
+ }
+ }
+
+ private void notifyNfcService(boolean enablePolling) {
+
+ IBinder nfcServiceBinder = getBinderService(NFC_SERVICE_BINDER_NAME);
+ if (nfcServiceBinder == null) {
+ Slog.w(TAG, "Could not connect to NFC service to notify it of camera state");
+ return;
+ }
+ INfcAdapter nfcAdapterRaw = INfcAdapter.Stub.asInterface(nfcServiceBinder);
+ int flags = enablePolling ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS;
+ if (DEBUG) Slog.v(TAG, "Setting NFC reader mode to flags " + flags);
+ try {
+ nfcAdapterRaw.setReaderMode(nfcInterfaceToken, null, flags, null);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Could not notify NFC service, remote exception: " + e);
+ }
+ }
+
private static int[] toArray(Collection<Integer> c) {
int len = c.size();
int[] ret = new int[len];
@@ -229,4 +332,15 @@
}
return ret;
}
+
+ private static String cameraStateToString(int newCameraState) {
+ switch (newCameraState) {
+ case CAMERA_STATE_OPEN: return "CAMERA_STATE_OPEN";
+ case CAMERA_STATE_ACTIVE: return "CAMERA_STATE_ACTIVE";
+ case CAMERA_STATE_IDLE: return "CAMERA_STATE_IDLE";
+ case CAMERA_STATE_CLOSED: return "CAMERA_STATE_CLOSED";
+ default: break;
+ }
+ return "CAMERA_STATE_UNKNOWN";
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 2846185..3df3cd0 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -146,7 +146,8 @@
} catch (RemoteException e) {
Log.wtf(TAG, "Problem registering observer", e);
}
- if (userHandle == UserHandle.USER_OWNER) {
+ // TODO: http://b/22950929
+ if (userHandle == UserHandle.USER_SYSTEM) {
// Owner's VPN also needs to handle restricted users
mUserIntentReceiver = new BroadcastReceiver() {
@Override
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index c998c2c..292aff9 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -790,7 +790,7 @@
for (AccountAndUser account : accounts) {
// If userId is specified, do not sync accounts of other users
- if (userId >= UserHandle.USER_OWNER && account.userId >= UserHandle.USER_OWNER
+ if (userId >= UserHandle.USER_SYSTEM && account.userId >= UserHandle.USER_SYSTEM
&& userId != account.userId) {
continue;
}
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index befa311..470bd5a 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -298,6 +298,7 @@
final int result = daemon.enroll(cryptoToken, groupId, timeout);
if (result != 0) {
Slog.w(TAG, "startEnroll failed, result=" + result);
+ dispatchError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
}
} catch (RemoteException e) {
Slog.e(TAG, "startEnroll failed", e);
@@ -391,6 +392,7 @@
final int result = daemon.authenticate(opId, groupId);
if (result != 0) {
Slog.w(TAG, "startAuthentication failed, result=" + result);
+ dispatchError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
}
} catch (RemoteException e) {
Slog.e(TAG, "startAuthentication failed", e);
@@ -433,12 +435,14 @@
return;
}
+ stopPendingOperations(true);
mRemoveClient = new ClientMonitor(token, receiver, userId, restricted);
// The fingerprint template ids will be removed when we get confirmation from the HAL
try {
final int result = daemon.remove(fingerId, userId);
if (result != 0) {
Slog.w(TAG, "startRemove with id = " + fingerId + " failed, result=" + result);
+ dispatchError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
}
} catch (RemoteException e) {
Slog.e(TAG, "startRemove failed", e);
@@ -764,6 +768,7 @@
mHandler.post(new Runnable() {
@Override
public void run() {
+ MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
startAuthentication(token, opId, effectiveGroupId, receiver, flags, restricted);
}
});
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 57ca552..5c60a61 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -2200,14 +2200,18 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
StringBuilder s = new StringBuilder();
- s.append(" mFixInterval=").append(mFixInterval).append("\n");
- s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append("\n");
- s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
- if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
+ s.append(" mFixInterval=").append(mFixInterval).append('\n');
+ s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
+ s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
+ s.append(" ( ");
+ if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");
if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
+ if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING ");
+ if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS ");
+ if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES ");
s.append(")\n");
s.append(native_get_internal_state());
diff --git a/services/core/java/com/android/server/location/LocationBlacklist.java b/services/core/java/com/android/server/location/LocationBlacklist.java
index 6f22689..3f3f828 100644
--- a/services/core/java/com/android/server/location/LocationBlacklist.java
+++ b/services/core/java/com/android/server/location/LocationBlacklist.java
@@ -50,7 +50,7 @@
private String[] mWhitelist = new String[0];
private String[] mBlacklist = new String[0];
- private int mCurrentUserId = UserHandle.USER_OWNER;
+ private int mCurrentUserId = UserHandle.USER_SYSTEM;
public LocationBlacklist(Context context, Handler handler) {
super(handler);
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 40956c1..19d8538 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -67,7 +67,7 @@
public void addSystemProvider(SystemConditionProviderService service) {
mSystemConditionProviders.add(service);
service.attachBase(mContext);
- registerService(service.asInterface(), service.getComponent(), UserHandle.USER_OWNER);
+ registerService(service.asInterface(), service.getComponent(), UserHandle.USER_SYSTEM);
}
public Iterable<SystemConditionProviderService> getSystemProviders() {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4351798..0c884f15 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -716,7 +716,7 @@
final IPackageManager pm = AppGlobals.getPackageManager();
final int enabled = pm.getApplicationEnabledSetting(pkgName,
changeUserId != UserHandle.USER_ALL ? changeUserId :
- UserHandle.USER_OWNER);
+ UserHandle.USER_SYSTEM);
if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|| enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
cancelNotifications = false;
@@ -1420,7 +1420,7 @@
if (!r.isSeen()) {
if (DBG) Slog.d(TAG, "Marking notification as seen " + keys[i]);
mAppUsageStats.reportEvent(r.sbn.getPackageName(),
- userId == UserHandle.USER_ALL ? UserHandle.USER_OWNER
+ userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM
: userId,
UsageEvents.Event.USER_INTERACTION);
r.setSeen();
@@ -1701,7 +1701,8 @@
@Override
public byte[] getBackupPayload(int user) {
if (DBG) Slog.d(TAG, "getBackupPayload u=" + user);
- if (user != UserHandle.USER_OWNER) {
+ //TODO: http://b/22388012
+ if (user != UserHandle.USER_SYSTEM) {
Slog.w(TAG, "getBackupPayload: cannot backup policy for user " + user);
return null;
}
@@ -1723,7 +1724,8 @@
Slog.w(TAG, "applyRestore: no payload to restore for user " + user);
return;
}
- if (user != UserHandle.USER_OWNER) {
+ //TODO: http://b/22388012
+ if (user != UserHandle.USER_SYSTEM) {
Slog.w(TAG, "applyRestore: cannot restore policy for user " + user);
return;
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index a089518..66381f5 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -148,7 +148,8 @@
if (!TextUtils.isEmpty(name)) {
if (forRestore) {
try {
- uid = pm.getPackageUid(name, UserHandle.USER_OWNER);
+ //TODO: http://b/22388012
+ uid = pm.getPackageUid(name, UserHandle.USER_SYSTEM);
} catch (NameNotFoundException e) {
// noop
}
@@ -213,7 +214,8 @@
final int N = mRecords.size();
for (int i = 0; i < N; i++) {
final Record r = mRecords.valueAt(i);
- if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_OWNER) {
+ //TODO: http://b/22388012
+ if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) {
continue;
}
out.startTag(null, TAG_PACKAGE);
@@ -437,7 +439,8 @@
final Record r = mRestoredWithoutUids.get(pkg);
if (r != null) {
try {
- r.uid = pm.getPackageUid(r.pkg, UserHandle.USER_OWNER);
+ //TODO: http://b/22388012
+ r.uid = pm.getPackageUid(r.pkg, UserHandle.USER_SYSTEM);
mRestoredWithoutUids.remove(pkg);
mRecords.put(recordKey(r.pkg, r.uid), r);
updated = true;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 57d7758..0a12d5a 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -85,7 +85,7 @@
private final Metrics mMetrics = new Metrics();
private int mZenMode;
- private int mUser = UserHandle.USER_OWNER;
+ private int mUser = UserHandle.USER_SYSTEM;
private ZenModeConfig mConfig;
private AudioManagerInternal mAudioManager;
private boolean mEffectsSuppressed;
@@ -99,7 +99,7 @@
appendDefaultScheduleRules(mDefaultConfig);
appendDefaultEventRules(mDefaultConfig);
mConfig = mDefaultConfig;
- mConfigs.put(UserHandle.USER_OWNER, mConfig);
+ mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
mSettingsObserver = new SettingsObserver(mHandler);
mSettingsObserver.observe();
mFiltering = new ZenModeFiltering(mContext);
@@ -152,7 +152,7 @@
}
public void onUserSwitched(int user) {
- if (mUser == user || user < UserHandle.USER_OWNER) return;
+ if (mUser == user || user < UserHandle.USER_SYSTEM) return;
mUser = user;
if (DEBUG) Log.d(TAG, "onUserSwitched u=" + user);
ZenModeConfig config = mConfigs.get(user);
@@ -165,7 +165,7 @@
}
public void onUserRemoved(int user) {
- if (user < UserHandle.USER_OWNER) return;
+ if (user < UserHandle.USER_SYSTEM) return;
if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user);
mConfigs.remove(user);
}
@@ -265,7 +265,8 @@
final ZenModeConfig config = ZenModeConfig.readXml(parser, mConfigMigration);
if (config != null) {
if (forRestore) {
- if (config.user != UserHandle.USER_OWNER) {
+ //TODO: http://b/22388012
+ if (config.user != UserHandle.USER_SYSTEM) {
return;
}
config.manualRule = null; // don't restore the manual rule
@@ -285,7 +286,8 @@
public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
final int N = mConfigs.size();
for (int i = 0; i < N; i++) {
- if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_OWNER) {
+ //TODO: http://b/22388012
+ if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_SYSTEM) {
continue;
}
mConfigs.valueAt(i).writeXml(out);
@@ -411,8 +413,7 @@
applyRestrictions(muteNotifications, USAGE_NOTIFICATION);
// call restrictions
- final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers
- || mEffectsSuppressed;
+ final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers;
applyRestrictions(muteCalls, USAGE_NOTIFICATION_RINGTONE);
// alarm restrictions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 47729f9..9e878e7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -71,7 +71,7 @@
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDWR;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
-import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER;
+import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
import static com.android.internal.util.ArrayUtils.appendInt;
@@ -1925,8 +1925,7 @@
mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
- mRestoredSettings = mSettings.readLPw(this, sUserManager.getUsers(false),
- mSdkVersion, mOnlyCore);
+ mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false));
String customResolverActivity = Resources.getSystem().getString(
R.string.config_customResolverActivity);
@@ -4555,7 +4554,7 @@
if (xpResolveInfo != null && isUserEnabled(xpResolveInfo.targetUserId)) {
List<ResolveInfo> result = new ArrayList<ResolveInfo>(1);
result.add(xpResolveInfo);
- return filterIfNotPrimaryUser(result, userId);
+ return filterIfNotSystemUser(result, userId);
}
// Check for results in the current profile.
@@ -4569,7 +4568,7 @@
result.add(xpResolveInfo);
Collections.sort(result, mResolvePrioritySorter);
}
- result = filterIfNotPrimaryUser(result, userId);
+ result = filterIfNotSystemUser(result, userId);
if (hasWebURI(intent)) {
CrossProfileDomainInfo xpDomainInfo = null;
final UserInfo parent = getProfileParent(userId);
@@ -4598,7 +4597,7 @@
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- return filterIfNotPrimaryUser(
+ return filterIfNotSystemUser(
mActivities.queryIntentForPackage(
intent, resolvedType, flags, pkg.activities, userId),
userId);
@@ -4645,7 +4644,7 @@
if (result == null) {
result = new CrossProfileDomainInfo();
result.resolveInfo =
- createForwardingResolveInfo(null, sourceUserId, parentUserId);
+ createForwardingResolveInfo(new IntentFilter(), sourceUserId, parentUserId);
result.bestDomainVerificationStatus = status;
} else {
result.bestDomainVerificationStatus = bestDomainVerificationStatus(status,
@@ -4685,17 +4684,17 @@
}
/**
- * Filter out activities with primaryUserOnly flag set, when current user is not the owner.
+ * Filter out activities with systemUserOnly flag set, when current user is not System.
*
* @return filtered list
*/
- private List<ResolveInfo> filterIfNotPrimaryUser(List<ResolveInfo> resolveInfos, int userId) {
- if (userId == UserHandle.USER_OWNER) {
+ private List<ResolveInfo> filterIfNotSystemUser(List<ResolveInfo> resolveInfos, int userId) {
+ if (userId == UserHandle.USER_SYSTEM) {
return resolveInfos;
}
for (int i = resolveInfos.size() - 1; i >= 0; i--) {
ResolveInfo info = resolveInfos.get(i);
- if ((info.activityInfo.flags & ActivityInfo.FLAG_PRIMARY_USER_ONLY) != 0) {
+ if ((info.activityInfo.flags & ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
resolveInfos.remove(i);
}
}
@@ -4950,18 +4949,25 @@
private ResolveInfo createForwardingResolveInfo(IntentFilter filter,
int sourceUserId, int targetUserId) {
ResolveInfo forwardingResolveInfo = new ResolveInfo();
+ long ident = Binder.clearCallingIdentity();
+ boolean targetIsProfile;
+ try {
+ targetIsProfile = sUserManager.getUserInfo(targetUserId).isManagedProfile();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
String className;
- if (targetUserId == UserHandle.USER_OWNER) {
- className = FORWARD_INTENT_TO_USER_OWNER;
- } else {
+ if (targetIsProfile) {
className = FORWARD_INTENT_TO_MANAGED_PROFILE;
+ } else {
+ className = FORWARD_INTENT_TO_PARENT;
}
ComponentName forwardingActivityComponentName = new ComponentName(
mAndroidApplication.packageName, className);
ActivityInfo forwardingActivityInfo = getActivityInfo(forwardingActivityComponentName, 0,
sourceUserId);
- if (targetUserId == UserHandle.USER_OWNER) {
- forwardingActivityInfo.showUserIcon = UserHandle.USER_OWNER;
+ if (!targetIsProfile) {
+ forwardingActivityInfo.showUserIcon = targetUserId;
forwardingResolveInfo.noResourceId = true;
}
forwardingResolveInfo.activityInfo = forwardingActivityInfo;
@@ -6113,7 +6119,7 @@
}
// Give priority to system apps that listen for pre boot complete.
Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
- ArraySet<String> pkgNames = getPackageNamesForIntent(intent);
+ ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
PackageParser.Package pkg = it.next();
if (pkgNames.contains(pkg.packageName)) {
@@ -6148,7 +6154,7 @@
}
// Give priority to apps that listen for boot complete.
intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
- pkgNames = getPackageNamesForIntent(intent);
+ pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
PackageParser.Package pkg = it.next();
if (pkgNames.contains(pkg.packageName)) {
@@ -6219,11 +6225,11 @@
}
}
- private ArraySet<String> getPackageNamesForIntent(Intent intent) {
+ private ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
List<ResolveInfo> ris = null;
try {
ris = AppGlobals.getPackageManager().queryIntentReceivers(
- intent, null, 0, UserHandle.USER_OWNER);
+ intent, null, 0, userId);
} catch (RemoteException e) {
}
ArraySet<String> pkgNames = new ArraySet<String>();
@@ -11846,8 +11852,9 @@
String pkgName = pkg.packageName;
if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
+ // TODO: b/23350563
final boolean dataDirExists = Environment
- .getDataUserPackageDirectory(volumeUuid, UserHandle.USER_OWNER, pkgName).exists();
+ .getDataUserPackageDirectory(volumeUuid, UserHandle.USER_SYSTEM, pkgName).exists();
synchronized(mPackages) {
if (mSettings.mRenamedPackages.containsKey(pkgName)) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 943e649..61d2676 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -23,12 +23,12 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
-import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.PACKAGE_INFO_GID;
import static com.android.server.pm.PackageManagerService.DEBUG_DOMAIN_VERIFICATION;
+import android.annotation.NonNull;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.IntentFilterVerificationInfo;
@@ -38,13 +38,10 @@
import android.os.Build;
import android.os.Environment;
import android.os.FileUtils;
-import android.os.IBinder;
import android.os.Handler;
import android.os.Message;
import android.os.PatternMatcher;
import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
@@ -2486,8 +2483,7 @@
}
}
- boolean readLPw(PackageManagerService service, List<UserInfo> users, int sdkVersion,
- boolean onlyCore) {
+ boolean readLPw(@NonNull List<UserInfo> users) {
FileInputStream str = null;
if (mBackupSettingsFilename.exists()) {
try {
@@ -2583,7 +2579,7 @@
String userStr = parser.getAttributeValue(null, ATTR_USER);
String codeStr = parser.getAttributeValue(null, ATTR_CODE);
if (name != null) {
- int userId = 0;
+ int userId = UserHandle.USER_SYSTEM;
boolean andCode = true;
try {
if (userStr != null) {
@@ -2672,14 +2668,8 @@
if (PackageManagerService.CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE) {
final VersionInfo internal = getInternalVersion();
if (!Build.FINGERPRINT.equals(internal.fingerprint)) {
- if (users == null) {
- mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile(
- UserHandle.USER_OWNER);
- } else {
- for (UserInfo user : users) {
- mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile(
- user.id);
- }
+ for (UserInfo user : users) {
+ mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile(user.id);
}
}
}
@@ -2722,23 +2712,15 @@
mBackupStoppedPackagesFilename.delete();
mStoppedPackagesFilename.delete();
// Migrate to new file format
- writePackageRestrictionsLPr(0);
+ writePackageRestrictionsLPr(UserHandle.USER_SYSTEM);
} else {
- if (users == null) {
- readPackageRestrictionsLPr(0);
- } else {
- for (UserInfo user : users) {
- readPackageRestrictionsLPr(user.id);
- }
+ for (UserInfo user : users) {
+ readPackageRestrictionsLPr(user.id);
}
}
- if (users == null) {
- mRuntimePermissionsPersistence.readStateForUserSyncLPr(UserHandle.USER_OWNER);
- } else {
- for (UserInfo user : users) {
- mRuntimePermissionsPersistence.readStateForUserSyncLPr(user.id);
- }
+ for (UserInfo user : users) {
+ mRuntimePermissionsPersistence.readStateForUserSyncLPr(user.id);
}
/*
@@ -4321,7 +4303,7 @@
pw.print(" sourcePackage="); pw.println(p.sourcePackage);
pw.print(" uid="); pw.print(p.uid);
pw.print(" gids="); pw.print(Arrays.toString(
- p.computeGids(UserHandle.USER_OWNER)));
+ p.computeGids(UserHandle.USER_SYSTEM)));
pw.print(" type="); pw.print(p.type);
pw.print(" prot=");
pw.println(PermissionInfo.protectionToString(p.protectionLevel));
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index fcfb5e8..4bfcb90 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.pm;
+import android.annotation.NonNull;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -132,7 +133,7 @@
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
- // Maximum number of managed profiles permitted is 1. This cannot be increased
+ // Maximum number of managed profiles permitted per user is 1. This cannot be increased
// without first making sure that the rest of the framework is prepared for it.
private static final int MAX_MANAGED_PROFILES = 1;
@@ -280,7 +281,7 @@
}
@Override
- public List<UserInfo> getUsers(boolean excludeDying) {
+ public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
checkManageUsersPermission("query users");
synchronized (mPackagesLock) {
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
@@ -418,9 +419,10 @@
return ui;
}
+ /** Called by PackageManagerService */
public boolean exists(int userId) {
synchronized (mPackagesLock) {
- return ArrayUtils.contains(mUserIds, userId);
+ return mUsers.get(userId) != null;
}
}
@@ -625,7 +627,7 @@
}
@Override
- public boolean canAddMoreManagedProfiles() {
+ public boolean canAddMoreManagedProfiles(int userId) {
checkManageUsersPermission("check if more managed profiles can be added.");
if (ActivityManager.isLowRamDeviceStatic()) {
return false;
@@ -634,10 +636,14 @@
PackageManager.FEATURE_MANAGED_USERS)) {
return false;
}
+ // Limit number of managed profiles that can be created
+ int managedProfilesCount = getProfiles(userId, true).size() - 1;
+ if (managedProfilesCount >= MAX_MANAGED_PROFILES) {
+ return false;
+ }
synchronized(mPackagesLock) {
- // Limit number of managed profiles that can be created
- if (numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true)
- >= MAX_MANAGED_PROFILES) {
+ UserInfo userInfo = getUserInfoLocked(userId);
+ if (!userInfo.canHaveProfile()) {
return false;
}
int usersCount = getAliveUsersExcludingGuestsCountLocked();
@@ -1236,10 +1242,6 @@
@Override
public UserInfo createProfileForUser(String name, int flags, int userId) {
checkManageUsersPermission("Only the system can create users");
- if (userId != UserHandle.USER_OWNER) {
- Slog.w(LOG_TAG, "Only user owner can have profiles");
- return null;
- }
return createUserInternal(name, flags, userId);
}
@@ -1271,7 +1273,8 @@
parent = getUserInfoLocked(parentId);
if (parent == null) return null;
}
- if (isManagedProfile && !canAddMoreManagedProfiles()) {
+ if (isManagedProfile && !canAddMoreManagedProfiles(parentId)) {
+ Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
return null;
}
if (!isGuest && !isManagedProfile && isUserLimitReachedLocked()) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 45bbf37..4aaba14 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2835,6 +2835,12 @@
}
}
}
+ } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
+ if (down) {
+ if (repeatCount == 0) {
+ showKeyboardShortcutsMenu();
+ }
+ }
} else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
if (down) {
if (repeatCount == 0) {
@@ -3255,6 +3261,17 @@
}
}
+ private void showKeyboardShortcutsMenu() {
+ try {
+ IStatusBarService statusbar = getStatusBarService();
+ if (statusbar != null) {
+ statusbar.showKeyboardShortcutsMenu();
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException when showing keyboard shortcuts menu", e);
+ }
+ }
+
private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
mPreloadedRecentApps = false; // preloading no longer needs to be canceled
try {
@@ -4438,7 +4455,7 @@
if (mAppsToBeHidden.isEmpty()) {
if (dismissKeyguard && !mKeyguardSecure) {
mAppsThatDismissKeyguard.add(appToken);
- } else {
+ } else if (win.isDrawnLw()) {
mWinShowWhenLocked = win;
mHideLockScreen = true;
mForceStatusBarFromKeyguard = false;
@@ -4472,7 +4489,7 @@
mWinDismissingKeyguard = win;
mSecureDismissingKeyguard = mKeyguardSecure;
mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
- } else if (mAppsToBeHidden.isEmpty() && showWhenLocked) {
+ } else if (mAppsToBeHidden.isEmpty() && showWhenLocked && win.isDrawnLw()) {
if (DEBUG_LAYOUT) Slog.v(TAG,
"Setting mHideLockScreen to true by win " + win);
mHideLockScreen = true;
@@ -6113,6 +6130,7 @@
}
startedWakingUp();
screenTurningOn(null);
+ screenTurnedOn();
}
ProgressDialog mBootMsgDialog = null;
diff --git a/services/core/java/com/android/server/policy/StatusBarController.java b/services/core/java/com/android/server/policy/StatusBarController.java
index d1b50da..b935f5a 100644
--- a/services/core/java/com/android/server/policy/StatusBarController.java
+++ b/services/core/java/com/android/server/policy/StatusBarController.java
@@ -72,7 +72,9 @@
if (statusbar != null) {
long startTime = calculateStatusBarTransitionStartTime(openAnimation,
closeAnimation);
- statusbar.appTransitionStarting(startTime, TRANSITION_DURATION);
+ long duration = closeAnimation != null || openAnimation != null
+ ? TRANSITION_DURATION : 0;
+ statusbar.appTransitionStarting(startTime, duration);
}
} catch (RemoteException e) {
Slog.e(mTag, "RemoteException when app transition is starting", e);
@@ -122,7 +124,7 @@
*
* @return the desired start time of the status bar transition, in uptime millis
*/
- private long calculateStatusBarTransitionStartTime(Animation openAnimation,
+ private static long calculateStatusBarTransitionStartTime(Animation openAnimation,
Animation closeAnimation) {
if (openAnimation != null && closeAnimation != null) {
TranslateAnimation openTranslateAnimation = findTranslateAnimation(openAnimation);
@@ -151,7 +153,7 @@
*
* @return the found animation, {@code null} otherwise
*/
- private TranslateAnimation findTranslateAnimation(Animation animation) {
+ private static TranslateAnimation findTranslateAnimation(Animation animation) {
if (animation instanceof TranslateAnimation) {
return (TranslateAnimation) animation;
} else if (animation instanceof AnimationSet) {
@@ -170,7 +172,7 @@
* Binary searches for a {@code t} such that there exists a {@code -0.01 < eps < 0.01} for which
* {@code interpolator(t + eps) > 0.99}.
*/
- private float findAlmostThereFraction(Interpolator interpolator) {
+ private static float findAlmostThereFraction(Interpolator interpolator) {
float val = 0.5f;
float adj = 0.25f;
while (adj >= 0.01f) {
diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index c71b48f..9916223 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -24,10 +24,12 @@
import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.text.TextUtils;
import android.util.Slog;
import java.io.PrintWriter;
import java.util.Arrays;
+import java.util.List;
/**
* A special helper class used by the WindowManager
@@ -52,8 +54,9 @@
private SensorManager mSensorManager;
private boolean mEnabled;
private int mRate;
+ private String mSensorType;
private Sensor mSensor;
- private SensorEventListenerImpl mSensorEventListener;
+ private OrientationJudge mOrientationJudge;
private int mCurrentRotation = -1;
private final Object mLock = new Object();
@@ -67,7 +70,7 @@
public WindowOrientationListener(Context context, Handler handler) {
this(context, handler, SensorManager.SENSOR_DELAY_UI);
}
-
+
/**
* Creates a new WindowOrientationListener.
*
@@ -84,11 +87,31 @@
mHandler = handler;
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
mRate = rate;
- mSensor = mSensorManager.getDefaultSensor(USE_GRAVITY_SENSOR
- ? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER);
- if (mSensor != null) {
- // Create listener only if sensors do exist
- mSensorEventListener = new SensorEventListenerImpl(context);
+
+ mSensorType = context.getResources().getString(
+ com.android.internal.R.string.config_orientationSensorType);
+ if (!TextUtils.isEmpty(mSensorType)) {
+ List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+ final int N = sensors.size();
+ for (int i = 0; i < N; i++) {
+ Sensor sensor = sensors.get(i);
+ if (mSensorType.equals(sensor.getStringType())) {
+ mSensor = sensor;
+ break;
+ }
+ }
+ if (mSensor != null) {
+ mOrientationJudge = new OrientationSensorJudge();
+ }
+ }
+
+ if (mOrientationJudge == null) {
+ mSensor = mSensorManager.getDefaultSensor(USE_GRAVITY_SENSOR
+ ? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER);
+ if (mSensor != null) {
+ // Create listener only if sensors do exist
+ mOrientationJudge = new AccelSensorJudge(context);
+ }
}
}
@@ -106,8 +129,8 @@
if (LOG) {
Slog.d(TAG, "WindowOrientationListener enabled");
}
- mSensorEventListener.resetLocked();
- mSensorManager.registerListener(mSensorEventListener, mSensor, mRate, mHandler);
+ mOrientationJudge.resetLocked();
+ mSensorManager.registerListener(mOrientationJudge, mSensor, mRate, mHandler);
mEnabled = true;
}
}
@@ -126,7 +149,7 @@
if (LOG) {
Slog.d(TAG, "WindowOrientationListener disabled");
}
- mSensorManager.unregisterListener(mSensorEventListener);
+ mSensorManager.unregisterListener(mOrientationJudge);
mEnabled = false;
}
}
@@ -134,8 +157,8 @@
public void onTouchStart() {
synchronized (mLock) {
- if (mSensorEventListener != null) {
- mSensorEventListener.onTouchStartLocked();
+ if (mOrientationJudge != null) {
+ mOrientationJudge.onTouchStartLocked();
}
}
}
@@ -144,8 +167,8 @@
long whenElapsedNanos = SystemClock.elapsedRealtimeNanos();
synchronized (mLock) {
- if (mSensorEventListener != null) {
- mSensorEventListener.onTouchEndLocked(whenElapsedNanos);
+ if (mOrientationJudge != null) {
+ mOrientationJudge.onTouchEndLocked(whenElapsedNanos);
}
}
}
@@ -172,7 +195,7 @@
public int getProposedRotation() {
synchronized (mLock) {
if (mEnabled) {
- return mSensorEventListener.getProposedRotationLocked();
+ return mOrientationJudge.getProposedRotationLocked();
}
return -1;
}
@@ -194,6 +217,8 @@
* It is called each time the orientation determination transitions from being
* uncertain to being certain again, even if it is the same orientation as before.
*
+ * This should only be called on the Handler thread.
+ *
* @param rotation The new orientation of the device, one of the Surface.ROTATION_* constants.
* @see android.view.Surface
*/
@@ -205,15 +230,77 @@
prefix += " ";
pw.println(prefix + "mEnabled=" + mEnabled);
pw.println(prefix + "mCurrentRotation=" + mCurrentRotation);
+ pw.println(prefix + "mSensorType=" + mSensorType);
pw.println(prefix + "mSensor=" + mSensor);
pw.println(prefix + "mRate=" + mRate);
- if (mSensorEventListener != null) {
- mSensorEventListener.dumpLocked(pw, prefix);
+ if (mOrientationJudge != null) {
+ mOrientationJudge.dumpLocked(pw, prefix);
}
}
}
+ abstract class OrientationJudge implements SensorEventListener {
+ // Number of nanoseconds per millisecond.
+ protected static final long NANOS_PER_MS = 1000000;
+
+ // Number of milliseconds per nano second.
+ protected static final float MILLIS_PER_NANO = 0.000001f;
+
+ // The minimum amount of time that must have elapsed since the screen was last touched
+ // before the proposed rotation can change.
+ protected static final long PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS =
+ 500 * NANOS_PER_MS;
+
+ /**
+ * Gets the proposed rotation.
+ *
+ * This method only returns a rotation if the orientation listener is certain
+ * of its proposal. If the rotation is indeterminate, returns -1.
+ *
+ * Should only be called when holding WindowOrientationListener lock.
+ *
+ * @return The proposed rotation, or -1 if unknown.
+ */
+ public abstract int getProposedRotationLocked();
+
+ /**
+ * Notifies the orientation judge that the screen is being touched.
+ *
+ * Should only be called when holding WindowOrientationListener lock.
+ */
+ public abstract void onTouchStartLocked();
+
+ /**
+ * Notifies the orientation judge that the screen is no longer being touched.
+ *
+ * Should only be called when holding WindowOrientationListener lock.
+ *
+ * @param whenElapsedNanos Given in the elapsed realtime nanos time base.
+ */
+ public abstract void onTouchEndLocked(long whenElapsedNanos);
+
+ /**
+ * Resets the state of the judge.
+ *
+ * Should only be called when holding WindowOrientationListener lock.
+ */
+ public abstract void resetLocked();
+
+ /**
+ * Dumps internal state of the orientation judge.
+ *
+ * Should only be called when holding WindowOrientationListener lock.
+ */
+ public abstract void dumpLocked(PrintWriter pw, String prefix);
+
+ @Override
+ public abstract void onAccuracyChanged(Sensor sensor, int accuracy);
+
+ @Override
+ public abstract void onSensorChanged(SensorEvent event);
+ }
+
/**
* This class filters the raw accelerometer data and tries to detect actual changes in
* orientation. This is a very ill-defined problem so there are a lot of tweakable parameters,
@@ -252,13 +339,10 @@
* See http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization for
* signal processing background.
*/
- final class SensorEventListenerImpl implements SensorEventListener {
+ final class AccelSensorJudge extends OrientationJudge {
// We work with all angles in degrees in this class.
private static final float RADIANS_TO_DEGREES = (float) (180 / Math.PI);
- // Number of nanoseconds per millisecond.
- private static final long NANOS_PER_MS = 1000000;
-
// Indices into SensorEvent.values for the accelerometer sensor.
private static final int ACCELEROMETER_DATA_X = 0;
private static final int ACCELEROMETER_DATA_Y = 1;
@@ -286,11 +370,6 @@
private static final long PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS =
500 * NANOS_PER_MS;
- // The minimum amount of time that must have elapsed since the screen was last touched
- // before the proposed rotation can change.
- private static final long PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS =
- 500 * NANOS_PER_MS;
-
// If the tilt angle remains greater than the specified angle for a minimum of
// the specified time, then the device is deemed to be lying flat
// (just chillin' on a table).
@@ -434,7 +513,7 @@
private long[] mTiltHistoryTimestampNanos = new long[TILT_HISTORY_SIZE];
private int mTiltHistoryIndex;
- public SensorEventListenerImpl(Context context) {
+ public AccelSensorJudge(Context context) {
// Load tilt tolerance configuration.
int[] tiltTolerance = context.getResources().getIntArray(
com.android.internal.R.array.config_autoRotationTiltTolerance);
@@ -455,11 +534,15 @@
}
}
+ @Override
public int getProposedRotationLocked() {
return mProposedRotation;
}
+ @Override
public void dumpLocked(PrintWriter pw, String prefix) {
+ pw.println(prefix + "AccelSensorJudge");
+ prefix += " ";
pw.println(prefix + "mProposedRotation=" + mProposedRotation);
pw.println(prefix + "mPredictedRotation=" + mPredictedRotation);
pw.println(prefix + "mLastFilteredX=" + mLastFilteredX);
@@ -689,6 +772,33 @@
}
}
+ @Override
+ public void onTouchStartLocked() {
+ mTouched = true;
+ }
+
+ @Override
+ public void onTouchEndLocked(long whenElapsedNanos) {
+ mTouched = false;
+ mTouchEndedTimestampNanos = whenElapsedNanos;
+ }
+
+ @Override
+ public void resetLocked() {
+ mLastFilteredTimestampNanos = Long.MIN_VALUE;
+ mProposedRotation = -1;
+ mFlatTimestampNanos = Long.MIN_VALUE;
+ mFlat = false;
+ mSwingTimestampNanos = Long.MIN_VALUE;
+ mSwinging = false;
+ mAccelerationTimestampNanos = Long.MIN_VALUE;
+ mAccelerating = false;
+ mOverhead = false;
+ clearPredictedRotationLocked();
+ clearTiltHistoryLocked();
+ }
+
+
/**
* Returns true if the tilt angle is acceptable for a given predicted rotation.
*/
@@ -787,20 +897,6 @@
return true;
}
- private void resetLocked() {
- mLastFilteredTimestampNanos = Long.MIN_VALUE;
- mProposedRotation = -1;
- mFlatTimestampNanos = Long.MIN_VALUE;
- mFlat = false;
- mSwingTimestampNanos = Long.MIN_VALUE;
- mSwinging = false;
- mAccelerationTimestampNanos = Long.MIN_VALUE;
- mAccelerating = false;
- mOverhead = false;
- clearPredictedRotationLocked();
- clearTiltHistoryLocked();
- }
-
private void clearPredictedRotationLocked() {
mPredictedRotation = -1;
mPredictedRotationTimestampNanos = Long.MIN_VALUE;
@@ -869,14 +965,147 @@
private float remainingMS(long now, long until) {
return now >= until ? 0 : (until - now) * 0.000001f;
}
+ }
- private void onTouchStartLocked() {
- mTouched = true;
+ final class OrientationSensorJudge extends OrientationJudge {
+ private boolean mTouching;
+ private long mTouchEndedTimestampNanos = Long.MIN_VALUE;
+ private int mProposedRotation = -1;
+ private int mDesiredRotation = -1;
+ private boolean mRotationEvaluationScheduled;
+
+ @Override
+ public int getProposedRotationLocked() {
+ return mProposedRotation;
}
- private void onTouchEndLocked(long whenElapsedNanos) {
- mTouched = false;
+ @Override
+ public void onTouchStartLocked() {
+ mTouching = true;
+ }
+
+ @Override
+ public void onTouchEndLocked(long whenElapsedNanos) {
+ mTouching = false;
mTouchEndedTimestampNanos = whenElapsedNanos;
+ if (mDesiredRotation != mProposedRotation) {
+ final long now = SystemClock.elapsedRealtimeNanos();
+ scheduleRotationEvaluationIfNecessaryLocked(now);
+ }
}
+
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ int newRotation;
+ synchronized (mLock) {
+ mDesiredRotation = (int) event.values[0];
+ newRotation = evaluateRotationChangeLocked();
+ }
+ if (newRotation >=0) {
+ onProposedRotationChanged(newRotation);
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) { }
+
+ @Override
+ public void dumpLocked(PrintWriter pw, String prefix) {
+ pw.println(prefix + "OrientationSensorJudge");
+ prefix += " ";
+ pw.println(prefix + "mDesiredRotation=" + mDesiredRotation);
+ pw.println(prefix + "mProposedRotation=" + mProposedRotation);
+ pw.println(prefix + "mTouching=" + mTouching);
+ pw.println(prefix + "mTouchEndedTimestampNanos=" + mTouchEndedTimestampNanos);
+ }
+
+ @Override
+ public void resetLocked() {
+ mProposedRotation = -1;
+ mDesiredRotation = -1;
+ mTouching = false;
+ mTouchEndedTimestampNanos = Long.MIN_VALUE;
+ unscheduleRotationEvaluationLocked();
+ }
+
+ public int evaluateRotationChangeLocked() {
+ unscheduleRotationEvaluationLocked();
+ if (mDesiredRotation == mProposedRotation) {
+ return -1;
+ }
+ final long now = SystemClock.elapsedRealtimeNanos();
+ if (isDesiredRotationAcceptableLocked(now)) {
+ mProposedRotation = mDesiredRotation;
+ return mProposedRotation;
+ } else {
+ scheduleRotationEvaluationIfNecessaryLocked(now);
+ }
+ return -1;
+ }
+
+ private boolean isDesiredRotationAcceptableLocked(long now) {
+ if (mTouching) {
+ return false;
+ }
+ if (now < mTouchEndedTimestampNanos + PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS) {
+ return false;
+ }
+ return true;
+ }
+
+ private void scheduleRotationEvaluationIfNecessaryLocked(long now) {
+ if (mRotationEvaluationScheduled || mDesiredRotation == mProposedRotation) {
+ if (LOG) {
+ Slog.d(TAG, "scheduleRotationEvaluationLocked: " +
+ "ignoring, an evaluation is already scheduled or is unnecessary.");
+ }
+ return;
+ }
+ if (mTouching) {
+ if (LOG) {
+ Slog.d(TAG, "scheduleRotationEvaluationLocked: " +
+ "ignoring, user is still touching the screen.");
+ }
+ return;
+ }
+ long timeOfNextPossibleRotationNanos =
+ mTouchEndedTimestampNanos + PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS;
+ if (now >= timeOfNextPossibleRotationNanos) {
+ if (LOG) {
+ Slog.d(TAG, "scheduleRotationEvaluationLocked: " +
+ "ignoring, already past the next possible time of rotation.");
+ }
+ return;
+ }
+ // Use a delay instead of an absolute time since handlers are in uptime millis and we
+ // use elapsed realtime.
+ final long delayMs =
+ (long) Math.ceil((timeOfNextPossibleRotationNanos - now) * MILLIS_PER_NANO);
+ mHandler.postDelayed(mRotationEvaluator, delayMs);
+ mRotationEvaluationScheduled = true;
+ }
+
+ private void unscheduleRotationEvaluationLocked() {
+ if (!mRotationEvaluationScheduled) {
+ return;
+ }
+ mHandler.removeCallbacks(mRotationEvaluator);
+ mRotationEvaluationScheduled = false;
+ }
+
+ private Runnable mRotationEvaluator = new Runnable() {
+ @Override
+ public void run() {
+ int newRotation;
+ synchronized (mLock) {
+ mRotationEvaluationScheduled = false;
+ newRotation = evaluateRotationChangeLocked();
+ }
+ if (newRotation >= 0) {
+ onProposedRotationChanged(newRotation);
+ }
+ }
+ };
}
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 5d52307..6b45941 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -32,6 +32,14 @@
private static final String TAG = "KeyguardServiceDelegate";
private static final boolean DEBUG = true;
+ private static final int SCREEN_STATE_OFF = 0;
+ private static final int SCREEN_STATE_TURNING_ON = 1;
+ private static final int SCREEN_STATE_ON = 2;
+
+ private static final int INTERACTIVE_STATE_SLEEP = 0;
+ private static final int INTERACTIVE_STATE_AWAKE = 1;
+ private static final int INTERACTIVE_STATE_GOING_TO_SLEEP = 2;
+
protected KeyguardServiceWrapper mKeyguardService;
private final Context mContext;
private final View mScrim; // shown if keyguard crashes
@@ -61,6 +69,8 @@
public int offReason;
public int currentUser;
public boolean bootCompleted;
+ public int screenState;
+ public int interactiveState;
};
public interface DrawnListener {
@@ -144,10 +154,17 @@
// If the system is ready, it means keyguard crashed and restarted.
mKeyguardService.onSystemReady();
// This is used to hide the scrim once keyguard displays.
- mKeyguardService.onStartedWakingUp();
- mKeyguardService.onScreenTurningOn(
- new KeyguardShowDelegate(mDrawnListenerWhenConnect));
- mKeyguardService.onScreenTurnedOn();
+ if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
+ mKeyguardService.onStartedWakingUp();
+ }
+ if (mKeyguardState.screenState == SCREEN_STATE_ON
+ || mKeyguardState.screenState == SCREEN_STATE_TURNING_ON) {
+ mKeyguardService.onScreenTurningOn(
+ new KeyguardShowDelegate(mDrawnListenerWhenConnect));
+ }
+ if (mKeyguardState.screenState == SCREEN_STATE_ON) {
+ mKeyguardService.onScreenTurnedOn();
+ }
mDrawnListenerWhenConnect = null;
}
if (mKeyguardState.bootCompleted) {
@@ -231,6 +248,7 @@
if (DEBUG) Log.v(TAG, "onStartedWakingUp()");
mKeyguardService.onStartedWakingUp();
}
+ mKeyguardState.interactiveState = INTERACTIVE_STATE_AWAKE;
}
public void onScreenTurnedOff() {
@@ -238,6 +256,7 @@
if (DEBUG) Log.v(TAG, "onScreenTurnedOff()");
mKeyguardService.onScreenTurnedOff();
}
+ mKeyguardState.screenState = SCREEN_STATE_OFF;
}
public void onScreenTurningOn(final DrawnListener drawnListener) {
@@ -252,6 +271,7 @@
mDrawnListenerWhenConnect = drawnListener;
showScrim();
}
+ mKeyguardState.screenState = SCREEN_STATE_TURNING_ON;
}
public void onScreenTurnedOn() {
@@ -259,6 +279,7 @@
if (DEBUG) Log.v(TAG, "onScreenTurnedOn()");
mKeyguardService.onScreenTurnedOn();
}
+ mKeyguardState.screenState = SCREEN_STATE_ON;
}
public void onStartedGoingToSleep(int why) {
@@ -266,12 +287,14 @@
mKeyguardService.onStartedGoingToSleep(why);
}
mKeyguardState.offReason = why;
+ mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP;
}
public void onFinishedGoingToSleep(int why) {
if (mKeyguardService != null) {
mKeyguardService.onFinishedGoingToSleep(why);
}
+ mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP;
}
public void setKeyguardEnabled(boolean enabled) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 130815e..5d01931 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -28,4 +28,5 @@
void showScreenPinningRequest();
void showAssistDisclosure();
void startAssist(Bundle args);
+ void onCameraLaunchGestureDetected();
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 2a817ea..87dc6c4 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -176,6 +176,16 @@
}
}
}
+
+ @Override
+ public void onCameraLaunchGestureDetected() {
+ if (mBar != null) {
+ try {
+ mBar.onCameraLaunchGestureDetected();
+ } catch (RemoteException e) {
+ }
+ }
+ }
};
// ================================================================================
@@ -494,6 +504,15 @@
}
@Override
+ public void showKeyboardShortcutsMenu() {
+ if (mBar != null) {
+ try {
+ mBar.showKeyboardShortcutsMenu();
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
public void setCurrentUser(int newUserId) {
if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId);
mCurrentUserId = newUserId;
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index b9e8851..f9d29ac 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -19,6 +19,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
import com.android.server.SystemService;
import org.xmlpull.v1.XmlPullParser;
@@ -59,6 +60,7 @@
import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
import android.util.Xml;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
@@ -96,16 +98,15 @@
private static final int MSG_UNREGISTER_LISTENER = 2;
private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
- private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
private static final int MSG_KEYGUARD_SHOWING_CHANGED = 6;
private static final int MSG_START_USER = 7;
private static final int MSG_CLEANUP_USER = 8;
private static final int MSG_SWITCH_USER = 9;
- private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
- private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
+ private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<>();
+ private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>();
private final Receiver mReceiver = new Receiver();
- private final SparseBooleanArray mUserHasAuthenticated = new SparseBooleanArray();
+
/* package */ final TrustArchive mArchive = new TrustArchive();
private final Context mContext;
private final LockPatternUtils mLockPatternUtils;
@@ -118,9 +119,6 @@
@GuardedBy("mDeviceLockedForUser")
private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
- @GuardedBy("mUserHasAuthenticatedSinceBoot")
- private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
-
private boolean mTrustAgentsCanRun = false;
private int mCurrentUser = UserHandle.USER_SYSTEM;
@@ -146,6 +144,7 @@
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
mReceiver.register(mContext);
+ mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
mTrustAgentsCanRun = true;
refreshAgentList(UserHandle.USER_ALL);
@@ -230,7 +229,7 @@
if (!userInfo.supportsSwitchToByUser()) continue;
if (!mActivityManager.isUserRunning(userInfo.id)) continue;
if (!lockPatternUtils.isSecure(userInfo.id)) continue;
- if (!getUserHasAuthenticated(userInfo.id)) continue;
+ if (!mStrongAuthTracker.isTrustAllowedForUser(userInfo.id)) continue;
DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
final boolean disableTrustAgents =
@@ -509,7 +508,7 @@
// Agent dispatch and aggregation
private boolean aggregateIsTrusted(int userId) {
- if (!getUserHasAuthenticated(userId)) {
+ if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
return false;
}
for (int i = 0; i < mActiveAgents.size(); i++) {
@@ -524,7 +523,7 @@
}
private boolean aggregateIsTrustManaged(int userId) {
- if (!getUserHasAuthenticated(userId)) {
+ if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
return false;
}
for (int i = 0; i < mActiveAgents.size(); i++) {
@@ -545,54 +544,6 @@
info.agent.onUnlockAttempt(successful);
}
}
-
- if (successful) {
- updateUserHasAuthenticated(userId);
- }
- }
-
- private void updateUserHasAuthenticated(int userId) {
- boolean changed = setUserHasAuthenticated(userId);
- if (changed) {
- refreshAgentList(userId);
- }
- }
-
- private boolean getUserHasAuthenticated(int userId) {
- return mUserHasAuthenticated.get(userId);
- }
-
- /**
- * @return whether the value has changed
- */
- private boolean setUserHasAuthenticated(int userId) {
- if (!mUserHasAuthenticated.get(userId)) {
- mUserHasAuthenticated.put(userId, true);
- synchronized (mUserHasAuthenticatedSinceBoot) {
- mUserHasAuthenticatedSinceBoot.put(userId, true);
- }
- return true;
- }
- return false;
- }
-
- private void clearUserHasAuthenticated(int userId) {
- if (userId == UserHandle.USER_ALL) {
- mUserHasAuthenticated.clear();
- } else {
- mUserHasAuthenticated.put(userId, false);
- }
- }
-
- private boolean getUserHasAuthenticatedSinceBoot(int userId) {
- synchronized (mUserHasAuthenticatedSinceBoot) {
- return mUserHasAuthenticatedSinceBoot.get(userId);
- }
- }
-
- private void requireCredentialEntry(int userId) {
- clearUserHasAuthenticated(userId);
- refreshAgentList(userId);
}
// Listeners
@@ -681,17 +632,6 @@
}
@Override
- public void reportRequireCredentialEntry(int userId) throws RemoteException {
- enforceReportPermission();
- if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_SYSTEM) {
- mHandler.obtainMessage(MSG_REQUIRE_CREDENTIAL_ENTRY, userId, 0).sendToTarget();
- } else {
- throw new IllegalArgumentException(
- "userId must be an explicit user id or USER_ALL");
- }
- }
-
- @Override
public void reportKeyguardShowingChanged() throws RemoteException {
enforceReportPermission();
// coalesce refresh messages.
@@ -734,18 +674,6 @@
}
}
- @Override
- public boolean hasUserAuthenticatedSinceBoot(int userId) throws RemoteException {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, null);
- long token = Binder.clearCallingIdentity();
- try {
- return getUserHasAuthenticatedSinceBoot(userId);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
private void enforceReportPermission() {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
@@ -794,9 +722,8 @@
fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
- fout.print(", hasAuthenticated=" + dumpBool(getUserHasAuthenticated(user.id)));
- fout.print(", hasAuthenticatedSinceBoot="
- + dumpBool(getUserHasAuthenticatedSinceBoot(user.id)));
+ fout.print(", strongAuthRequired=" + dumpHex(
+ mStrongAuthTracker.getStrongAuthForUser(user.id)));
fout.println();
fout.println(" Enabled agents:");
boolean duplicateSimpleNames = false;
@@ -831,6 +758,10 @@
private String dumpBool(boolean b) {
return b ? "1" : "0";
}
+
+ private String dumpHex(int i) {
+ return "0x" + Integer.toHexString(i);
+ }
};
private int resolveProfileParent(int userId) {
@@ -864,9 +795,6 @@
// This is also called when the security mode of a user changes.
refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
- case MSG_REQUIRE_CREDENTIAL_ENTRY:
- requireCredentialEntry(msg.arg1);
- break;
case MSG_KEYGUARD_SHOWING_CHANGED:
refreshDeviceLockedForUser(mCurrentUser);
break;
@@ -900,6 +828,13 @@
}
};
+ private final StrongAuthTracker mStrongAuthTracker = new StrongAuthTracker() {
+ @Override
+ public void onStrongAuthRequiredChanged(int userId) {
+ refreshAgentList(userId);
+ }
+ };
+
private class Receiver extends BroadcastReceiver {
@Override
@@ -908,8 +843,6 @@
if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
refreshAgentList(getSendingUserId());
updateDevicePolicyFeatures();
- } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
- updateUserHasAuthenticated(getSendingUserId());
} else if (Intent.ACTION_USER_ADDED.equals(action)) {
int userId = getUserId(intent);
if (userId > 0) {
@@ -918,7 +851,6 @@
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
int userId = getUserId(intent);
if (userId > 0) {
- mUserHasAuthenticated.delete(userId);
synchronized (mUserIsTrusted) {
mUserIsTrusted.delete(userId);
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index dfdb29c..de7c07e 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -26,6 +26,8 @@
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.util.Slog;
+import android.util.SparseArray;
+import android.view.AppTransitionAnimationSpec;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -153,22 +155,25 @@
private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN = 3;
private String mNextAppTransitionPackage;
- private Bitmap mNextAppTransitionThumbnail;
// Used for thumbnail transitions. True if we're scaling up, false if scaling down
private boolean mNextAppTransitionScaleUp;
private IRemoteCallback mNextAppTransitionCallback;
private int mNextAppTransitionEnter;
private int mNextAppTransitionExit;
private int mNextAppTransitionInPlace;
- private int mNextAppTransitionStartX;
- private int mNextAppTransitionStartY;
- private int mNextAppTransitionStartWidth;
- private int mNextAppTransitionStartHeight;
+
+ // Keyed by task id.
+ private final SparseArray<AppTransitionAnimationSpec> mNextAppTransitionAnimationsSpecs
+ = new SparseArray<>();
+ private AppTransitionAnimationSpec mDefaultNextAppTransitionAnimationSpec;
+
private Rect mNextAppTransitionInsets = new Rect();
private Rect mTmpFromClipRect = new Rect();
private Rect mTmpToClipRect = new Rect();
+ private final Rect mTmpStartRect = new Rect();
+
private final static int APP_STATE_IDLE = 0;
private final static int APP_STATE_READY = 1;
private final static int APP_STATE_RUNNING = 2;
@@ -276,8 +281,9 @@
mAppTransitionState = APP_STATE_TIMEOUT;
}
- Bitmap getNextAppTransitionThumbnail() {
- return mNextAppTransitionThumbnail;
+ Bitmap getAppTransitionThumbnailHeader(int taskId) {
+ AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId);
+ return spec != null ? spec.bitmap : null;
}
/** Returns whether the next thumbnail transition is aspect scaled up. */
@@ -291,14 +297,6 @@
return mNextAppTransitionScaleUp;
}
- int getStartingX() {
- return mNextAppTransitionStartX;
- }
-
- int getStartingY() {
- return mNextAppTransitionStartY;
- }
-
boolean prepare() {
if (!isRunning()) {
mAppTransitionState = APP_STATE_IDLE;
@@ -321,7 +319,7 @@
void clear() {
mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
mNextAppTransitionPackage = null;
- mNextAppTransitionThumbnail = null;
+ mNextAppTransitionAnimationsSpecs.clear();
}
void freeze() {
@@ -459,16 +457,17 @@
return -startPos / denom;
}
- private Animation createScaleUpAnimationLocked(int transit, boolean enter,
- int appWidth, int appHeight) {
+ private Animation createScaleUpAnimationLocked(
+ int transit, boolean enter, int appWidth, int appHeight) {
Animation a = null;
+ getDefaultNextAppTransitionStartRect(mTmpStartRect);
if (enter) {
// Entering app zooms out from the center of the initial rect.
- float scaleW = mNextAppTransitionStartWidth / (float) appWidth;
- float scaleH = mNextAppTransitionStartHeight / (float) appHeight;
+ float scaleW = mTmpStartRect.width() / (float) appWidth;
+ float scaleH = mTmpStartRect.height() / (float) appHeight;
Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
- computePivot(mNextAppTransitionStartX, scaleW),
- computePivot(mNextAppTransitionStartY, scaleH));
+ computePivot(mTmpStartRect.left, scaleW),
+ computePivot(mTmpStartRect.right, scaleH));
scale.setInterpolator(mDecelerateInterpolator);
Animation alpha = new AlphaAnimation(0, 1);
@@ -512,6 +511,32 @@
return a;
}
+ private void getDefaultNextAppTransitionStartRect(Rect rect) {
+ if (mDefaultNextAppTransitionAnimationSpec == null ||
+ mDefaultNextAppTransitionAnimationSpec.rect == null) {
+ Slog.wtf(TAG, "Starting rect for app requested, but none available", new Throwable());
+ rect.setEmpty();
+ } else {
+ rect.set(mDefaultNextAppTransitionAnimationSpec.rect);
+ }
+ }
+
+ void getNextAppTransitionStartRect(int taskId, Rect rect) {
+ AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId);
+ if (spec == null || spec.rect == null) {
+ Slog.wtf(TAG, "Starting rect for task: " + taskId + " requested, but not available",
+ new Throwable());
+ rect.setEmpty();
+ } else {
+ rect.set(spec.rect);
+ }
+ }
+
+ private void putDefaultNextAppTransitionCoordinates(int left, int top, int width, int height) {
+ mDefaultNextAppTransitionAnimationSpec = new AppTransitionAnimationSpec(-1 /* taskId */,
+ null /* bitmap */, new Rect(left, top, left + width, top + height));
+ }
+
private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame) {
final Animation anim;
if (enter) {
@@ -519,28 +544,27 @@
final int appWidth = appFrame.width();
final int appHeight = appFrame.height();
+ getDefaultNextAppTransitionStartRect(mTmpStartRect);
float t = 0f;
if (appHeight > 0) {
- t = (float) mNextAppTransitionStartY / appHeight;
+ t = (float) mTmpStartRect.left / appHeight;
}
int translationY = mClipRevealTranslationY
+ (int)(appHeight / 7f * t);
- int centerX = mNextAppTransitionStartX + mNextAppTransitionStartWidth / 2;
- int centerY = mNextAppTransitionStartY + mNextAppTransitionStartHeight / 2;
+ int centerX = mTmpStartRect.centerX();
+ int centerY = mTmpStartRect.centerY();
+ int halfWidth = mTmpStartRect.width() / 2;
+ int halfHeight = mTmpStartRect.height() / 2;
// Clip third of the from size of launch icon, expand to full width/height
Animation clipAnimLR = new ClipRectLRAnimation(
- centerX - mNextAppTransitionStartWidth / 2,
- centerX + mNextAppTransitionStartWidth / 2,
- 0, appWidth);
+ centerX - halfWidth, centerX + halfWidth, 0, appWidth);
clipAnimLR.setInterpolator(mClipHorizontalInterpolator);
clipAnimLR.setDuration((long) (DEFAULT_APP_TRANSITION_DURATION / 2.5f));
- Animation clipAnimTB = new ClipRectTBAnimation(
- centerY - mNextAppTransitionStartHeight / 2 - translationY,
- centerY + mNextAppTransitionStartHeight / 2 - translationY,
- 0, appHeight);
+ Animation clipAnimTB = new ClipRectTBAnimation(centerY - halfHeight - translationY,
+ centerY + halfHeight/ 2 - translationY, 0, appHeight);
clipAnimTB.setInterpolator(mTouchResponseInterpolator);
clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION);
@@ -649,31 +673,32 @@
/**
* This animation runs for the thumbnail that gets cross faded with the enter/exit activity
- * when a thumbnail is specified with the activity options.
+ * when a thumbnail is specified with the pending animation override.
*/
- Animation createThumbnailAspectScaleAnimationLocked(Rect appRect) {
+ Animation createThumbnailAspectScaleAnimationLocked(Rect appRect, Bitmap thumbnailHeader,
+ final int taskId) {
Animation a;
- final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+ final int thumbWidthI = thumbnailHeader.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
- final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+ final int thumbHeightI = thumbnailHeader.getHeight();
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
final int appWidth = appRect.width();
float scaleW = appWidth / thumbWidth;
float unscaledHeight = thumbHeight * scaleW;
- float unscaledStartY = mNextAppTransitionStartY - (unscaledHeight - thumbHeight) / 2f;
+ getNextAppTransitionStartRect(taskId, mTmpStartRect);
+ float unscaledStartY = mTmpStartRect.top - (unscaledHeight - thumbHeight) / 2f;
if (mNextAppTransitionScaleUp) {
// Animation up from the thumbnail to the full screen
Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
- mNextAppTransitionStartX + (thumbWidth / 2f),
- mNextAppTransitionStartY + (thumbHeight / 2f));
+ mTmpStartRect.left + (thumbWidth / 2f), mTmpStartRect.top + (thumbHeight / 2f));
scale.setInterpolator(mTouchResponseInterpolator);
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Animation alpha = new AlphaAnimation(1, 0);
alpha.setInterpolator(mThumbnailFadeOutInterpolator);
alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
final float toX = appRect.left + appRect.width() / 2 -
- (mNextAppTransitionStartX + thumbWidth / 2);
+ (mTmpStartRect.left + thumbWidth / 2);
final float toY = appRect.top + mNextAppTransitionInsets.top + -unscaledStartY;
Animation translate = new TranslateAnimation(0, toX, 0, toY);
translate.setInterpolator(mTouchResponseInterpolator);
@@ -688,8 +713,7 @@
} else {
// Animation down from the full screen to the thumbnail
Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f,
- mNextAppTransitionStartX + (thumbWidth / 2f),
- mNextAppTransitionStartY + (thumbHeight / 2f));
+ mTmpStartRect.left + (thumbWidth / 2f), mTmpStartRect.top + (thumbHeight / 2f));
scale.setInterpolator(mTouchResponseInterpolator);
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Animation alpha = new AlphaAnimation(0f, 1f);
@@ -718,11 +742,13 @@
*/
Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState,
int appWidth, int appHeight, int orientation, int transit, Rect containingFrame,
- Rect contentInsets, @Nullable Rect surfaceInsets, boolean resizedWindow) {
+ Rect contentInsets, @Nullable Rect surfaceInsets, boolean resizedWindow,
+ int taskId) {
Animation a;
- final int thumbWidthI = mNextAppTransitionStartWidth;
+ getDefaultNextAppTransitionStartRect(mTmpStartRect);
+ final int thumbWidthI = mTmpStartRect.width();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
- final int thumbHeightI = mNextAppTransitionStartHeight;
+ final int thumbHeightI = mTmpStartRect.height();
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
// Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
@@ -733,7 +759,7 @@
case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
if (resizedWindow) {
a = createAspectScaledThumbnailEnterNonFullscreenAnimationLocked(
- containingFrame, surfaceInsets);
+ containingFrame, surfaceInsets, taskId);
} else {
// App window scaling up to become full screen
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
@@ -759,8 +785,8 @@
mNextAppTransitionInsets.set(contentInsets);
Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
- computePivot(mNextAppTransitionStartX, scale),
- computePivot(mNextAppTransitionStartY, scale));
+ computePivot(mTmpStartRect.left, scale),
+ computePivot(mTmpStartRect.top, scale));
Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
@@ -819,8 +845,8 @@
mNextAppTransitionInsets.set(contentInsets);
Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
- computePivot(mNextAppTransitionStartX, scale),
- computePivot(mNextAppTransitionStartY, scale));
+ computePivot(mTmpStartRect.left, scale),
+ computePivot(mTmpStartRect.top, scale));
Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
@@ -844,11 +870,12 @@
}
private Animation createAspectScaledThumbnailEnterNonFullscreenAnimationLocked(
- Rect containingFrame, @Nullable Rect surfaceInsets) {
- float width = containingFrame.width();
- float height = containingFrame.height();
- float scaleWidth = mNextAppTransitionStartWidth / width;
- float scaleHeight = mNextAppTransitionStartHeight / height;
+ Rect frame, @Nullable Rect surfaceInsets, int taskId) {
+ getNextAppTransitionStartRect(taskId, mTmpStartRect);
+ float width = frame.width();
+ float height = frame.height();
+ float scaleWidth = mTmpStartRect.width() / width;
+ float scaleHeight = mTmpStartRect.height() / height;
AnimationSet set = new AnimationSet(true);
int surfaceInsetsHorizontal = surfaceInsets == null
? 0 : surfaceInsets.left + surfaceInsets.right;
@@ -858,10 +885,10 @@
// we need to account for surface insets that will be used to enlarge the surface.
ScaleAnimation scale = new ScaleAnimation(scaleWidth, 1, scaleHeight, 1,
(width + surfaceInsetsHorizontal) / 2, (height + surfaceInsetsVertical) / 2);
- int fromX = mNextAppTransitionStartX + mNextAppTransitionStartWidth / 2
- - (containingFrame.left + containingFrame.width() / 2);
- int fromY = mNextAppTransitionStartY + mNextAppTransitionStartHeight / 2
- - (containingFrame.top + containingFrame.height() / 2);
+ int fromX = mTmpStartRect.left + mTmpStartRect.width() / 2
+ - (frame.left + frame.width() / 2);
+ int fromY = mTmpStartRect.top + mTmpStartRect.height() / 2
+ - (frame.top + frame.height() / 2);
TranslateAnimation translation = new TranslateAnimation(fromX, 0, fromY, 0);
set.addAnimation(scale);
set.addAnimation(translation);
@@ -870,13 +897,15 @@
/**
* This animation runs for the thumbnail that gets cross faded with the enter/exit activity
- * when a thumbnail is specified with the activity options.
+ * when a thumbnail is specified with the pending animation override.
*/
- Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
+ Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit,
+ Bitmap thumbnailHeader) {
Animation a;
- final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+ getDefaultNextAppTransitionStartRect(mTmpStartRect);
+ final int thumbWidthI = thumbnailHeader.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
- final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+ final int thumbHeightI = thumbnailHeader.getHeight();
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
if (mNextAppTransitionScaleUp) {
@@ -884,8 +913,8 @@
float scaleW = appWidth / thumbWidth;
float scaleH = appHeight / thumbHeight;
Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
- computePivot(mNextAppTransitionStartX, 1 / scaleW),
- computePivot(mNextAppTransitionStartY, 1 / scaleH));
+ computePivot(mTmpStartRect.left, 1 / scaleW),
+ computePivot(mTmpStartRect.top, 1 / scaleH));
scale.setInterpolator(mDecelerateInterpolator);
Animation alpha = new AlphaAnimation(1, 0);
@@ -901,8 +930,8 @@
float scaleW = appWidth / thumbWidth;
float scaleH = appHeight / thumbHeight;
a = new ScaleAnimation(scaleW, 1, scaleH, 1,
- computePivot(mNextAppTransitionStartX, 1 / scaleW),
- computePivot(mNextAppTransitionStartY, 1 / scaleH));
+ computePivot(mTmpStartRect.left, 1 / scaleW),
+ computePivot(mTmpStartRect.top, 1 / scaleH));
}
return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
@@ -913,11 +942,13 @@
* leaving, and the activity that is entering.
*/
Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
- int appHeight, int transit) {
+ int appHeight, int transit, int taskId) {
+ Bitmap thumbnailHeader = getAppTransitionThumbnailHeader(taskId);
Animation a;
- final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+ getDefaultNextAppTransitionStartRect(mTmpStartRect);
+ final int thumbWidthI = thumbnailHeader != null ? thumbnailHeader.getWidth() : appWidth;
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
- final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+ final int thumbHeightI = thumbnailHeader != null ? thumbnailHeader.getHeight() : appHeight;
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
switch (thumbTransitState) {
@@ -926,8 +957,8 @@
float scaleW = thumbWidth / appWidth;
float scaleH = thumbHeight / appHeight;
a = new ScaleAnimation(scaleW, 1, scaleH, 1,
- computePivot(mNextAppTransitionStartX, scaleW),
- computePivot(mNextAppTransitionStartY, scaleH));
+ computePivot(mTmpStartRect.left, scaleW),
+ computePivot(mTmpStartRect.top, scaleH));
break;
}
case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
@@ -954,8 +985,8 @@
float scaleW = thumbWidth / appWidth;
float scaleH = thumbHeight / appHeight;
Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
- computePivot(mNextAppTransitionStartX, scaleW),
- computePivot(mNextAppTransitionStartY, scaleH));
+ computePivot(mTmpStartRect.left, scaleW),
+ computePivot(mTmpStartRect.top, scaleH));
Animation alpha = new AlphaAnimation(1, 0);
@@ -987,7 +1018,7 @@
Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
int appWidth, int appHeight, int orientation, Rect containingFrame, Rect contentInsets,
@Nullable Rect surfaceInsets, Rect appFrame, boolean isVoiceInteraction,
- boolean resizedWindow) {
+ boolean resizedWindow, int taskId) {
Animation a;
if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
|| transit == TRANSIT_TASK_OPEN
@@ -1042,7 +1073,7 @@
mNextAppTransitionScaleUp =
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
- appWidth, appHeight, transit);
+ appWidth, appHeight, transit, taskId);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
String animName = mNextAppTransitionScaleUp ?
"ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
@@ -1057,7 +1088,7 @@
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
a = createAspectScaledThumbnailEnterExitAnimationLocked(
getThumbnailTransitionState(enter), appWidth, appHeight, orientation, transit,
- containingFrame, contentInsets, surfaceInsets, resizedWindow);
+ containingFrame, contentInsets, surfaceInsets, resizedWindow, taskId);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
String animName = mNextAppTransitionScaleUp ?
"ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN";
@@ -1147,7 +1178,7 @@
if (isTransitionSet()) {
mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
mNextAppTransitionPackage = packageName;
- mNextAppTransitionThumbnail = null;
+ mNextAppTransitionAnimationsSpecs.clear();
mNextAppTransitionEnter = enterAnim;
mNextAppTransitionExit = exitAnim;
postAnimationCallback();
@@ -1158,15 +1189,13 @@
}
void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
- int startHeight) {
+ int startHeight) {
if (isTransitionSet()) {
mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP;
mNextAppTransitionPackage = null;
- mNextAppTransitionThumbnail = null;
- mNextAppTransitionStartX = startX;
- mNextAppTransitionStartY = startY;
- mNextAppTransitionStartWidth = startWidth;
- mNextAppTransitionStartHeight = startHeight;
+ mNextAppTransitionAnimationsSpecs.clear();
+ putDefaultNextAppTransitionCoordinates(startX, startY, startX + startWidth,
+ startY + startHeight);
postAnimationCallback();
mNextAppTransitionCallback = null;
}
@@ -1176,10 +1205,7 @@
int startWidth, int startHeight) {
if (isTransitionSet()) {
mNextAppTransitionType = NEXT_TRANSIT_TYPE_CLIP_REVEAL;
- mNextAppTransitionStartX = startX;
- mNextAppTransitionStartY = startY;
- mNextAppTransitionStartWidth = startWidth;
- mNextAppTransitionStartHeight = startHeight;
+ putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight);
postAnimationCallback();
mNextAppTransitionCallback = null;
}
@@ -1191,10 +1217,9 @@
mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP
: NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN;
mNextAppTransitionPackage = null;
- mNextAppTransitionThumbnail = srcThumb;
+ mNextAppTransitionAnimationsSpecs.clear();
mNextAppTransitionScaleUp = scaleUp;
- mNextAppTransitionStartX = startX;
- mNextAppTransitionStartY = startY;
+ putDefaultNextAppTransitionCoordinates(startX, startY, 0 ,0);
postAnimationCallback();
mNextAppTransitionCallback = startedCallback;
} else {
@@ -1208,12 +1233,9 @@
mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
: NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
mNextAppTransitionPackage = null;
- mNextAppTransitionThumbnail = srcThumb;
+ mNextAppTransitionAnimationsSpecs.clear();
mNextAppTransitionScaleUp = scaleUp;
- mNextAppTransitionStartX = startX;
- mNextAppTransitionStartY = startY;
- mNextAppTransitionStartWidth = targetWidth;
- mNextAppTransitionStartHeight = targetHeight;
+ putDefaultNextAppTransitionCoordinates(startX, startY, targetWidth, targetHeight);
postAnimationCallback();
mNextAppTransitionCallback = startedCallback;
} else {
@@ -1221,6 +1243,27 @@
}
}
+ public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
+ IRemoteCallback callback, boolean scaleUp) {
+ if (isTransitionSet()) {
+ mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
+ : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
+ mNextAppTransitionPackage = null;
+ mNextAppTransitionAnimationsSpecs.clear();
+ mNextAppTransitionScaleUp = scaleUp;
+ for (int i = 0; i < specs.length; i++) {
+ AppTransitionAnimationSpec spec = specs[i];
+ if (spec != null) {
+ mNextAppTransitionAnimationsSpecs.put(spec.taskId, spec);
+ }
+ }
+ postAnimationCallback();
+ mNextAppTransitionCallback = callback;
+ } else {
+ postAnimationCallback();
+ }
+ }
+
void overrideInPlaceAppTransition(String packageName, int anim) {
if (isTransitionSet()) {
mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE;
@@ -1350,33 +1393,30 @@
pw.print(prefix); pw.print("mNextAppTransitionInPlace=0x");
pw.print(Integer.toHexString(mNextAppTransitionInPlace));
break;
- case NEXT_TRANSIT_TYPE_SCALE_UP:
+ case NEXT_TRANSIT_TYPE_SCALE_UP: {
+ getDefaultNextAppTransitionStartRect(mTmpStartRect);
pw.print(prefix); pw.print("mNextAppTransitionStartX=");
- pw.print(mNextAppTransitionStartX);
+ pw.print(mTmpStartRect.left);
pw.print(" mNextAppTransitionStartY=");
- pw.println(mNextAppTransitionStartY);
+ pw.println(mTmpStartRect.top);
pw.print(prefix); pw.print("mNextAppTransitionStartWidth=");
- pw.print(mNextAppTransitionStartWidth);
+ pw.print(mTmpStartRect.width());
pw.print(" mNextAppTransitionStartHeight=");
- pw.println(mNextAppTransitionStartHeight);
+ pw.println(mTmpStartRect.height());
break;
+ }
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
- case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
- pw.print(prefix); pw.print("mNextAppTransitionThumbnail=");
- pw.print(mNextAppTransitionThumbnail);
- pw.print(" mNextAppTransitionStartX=");
- pw.print(mNextAppTransitionStartX);
- pw.print(" mNextAppTransitionStartY=");
- pw.println(mNextAppTransitionStartY);
- pw.print(prefix); pw.print("mNextAppTransitionStartWidth=");
- pw.print(mNextAppTransitionStartWidth);
- pw.print(" mNextAppTransitionStartHeight=");
- pw.println(mNextAppTransitionStartHeight);
+ case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN: {
+ pw.print(prefix); pw.print("mDefaultNextAppTransitionAnimationSpec=");
+ pw.println(mDefaultNextAppTransitionAnimationSpec);
+ pw.print(prefix); pw.print("mNextAppTransitionAnimationsSpecs=");
+ pw.println(mNextAppTransitionAnimationsSpecs);
pw.print(prefix); pw.print("mNextAppTransitionScaleUp=");
pw.println(mNextAppTransitionScaleUp);
break;
+ }
}
if (mNextAppTransitionCallback != null) {
pw.print(prefix); pw.print("mNextAppTransitionCallback=");
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index df7b23d..2828cd0 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -193,6 +193,7 @@
final int windowCount = mAppToken.allAppWindows.size();
final int adj = animLayerAdjustment;
thumbnailLayer = -1;
+ final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
for (int i = 0; i < windowCount; i++) {
final WindowState w = mAppToken.allAppWindows.get(i);
final WindowStateAnimator winAnimator = w.mWinAnimator;
@@ -204,9 +205,7 @@
if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
mService.setInputMethodAnimLayerAdjustment(adj);
}
- if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) {
- mService.setWallpaperAnimLayerAdjustmentLocked(adj);
- }
+ wallpaperController.setAnimLayerAdjustment(w, adj);
}
}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 222945c..e87dcde 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
import com.android.server.input.InputApplicationHandle;
import com.android.server.input.InputWindowHandle;
import com.android.server.wm.WindowManagerService.DragInputEventReceiver;
@@ -413,7 +414,7 @@
continue;
}
- child.getTaskBounds(mTmpRect);
+ child.getTaskBounds(mTmpRect, !BOUNDS_FOR_TOUCH);
if (!mTmpRect.contains(x, y)) {
// outside of this window's activity stack == don't tell about drags
continue;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 21e92c9..b3244ff 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
import android.app.ActivityManagerNative;
import android.graphics.Rect;
import android.os.RemoteException;
@@ -177,7 +178,7 @@
if (modal && child.mAppToken != null) {
// Limit the outer touch to the activity stack region.
flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
- child.getTaskBounds(mTmpRect);
+ child.getTaskBounds(mTmpRect, BOUNDS_FOR_TOUCH);
inputWindowHandle.touchableRegion.set(mTmpRect);
} else {
// Not modal or full screen modal
@@ -260,6 +261,7 @@
// Add all windows on the default display.
final int numDisplays = mService.mDisplayContents.size();
+ final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
WindowList windows = mService.mDisplayContents.valueAt(displayNdx).getWindowList();
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
@@ -287,7 +289,7 @@
!= 0) {
disableWallpaperTouchEvents = true;
}
- final boolean hasWallpaper = (child == mService.mWallpaperTarget)
+ final boolean hasWallpaper = wallpaperController.isWallpaperTarget(child)
&& (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0
&& !disableWallpaperTouchEvents;
final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 75bb10a..12f61f9 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -403,7 +403,7 @@
synchronized(mService.mWindowMap) {
long ident = Binder.clearCallingIdentity();
try {
- mService.setWindowWallpaperPositionLocked(
+ mService.mWallpaperControllerLocked.setWindowWallpaperPosition(
mService.windowForClientLocked(this, window, true),
x, y, xStep, yStep);
} finally {
@@ -413,14 +413,16 @@
}
public void wallpaperOffsetsComplete(IBinder window) {
- mService.wallpaperOffsetsComplete(window);
+ synchronized (mService.mWindowMap) {
+ mService.mWallpaperControllerLocked.wallpaperOffsetsComplete(window);
+ }
}
public void setWallpaperDisplayOffset(IBinder window, int x, int y) {
synchronized(mService.mWindowMap) {
long ident = Binder.clearCallingIdentity();
try {
- mService.setWindowWallpaperDisplayOffsetLocked(
+ mService.mWallpaperControllerLocked.setWindowWallpaperDisplayOffset(
mService.windowForClientLocked(this, window, true), x, y);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -433,7 +435,7 @@
synchronized(mService.mWindowMap) {
long ident = Binder.clearCallingIdentity();
try {
- return mService.sendWindowWallpaperCommandLocked(
+ return mService.mWallpaperControllerLocked.sendWindowWallpaperCommand(
mService.windowForClientLocked(this, window, true),
action, x, y, z, extras, sync);
} finally {
@@ -443,7 +445,9 @@
}
public void wallpaperCommandComplete(IBinder window, Bundle result) {
- mService.wallpaperCommandComplete(window, result);
+ synchronized (mService.mWindowMap) {
+ mService.mWallpaperControllerLocked.wallpaperCommandComplete(window);
+ }
}
public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
new file mode 100644
index 0000000..d0962f4
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -0,0 +1,916 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+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 android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.server.wm.WindowManagerService.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerService.DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.WindowManagerService.DEBUG_LAYERS;
+import static com.android.server.wm.WindowManagerService.DEBUG_WINDOW_MOVEMENT;
+import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerService.DEBUG_WALLPAPER;
+import static com.android.server.wm.WindowManagerService.DEBUG_WALLPAPER_LIGHT;
+import static com.android.server.wm.WindowManagerService.H.WALLPAPER_DRAW_PENDING_TIMEOUT;
+import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
+import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
+
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.view.DisplayInfo;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Controls wallpaper windows visibility, ordering, and so on.
+ * NOTE: All methods in this class must be called with the window manager service lock held.
+ */
+class WallpaperController {
+ private static final String TAG = com.android.server.wm.WindowManagerService.TAG;
+ final private WindowManagerService mService;
+
+ private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<>();
+
+ // If non-null, this is the currently visible window that is associated
+ // with the wallpaper.
+ private WindowState mWallpaperTarget = null;
+ // If non-null, we are in the middle of animating from one wallpaper target
+ // to another, and this is the lower one in Z-order.
+ private WindowState mLowerWallpaperTarget = null;
+ // If non-null, we are in the middle of animating from one wallpaper target
+ // to another, and this is the higher one in Z-order.
+ private WindowState mUpperWallpaperTarget = null;
+
+ private int mWallpaperAnimLayerAdjustment;
+
+ private float mLastWallpaperX = -1;
+ private float mLastWallpaperY = -1;
+ private float mLastWallpaperXStep = -1;
+ private float mLastWallpaperYStep = -1;
+ private int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
+ private int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
+
+ // This is set when we are waiting for a wallpaper to tell us it is done
+ // changing its scroll position.
+ WindowState mWaitingOnWallpaper;
+
+ // The last time we had a timeout when waiting for a wallpaper.
+ private long mLastWallpaperTimeoutTime;
+ // We give a wallpaper up to 150ms to finish scrolling.
+ private static final long WALLPAPER_TIMEOUT = 150;
+ // Time we wait after a timeout before trying to wait again.
+ private static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
+
+ // Set to the wallpaper window we would like to hide once the transition animations are done.
+ // This is useful in cases where we don't want the wallpaper to be hidden when the close app
+ // is a wallpaper target and is done animating out, but the opening app isn't a wallpaper
+ // target and isn't done animating in.
+ private WindowState mDeferredHideWallpaper = null;
+
+ // We give a wallpaper up to 500ms to finish drawing before playing app transitions.
+ private static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500;
+ private static final int WALLPAPER_DRAW_NORMAL = 0;
+ private static final int WALLPAPER_DRAW_PENDING = 1;
+ private static final int WALLPAPER_DRAW_TIMEOUT = 2;
+ private int mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
+
+ private final FindWallpaperTargetResult mFindResults = new FindWallpaperTargetResult();
+
+ public WallpaperController(WindowManagerService service) {
+ mService = service;
+ }
+
+ WindowState getWallpaperTarget() {
+ return mWallpaperTarget;
+ }
+
+ WindowState getLowerWallpaperTarget() {
+ return mLowerWallpaperTarget;
+ }
+
+ WindowState getUpperWallpaperTarget() {
+ return mUpperWallpaperTarget;
+ }
+
+ boolean isWallpaperTarget(WindowState win) {
+ return win == mWallpaperTarget;
+ }
+
+ boolean isBelowWallpaperTarget(WindowState win) {
+ return mWallpaperTarget != null && mWallpaperTarget.mLayer >= win.mBaseLayer;
+ }
+
+ boolean isWallpaperVisible() {
+ return isWallpaperVisible(mWallpaperTarget);
+ }
+
+ private boolean isWallpaperVisible(WindowState wallpaperTarget) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
+ + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
+ + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
+ ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
+ + " upper=" + mUpperWallpaperTarget
+ + " lower=" + mLowerWallpaperTarget);
+ return (wallpaperTarget != null
+ && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
+ && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
+ || mUpperWallpaperTarget != null
+ || mLowerWallpaperTarget != null;
+ }
+
+ boolean isWallpaperTargetAnimating() {
+ return mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
+ && !mWallpaperTarget.mWinAnimator.isDummyAnimation();
+ }
+
+ void updateWallpaperVisibility() {
+ final boolean visible = isWallpaperVisible(mWallpaperTarget);
+ final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
+ if (displayContent == null) {
+ return;
+ }
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ final int dw = displayInfo.logicalWidth;
+ final int dh = displayInfo.logicalHeight;
+
+ for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+ WindowToken token = mWallpaperTokens.get(curTokenNdx);
+ if (token.hidden == visible) {
+ token.hidden = !visible;
+ // Need to do a layout to ensure the wallpaper now has the
+ // correct size.
+ displayContent.layoutNeeded = true;
+ }
+
+ final WindowList windows = token.windows;
+ for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ WindowState wallpaper = windows.get(wallpaperNdx);
+ if (visible) {
+ updateWallpaperOffset(wallpaper, dw, dh, false);
+ }
+
+ dispatchWallpaperVisibility(wallpaper, visible);
+ }
+ }
+ }
+
+ void hideDeferredWallpapersIfNeeded() {
+ if (mDeferredHideWallpaper != null) {
+ hideWallpapers(mDeferredHideWallpaper);
+ mDeferredHideWallpaper = null;
+ }
+ }
+
+ void hideWallpapers(final WindowState winGoingAway) {
+ if (mWallpaperTarget != null
+ && (mWallpaperTarget != winGoingAway || mLowerWallpaperTarget != null)) {
+ return;
+ }
+ if (mService.mAppTransition.isRunning()) {
+ // Defer hiding the wallpaper when app transition is running until the animations
+ // are done.
+ mDeferredHideWallpaper = winGoingAway;
+ return;
+ }
+
+ final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
+ for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
+ final WindowToken token = mWallpaperTokens.get(i);
+ for (int j = token.windows.size() - 1; j >= 0; j--) {
+ final WindowState wallpaper = token.windows.get(j);
+ final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
+ if (!winAnimator.mLastHidden || wasDeferred) {
+ winAnimator.hide();
+ dispatchWallpaperVisibility(wallpaper, false);
+ final DisplayContent displayContent = wallpaper.getDisplayContent();
+ if (displayContent != null) {
+ displayContent.pendingLayoutChanges |=
+ WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ }
+ }
+ }
+ if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
+ + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
+ + mLowerWallpaperTarget + "\n" + Debug.getCallers(5, " "));
+ token.hidden = true;
+ }
+ }
+
+ /**
+ * Check wallpaper for visibility change and notify window if so.
+ * @param wallpaper The wallpaper to test and notify.
+ * @param visible Current visibility.
+ */
+ void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
+ // Only send notification if the visibility actually changed and we are not trying to hide
+ // the wallpaper when we are deferring hiding of the wallpaper.
+ if (wallpaper.mWallpaperVisible != visible
+ && (mDeferredHideWallpaper == null || visible)) {
+ wallpaper.mWallpaperVisible = visible;
+ try {
+ if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "Updating vis of wallpaper " + wallpaper
+ + ": " + visible + " from:\n" + Debug.getCallers(4, " "));
+ wallpaper.mClient.dispatchAppVisibility(visible);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ boolean updateWallpaperOffset(WindowState wallpaperWin, int dw, int dh, boolean sync) {
+ boolean rawChanged = false;
+ float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
+ float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
+ int availw = wallpaperWin.mFrame.right - wallpaperWin.mFrame.left - dw;
+ int offset = availw > 0 ? -(int)(availw * wpx + .5f) : 0;
+ if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ offset += mLastWallpaperDisplayOffsetX;
+ }
+ boolean changed = wallpaperWin.mXOffset != offset;
+ if (changed) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " x: " + offset);
+ wallpaperWin.mXOffset = offset;
+ }
+ if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
+ wallpaperWin.mWallpaperX = wpx;
+ wallpaperWin.mWallpaperXStep = wpxs;
+ rawChanged = true;
+ }
+
+ float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
+ float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
+ int availh = wallpaperWin.mFrame.bottom - wallpaperWin.mFrame.top - dh;
+ offset = availh > 0 ? -(int)(availh * wpy + .5f) : 0;
+ if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ offset += mLastWallpaperDisplayOffsetY;
+ }
+ if (wallpaperWin.mYOffset != offset) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " y: " + offset);
+ changed = true;
+ wallpaperWin.mYOffset = offset;
+ }
+ if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
+ wallpaperWin.mWallpaperY = wpy;
+ wallpaperWin.mWallpaperYStep = wpys;
+ rawChanged = true;
+ }
+
+ if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
+ WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
+ try {
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
+ + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
+ + " y=" + wallpaperWin.mWallpaperY);
+ if (sync) {
+ mWaitingOnWallpaper = wallpaperWin;
+ }
+ wallpaperWin.mClient.dispatchWallpaperOffsets(
+ wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
+ wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
+ if (sync) {
+ if (mWaitingOnWallpaper != null) {
+ long start = SystemClock.uptimeMillis();
+ if ((mLastWallpaperTimeoutTime + WALLPAPER_TIMEOUT_RECOVERY)
+ < start) {
+ try {
+ if (DEBUG_WALLPAPER) Slog.v(TAG,
+ "Waiting for offset complete...");
+ mService.mWindowMap.wait(WALLPAPER_TIMEOUT);
+ } catch (InterruptedException e) {
+ }
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
+ if ((start + WALLPAPER_TIMEOUT) < SystemClock.uptimeMillis()) {
+ Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
+ + wallpaperWin);
+ mLastWallpaperTimeoutTime = start;
+ }
+ }
+ mWaitingOnWallpaper = null;
+ }
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
+ return changed;
+ }
+
+ void setWindowWallpaperPosition(
+ WindowState window, float x, float y, float xStep, float yStep) {
+ if (window.mWallpaperX != x || window.mWallpaperY != y) {
+ window.mWallpaperX = x;
+ window.mWallpaperY = y;
+ window.mWallpaperXStep = xStep;
+ window.mWallpaperYStep = yStep;
+ updateWallpaperOffsetLocked(window, true);
+ }
+ }
+
+ void setWindowWallpaperDisplayOffset(WindowState window, int x, int y) {
+ if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) {
+ window.mWallpaperDisplayOffsetX = x;
+ window.mWallpaperDisplayOffsetY = y;
+ updateWallpaperOffsetLocked(window, true);
+ }
+ }
+
+ Bundle sendWindowWallpaperCommand(
+ WindowState window, String action, int x, int y, int z, Bundle extras, boolean sync) {
+ if (window == mWallpaperTarget
+ || window == mLowerWallpaperTarget
+ || window == mUpperWallpaperTarget) {
+ boolean doWait = sync;
+ for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+ final WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
+ for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ WindowState wallpaper = windows.get(wallpaperNdx);
+ try {
+ wallpaper.mClient.dispatchWallpaperCommand(action,
+ x, y, z, extras, sync);
+ // We only want to be synchronous with one wallpaper.
+ sync = false;
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ if (doWait) {
+ // TODO: Need to wait for result.
+ }
+ }
+
+ return null;
+ }
+
+ void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
+ final DisplayContent displayContent = changingTarget.getDisplayContent();
+ if (displayContent == null) {
+ return;
+ }
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ final int dw = displayInfo.logicalWidth;
+ final int dh = displayInfo.logicalHeight;
+
+ WindowState target = mWallpaperTarget;
+ if (target != null) {
+ if (target.mWallpaperX >= 0) {
+ mLastWallpaperX = target.mWallpaperX;
+ } else if (changingTarget.mWallpaperX >= 0) {
+ mLastWallpaperX = changingTarget.mWallpaperX;
+ }
+ if (target.mWallpaperY >= 0) {
+ mLastWallpaperY = target.mWallpaperY;
+ } else if (changingTarget.mWallpaperY >= 0) {
+ mLastWallpaperY = changingTarget.mWallpaperY;
+ }
+ if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
+ } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
+ }
+ if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
+ } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
+ }
+ if (target.mWallpaperXStep >= 0) {
+ mLastWallpaperXStep = target.mWallpaperXStep;
+ } else if (changingTarget.mWallpaperXStep >= 0) {
+ mLastWallpaperXStep = changingTarget.mWallpaperXStep;
+ }
+ if (target.mWallpaperYStep >= 0) {
+ mLastWallpaperYStep = target.mWallpaperYStep;
+ } else if (changingTarget.mWallpaperYStep >= 0) {
+ mLastWallpaperYStep = changingTarget.mWallpaperYStep;
+ }
+ }
+
+ for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+ WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
+ for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ WindowState wallpaper = windows.get(wallpaperNdx);
+ if (updateWallpaperOffset(wallpaper, dw, dh, sync)) {
+ WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
+ winAnimator.computeShownFrameLocked();
+ // No need to lay out the windows - we can just set the wallpaper position
+ // directly.
+ winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
+ // We only want to be synchronous with one wallpaper.
+ sync = false;
+ }
+ }
+ }
+ }
+
+ void clearLastWallpaperTimeoutTime() {
+ mLastWallpaperTimeoutTime = 0;
+ }
+
+ void wallpaperCommandComplete(IBinder window) {
+ if (mWaitingOnWallpaper != null &&
+ mWaitingOnWallpaper.mClient.asBinder() == window) {
+ mWaitingOnWallpaper = null;
+ mService.mWindowMap.notifyAll();
+ }
+ }
+
+ void wallpaperOffsetsComplete(IBinder window) {
+ if (mWaitingOnWallpaper != null &&
+ mWaitingOnWallpaper.mClient.asBinder() == window) {
+ mWaitingOnWallpaper = null;
+ mService.mWindowMap.notifyAll();
+ }
+ }
+
+ int getAnimLayerAdjustment() {
+ return mWallpaperAnimLayerAdjustment;
+ }
+
+ void setAnimLayerAdjustment(WindowState win, int adj) {
+ if (win != mWallpaperTarget || mLowerWallpaperTarget != null) {
+ return;
+ }
+
+ if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Setting wallpaper layer adj to " + adj);
+ mWallpaperAnimLayerAdjustment = adj;
+ for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
+ WindowList windows = mWallpaperTokens.get(i).windows;
+ for (int j = windows.size() - 1; j >= 0; j--) {
+ WindowState wallpaper = windows.get(j);
+ wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
+ if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
+ + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
+ }
+ }
+ }
+
+ private void findWallpaperTarget(WindowList windows, FindWallpaperTargetResult result) {
+
+ final WindowAnimator winAnimator = mService.mAnimator;
+ result.reset();
+ WindowState w = null;
+ int windowDetachedI = -1;
+ boolean resetTopWallpaper = false;
+ boolean inFreeformSpace = false;
+ for (int i = windows.size() - 1; i >= 0; i--) {
+ w = windows.get(i);
+ if ((w.mAttrs.type == TYPE_WALLPAPER)) {
+ if (result.topWallpaper == null || resetTopWallpaper) {
+ result.setTopWallpaper(w, i);
+ resetTopWallpaper = false;
+ }
+ continue;
+ }
+ 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);
+ continue;
+ }
+ }
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
+ + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
+
+ if (!inFreeformSpace) {
+ TaskStack stack = w.getStack();
+ inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
+ }
+
+ // If the app is executing an animation because the keyguard is going away,
+ // keep the wallpaper during the animation so it doesn't flicker out.
+ final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0
+ || (w.mAppToken != null && w.mWinAnimator.mKeyguardGoingAwayAnimation);
+ if (hasWallpaper && w.isOnScreen()
+ && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w);
+ result.setWallpaperTarget(w, i);
+ if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
+ // 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.");
+ continue;
+ }
+ break;
+ } else if (w == winAnimator.mWindowDetachedWallpaper) {
+ windowDetachedI = i;
+ }
+ }
+
+ if (result.wallpaperTarget == null && windowDetachedI >= 0) {
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "Found animating detached wallpaper activity: #" + windowDetachedI + "=" + w);
+ result.setWallpaperTarget(w, windowDetachedI);
+ }
+ if (result.wallpaperTarget == null && inFreeformSpace) {
+ // In freeform mode we set the wallpaper as its own target, so we don't need an
+ // additional window to make it visible.
+ result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
+ }
+ }
+
+ private boolean updateWallpaperWindowsTarget(
+ WindowList windows, FindWallpaperTargetResult result) {
+
+ boolean targetChanged = false;
+ WindowState wallpaperTarget = result.wallpaperTarget;
+ int wallpaperTargetIndex = result.wallpaperTargetIndex;
+
+ if (mWallpaperTarget != wallpaperTarget
+ && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != wallpaperTarget)) {
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "New wallpaper target: " + wallpaperTarget + " oldTarget: " + mWallpaperTarget);
+
+ mLowerWallpaperTarget = null;
+ mUpperWallpaperTarget = null;
+
+ WindowState oldW = mWallpaperTarget;
+ mWallpaperTarget = wallpaperTarget;
+ targetChanged = true;
+
+ // Now what is happening... if the current and new targets are animating,
+ // then we are in our super special mode!
+ if (wallpaperTarget != null && oldW != null) {
+ boolean oldAnim = oldW.isAnimatingLw();
+ boolean foundAnim = wallpaperTarget.isAnimatingLw();
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "New animation: " + foundAnim + " old animation: " + oldAnim);
+ if (foundAnim && oldAnim) {
+ int oldI = windows.indexOf(oldW);
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "New i: " + wallpaperTargetIndex + " old i: " + oldI);
+ if (oldI >= 0) {
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "Animating wallpapers: old#" + oldI + "=" + oldW + "; new#"
+ + wallpaperTargetIndex + "=" + wallpaperTarget);
+
+ // Set the new target correctly.
+ if (wallpaperTarget.mAppToken != null
+ && wallpaperTarget.mAppToken.hiddenRequested) {
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "Old wallpaper still the target.");
+ mWallpaperTarget = oldW;
+ wallpaperTarget = oldW;
+ wallpaperTargetIndex = oldI;
+ }
+ // Now set the upper and lower wallpaper targets correctly,
+ // and make sure that we are positioning the wallpaper below the lower.
+ else if (wallpaperTargetIndex > oldI) {
+ // The new target is on top of the old one.
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "Found target above old target.");
+ mUpperWallpaperTarget = wallpaperTarget;
+ mLowerWallpaperTarget = oldW;
+ wallpaperTarget = oldW;
+ wallpaperTargetIndex = oldI;
+ } else {
+ // The new target is below the old one.
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "Found target below old target.");
+ mUpperWallpaperTarget = oldW;
+ mLowerWallpaperTarget = wallpaperTarget;
+ }
+ }
+ }
+ }
+
+ } else if (mLowerWallpaperTarget != null) {
+ // Is it time to stop animating?
+ if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "No longer animating wallpaper targets!");
+ mLowerWallpaperTarget = null;
+ mUpperWallpaperTarget = null;
+ mWallpaperTarget = wallpaperTarget;
+ targetChanged = true;
+ }
+ }
+
+ result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
+ return targetChanged;
+ }
+
+ boolean updateWallpaperWindowsTargetByLayer(
+ WindowList windows, FindWallpaperTargetResult result) {
+
+ WindowState wallpaperTarget = result.wallpaperTarget;
+ int wallpaperTargetIndex = result.wallpaperTargetIndex;
+ boolean visible = wallpaperTarget != null;
+
+ if (visible) {
+ // The window is visible to the compositor...but is it visible to the user?
+ // That is what the wallpaper cares about.
+ visible = isWallpaperVisible(wallpaperTarget);
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
+
+ // If the wallpaper target is animating, we may need to copy its layer adjustment.
+ // Only do this if we are not transferring between two wallpaper targets.
+ mWallpaperAnimLayerAdjustment =
+ (mLowerWallpaperTarget == null && wallpaperTarget.mAppToken != null)
+ ? wallpaperTarget.mAppToken.mAppAnimator.animLayerAdjustment : 0;
+
+ final int maxLayer = (mService.mPolicy.getMaxWallpaperLayer() * TYPE_LAYER_MULTIPLIER)
+ + TYPE_LAYER_OFFSET;
+
+ // Now w is the window we are supposed to be behind... but we
+ // need to be sure to also be behind any of its attached windows,
+ // AND any starting window associated with it, AND below the
+ // maximum layer the policy allows for wallpapers.
+ while (wallpaperTargetIndex > 0) {
+ WindowState wb = windows.get(wallpaperTargetIndex - 1);
+ if (wb.mBaseLayer < maxLayer &&
+ wb.mAttachedWindow != wallpaperTarget &&
+ (wallpaperTarget.mAttachedWindow == null ||
+ wb.mAttachedWindow != wallpaperTarget.mAttachedWindow) &&
+ (wb.mAttrs.type != TYPE_APPLICATION_STARTING
+ || wallpaperTarget.mToken == null
+ || wb.mToken != wallpaperTarget.mToken)) {
+ // This window is not related to the previous one in any
+ // interesting way, so stop here.
+ break;
+ }
+ wallpaperTarget = wb;
+ wallpaperTargetIndex--;
+ }
+ } else {
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
+ }
+
+ result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
+ return visible;
+ }
+
+ boolean updateWallpaperWindowsPlacement(WindowList windows,
+ WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible) {
+
+ // TODO(multidisplay): Wallpapers on main screen only.
+ final DisplayInfo displayInfo = mService.getDefaultDisplayContentLocked().getDisplayInfo();
+ final int dw = displayInfo.logicalWidth;
+ final int dh = displayInfo.logicalHeight;
+
+ // Start stepping backwards from here, ensuring that our wallpaper windows
+ // are correctly placed.
+ boolean changed = false;
+ for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+ WindowToken token = mWallpaperTokens.get(curTokenNdx);
+ if (token.hidden == visible) {
+ if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
+ "Wallpaper token " + token + " hidden=" + !visible);
+ token.hidden = !visible;
+ // Need to do a layout to ensure the wallpaper now has the correct size.
+ mService.getDefaultDisplayContentLocked().layoutNeeded = true;
+ }
+
+ final WindowList tokenWindows = token.windows;
+ for (int wallpaperNdx = tokenWindows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ WindowState wallpaper = tokenWindows.get(wallpaperNdx);
+
+ if (visible) {
+ updateWallpaperOffset(wallpaper, dw, dh, false);
+ }
+
+ // First, make sure the client has the current visibility state.
+ dispatchWallpaperVisibility(wallpaper, visible);
+
+ wallpaper.mWinAnimator.mAnimLayer =
+ wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
+ if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
+ + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
+
+ // First, if this window is at the current index, then all is well.
+ if (wallpaper == wallpaperTarget) {
+ wallpaperTargetIndex--;
+ wallpaperTarget = wallpaperTargetIndex > 0
+ ? windows.get(wallpaperTargetIndex - 1) : null;
+ continue;
+ }
+
+ // The window didn't match... the current wallpaper window,
+ // wherever it is, is in the wrong place, so make sure it is not in the list.
+ int oldIndex = windows.indexOf(wallpaper);
+ if (oldIndex >= 0) {
+ if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
+ "Wallpaper removing at " + oldIndex + ": " + wallpaper);
+ windows.remove(oldIndex);
+ mService.mWindowsChanged = true;
+ if (oldIndex < wallpaperTargetIndex) {
+ wallpaperTargetIndex--;
+ }
+ }
+
+ // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
+ // layer. For keyguard over wallpaper put the wallpaper under the keyguard.
+ int insertionIndex = 0;
+ if (visible && wallpaperTarget != null) {
+ final int type = wallpaperTarget.mAttrs.type;
+ final int privateFlags = wallpaperTarget.mAttrs.privateFlags;
+ if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
+ || type == TYPE_KEYGUARD_SCRIM) {
+ insertionIndex = windows.indexOf(wallpaperTarget);
+ }
+ }
+ if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
+ "Moving wallpaper " + wallpaper
+ + " from " + oldIndex + " to " + insertionIndex);
+
+ windows.add(insertionIndex, wallpaper);
+ mService.mWindowsChanged = true;
+ changed = true;
+ }
+ }
+
+ return changed;
+ }
+
+ boolean adjustWallpaperWindows() {
+ mService.mInnerFields.mWallpaperMayChange = false;
+
+ final WindowList windows = mService.getDefaultWindowListLocked();
+ // First find top-most window that has asked to be on top of the wallpaper;
+ // all wallpapers go behind it.
+ findWallpaperTarget(windows, mFindResults);
+ final boolean targetChanged = updateWallpaperWindowsTarget(windows, mFindResults);
+ final boolean visible = updateWallpaperWindowsTargetByLayer(windows, mFindResults);
+ WindowState wallpaperTarget = mFindResults.wallpaperTarget;
+ int wallpaperTargetIndex = mFindResults.wallpaperTargetIndex;
+
+ if (wallpaperTarget == null && mFindResults.topWallpaper != null) {
+ // There is no wallpaper target, so it goes at the bottom.
+ // We will assume it is the same place as last time, if known.
+ wallpaperTarget = mFindResults.topWallpaper;
+ wallpaperTargetIndex = mFindResults.topWallpaperIndex + 1;
+ } else {
+ // Okay i is the position immediately above the wallpaper.
+ // Look at what is below it for later.
+ wallpaperTarget = wallpaperTargetIndex > 0
+ ? windows.get(wallpaperTargetIndex - 1) : null;
+ }
+
+ if (visible) {
+ if (mWallpaperTarget.mWallpaperX >= 0) {
+ mLastWallpaperX = mWallpaperTarget.mWallpaperX;
+ mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
+ }
+ if (mWallpaperTarget.mWallpaperY >= 0) {
+ mLastWallpaperY = mWallpaperTarget.mWallpaperY;
+ mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
+ }
+ if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
+ }
+ if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
+ }
+ }
+
+ final boolean changed = updateWallpaperWindowsPlacement(
+ windows, wallpaperTarget, wallpaperTargetIndex, visible);
+
+ if (targetChanged && DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "New wallpaper: target="
+ + mWallpaperTarget + " lower=" + mLowerWallpaperTarget + " upper="
+ + mUpperWallpaperTarget);
+
+ return changed;
+ }
+
+ boolean processWallpaperDrawPendingTimeout() {
+ if (mWallpaperDrawState == WALLPAPER_DRAW_PENDING) {
+ mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
+ if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
+ "*** WALLPAPER DRAW TIMEOUT");
+ return true;
+ }
+ return false;
+ }
+
+ boolean wallpaperTransitionReady() {
+ boolean transitionReady = true;
+ boolean wallpaperReady = true;
+ for (int curTokenIndex = mWallpaperTokens.size() - 1;
+ curTokenIndex >= 0 && wallpaperReady; curTokenIndex--) {
+ WindowToken token = mWallpaperTokens.get(curTokenIndex);
+ for (int curWallpaperIndex = token.windows.size() - 1; curWallpaperIndex >= 0;
+ curWallpaperIndex--) {
+ WindowState wallpaper = token.windows.get(curWallpaperIndex);
+ if (wallpaper.mWallpaperVisible && !wallpaper.isDrawnLw()) {
+ // We've told this wallpaper to be visible, but it is not drawn yet
+ wallpaperReady = false;
+ if (mWallpaperDrawState != WALLPAPER_DRAW_TIMEOUT) {
+ // wait for this wallpaper until it is drawn or timeout
+ transitionReady = false;
+ }
+ if (mWallpaperDrawState == WALLPAPER_DRAW_NORMAL) {
+ mWallpaperDrawState = WALLPAPER_DRAW_PENDING;
+ mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
+ mService.mH.sendEmptyMessageDelayed(WALLPAPER_DRAW_PENDING_TIMEOUT,
+ WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION);
+ }
+ if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
+ "Wallpaper should be visible but has not been drawn yet. " +
+ "mWallpaperDrawState=" + mWallpaperDrawState);
+ break;
+ }
+ }
+ }
+ if (wallpaperReady) {
+ mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
+ mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
+ }
+
+ return transitionReady;
+ }
+
+ void addWallpaperToken(WindowToken token) {
+ mWallpaperTokens.add(token);
+ }
+
+ void removeWallpaperToken(WindowToken token) {
+ mWallpaperTokens.remove(token);
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget);
+ if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
+ pw.print(prefix); pw.print("mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
+ pw.print(prefix); pw.print("mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
+ }
+ pw.print(prefix); pw.print("mLastWallpaperX="); pw.print(mLastWallpaperX);
+ pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
+ if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
+ || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ pw.print(prefix);
+ pw.print("mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
+ pw.print(" mLastWallpaperDisplayOffsetY="); pw.println(mLastWallpaperDisplayOffsetY);
+ }
+ }
+
+ 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 {
+ int topWallpaperIndex = 0;
+ WindowState topWallpaper = null;
+ int wallpaperTargetIndex = 0;
+ WindowState wallpaperTarget = null;
+
+ void setTopWallpaper(WindowState win, int index) {
+ topWallpaper = win;
+ topWallpaperIndex = index;
+ }
+
+ void setWallpaperTarget(WindowState win, int index) {
+ wallpaperTarget = win;
+ wallpaperTargetIndex = index;
+ }
+
+ void reset() {
+ topWallpaperIndex = 0;
+ topWallpaper = null;
+ wallpaperTargetIndex = 0;
+ wallpaperTarget = null;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 7578256..e6a1be1 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -258,6 +258,7 @@
boolean startingInUnForceHiding = false;
ArrayList<WindowStateAnimator> unForceHiding = null;
WindowState wallpaper = null;
+ final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
for (int i = windows.size() - 1; i >= 0; i--) {
WindowState win = windows.get(i);
WindowStateAnimator winAnimator = win.mWinAnimator;
@@ -294,7 +295,8 @@
", nowAnimating=" + nowAnimating);
}
- if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
+ if (wasAnimating && !winAnimator.mAnimating
+ && wallpaperController.isWallpaperTarget(win)) {
mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 355b09b..cf690a5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -78,6 +78,7 @@
import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.TypedValue;
+import android.view.AppTransitionAnimationSpec;
import android.view.Choreographer;
import android.view.Display;
import android.view.DisplayInfo;
@@ -113,6 +114,7 @@
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.FastPrintWriter;
@@ -176,7 +178,6 @@
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_KEYGUARD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
@@ -443,6 +444,7 @@
final float[] mTmpFloats = new float[9];
final Rect mTmpContentRect = new Rect();
+ private final Rect mTmpStartRect = new Rect();
boolean mDisplayReady;
boolean mSafeMode;
@@ -550,7 +552,7 @@
boolean mHardKeyboardAvailable;
boolean mShowImeWithHardKeyboard;
- OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
+ WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
SettingsObserver mSettingsObserver;
private final class SettingsObserver extends ContentObserver {
@@ -579,48 +581,10 @@
}
}
- private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
+ WallpaperController mWallpaperControllerLocked;
- // If non-null, this is the currently visible window that is associated
- // with the wallpaper.
- WindowState mWallpaperTarget = null;
- // If non-null, we are in the middle of animating from one wallpaper target
- // to another, and this is the lower one in Z-order.
- WindowState mLowerWallpaperTarget = null;
- // If non-null, we are in the middle of animating from one wallpaper target
- // to another, and this is the higher one in Z-order.
- WindowState mUpperWallpaperTarget = null;
- int mWallpaperAnimLayerAdjustment;
- float mLastWallpaperX = -1;
- float mLastWallpaperY = -1;
- float mLastWallpaperXStep = -1;
- float mLastWallpaperYStep = -1;
- int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
- int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
- // This is set when we are waiting for a wallpaper to tell us it is done
- // changing its scroll position.
- WindowState mWaitingOnWallpaper;
- // The last time we had a timeout when waiting for a wallpaper.
- long mLastWallpaperTimeoutTime;
- // We give a wallpaper up to 150ms to finish scrolling.
- static final long WALLPAPER_TIMEOUT = 150;
- // Time we wait after a timeout before trying to wait again.
- static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
boolean mAnimateWallpaperWithTarget;
- // We give a wallpaper up to 500ms to finish drawing before playing app transitions.
- static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500;
- static final int WALLPAPER_DRAW_NORMAL = 0;
- static final int WALLPAPER_DRAW_PENDING = 1;
- static final int WALLPAPER_DRAW_TIMEOUT = 2;
- int mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
-
- // Set to the wallpaper window we would like to hide once the transition animations are done.
- // This is useful in cases where we don't want the wallpaper to be hidden when the close app
- // is a wallpaper target and is done animating out, but the opening app isn't a wallpaper
- // target and isn't done animating in.
- WindowState mDeferredHideWallpaper = null;
-
AppWindowToken mFocusedApp = null;
PowerManager mPowerManager;
@@ -634,6 +598,7 @@
final InputManagerService mInputManager;
final DisplayManagerInternal mDisplayManagerInternal;
final DisplayManager mDisplayManager;
+ final Display[] mDisplays;
// Who is holding the screen on.
Session mHoldingScreenOn;
@@ -804,7 +769,7 @@
private ViewServer mViewServer;
private final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
- private boolean mWindowsChanged = false;
+ boolean mWindowsChanged = false;
public interface WindowChangeListener {
public void windowsChanged();
@@ -907,8 +872,8 @@
mFxSession = new SurfaceSession();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
- Display[] displays = mDisplayManager.getDisplays();
- for (Display display : displays) {
+ mDisplays = mDisplayManager.getDisplays();
+ for (Display display : mDisplays) {
createDisplayContentLocked(display);
}
@@ -988,6 +953,8 @@
updateCircularDisplayMaskIfNeeded();
showEmulatorDisplayOverlayIfNeeded();
+
+ mWallpaperControllerLocked = new WallpaperController(this);
}
public InputMonitor getInputMonitor() {
@@ -1767,578 +1734,6 @@
return true;
}
- private boolean isWallpaperVisible(WindowState wallpaperTarget) {
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
- + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
- + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
- ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
- + " upper=" + mUpperWallpaperTarget
- + " lower=" + mLowerWallpaperTarget);
- return (wallpaperTarget != null
- && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
- && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
- || mUpperWallpaperTarget != null
- || mLowerWallpaperTarget != null;
- }
-
- void hideWallpapersLocked(final WindowState winGoingAway) {
- if (mWallpaperTarget != null
- && (mWallpaperTarget != winGoingAway || mLowerWallpaperTarget != null)) {
- return;
- }
- if (mAppTransition.isRunning()) {
- // Defer hiding the wallpaper when app transition is running until the animations
- // are done.
- mDeferredHideWallpaper = winGoingAway;
- return;
- }
-
- final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
- for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
- final WindowToken token = mWallpaperTokens.get(i);
- for (int j = token.windows.size() - 1; j >= 0; j--) {
- final WindowState wallpaper = token.windows.get(j);
- final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
- if (!winAnimator.mLastHidden || wasDeferred) {
- winAnimator.hide();
- dispatchWallpaperVisibility(wallpaper, false);
- final DisplayContent displayContent = wallpaper.getDisplayContent();
- if (displayContent != null) {
- displayContent.pendingLayoutChanges |=
- WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
- }
- }
- }
- if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
- + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
- + mLowerWallpaperTarget + "\n" + Debug.getCallers(5, " "));
- token.hidden = true;
- }
- }
-
- boolean adjustWallpaperWindowsLocked() {
- mInnerFields.mWallpaperMayChange = false;
- boolean targetChanged = false;
-
- // TODO(multidisplay): Wallpapers on main screen only.
- final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
- final int dw = displayInfo.logicalWidth;
- final int dh = displayInfo.logicalHeight;
-
- // First find top-most window that has asked to be on top of the
- // wallpaper; all wallpapers go behind it.
- final WindowList windows = getDefaultWindowListLocked();
- int N = windows.size();
- WindowState w = null;
- WindowState foundW = null;
- int foundI = 0;
- WindowState topCurW = null;
- int topCurI = 0;
- int windowDetachedI = -1;
- int i = N;
- while (i > 0) {
- i--;
- w = windows.get(i);
- if ((w.mAttrs.type == TYPE_WALLPAPER)) {
- if (topCurW == null) {
- topCurW = w;
- topCurI = i;
- }
- continue;
- }
- topCurW = null;
- if (w != mAnimator.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);
- continue;
- }
- }
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
- + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
-
- // If the app is executing an animation because the keyguard is going away, keep the
- // wallpaper during the animation so it doesn't flicker out.
- final boolean hasWallpaper = (w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
- || (w.mAppToken != null
- && w.mWinAnimator.mKeyguardGoingAwayAnimation);
- if (hasWallpaper && w.isOnScreen()
- && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "Found wallpaper target: #" + i + "=" + w);
- foundW = w;
- foundI = i;
- if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
- // The current wallpaper target is animating, so we'll
- // look behind it for another possible target and figure
- // out what is going on below.
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
- + ": token animating, looking behind.");
- continue;
- }
- break;
- } else if (w == mAnimator.mWindowDetachedWallpaper) {
- windowDetachedI = i;
- }
- }
-
- if (foundW == null && windowDetachedI >= 0) {
- if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
- "Found animating detached wallpaper activity: #" + i + "=" + w);
- foundW = w;
- foundI = windowDetachedI;
- }
-
- if (mWallpaperTarget != foundW
- && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) {
- if (DEBUG_WALLPAPER_LIGHT) {
- Slog.v(TAG, "New wallpaper target: " + foundW
- + " oldTarget: " + mWallpaperTarget);
- }
-
- mLowerWallpaperTarget = null;
- mUpperWallpaperTarget = null;
-
- WindowState oldW = mWallpaperTarget;
- mWallpaperTarget = foundW;
- targetChanged = true;
-
- // Now what is happening... if the current and new targets are
- // animating, then we are in our super special mode!
- if (foundW != null && oldW != null) {
- boolean oldAnim = oldW.isAnimatingLw();
- boolean foundAnim = foundW.isAnimatingLw();
- if (DEBUG_WALLPAPER_LIGHT) {
- Slog.v(TAG, "New animation: " + foundAnim
- + " old animation: " + oldAnim);
- }
- if (foundAnim && oldAnim) {
- int oldI = windows.indexOf(oldW);
- if (DEBUG_WALLPAPER_LIGHT) {
- Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
- }
- if (oldI >= 0) {
- if (DEBUG_WALLPAPER_LIGHT) {
- Slog.v(TAG, "Animating wallpapers: old#" + oldI
- + "=" + oldW + "; new#" + foundI
- + "=" + foundW);
- }
-
- // Set the new target correctly.
- if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
- if (DEBUG_WALLPAPER_LIGHT) {
- Slog.v(TAG, "Old wallpaper still the target.");
- }
- mWallpaperTarget = oldW;
- foundW = oldW;
- foundI = oldI;
- }
- // Now set the upper and lower wallpaper targets
- // correctly, and make sure that we are positioning
- // the wallpaper below the lower.
- else if (foundI > oldI) {
- // The new target is on top of the old one.
- if (DEBUG_WALLPAPER_LIGHT) {
- Slog.v(TAG, "Found target above old target.");
- }
- mUpperWallpaperTarget = foundW;
- mLowerWallpaperTarget = oldW;
- foundW = oldW;
- foundI = oldI;
- } else {
- // The new target is below the old one.
- if (DEBUG_WALLPAPER_LIGHT) {
- Slog.v(TAG, "Found target below old target.");
- }
- mUpperWallpaperTarget = oldW;
- mLowerWallpaperTarget = foundW;
- }
- }
- }
- }
-
- } else if (mLowerWallpaperTarget != null) {
- // Is it time to stop animating?
- if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
- if (DEBUG_WALLPAPER_LIGHT) {
- Slog.v(TAG, "No longer animating wallpaper targets!");
- }
- mLowerWallpaperTarget = null;
- mUpperWallpaperTarget = null;
- mWallpaperTarget = foundW;
- targetChanged = true;
- }
- }
-
- boolean visible = foundW != null;
- if (visible) {
- // The window is visible to the compositor... but is it visible
- // to the user? That is what the wallpaper cares about.
- visible = isWallpaperVisible(foundW);
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
-
- // If the wallpaper target is animating, we may need to copy
- // its layer adjustment. Only do this if we are not transfering
- // between two wallpaper targets.
- mWallpaperAnimLayerAdjustment =
- (mLowerWallpaperTarget == null && foundW.mAppToken != null)
- ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
-
- final int maxLayer = mPolicy.getMaxWallpaperLayer()
- * TYPE_LAYER_MULTIPLIER
- + TYPE_LAYER_OFFSET;
-
- // Now w is the window we are supposed to be behind... but we
- // need to be sure to also be behind any of its attached windows,
- // AND any starting window associated with it, AND below the
- // maximum layer the policy allows for wallpapers.
- while (foundI > 0) {
- WindowState wb = windows.get(foundI - 1);
- if (wb.mBaseLayer < maxLayer &&
- wb.mAttachedWindow != foundW &&
- (foundW.mAttachedWindow == null ||
- wb.mAttachedWindow != foundW.mAttachedWindow) &&
- (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
- foundW.mToken == null || wb.mToken != foundW.mToken)) {
- // This window is not related to the previous one in any
- // interesting way, so stop here.
- break;
- }
- foundW = wb;
- foundI--;
- }
- } else {
- if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
- }
-
- if (foundW == null && topCurW != null) {
- // There is no wallpaper target, so it goes at the bottom.
- // We will assume it is the same place as last time, if known.
- foundW = topCurW;
- foundI = topCurI+1;
- } else {
- // Okay i is the position immediately above the wallpaper. Look at
- // what is below it for later.
- foundW = foundI > 0 ? windows.get(foundI - 1) : null;
- }
-
- if (visible) {
- if (mWallpaperTarget.mWallpaperX >= 0) {
- mLastWallpaperX = mWallpaperTarget.mWallpaperX;
- mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
- }
- if (mWallpaperTarget.mWallpaperY >= 0) {
- mLastWallpaperY = mWallpaperTarget.mWallpaperY;
- mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
- }
- if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
- mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
- }
- if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
- mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
- }
- }
-
- // Start stepping backwards from here, ensuring that our wallpaper windows
- // are correctly placed.
- boolean changed = false;
- for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
- WindowToken token = mWallpaperTokens.get(curTokenNdx);
- if (token.hidden == visible) {
- if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
- "Wallpaper token " + token + " hidden=" + !visible);
- token.hidden = !visible;
- // Need to do a layout to ensure the wallpaper now has the correct size.
- getDefaultDisplayContentLocked().layoutNeeded = true;
- }
-
- final WindowList tokenWindows = token.windows;
- for (int wallpaperNdx = tokenWindows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
- WindowState wallpaper = tokenWindows.get(wallpaperNdx);
-
- if (visible) {
- updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
- }
-
- // First, make sure the client has the current visibility state.
- dispatchWallpaperVisibility(wallpaper, visible);
-
- wallpaper.mWinAnimator.mAnimLayer =
- wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
- if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
- + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
-
- // First, if this window is at the current index, then all is well.
- if (wallpaper == foundW) {
- foundI--;
- foundW = foundI > 0 ? windows.get(foundI - 1) : null;
- continue;
- }
-
- // The window didn't match... the current wallpaper window,
- // wherever it is, is in the wrong place, so make sure it is
- // not in the list.
- int oldIndex = windows.indexOf(wallpaper);
- if (oldIndex >= 0) {
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
- + oldIndex + ": " + wallpaper);
- windows.remove(oldIndex);
- mWindowsChanged = true;
- if (oldIndex < foundI) {
- foundI--;
- }
- }
-
- // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
- // layer. For keyguard over wallpaper put the wallpaper under the keyguard.
- int insertionIndex = 0;
- if (visible && foundW != null) {
- final int type = foundW.mAttrs.type;
- final int privateFlags = foundW.mAttrs.privateFlags;
- if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
- || type == TYPE_KEYGUARD_SCRIM) {
- insertionIndex = windows.indexOf(foundW);
- }
- }
- if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
- Slog.v(TAG, "Moving wallpaper " + wallpaper
- + " from " + oldIndex + " to " + insertionIndex);
- }
-
- windows.add(insertionIndex, wallpaper);
- mWindowsChanged = true;
- changed = true;
- }
- }
-
- if (targetChanged && DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "New wallpaper: target="
- + mWallpaperTarget + " lower=" + mLowerWallpaperTarget + " upper="
- + mUpperWallpaperTarget);
-
- return changed;
- }
-
- void setWallpaperAnimLayerAdjustmentLocked(int adj) {
- if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Setting wallpaper layer adj to " + adj);
- mWallpaperAnimLayerAdjustment = adj;
- for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
- WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
- for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
- WindowState wallpaper = windows.get(wallpaperNdx);
- wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
- if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
- + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
- }
- }
- }
-
- boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
- boolean sync) {
- boolean changed = false;
- boolean rawChanged = false;
- float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
- float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
- int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
- int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
- if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
- offset += mLastWallpaperDisplayOffsetX;
- }
- changed = wallpaperWin.mXOffset != offset;
- if (changed) {
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
- + wallpaperWin + " x: " + offset);
- wallpaperWin.mXOffset = offset;
- }
- if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
- wallpaperWin.mWallpaperX = wpx;
- wallpaperWin.mWallpaperXStep = wpxs;
- rawChanged = true;
- }
-
- float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
- float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
- int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
- offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
- if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
- offset += mLastWallpaperDisplayOffsetY;
- }
- if (wallpaperWin.mYOffset != offset) {
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
- + wallpaperWin + " y: " + offset);
- changed = true;
- wallpaperWin.mYOffset = offset;
- }
- if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
- wallpaperWin.mWallpaperY = wpy;
- wallpaperWin.mWallpaperYStep = wpys;
- rawChanged = true;
- }
-
- if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
- WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
- try {
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
- + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
- + " y=" + wallpaperWin.mWallpaperY);
- if (sync) {
- mWaitingOnWallpaper = wallpaperWin;
- }
- wallpaperWin.mClient.dispatchWallpaperOffsets(
- wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
- wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
- if (sync) {
- if (mWaitingOnWallpaper != null) {
- long start = SystemClock.uptimeMillis();
- if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
- < start) {
- try {
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "Waiting for offset complete...");
- mWindowMap.wait(WALLPAPER_TIMEOUT);
- } catch (InterruptedException e) {
- }
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
- if ((start+WALLPAPER_TIMEOUT)
- < SystemClock.uptimeMillis()) {
- Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
- + wallpaperWin);
- mLastWallpaperTimeoutTime = start;
- }
- }
- mWaitingOnWallpaper = null;
- }
- }
- } catch (RemoteException e) {
- }
- }
-
- return changed;
- }
-
- void wallpaperOffsetsComplete(IBinder window) {
- synchronized (mWindowMap) {
- if (mWaitingOnWallpaper != null &&
- mWaitingOnWallpaper.mClient.asBinder() == window) {
- mWaitingOnWallpaper = null;
- mWindowMap.notifyAll();
- }
- }
- }
-
- void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
- final DisplayContent displayContent = changingTarget.getDisplayContent();
- if (displayContent == null) {
- return;
- }
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final int dw = displayInfo.logicalWidth;
- final int dh = displayInfo.logicalHeight;
-
- WindowState target = mWallpaperTarget;
- if (target != null) {
- if (target.mWallpaperX >= 0) {
- mLastWallpaperX = target.mWallpaperX;
- } else if (changingTarget.mWallpaperX >= 0) {
- mLastWallpaperX = changingTarget.mWallpaperX;
- }
- if (target.mWallpaperY >= 0) {
- mLastWallpaperY = target.mWallpaperY;
- } else if (changingTarget.mWallpaperY >= 0) {
- mLastWallpaperY = changingTarget.mWallpaperY;
- }
- if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
- mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
- } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
- mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
- }
- if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
- mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
- } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
- mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
- }
- if (target.mWallpaperXStep >= 0) {
- mLastWallpaperXStep = target.mWallpaperXStep;
- } else if (changingTarget.mWallpaperXStep >= 0) {
- mLastWallpaperXStep = changingTarget.mWallpaperXStep;
- }
- if (target.mWallpaperYStep >= 0) {
- mLastWallpaperYStep = target.mWallpaperYStep;
- } else if (changingTarget.mWallpaperYStep >= 0) {
- mLastWallpaperYStep = changingTarget.mWallpaperYStep;
- }
- }
-
- for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
- WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
- for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
- WindowState wallpaper = windows.get(wallpaperNdx);
- if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
- WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
- winAnimator.computeShownFrameLocked();
- // No need to lay out the windows - we can just set the wallpaper position
- // directly.
- winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
- // We only want to be synchronous with one wallpaper.
- sync = false;
- }
- }
- }
- }
-
- /**
- * Check wallpaper for visibility change and notify window if so.
- * @param wallpaper The wallpaper to test and notify.
- * @param visible Current visibility.
- */
- void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
- // Only send notification if the visibility actually changed and we are not trying to hide
- // the wallpaper when we are deferring hiding of the wallpaper.
- if (wallpaper.mWallpaperVisible != visible
- && (mDeferredHideWallpaper == null || visible)) {
- wallpaper.mWallpaperVisible = visible;
- try {
- if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
- "Updating vis of wallpaper " + wallpaper
- + ": " + visible + " from:\n" + Debug.getCallers(4, " "));
- wallpaper.mClient.dispatchAppVisibility(visible);
- } catch (RemoteException e) {
- }
- }
- }
-
- private void updateWallpaperVisibilityLocked() {
- final boolean visible = isWallpaperVisible(mWallpaperTarget);
- final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
- if (displayContent == null) {
- return;
- }
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final int dw = displayInfo.logicalWidth;
- final int dh = displayInfo.logicalHeight;
-
- for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
- WindowToken token = mWallpaperTokens.get(curTokenNdx);
- if (token.hidden == visible) {
- token.hidden = !visible;
- // Need to do a layout to ensure the wallpaper now has the
- // correct size.
- displayContent.layoutNeeded = true;
- }
-
- final WindowList windows = token.windows;
- for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
- WindowState wallpaper = windows.get(wallpaperNdx);
- if (visible) {
- updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
- }
-
- dispatchWallpaperVisibility(wallpaper, visible);
- }
- }
- }
-
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
@@ -2561,12 +1956,11 @@
} else {
addWindowToListInOrderLocked(win, true);
if (type == TYPE_WALLPAPER) {
- mLastWallpaperTimeoutTime = 0;
+ mWallpaperControllerLocked.clearLastWallpaperTimeoutTime();
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
} else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- } else if (mWallpaperTarget != null
- && mWallpaperTarget.mLayer >= win.mBaseLayer) {
+ } else if (mWallpaperControllerLocked.isBelowWallpaperTarget(win)) {
// If there is currently a wallpaper being shown, and
// the base layer of the new window is below the current
// layer of the target window, then adjust the wallpaper.
@@ -2863,7 +2257,7 @@
}
if (win.mAttrs.type == TYPE_WALLPAPER) {
- mLastWallpaperTimeoutTime = 0;
+ mWallpaperControllerLocked.clearLastWallpaperTimeoutTime();
getDefaultDisplayContentLocked().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
} else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
@@ -2983,62 +2377,6 @@
}
}
- public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
- float xStep, float yStep) {
- if (window.mWallpaperX != x || window.mWallpaperY != y) {
- window.mWallpaperX = x;
- window.mWallpaperY = y;
- window.mWallpaperXStep = xStep;
- window.mWallpaperYStep = yStep;
- updateWallpaperOffsetLocked(window, true);
- }
- }
-
- void wallpaperCommandComplete(IBinder window, Bundle result) {
- synchronized (mWindowMap) {
- if (mWaitingOnWallpaper != null &&
- mWaitingOnWallpaper.mClient.asBinder() == window) {
- mWaitingOnWallpaper = null;
- mWindowMap.notifyAll();
- }
- }
- }
-
- public void setWindowWallpaperDisplayOffsetLocked(WindowState window, int x, int y) {
- if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) {
- window.mWallpaperDisplayOffsetX = x;
- window.mWallpaperDisplayOffsetY = y;
- updateWallpaperOffsetLocked(window, true);
- }
- }
-
- public Bundle sendWindowWallpaperCommandLocked(WindowState window,
- String action, int x, int y, int z, Bundle extras, boolean sync) {
- if (window == mWallpaperTarget || window == mLowerWallpaperTarget
- || window == mUpperWallpaperTarget) {
- boolean doWait = sync;
- for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
- final WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
- for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
- WindowState wallpaper = windows.get(wallpaperNdx);
- try {
- wallpaper.mClient.dispatchWallpaperCommand(action,
- x, y, z, extras, sync);
- // We only want to be synchronous with one wallpaper.
- sync = false;
- } catch (RemoteException e) {
- }
- }
- }
-
- if (doWait) {
- // XXX Need to wait for result.
- }
- }
-
- return null;
- }
-
public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
synchronized (mWindowMap) {
if (mAccessibilityController != null) {
@@ -3293,7 +2631,7 @@
// Currently in a hide animation... turn this into
// an exit.
win.mExiting = true;
- } else if (win == mWallpaperTarget) {
+ } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
// If the wallpaper is currently behind this
// window, we need to change both of them inside
// of a transaction to avoid artifacts.
@@ -3351,8 +2689,8 @@
performLayoutAndPlaceSurfacesLocked();
if (toBeDisplayed && win.mIsWallpaper) {
DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
- updateWallpaperOffsetLocked(win,
- displayInfo.logicalWidth, displayInfo.logicalHeight, false);
+ mWallpaperControllerLocked.updateWallpaperOffset(
+ win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
}
if (win.mAppToken != null) {
win.mAppToken.updateReportedVisibilityLocked();
@@ -3468,12 +2806,17 @@
Rect appFrame = new Rect(0, 0, width, height);
Rect surfaceInsets = null;
final boolean fullscreen = win != null && win.isFullscreen(width, height);
- // Dialog activities have windows with containing frame being very large, but not
- // exactly fullscreen and much smaller mFrame. We use this distinction to identify
- // dialog activities.
- final boolean dialogWindow = win != null && !win.mContainingFrame.equals(win.mFrame);
+ final boolean freeform = win != null && win.inFreeformWorkspace();
if (win != null) {
- containingFrame.set(win.mContainingFrame);
+ // Containing frame will usually cover the whole screen, including dialog windows.
+ // For freeform workspace windows it will not cover the whole screen and it also
+ // won't exactly match the final freeform window frame (e.g. when overlapping with
+ // the status bar). In that case we need to use the final frame.
+ if (freeform) {
+ containingFrame.set(win.mFrame);
+ } else {
+ containingFrame.set(win.mContainingFrame);
+ }
surfaceInsets = win.getAttrs().surfaceInsets;
if (fullscreen) {
// For fullscreen windows use the window frames and insets to set the thumbnail
@@ -3492,10 +2835,9 @@
// screen gets the enter animation. Both appear in the mOpeningApps set.
enter = false;
}
- final boolean resizedWindow = !fullscreen && !dialogWindow;
Animation a = mAppTransition.loadAnimation(lp, transit, enter, containingWidth,
containingHeight, mCurConfiguration.orientation, containingFrame, contentInsets,
- surfaceInsets, appFrame, isVoiceInteraction, resizedWindow);
+ surfaceInsets, appFrame, isVoiceInteraction, freeform, atoken.mTask.mTaskId);
if (a != null) {
if (DEBUG_ANIM) {
RuntimeException e = null;
@@ -3629,7 +2971,7 @@
wtoken = new WindowToken(this, token, type, true);
mTokenMap.put(token, wtoken);
if (type == TYPE_WALLPAPER) {
- mWallpaperTokens.add(wtoken);
+ mWallpaperControllerLocked.addWallpaperToken(wtoken);
}
}
}
@@ -3685,10 +3027,10 @@
if (delayed && displayContent != null) {
displayContent.mExitingTokens.add(wtoken);
} else if (wtoken.windowType == TYPE_WALLPAPER) {
- mWallpaperTokens.remove(wtoken);
+ mWallpaperControllerLocked.removeWallpaperToken(wtoken);
}
} else if (wtoken.windowType == TYPE_WALLPAPER) {
- mWallpaperTokens.remove(wtoken);
+ mWallpaperControllerLocked.removeWallpaperToken(wtoken);
}
mInputMonitor.updateInputWindowsLw(true /*force*/);
@@ -4219,6 +3561,14 @@
}
@Override
+ public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
+ IRemoteCallback callback, boolean scaleUp) {
+ synchronized (mWindowMap) {
+ mAppTransition.overridePendingAppTransitionMultiThumb(specs, callback, scaleUp);
+ }
+ }
+
+ @Override
public void overridePendingAppTransitionInPlace(String packageName, int anim) {
synchronized(mWindowMap) {
mAppTransition.overrideInPlaceAppTransition(packageName, anim);
@@ -4427,7 +3777,7 @@
}
if (ent.array.getBoolean(
com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
- if (mWallpaperTarget == null) {
+ if (mWallpaperControllerLocked.getWallpaperTarget() == null) {
// If this theme is requesting a wallpaper, and the wallpaper
// is not curently visible, then this effectively serves as
// an opaque window and our starting window transition animation
@@ -5853,6 +5203,7 @@
if (!mBootAnimationStopped) {
// Do this one time.
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
try {
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
if (surfaceFlinger != null) {
@@ -5875,6 +5226,7 @@
}
EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
+ Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
mDisplayEnabled = true;
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
@@ -6286,7 +5638,7 @@
int right = wf.right - cr.right;
int bottom = wf.bottom - cr.bottom;
frame.union(left, top, right, bottom);
- ws.getTaskBounds(stackBounds);
+ ws.getTaskBounds(stackBounds, !BOUNDS_FOR_TOUCH);
if (!frame.intersect(stackBounds)) {
// Set frame empty if there's no intersection.
frame.setEmpty();
@@ -7459,12 +6811,6 @@
mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
}
- public boolean isHardKeyboardAvailable() {
- synchronized (mWindowMap) {
- return mHardKeyboardAvailable;
- }
- }
-
public void updateShowImeWithHardKeyboard() {
synchronized (mWindowMap) {
final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
@@ -7477,16 +6823,9 @@
}
}
- public void setOnHardKeyboardStatusChangeListener(
- OnHardKeyboardStatusChangeListener listener) {
- synchronized (mWindowMap) {
- mHardKeyboardStatusChangeListener = listener;
- }
- }
-
void notifyHardKeyboardStatusChange() {
final boolean available;
- final OnHardKeyboardStatusChangeListener listener;
+ final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
synchronized (mWindowMap) {
listener = mHardKeyboardStatusChangeListener;
available = mHardKeyboardAvailable;
@@ -7656,7 +6995,9 @@
}
public void displayReady() {
- displayReady(Display.DEFAULT_DISPLAY);
+ for (Display display : mDisplays) {
+ displayReady(display.getDisplayId());
+ }
synchronized(mWindowMap) {
final DisplayContent displayContent = getDefaultDisplayContentLocked();
@@ -8282,10 +7623,7 @@
break;
case WALLPAPER_DRAW_PENDING_TIMEOUT: {
synchronized (mWindowMap) {
- if (mWallpaperDrawState == WALLPAPER_DRAW_PENDING) {
- mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
- if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
- "*** WALLPAPER DRAW TIMEOUT");
+ if (mWallpaperControllerLocked.processWallpaperDrawPendingTimeout()) {
performLayoutAndPlaceSurfacesLocked();
}
}
@@ -8908,7 +8246,7 @@
if (w.mIsImWindow) {
winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
} else if (w.mIsWallpaper) {
- winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
+ winAnimator.mAnimLayer += mWallpaperControllerLocked.getAnimLayerAdjustment();
}
if (winAnimator.mAnimLayer != oldLayer) {
layerChanged = true;
@@ -9209,404 +8547,399 @@
* @return bitmap indicating if another pass through layout must be made.
*/
public int handleAppTransitionReadyLocked(WindowList windows) {
- int changes = 0;
- int i;
int appsCount = mOpeningApps.size();
- boolean goodToGo = true;
+ if (!checkIfTransitionGoodToGo(appsCount)) {
+ return 0;
+ }
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
+ int transit = mAppTransition.getAppTransition();
+ if (mSkipAppTransitionAnimation) {
+ transit = AppTransition.TRANSIT_UNSET;
+ }
+ mSkipAppTransitionAnimation = false;
+ mNoAnimationNotifyOnTransitionFinished.clear();
+
+ mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
+
+ rebuildAppWindowListLocked();
+
+ mInnerFields.mWallpaperMayChange = false;
+
+ // The top-most window will supply the layout params,
+ // and we will determine it below.
+ LayoutParams animLp = null;
+ int bestAnimLayer = -1;
+ boolean fullscreenAnim = false;
+ boolean voiceInteraction = false;
+
+ final WindowState lowerWallpaperTarget =
+ mWallpaperControllerLocked.getLowerWallpaperTarget();
+ final WindowState upperWallpaperTarget =
+ mWallpaperControllerLocked.getUpperWallpaperTarget();
+
+ boolean openingAppHasWallpaper = false;
+ boolean closingAppHasWallpaper = false;
+ final AppWindowToken lowerWallpaperAppToken;
+ final AppWindowToken upperWallpaperAppToken;
+ if (lowerWallpaperTarget == null) {
+ lowerWallpaperAppToken = upperWallpaperAppToken = null;
+ } else {
+ lowerWallpaperAppToken = lowerWallpaperTarget.mAppToken;
+ upperWallpaperAppToken = upperWallpaperTarget.mAppToken;
+ }
+
+ int i;
+ // Do a first pass through the tokens for two
+ // things:
+ // (1) Determine if both the closing and opening
+ // app token sets are wallpaper targets, in which
+ // case special animations are needed
+ // (since the wallpaper needs to stay static
+ // behind them).
+ // (2) Find the layout params of the top-most
+ // application window in the tokens, which is
+ // what will control the animation theme.
+ final int closingAppsCount = mClosingApps.size();
+ appsCount = closingAppsCount + mOpeningApps.size();
+ for (i = 0; i < appsCount; i++) {
+ final AppWindowToken wtoken;
+ if (i < closingAppsCount) {
+ wtoken = mClosingApps.valueAt(i);
+ if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
+ closingAppHasWallpaper = true;
+ }
+ } else {
+ wtoken = mOpeningApps.valueAt(i - closingAppsCount);
+ if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
+ openingAppHasWallpaper = true;
+ }
+ }
+
+ voiceInteraction |= wtoken.voiceInteraction;
+
+ if (wtoken.appFullscreen) {
+ WindowState ws = wtoken.findMainWindow();
+ if (ws != null) {
+ animLp = ws.mAttrs;
+ bestAnimLayer = ws.mLayer;
+ fullscreenAnim = true;
+ }
+ } else if (!fullscreenAnim) {
+ WindowState ws = wtoken.findMainWindow();
+ if (ws != null) {
+ if (ws.mLayer > bestAnimLayer) {
+ animLp = ws.mAttrs;
+ bestAnimLayer = ws.mLayer;
+ }
+ }
+ }
+ }
+
+ transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
+ closingAppHasWallpaper, lowerWallpaperTarget, upperWallpaperTarget);
+
+ // If all closing windows are obscured, then there is
+ // no need to do an animation. This is the case, for
+ // example, when this transition is being done behind
+ // the lock screen.
+ if (!mPolicy.allowAppAnimationsLw()) {
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "Animations disallowed by keyguard or dream.");
+ animLp = null;
+ }
+
+ processApplicationsAnimatingInPlace(transit);
+
+ AppWindowToken topClosingApp = null;
+ int topClosingLayer = 0;
+ appsCount = mClosingApps.size();
+ for (i = 0; i < appsCount; i++) {
+ AppWindowToken wtoken = mClosingApps.valueAt(i);
+ final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
+ appAnimator.clearThumbnail();
+ appAnimator.animation = null;
+ wtoken.inPendingTransaction = false;
+ setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
+ wtoken.updateReportedVisibilityLocked();
+ // Force the allDrawn flag, because we want to start
+ // this guy's animations regardless of whether it's
+ // gotten drawn.
+ wtoken.allDrawn = true;
+ wtoken.deferClearAllDrawn = false;
+ // Ensure that apps that are mid-starting are also scheduled to have their
+ // starting windows removed after the animation is complete
+ if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) {
+ scheduleRemoveStartingWindowLocked(wtoken);
+ }
+ mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
+
+ if (animLp != null) {
+ int layer = -1;
+ for (int j = 0; j < wtoken.windows.size(); j++) {
+ WindowState win = wtoken.windows.get(j);
+ if (win.mWinAnimator.mAnimLayer > layer) {
+ layer = win.mWinAnimator.mAnimLayer;
+ }
+ }
+ if (topClosingApp == null || layer > topClosingLayer) {
+ topClosingApp = wtoken;
+ topClosingLayer = layer;
+ }
+ }
+ }
+
+ AppWindowToken topOpeningApp = null;
+ appsCount = mOpeningApps.size();
+ for (i = 0; i < appsCount; i++) {
+ AppWindowToken wtoken = mOpeningApps.valueAt(i);
+ final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
+
+ if (!appAnimator.usingTransferredAnimation) {
+ appAnimator.clearThumbnail();
+ appAnimator.animation = null;
+ }
+ wtoken.inPendingTransaction = false;
+ if (!setTokenVisibilityLocked(
+ wtoken, animLp, true, transit, false, voiceInteraction)){
+ // This token isn't going to be animating. Add it to the list of tokens to
+ // be notified of app transition complete since the notification will not be
+ // sent be the app window animator.
+ mNoAnimationNotifyOnTransitionFinished.add(wtoken.token);
+ }
+ wtoken.updateReportedVisibilityLocked();
+ wtoken.waitingToShow = false;
+
+ appAnimator.mAllAppWinAnimators.clear();
+ final int windowsCount = wtoken.allAppWindows.size();
+ for (int j = 0; j < windowsCount; j++) {
+ appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
+ }
+ mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+ mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
+
+ int topOpeningLayer = 0;
+ if (animLp != null) {
+ int layer = -1;
+ for (int j = 0; j < wtoken.windows.size(); j++) {
+ WindowState win = wtoken.windows.get(j);
+ if (win.mWinAnimator.mAnimLayer > layer) {
+ layer = win.mWinAnimator.mAnimLayer;
+ }
+ }
+ if (topOpeningApp == null || layer > topOpeningLayer) {
+ topOpeningApp = wtoken;
+ topOpeningLayer = layer;
+ }
+ }
+ createThumbnailAppAnimator(transit, wtoken, topOpeningLayer, topClosingLayer);
+ }
+
+ AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
+ topOpeningApp.mAppAnimator;
+ AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
+ topClosingApp.mAppAnimator;
+
+ mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator);
+ mAppTransition.postAnimationCallback();
+ mAppTransition.clear();
+
+ mOpeningApps.clear();
+ mClosingApps.clear();
+
+ // This has changed the visibility of windows, so perform
+ // a new layout to get them all up-to-date.
+ getDefaultDisplayContentLocked().layoutNeeded = true;
+
+ // TODO(multidisplay): IMEs are only supported on the default display.
+ if (windows == getDefaultWindowListLocked()
+ && !moveInputMethodWindowsIfNeededLocked(true)) {
+ assignLayersLocked(windows);
+ }
+ updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/);
+ mFocusMayChange = false;
+ notifyActivityDrawnForKeyguard();
+ return WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
+ | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
+
+ }
+
+ private int maybeUpdateTransitToWallpaper(int transit, boolean openingAppHasWallpaper,
+ boolean closingAppHasWallpaper, WindowState lowerWallpaperTarget,
+ WindowState upperWallpaperTarget) {
+ // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
+ final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
+ final WindowState oldWallpaper = mWallpaperControllerLocked.isWallpaperTargetAnimating()
+ ? null : wallpaperTarget;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "New wallpaper target=" + wallpaperTarget
+ + ", oldWallpaper=" + oldWallpaper
+ + ", lower target=" + lowerWallpaperTarget
+ + ", upper target=" + upperWallpaperTarget);
+ mAnimateWallpaperWithTarget = false;
+ if (closingAppHasWallpaper && openingAppHasWallpaper) {
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
+ switch (transit) {
+ case AppTransition.TRANSIT_ACTIVITY_OPEN:
+ case AppTransition.TRANSIT_TASK_OPEN:
+ case AppTransition.TRANSIT_TASK_TO_FRONT:
+ transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
+ break;
+ case AppTransition.TRANSIT_ACTIVITY_CLOSE:
+ case AppTransition.TRANSIT_TASK_CLOSE:
+ case AppTransition.TRANSIT_TASK_TO_BACK:
+ transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
+ break;
+ }
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "New transit: " + AppTransition.appTransitionToString(transit));
+ } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
+ && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
+ // We are transitioning from an activity with
+ // a wallpaper to one without.
+ transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "New transit away from wallpaper: "
+ + AppTransition.appTransitionToString(transit));
+ } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()) {
+ // We are transitioning from an activity without
+ // a wallpaper to now showing the wallpaper
+ transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "New transit into wallpaper: "
+ + AppTransition.appTransitionToString(transit));
+ } else {
+ mAnimateWallpaperWithTarget = true;
+ }
+ return transit;
+ }
+
+ private void processApplicationsAnimatingInPlace(int transit) {
+ if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
+ // Find the focused window
+ final WindowState win =
+ findFocusedWindowLocked(getDefaultDisplayContentLocked());
+ if (win != null) {
+ final AppWindowToken wtoken = win.mAppToken;
+ final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken);
+ appAnimator.clearThumbnail();
+ appAnimator.animation = null;
+ updateTokenInPlaceLocked(wtoken, transit);
+ wtoken.updateReportedVisibilityLocked();
+
+ appAnimator.mAllAppWinAnimators.clear();
+ final int N = wtoken.allAppWindows.size();
+ for (int j = 0; j < N; j++) {
+ appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
+ }
+ mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
+ mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+ }
+ }
+ }
+
+ private boolean checkIfTransitionGoodToGo(int appsCount) {
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"Checking " + appsCount + " opening apps (frozen="
- + mDisplayFrozen + " timeout="
- + mAppTransition.isTimeout() + ")...");
+ + mDisplayFrozen + " timeout="
+ + mAppTransition.isTimeout() + ")...");
if (!mAppTransition.isTimeout()) {
- for (i = 0; i < appsCount && goodToGo; i++) {
+ for (int i = 0; i < appsCount; i++) {
AppWindowToken wtoken = mOpeningApps.valueAt(i);
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"Check opening app=" + wtoken + ": allDrawn="
+ wtoken.allDrawn + " startingDisplayed="
+ wtoken.startingDisplayed + " startingMoved="
+ wtoken.startingMoved);
- if (!wtoken.allDrawn && !wtoken.startingDisplayed
- && !wtoken.startingMoved) {
- goodToGo = false;
+ if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
+ return false;
}
}
- if (goodToGo && isWallpaperVisible(mWallpaperTarget)) {
- boolean wallpaperGoodToGo = true;
- for (int curTokenIndex = mWallpaperTokens.size() - 1;
- curTokenIndex >= 0 && wallpaperGoodToGo; curTokenIndex--) {
- WindowToken token = mWallpaperTokens.get(curTokenIndex);
- for (int curWallpaperIndex = token.windows.size() - 1; curWallpaperIndex >= 0;
- curWallpaperIndex--) {
- WindowState wallpaper = token.windows.get(curWallpaperIndex);
- if (wallpaper.mWallpaperVisible && !wallpaper.isDrawnLw()) {
- // We've told this wallpaper to be visible, but it is not drawn yet
- wallpaperGoodToGo = false;
- if (mWallpaperDrawState != WALLPAPER_DRAW_TIMEOUT) {
- // wait for this wallpaper until it is drawn or timeout
- goodToGo = false;
- }
- if (mWallpaperDrawState == WALLPAPER_DRAW_NORMAL) {
- mWallpaperDrawState = WALLPAPER_DRAW_PENDING;
- mH.removeMessages(H.WALLPAPER_DRAW_PENDING_TIMEOUT);
- mH.sendEmptyMessageDelayed(H.WALLPAPER_DRAW_PENDING_TIMEOUT,
- WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION);
- }
- if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
- "Wallpaper should be visible but has not been drawn yet. " +
- "mWallpaperDrawState=" + mWallpaperDrawState);
- break;
- }
- }
- }
- if (wallpaperGoodToGo) {
- mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
- mH.removeMessages(H.WALLPAPER_DRAW_PENDING_TIMEOUT);
- }
- }
+ // If the wallpaper is visible, we need to check it's ready too.
+ return !mWallpaperControllerLocked.isWallpaperVisible() ||
+ mWallpaperControllerLocked.wallpaperTransitionReady();
}
- if (goodToGo) {
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
- int transit = mAppTransition.getAppTransition();
- if (mSkipAppTransitionAnimation) {
- transit = AppTransition.TRANSIT_UNSET;
- }
- mSkipAppTransitionAnimation = false;
- mNoAnimationNotifyOnTransitionFinished.clear();
+ return true;
+ }
- mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
-
- rebuildAppWindowListLocked();
-
- // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
- WindowState oldWallpaper =
- mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
- && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
- ? null : mWallpaperTarget;
-
- mInnerFields.mWallpaperMayChange = false;
-
- // The top-most window will supply the layout params,
- // and we will determine it below.
- LayoutParams animLp = null;
- int bestAnimLayer = -1;
- boolean fullscreenAnim = false;
- boolean voiceInteraction = false;
-
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "New wallpaper target=" + mWallpaperTarget
- + ", oldWallpaper=" + oldWallpaper
- + ", lower target=" + mLowerWallpaperTarget
- + ", upper target=" + mUpperWallpaperTarget);
-
- boolean openingAppHasWallpaper = false;
- boolean closingAppHasWallpaper = false;
- final AppWindowToken lowerWallpaperAppToken;
- final AppWindowToken upperWallpaperAppToken;
- if (mLowerWallpaperTarget == null) {
- lowerWallpaperAppToken = upperWallpaperAppToken = null;
- } else {
- lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
- upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
- }
-
- // Do a first pass through the tokens for two
- // things:
- // (1) Determine if both the closing and opening
- // app token sets are wallpaper targets, in which
- // case special animations are needed
- // (since the wallpaper needs to stay static
- // behind them).
- // (2) Find the layout params of the top-most
- // application window in the tokens, which is
- // what will control the animation theme.
- final int closingAppsCount = mClosingApps.size();
- appsCount = closingAppsCount + mOpeningApps.size();
- for (i = 0; i < appsCount; i++) {
- final AppWindowToken wtoken;
- if (i < closingAppsCount) {
- wtoken = mClosingApps.valueAt(i);
- if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
- closingAppHasWallpaper = true;
- }
- } else {
- wtoken = mOpeningApps.valueAt(i - closingAppsCount);
- if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
- openingAppHasWallpaper = true;
- }
- }
-
- voiceInteraction |= wtoken.voiceInteraction;
-
- if (wtoken.appFullscreen) {
- WindowState ws = wtoken.findMainWindow();
- if (ws != null) {
- animLp = ws.mAttrs;
- bestAnimLayer = ws.mLayer;
- fullscreenAnim = true;
- }
- } else if (!fullscreenAnim) {
- WindowState ws = wtoken.findMainWindow();
- if (ws != null) {
- if (ws.mLayer > bestAnimLayer) {
- animLp = ws.mAttrs;
- bestAnimLayer = ws.mLayer;
- }
- }
- }
- }
-
- mAnimateWallpaperWithTarget = false;
- if (closingAppHasWallpaper && openingAppHasWallpaper) {
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
- switch (transit) {
- case AppTransition.TRANSIT_ACTIVITY_OPEN:
- case AppTransition.TRANSIT_TASK_OPEN:
- case AppTransition.TRANSIT_TASK_TO_FRONT:
- transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
- break;
- case AppTransition.TRANSIT_ACTIVITY_CLOSE:
- case AppTransition.TRANSIT_TASK_CLOSE:
- case AppTransition.TRANSIT_TASK_TO_BACK:
- transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
- break;
- }
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "New transit: " + AppTransition.appTransitionToString(transit));
- } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
- && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
- // We are transitioning from an activity with
- // a wallpaper to one without.
- transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "New transit away from wallpaper: "
- + AppTransition.appTransitionToString(transit));
- } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
- // We are transitioning from an activity without
- // a wallpaper to now showing the wallpaper
- transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "New transit into wallpaper: "
- + AppTransition.appTransitionToString(transit));
- } else {
- mAnimateWallpaperWithTarget = true;
- }
-
- // If all closing windows are obscured, then there is
- // no need to do an animation. This is the case, for
- // example, when this transition is being done behind
- // the lock screen.
- if (!mPolicy.allowAppAnimationsLw()) {
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "Animations disallowed by keyguard or dream.");
- animLp = null;
- }
-
- AppWindowToken topOpeningApp = null;
- AppWindowToken topClosingApp = null;
- int topOpeningLayer = 0;
- int topClosingLayer = 0;
-
- // Process all applications animating in place
- if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
- // Find the focused window
- final WindowState win =
- findFocusedWindowLocked(getDefaultDisplayContentLocked());
- if (win != null) {
- final AppWindowToken wtoken = win.mAppToken;
- final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken);
- appAnimator.clearThumbnail();
- appAnimator.animation = null;
- updateTokenInPlaceLocked(wtoken, transit);
- wtoken.updateReportedVisibilityLocked();
-
- appAnimator.mAllAppWinAnimators.clear();
- final int N = wtoken.allAppWindows.size();
- for (int j = 0; j < N; j++) {
- appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
- }
- mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
- mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
- }
- }
-
- appsCount = mOpeningApps.size();
- for (i = 0; i < appsCount; i++) {
- AppWindowToken wtoken = mOpeningApps.valueAt(i);
- final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
-
- if (!appAnimator.usingTransferredAnimation) {
- appAnimator.clearThumbnail();
- appAnimator.animation = null;
- }
- wtoken.inPendingTransaction = false;
- if (!setTokenVisibilityLocked(
- wtoken, animLp, true, transit, false, voiceInteraction)){
- // This token isn't going to be animating. Add it to the list of tokens to
- // be notified of app transition complete since the notification will not be
- // sent be the app window animator.
- mNoAnimationNotifyOnTransitionFinished.add(wtoken.token);
- }
- wtoken.updateReportedVisibilityLocked();
- wtoken.waitingToShow = false;
-
- appAnimator.mAllAppWinAnimators.clear();
- final int windowsCount = wtoken.allAppWindows.size();
- for (int j = 0; j < windowsCount; j++) {
- appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
- }
- mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
- mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
-
- if (animLp != null) {
- int layer = -1;
- for (int j = 0; j < wtoken.windows.size(); j++) {
- WindowState win = wtoken.windows.get(j);
- if (win.mWinAnimator.mAnimLayer > layer) {
- layer = win.mWinAnimator.mAnimLayer;
- }
- }
- if (topOpeningApp == null || layer > topOpeningLayer) {
- topOpeningApp = wtoken;
- topOpeningLayer = layer;
- }
- }
- }
- appsCount = mClosingApps.size();
- for (i = 0; i < appsCount; i++) {
- AppWindowToken wtoken = mClosingApps.valueAt(i);
- final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
- appAnimator.clearThumbnail();
- appAnimator.animation = null;
- wtoken.inPendingTransaction = false;
- setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
- wtoken.updateReportedVisibilityLocked();
- // Force the allDrawn flag, because we want to start
- // this guy's animations regardless of whether it's
- // gotten drawn.
- wtoken.allDrawn = true;
- wtoken.deferClearAllDrawn = false;
- // Ensure that apps that are mid-starting are also scheduled to have their
- // starting windows removed after the animation is complete
- if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) {
- scheduleRemoveStartingWindowLocked(wtoken);
- }
- mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
-
- if (animLp != null) {
- int layer = -1;
- for (int j = 0; j < wtoken.windows.size(); j++) {
- WindowState win = wtoken.windows.get(j);
- if (win.mWinAnimator.mAnimLayer > layer) {
- layer = win.mWinAnimator.mAnimLayer;
- }
- }
- if (topClosingApp == null || layer > topClosingLayer) {
- topClosingApp = wtoken;
- topClosingLayer = layer;
- }
- }
- }
-
- AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
- topOpeningApp.mAppAnimator;
- AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
- topClosingApp.mAppAnimator;
- Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
- if (nextAppTransitionThumbnail != null
- && openingAppAnimator != null && openingAppAnimator.animation != null &&
- nextAppTransitionThumbnail.getConfig() != Config.ALPHA_8) {
- // This thumbnail animation is very special, we need to have
- // an extra surface with the thumbnail included with the animation.
- Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
- nextAppTransitionThumbnail.getHeight());
- try {
- // TODO(multi-display): support other displays
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
- final Display display = displayContent.getDisplay();
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-
- // Create a new surface for the thumbnail
- SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
- "thumbnail anim", dirty.width(), dirty.height(),
- PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
- surfaceControl.setLayerStack(display.getLayerStack());
- if (SHOW_TRANSACTIONS) {
- Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
- }
-
- // Draw the thumbnail onto the surface
- Surface drawSurface = new Surface();
- drawSurface.copyFrom(surfaceControl);
- Canvas c = drawSurface.lockCanvas(dirty);
- c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
- drawSurface.unlockCanvasAndPost(c);
- drawSurface.release();
-
- // Get the thumbnail animation
- Animation anim;
- if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
- // If this is a multi-window scenario, we use the windows frame as
- // destination of the thumbnail header animation. If this is a full screen
- // window scenario, we use the whole display as the target.
- WindowState win = topOpeningApp.findMainWindow();
- Rect appRect = win != null ? win.getContentFrameLw() :
- new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
- // For the new aspect-scaled transition, we want it to always show
- // above the animating opening/closing window, and we want to
- // synchronize its thumbnail surface with the surface for the
- // open/close animation (only on the way down)
- anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect);
- openingAppAnimator.thumbnailForceAboveLayer = Math.max(topOpeningLayer,
- topClosingLayer);
- openingAppAnimator.deferThumbnailDestruction =
- !mAppTransition.isNextThumbnailTransitionScaleUp();
- } else {
- anim = mAppTransition.createThumbnailScaleAnimationLocked(
- displayInfo.appWidth, displayInfo.appHeight, transit);
- }
- anim.restrictDuration(MAX_ANIMATION_DURATION);
- anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
-
- openingAppAnimator.thumbnail = surfaceControl;
- openingAppAnimator.thumbnailLayer = topOpeningLayer;
- openingAppAnimator.thumbnailAnimation = anim;
- openingAppAnimator.thumbnailX = mAppTransition.getStartingX();
- openingAppAnimator.thumbnailY = mAppTransition.getStartingY();
- } catch (OutOfResourcesException e) {
- Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
- + " h=" + dirty.height(), e);
- openingAppAnimator.clearThumbnail();
- }
- }
-
- mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator);
- mAppTransition.postAnimationCallback();
- mAppTransition.clear();
-
- mOpeningApps.clear();
- mClosingApps.clear();
-
- // This has changed the visibility of windows, so perform
- // a new layout to get them all up-to-date.
- changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
- | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
- getDefaultDisplayContentLocked().layoutNeeded = true;
-
- // TODO(multidisplay): IMEs are only supported on the default display.
- if (windows == getDefaultWindowListLocked()
- && !moveInputMethodWindowsIfNeededLocked(true)) {
- assignLayersLocked(windows);
- }
- updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/);
- mFocusMayChange = false;
- notifyActivityDrawnForKeyguard();
+ private void createThumbnailAppAnimator(int transit, AppWindowToken appToken,
+ int openingLayer, int closingLayer) {
+ AppWindowAnimator openingAppAnimator = (appToken == null) ? null : appToken.mAppAnimator;
+ if (openingAppAnimator == null || openingAppAnimator.animation == null) {
+ return;
}
+ final int taskId = appToken.mTask.mTaskId;
+ Bitmap thumbnailHeader = mAppTransition.getAppTransitionThumbnailHeader(taskId);
+ if (thumbnailHeader == null || thumbnailHeader.getConfig() == Config.ALPHA_8) {
+ return;
+ }
+ // This thumbnail animation is very special, we need to have
+ // an extra surface with the thumbnail included with the animation.
+ Rect dirty = new Rect(0, 0, thumbnailHeader.getWidth(), thumbnailHeader.getHeight());
+ try {
+ // TODO(multi-display): support other displays
+ final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ final Display display = displayContent.getDisplay();
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- return changes;
+ // Create a new surface for the thumbnail
+ SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
+ "thumbnail anim", dirty.width(), dirty.height(),
+ PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ surfaceControl.setLayerStack(display.getLayerStack());
+ if (SHOW_TRANSACTIONS) {
+ Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
+ }
+
+ // Draw the thumbnail onto the surface
+ Surface drawSurface = new Surface();
+ drawSurface.copyFrom(surfaceControl);
+ Canvas c = drawSurface.lockCanvas(dirty);
+ c.drawBitmap(thumbnailHeader, 0, 0, null);
+ drawSurface.unlockCanvasAndPost(c);
+ drawSurface.release();
+
+ // Get the thumbnail animation
+ Animation anim;
+ if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
+ // If this is a multi-window scenario, we use the windows frame as
+ // destination of the thumbnail header animation. If this is a full screen
+ // window scenario, we use the whole display as the target.
+ WindowState win = appToken.findMainWindow();
+ Rect appRect = win != null ? win.getContentFrameLw() :
+ new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
+ // For the new aspect-scaled transition, we want it to always show
+ // above the animating opening/closing window, and we want to
+ // synchronize its thumbnail surface with the surface for the
+ // open/close animation (only on the way down)
+ anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect,
+ thumbnailHeader, taskId);
+ Log.d(TAG, "assigning thumbnail force above layer: " + openingLayer + " " +
+ closingLayer);
+ openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer);
+ openingAppAnimator.deferThumbnailDestruction =
+ !mAppTransition.isNextThumbnailTransitionScaleUp();
+ } else {
+ anim = mAppTransition.createThumbnailScaleAnimationLocked(
+ displayInfo.appWidth, displayInfo.appHeight, transit, thumbnailHeader);
+ }
+ anim.restrictDuration(MAX_ANIMATION_DURATION);
+ anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
+
+ openingAppAnimator.thumbnail = surfaceControl;
+ openingAppAnimator.thumbnailLayer = openingLayer;
+ openingAppAnimator.thumbnailAnimation = anim;
+ mAppTransition.getNextAppTransitionStartRect(taskId, mTmpStartRect);
+ openingAppAnimator.thumbnailX = mTmpStartRect.left;
+ openingAppAnimator.thumbnailY = mTmpStartRect.top;
+ } catch (OutOfResourcesException e) {
+ Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
+ + " h=" + dirty.height(), e);
+ openingAppAnimator.clearThumbnail();
+ }
}
/**
@@ -9624,10 +8957,7 @@
}
mNoAnimationNotifyOnTransitionFinished.clear();
- if (mDeferredHideWallpaper != null) {
- hideWallpapersLocked(mDeferredHideWallpaper);
- mDeferredHideWallpaper = null;
- }
+ mWallpaperControllerLocked.hideDeferredWallpapersIfNeeded();
// Restore window app tokens to the ActivityManager views
ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
@@ -9948,7 +9278,7 @@
if ((displayContent.pendingLayoutChanges &
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
- adjustWallpaperWindowsLocked()) {
+ mWallpaperControllerLocked.adjustWallpaperWindows()) {
assignLayersLocked(windows);
displayContent.layoutNeeded = true;
}
@@ -10020,12 +9350,12 @@
handleFlagDimBehind(w);
}
- if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
- && w.isVisibleLw()) {
+ if (isDefaultDisplay && obscuredChanged
+ && mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) {
// This is the wallpaper target and its obscured state
// changed... make sure the current wallaper's visibility
// has been updated accordingly.
- updateWallpaperVisibilityLocked();
+ mWallpaperControllerLocked.updateWallpaperVisibility();
}
final WindowStateAnimator winAnimator = w.mWinAnimator;
@@ -10274,7 +9604,7 @@
if (mInputMethodWindow == win) {
mInputMethodWindow = null;
}
- if (win == mWallpaperTarget) {
+ if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
wallpaperDestroyed = true;
}
win.mWinAnimator.destroySurfaceLocked();
@@ -10291,7 +9621,7 @@
if (!token.hasVisible) {
exitingTokens.remove(i);
if (token.windowType == TYPE_WALLPAPER) {
- mWallpaperTokens.remove(token);
+ mWallpaperControllerLocked.removeWallpaperToken(token);
}
}
}
@@ -10438,8 +9768,8 @@
": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
" mHasSurface=" + win.mHasSurface +
" drawState=" + win.mWinAnimator.mDrawState);
- if (win.mRemoved || !win.mHasSurface) {
- // Window has been removed; no draw will now happen, so stop waiting.
+ if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
+ // Window has been removed or hidden; no draw will now happen, so stop waiting.
if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win);
mWaitingForDrawn.remove(win);
} else if (win.hasDrawnLw()) {
@@ -11091,23 +10421,6 @@
}
}
- // It is assumed that this method is called only by InputMethodManagerService.
- public void saveLastInputMethodWindowForTransition() {
- synchronized (mWindowMap) {
- // TODO(multidisplay): Pass in the displayID.
- DisplayContent displayContent = getDefaultDisplayContentLocked();
- if (mInputMethodWindow != null) {
- mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
- }
- }
- }
-
- public int getInputMethodWindowVisibleHeight() {
- synchronized (mWindowMap) {
- return mPolicy.getInputMethodWindowVisibleHeightLw();
- }
- }
-
@Override
public boolean hasNavigationBar() {
return mPolicy.hasNavigationBar();
@@ -11198,21 +10511,7 @@
}
}
}
- if (!mWallpaperTokens.isEmpty()) {
- pw.println();
- pw.println(" Wallpaper tokens:");
- for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
- WindowToken token = mWallpaperTokens.get(i);
- pw.print(" Wallpaper #"); pw.print(i);
- pw.print(' '); pw.print(token);
- if (dumpAll) {
- pw.println(':');
- token.dump(pw, " ");
- } else {
- pw.println();
- }
- }
- }
+ mWallpaperControllerLocked.dumpTokens(pw, " ", dumpAll);
if (!mFinishedStarting.isEmpty()) {
pw.println();
pw.println(" Finishing start of application tokens:");
@@ -11412,25 +10711,13 @@
if (mInputMethodWindow != null) {
pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
}
- pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
- if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
- pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
- pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
- }
- pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
- pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
- if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
- || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
- pw.print(" mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
- pw.print(" mLastWallpaperDisplayOffsetY=");
- pw.println(mLastWallpaperDisplayOffsetY);
- }
+ mWallpaperControllerLocked.dump(pw, " ");
if (mInputMethodAnimLayerAdjustment != 0 ||
- mWallpaperAnimLayerAdjustment != 0) {
+ mWallpaperControllerLocked.getAnimLayerAdjustment() != 0) {
pw.print(" mInputMethodAnimLayerAdjustment=");
pw.print(mInputMethodAnimLayerAdjustment);
pw.print(" mWallpaperAnimLayerAdjustment=");
- pw.println(mWallpaperAnimLayerAdjustment);
+ pw.println(mWallpaperControllerLocked.getAnimLayerAdjustment());
}
pw.print(" mSystemBooted="); pw.print(mSystemBooted);
pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
@@ -11723,10 +11010,6 @@
synchronized (mWindowMap) { }
}
- public interface OnHardKeyboardStatusChangeListener {
- public void onHardKeyboardStatusChange(boolean available);
- }
-
void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
@@ -11985,12 +11268,18 @@
final WindowList windows = getDefaultWindowListLocked();
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
final WindowState win = windows.get(winNdx);
+ final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
if (win.isVisibleLw()
- && (win.mAppToken != null || mPolicy.isForceHiding(win.mAttrs))) {
+ && (win.mAppToken != null || isForceHiding)) {
win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
// Force add to mResizingWindows.
win.mLastContentInsets.set(-1, -1, -1, -1);
mWaitingForDrawn.add(win);
+
+ // No need to wait for the windows below Keyguard.
+ if (isForceHiding) {
+ break;
+ }
}
}
requestTraversalLocked();
@@ -12028,5 +11317,39 @@
mAppTransition.registerListenerLocked(listener);
}
}
+
+ @Override
+ public int getInputMethodWindowVisibleHeight() {
+ synchronized (mWindowMap) {
+ return mPolicy.getInputMethodWindowVisibleHeightLw();
+ }
+ }
+
+ @Override
+ public void saveLastInputMethodWindowForTransition() {
+ synchronized (mWindowMap) {
+ // TODO(multidisplay): Pass in the displayID.
+ DisplayContent displayContent = getDefaultDisplayContentLocked();
+ if (mInputMethodWindow != null) {
+ mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
+ }
+ }
+ }
+
+ @Override
+ public boolean isHardKeyboardAvailable() {
+ synchronized (mWindowMap) {
+ return mHardKeyboardAvailable;
+ }
+ }
+
+ @Override
+ public void setOnHardKeyboardStatusChangeListener(
+ OnHardKeyboardStatusChangeListener listener) {
+ synchronized (mWindowMap) {
+ mHardKeyboardStatusChangeListener = listener;
+ }
+ }
+
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4061149..761e5eb 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
@@ -33,11 +34,11 @@
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
import android.app.AppOpsManager;
-import android.os.Debug;
import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.SystemClock;
import android.os.WorkSource;
+import android.util.DisplayMetrics;
import android.util.TimeUtils;
import android.view.Display;
import android.view.IWindowFocusObserver;
@@ -78,6 +79,16 @@
final class WindowState implements WindowManagerPolicy.WindowState {
static final String TAG = "WindowState";
+ // The minimal size of a window within the usable area of the freeform stack.
+ private static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48;
+ private static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32;
+
+ // The thickness of a window resize handle outside the window bounds on the free form workspace
+ // to capture touch events in that area.
+ private static final int RESIZE_HANDLE_WIDTH_IN_DP = 10;
+
+ static final boolean BOUNDS_FOR_TOUCH = true;
+
final WindowManagerService mService;
final WindowManagerPolicy mPolicy;
final Context mContext;
@@ -537,6 +548,7 @@
final Task task = mAppToken != null ? getTask() : null;
final boolean nonFullscreenTask = task != null && !task.isFullscreen();
+ final boolean freeformWorkspace = inFreeformWorkspace();
if (nonFullscreenTask) {
task.getBounds(mContainingFrame);
final WindowState imeWin = mService.mInputMethodWindow;
@@ -545,10 +557,20 @@
// IME is up and obscuring this window. Adjust the window position so it is visible.
mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
}
- // Make sure the containing frame is within the content frame so we don't layout
- // resized window under screen decorations.
- if (!mContainingFrame.intersect(cf)) {
- mContainingFrame.set(cf);
+
+ if (freeformWorkspace) {
+ // In free form mode we have only to set the rectangle if it wasn't set already. No
+ // need to intersect it with the (visible) "content frame" since it is allowed to
+ // be outside the visible desktop.
+ if (mContainingFrame.isEmpty()) {
+ mContainingFrame.set(cf);
+ }
+ } else {
+ // Make sure the containing frame is within the content frame so we don't layout
+ // resized window under screen decorations.
+ if (!mContainingFrame.intersect(cf)) {
+ mContainingFrame.set(cf);
+ }
}
mDisplayFrame.set(mContainingFrame);
} else {
@@ -652,20 +674,38 @@
// Make sure the content and visible frames are inside of the
// final window frame.
- mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
- Math.max(mContentFrame.top, mFrame.top),
- Math.min(mContentFrame.right, mFrame.right),
- Math.min(mContentFrame.bottom, mFrame.bottom));
+ if (freeformWorkspace && !mFrame.isEmpty()) {
+ // Keep the frame out of the blocked system area, limit it in size to the content area
+ // and make sure that there is always a minimum visible so that the user can drag it
+ // into a usable area..
+ final int height = Math.min(mFrame.height(), mContentFrame.height());
+ final int width = Math.min(mContentFrame.width(), mFrame.width());
+ final int minVisibleHeight = calculatePixelFromDp(MINIMUM_VISIBLE_HEIGHT_IN_DP);
+ final int minVisibleWidth = calculatePixelFromDp(MINIMUM_VISIBLE_WIDTH_IN_DP);
+ final int top = Math.max(mContentFrame.top,
+ Math.min(mFrame.top, mContentFrame.bottom - minVisibleHeight));
+ final int left = Math.max(mContentFrame.left + minVisibleWidth - width,
+ Math.min(mFrame.left, mContentFrame.right - minVisibleWidth));
+ mFrame.set(left, top, left + width, top + height);
+ mContentFrame.set(mFrame);
+ mVisibleFrame.set(mContentFrame);
+ mStableFrame.set(mContentFrame);
+ } else {
+ mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
+ Math.max(mContentFrame.top, mFrame.top),
+ Math.min(mContentFrame.right, mFrame.right),
+ Math.min(mContentFrame.bottom, mFrame.bottom));
- mVisibleFrame.set(Math.max(mVisibleFrame.left, mFrame.left),
- Math.max(mVisibleFrame.top, mFrame.top),
- Math.min(mVisibleFrame.right, mFrame.right),
- Math.min(mVisibleFrame.bottom, mFrame.bottom));
+ mVisibleFrame.set(Math.max(mVisibleFrame.left, mFrame.left),
+ Math.max(mVisibleFrame.top, mFrame.top),
+ Math.min(mVisibleFrame.right, mFrame.right),
+ Math.min(mVisibleFrame.bottom, mFrame.bottom));
- mStableFrame.set(Math.max(mStableFrame.left, mFrame.left),
- Math.max(mStableFrame.top, mFrame.top),
- Math.min(mStableFrame.right, mFrame.right),
- Math.min(mStableFrame.bottom, mFrame.bottom));
+ mStableFrame.set(Math.max(mStableFrame.left, mFrame.left),
+ Math.max(mStableFrame.top, mFrame.top),
+ Math.min(mStableFrame.right, mFrame.right),
+ Math.min(mStableFrame.bottom, mFrame.bottom));
+ }
mOverscanInsets.set(Math.max(mOverscanFrame.left - mFrame.left, 0),
Math.max(mOverscanFrame.top - mFrame.top, 0),
@@ -707,8 +747,8 @@
final DisplayContent displayContent = getDisplayContent();
if (displayContent != null) {
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- mService.updateWallpaperOffsetLocked(this,
- displayInfo.logicalWidth, displayInfo.logicalHeight, false);
+ mService.mWallpaperControllerLocked.updateWallpaperOffset(
+ this, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
}
}
@@ -875,10 +915,22 @@
return mDisplayContent.getHomeStack();
}
- void getTaskBounds(Rect bounds) {
+ /**
+ * Retrieves the bounds for a task.
+ * @param bounds The rect which gets the bounds.
+ * @param forTouch Pass in BOUNDS_FOR_TOUCH to get touch related bounds, otherwise visible
+ * bounds will be returned.
+ */
+ void getTaskBounds(Rect bounds, boolean forTouch) {
final Task task = getTask();
if (task != null) {
task.getBounds(bounds);
+ if (forTouch == BOUNDS_FOR_TOUCH) {
+ if (inFreeformWorkspace()) {
+ final int delta = calculatePixelFromDp(RESIZE_HANDLE_WIDTH_IN_DP);
+ bounds.inset(-delta, -delta);
+ }
+ }
return;
}
bounds.set(mFrame);
@@ -1577,6 +1629,19 @@
}
}
+ boolean inFreeformWorkspace() {
+ final Task task = getTask();
+ return task != null && task.mStack != null &&
+ task.mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
+ }
+
+ private int calculatePixelFromDp(int dp) {
+ final Configuration serviceConfig = mService.mCurConfiguration;
+ // TODO(multidisplay): Update Dp to that of display stack is on.
+ final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ return (int)(dp * density);
+ }
+
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
final TaskStack stack = getStack();
pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId());
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 28491e4..109e627 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -47,7 +47,6 @@
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import android.view.View;
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
import android.view.WindowManager.LayoutParams;
@@ -77,6 +76,7 @@
final WindowManagerPolicy mPolicy;
final Context mContext;
final boolean mIsWallpaper;
+ final WallpaperController mWallpaperControllerLocked;
// Currently running animation.
boolean mAnimating;
@@ -209,6 +209,7 @@
mSession = win.mSession;
mAttrType = win.mAttrs.type;
mIsWallpaper = win.mIsWallpaper;
+ mWallpaperControllerLocked = mService.mWallpaperControllerLocked;
}
public void setAnimation(Animation anim, long startTime) {
@@ -375,7 +376,7 @@
if (mWin.mIsImWindow) {
mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
} else if (mIsWallpaper) {
- mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
+ mAnimLayer += mWallpaperControllerLocked.getAnimLayerAdjustment();
}
if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
+ " anim layer: " + mAnimLayer);
@@ -484,7 +485,7 @@
mService.mPendingRemove.add(mWin);
mWin.mRemoveOnExit = false;
}
- mService.hideWallpapersLocked(mWin);
+ mWallpaperControllerLocked.hideWallpapers(mWin);
}
void hide() {
@@ -986,7 +987,7 @@
}
mSurfaceControl.destroy();
}
- mService.hideWallpapersLocked(mWin);
+ mWallpaperControllerLocked.hideWallpapers(mWin);
} catch (RuntimeException e) {
Slog.w(TAG, "Exception thrown when destroying Window " + this
+ " surface " + mSurfaceControl + " session " + mSession
@@ -1012,7 +1013,7 @@
WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
}
mPendingDestroySurface.destroy();
- mService.hideWallpapersLocked(mWin);
+ mWallpaperControllerLocked.hideWallpapers(mWin);
}
} catch (RuntimeException e) {
Slog.w(TAG, "Exception thrown when destroying Window "
@@ -1033,7 +1034,7 @@
// Wallpapers are animated based on the "real" window they
// are currently targeting.
- final WindowState wallpaperTarget = mService.mWallpaperTarget;
+ final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
if (mIsWallpaper && wallpaperTarget != null && mService.mAnimateWallpaperWithTarget) {
final WindowStateAnimator wallpaperAnimator = wallpaperTarget.mWinAnimator;
if (wallpaperAnimator.mHasLocalTransformation &&
@@ -1467,7 +1468,7 @@
hide();
} else if (w.mAttachedHidden || !w.isOnScreen()) {
hide();
- mService.hideWallpapersLocked(w);
+ mWallpaperControllerLocked.hideWallpapers(w);
// If we are waiting for this window to handle an
// orientation change, well, it is hidden, so
@@ -1522,7 +1523,7 @@
if (showSurfaceRobustlyLocked()) {
mLastHidden = false;
if (mIsWallpaper) {
- mService.dispatchWallpaperVisibility(w, true);
+ mWallpaperControllerLocked.dispatchWallpaperVisibility(w, true);
}
// This draw means the difference between unique content and mirroring.
// Run another pass through performLayout to set mHasContent in the
@@ -1589,8 +1590,6 @@
final int left = ((int) shownFrame.left) - attrs.surfaceInsets.left;
final int top = ((int) shownFrame.top) - attrs.surfaceInsets.top;
if (mSurfaceX != left || mSurfaceY != top) {
- mSurfaceX = left;
- mSurfaceY = top;
if (mAnimating) {
// If this window (or its app token) is animating, then the position
// of the surface will be re-computed on the next animation frame.
@@ -1598,6 +1597,8 @@
// transformation is being applied by the animation.
return;
}
+ mSurfaceX = left;
+ mSurfaceY = top;
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
SurfaceControl.openTransaction();
try {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cd2885b..8788908 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21,6 +21,7 @@
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.TEXT;
@@ -44,6 +45,7 @@
import android.app.admin.IDevicePolicyManager;
import android.app.admin.SystemUpdatePolicy;
import android.app.backup.IBackupManager;
+import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -2957,7 +2959,8 @@
}
boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
if (requireEntry) {
- utils.requireCredentialEntry(UserHandle.USER_ALL);
+ utils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
+ UserHandle.USER_ALL);
}
synchronized (this) {
int newOwner = requireEntry ? callingUid : -1;
@@ -3089,7 +3092,8 @@
mPowerManager.goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);
// Ensure the device is locked
- new LockPatternUtils(mContext).requireCredentialEntry(UserHandle.USER_ALL);
+ new LockPatternUtils(mContext).requireStrongAuth(
+ STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW, UserHandle.USER_ALL);
getWindowManager().lockNow(null);
} catch (RemoteException e) {
} finally {
@@ -4232,6 +4236,17 @@
mDeviceOwner.clearDeviceOwner();
mDeviceOwner.writeOwnerFile();
updateDeviceOwnerLocked();
+ // Reactivate backup service.
+ long ident = Binder.clearCallingIdentity();
+ try {
+ IBackupManager ibm = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+ ibm.setBackupServiceActive(UserHandle.USER_OWNER, true);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed reactivating backup service.", e);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}
}
@@ -4523,12 +4538,12 @@
long id = Binder.clearCallingIdentity();
try {
mUserManager.setUserEnabled(userId);
+ UserInfo parent = mUserManager.getProfileParent(userId);
Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
intent.putExtra(Intent.EXTRA_USER, new UserHandle(userHandle));
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
Intent.FLAG_RECEIVER_FOREGROUND);
- // TODO This should send to parent of profile (which is always owner at the moment).
- mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(parent.id));
} finally {
restoreCallingIdentity(id);
}
@@ -4963,13 +4978,19 @@
IPackageManager pm = AppGlobals.getPackageManager();
long id = Binder.clearCallingIdentity();
try {
+ UserInfo parent = mUserManager.getProfileParent(callingUserId);
+ if (parent == null) {
+ Slog.e(LOG_TAG, "Cannot call addCrossProfileIntentFilter if there is no "
+ + "parent");
+ return;
+ }
if ((flags & DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED) != 0) {
pm.addCrossProfileIntentFilter(filter, who.getPackageName(), callingUserId,
- UserHandle.USER_OWNER, 0);
+ parent.id, 0);
}
if ((flags & DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT) != 0) {
pm.addCrossProfileIntentFilter(filter, who.getPackageName(),
- UserHandle.USER_OWNER, callingUserId, 0);
+ parent.id, callingUserId, 0);
}
} catch (RemoteException re) {
// Shouldn't happen
@@ -4988,12 +5009,18 @@
IPackageManager pm = AppGlobals.getPackageManager();
long id = Binder.clearCallingIdentity();
try {
- // Removing those that go from the managed profile to the primary user.
+ UserInfo parent = mUserManager.getProfileParent(callingUserId);
+ if (parent == null) {
+ Slog.e(LOG_TAG, "Cannot call clearCrossProfileIntentFilter if there is no "
+ + "parent");
+ return;
+ }
+ // Removing those that go from the managed profile to the parent.
pm.clearCrossProfileIntentFilters(callingUserId, who.getPackageName());
- // And those that go from the primary user to the managed profile.
+ // And those that go from the parent to the managed profile.
// If we want to support multiple managed profiles, we will have to only remove
// those that have callingUserId as their target.
- pm.clearCrossProfileIntentFilters(UserHandle.USER_OWNER, who.getPackageName());
+ pm.clearCrossProfileIntentFilters(parent.id, who.getPackageName());
} catch (RemoteException re) {
// Shouldn't happen
} finally {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ed32c76..21dd647b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -546,7 +546,7 @@
if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
try {
Slog.i(TAG, "Input Method Service");
- imm = new InputMethodManagerService(context, wm);
+ imm = new InputMethodManagerService(context);
ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
} catch (Throwable e) {
reportWtf("starting Input Manager Service", e);
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 33979b1..3ad26d3 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -13,6 +13,7 @@
services.net \
easymocklib \
guava \
+ android-support-test \
mockito-target
LOCAL_JAVA_LIBRARIES := android.test.runner
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 919293a..386a9cb 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -69,7 +69,7 @@
</application>
<instrumentation
- android:name="android.test.InstrumentationTestRunner"
+ android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.frameworks.servicestests"
android:label="Frameworks Services Tests" />
</manifest>
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 696f106..b4c76b7 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -943,8 +943,7 @@
if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
- capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP ||
- capability == NET_CAPABILITY_TRUSTED || capability == NET_CAPABILITY_NOT_VPN) {
+ capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
} else {
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index ed1db6f..bf6343f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -21,8 +21,11 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageParser;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
import android.test.AndroidTestCase;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -36,6 +39,8 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.List;
public class PackageManagerSettingsTests extends AndroidTestCase {
private static final String PACKAGE_NAME_2 = "com.google.app2";
@@ -45,6 +50,12 @@
public static final String TAG = "PackageManagerSettingsTests";
protected final String PREFIX = "android.content.pm";
+ private @NonNull List<UserInfo> createFakeUsers() {
+ ArrayList<UserInfo> users = new ArrayList<>();
+ users.add(new UserInfo(UserHandle.USER_SYSTEM, "test user", UserInfo.FLAG_INITIALIZED));
+ return users;
+ }
+
private void writeFile(File file, byte[] data) {
file.mkdirs();
try {
@@ -245,7 +256,7 @@
writeOldFiles();
createUserManagerServiceRef();
Settings settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(createFakeUsers()));
verifyKeySetMetaData(settings);
}
@@ -257,11 +268,11 @@
writeOldFiles();
createUserManagerServiceRef();
Settings settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(createFakeUsers()));
/* write out, read back in and verify the same */
settings.writeLPr();
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(createFakeUsers()));
verifyKeySetMetaData(settings);
}
@@ -269,7 +280,7 @@
// Write the package files and make sure they're parsed properly the first time
writeOldFiles();
Settings settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(createFakeUsers()));
assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_3));
assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_1));
@@ -289,12 +300,12 @@
writeOldFiles();
createUserManagerServiceRef();
Settings settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(createFakeUsers()));
settings.writeLPr();
// Create Settings again to make it read from the new files
settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(createFakeUsers()));
PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_2);
assertEquals(COMPONENT_ENABLED_STATE_DISABLED_USER, ps.getEnabled(0));
@@ -305,7 +316,7 @@
// Write the package files and make sure they're parsed properly the first time
writeOldFiles();
Settings settings = new Settings(getContext().getFilesDir(), new Object());
- assertEquals(true, settings.readLPw(null, null, 0, false));
+ assertEquals(true, settings.readLPw(createFakeUsers()));
// Enable/Disable a package
PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 2d47c24..86f5ed7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -38,7 +38,8 @@
@Override
public void setUp() throws Exception {
- mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+ super.setUp();
+ mUserManager = UserManager.get(getContext());
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
getContext().registerReceiver(new BroadcastReceiver() {
@Override
@@ -64,14 +65,18 @@
private void removeExistingUsers() {
List<UserInfo> list = mUserManager.getUsers();
for (UserInfo user : list) {
- if (user.id != UserHandle.USER_OWNER) {
+ // Keep system and primary user.
+ // We do not have to keep primary user, but in split system user mode, we need it
+ // until http://b/22976637 is fixed. Right now in split system user mode, you need to
+ // switch to primary user and run tests under primary user.
+ if (user.id != UserHandle.USER_SYSTEM && !user.isPrimary()) {
removeUser(user.id);
}
}
}
- public void testHasPrimary() throws Exception {
- assertTrue(findUser(0));
+ public void testHasSystemUser() throws Exception {
+ assertTrue(findUser(UserHandle.USER_SYSTEM));
}
public void testAddUser() throws Exception {
@@ -122,10 +127,11 @@
// Make sure only one managed profile can be created
public void testAddManagedProfile() throws Exception {
+ final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo userInfo1 = createProfileForUser("Managed 1",
- UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
+ UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
UserInfo userInfo2 = createProfileForUser("Managed 2",
- UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
+ UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
assertNotNull(userInfo1);
assertNull(userInfo2);
// Verify that current user is not a managed profile
@@ -133,17 +139,18 @@
}
public void testGetUserCreationTime() throws Exception {
+ final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo profile = createProfileForUser("Managed 1",
- UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
+ UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
assertNotNull(profile);
assertTrue("creationTime must be set when the profile is created",
profile.creationTime > 0);
assertEquals(profile.creationTime, mUserManager.getUserCreationTime(
new UserHandle(profile.id)));
- long ownerCreationTime = mUserManager.getUserInfo(UserHandle.USER_OWNER).creationTime;
+ long ownerCreationTime = mUserManager.getUserInfo(primaryUserId).creationTime;
assertEquals(ownerCreationTime, mUserManager.getUserCreationTime(
- new UserHandle(UserHandle.USER_OWNER)));
+ new UserHandle(primaryUserId)));
try {
int noSuchUserId = 100500;
@@ -177,11 +184,11 @@
}
public void testSerialNumber() {
- UserInfo user1 = createUser("User 1", UserInfo.FLAG_RESTRICTED);
+ UserInfo user1 = createUser("User 1", 0);
int serialNumber1 = user1.serialNumber;
assertEquals(serialNumber1, mUserManager.getUserSerialNumber(user1.id));
assertEquals(user1.id, mUserManager.getUserHandle(serialNumber1));
- UserInfo user2 = createUser("User 2", UserInfo.FLAG_RESTRICTED);
+ UserInfo user2 = createUser("User 2", 0);
int serialNumber2 = user2.serialNumber;
assertFalse(serialNumber1 == serialNumber2);
assertEquals(serialNumber2, mUserManager.getUserSerialNumber(user2.id));
@@ -203,17 +210,15 @@
}
public void testRestrictions() {
- List<UserInfo> users = mUserManager.getUsers();
- if (users.size() > 1) {
- Bundle restrictions = new Bundle();
- restrictions.putBoolean(UserManager.DISALLOW_INSTALL_APPS, true);
- restrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, false);
- mUserManager.setUserRestrictions(restrictions, new UserHandle(users.get(1).id));
- Bundle stored = mUserManager.getUserRestrictions(new UserHandle(users.get(1).id));
- assertEquals(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI), false);
- assertEquals(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS), false);
- assertEquals(stored.getBoolean(UserManager.DISALLOW_INSTALL_APPS), true);
- }
+ UserInfo testUser = createUser("User 1", 0);
+ Bundle restrictions = new Bundle();
+ restrictions.putBoolean(UserManager.DISALLOW_INSTALL_APPS, true);
+ restrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, false);
+ mUserManager.setUserRestrictions(restrictions, new UserHandle(testUser.id));
+ Bundle stored = mUserManager.getUserRestrictions(new UserHandle(testUser.id));
+ assertEquals(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI), false);
+ assertEquals(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS), false);
+ assertEquals(stored.getBoolean(UserManager.DISALLOW_INSTALL_APPS), true);
}
private void removeUser(int userId) {
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index fb9a3a3..b021e80 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -61,6 +61,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Scanner;
+import java.util.Set;
/**
* UsbDeviceManager manages USB state in device mode.
@@ -148,6 +149,7 @@
private String[] mAccessoryStrings;
private UsbDebuggingManager mDebuggingManager;
private final UsbAlsaManager mUsbAlsaManager;
+ private Intent mBroadcastedIntent;
private class AdbSettingsObserver extends ContentObserver {
public AdbSettingsObserver() {
@@ -427,7 +429,7 @@
if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked: " + enable);
mUsbDataUnlocked = enable;
updateUsbNotification();
- updateUsbStateBroadcast();
+ updateUsbStateBroadcastIfNeeded();
setEnabledFunctions(mCurrentFunctions, true);
}
@@ -574,7 +576,33 @@
}
}
- private void updateUsbStateBroadcast() {
+ private boolean isUsbStateChanged(Intent intent) {
+ final Set<String> keySet = intent.getExtras().keySet();
+ if (mBroadcastedIntent == null) {
+ for (String key : keySet) {
+ if (intent.getBooleanExtra(key, false)) {
+ // MTP function is enabled by default.
+ if (UsbManager.USB_FUNCTION_MTP.equals(key)) {
+ continue;
+ }
+ return true;
+ }
+ }
+ } else {
+ if (!keySet.equals(mBroadcastedIntent.getExtras().keySet())) {
+ return true;
+ }
+ for (String key : keySet) {
+ if (intent.getBooleanExtra(key, false) !=
+ mBroadcastedIntent.getBooleanExtra(key, false)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void updateUsbStateBroadcastIfNeeded() {
// send a sticky broadcast containing current USB state
Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
@@ -586,13 +614,25 @@
if (mCurrentFunctions != null) {
String[] functions = mCurrentFunctions.split(",");
for (int i = 0; i < functions.length; i++) {
- intent.putExtra(functions[i], true);
+ final String function = functions[i];
+ if (UsbManager.USB_FUNCTION_NONE.equals(function)) {
+ continue;
+ }
+ intent.putExtra(function, true);
}
}
- if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " connected: " + mConnected
- + " configured: " + mConfigured);
+ // send broadcast intent only if the USB state has changed
+ if (!isUsbStateChanged(intent)) {
+ if (DEBUG) {
+ Slog.d(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras());
+ }
+ return;
+ }
+
+ if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras());
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ mBroadcastedIntent = intent;
}
private void updateUsbFunctions() {
@@ -670,7 +710,7 @@
setEnabledFunctions(null, false);
}
if (mBootCompleted) {
- updateUsbStateBroadcast();
+ updateUsbStateBroadcastIfNeeded();
updateUsbFunctions();
}
break;
@@ -694,7 +734,7 @@
case MSG_SYSTEM_READY:
updateUsbNotification();
updateAdbNotification();
- updateUsbStateBroadcast();
+ updateUsbStateBroadcastIfNeeded();
updateUsbFunctions();
break;
case MSG_BOOT_COMPLETED:
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index d91fa90..2d31a78 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -512,8 +512,8 @@
Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Objects.equals(mVideoState, d.mVideoState) &&
Objects.equals(mStatusHints, d.mStatusHints) &&
- Objects.equals(mExtras, d.mExtras) &&
- Objects.equals(mIntentExtras, d.mIntentExtras);
+ areBundlesEqual(mExtras, d.mExtras) &&
+ areBundlesEqual(mIntentExtras, d.mIntentExtras);
}
return false;
}
@@ -1253,4 +1253,32 @@
});
}
}
+
+ /**
+ * Determines if two bundles are equal.
+ *
+ * @param bundle The original bundle.
+ * @param newBundle The bundle to compare with.
+ * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
+ */
+ private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
+ if (bundle == null || newBundle == null) {
+ return bundle == newBundle;
+ }
+
+ if (bundle.size() != newBundle.size()) {
+ return false;
+ }
+
+ for(String key : bundle.keySet()) {
+ if (key != null) {
+ final Object value = bundle.get(key);
+ final Object newValue = newBundle.get(key);
+ if (!Objects.equals(value, newValue)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3054422..e3f3c75 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -266,6 +266,13 @@
public static final String KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL =
"carrier_instant_lettering_available_bool";
+ /*
+ * Flag specifying whether IMS should be the first phone attempted for E911 even if the
+ * phone is not in service.
+ */
+ public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL
+ = "carrier_use_ims_first_for_emergency_bool";
+
/**
* If Voice Radio Technology is RIL_RADIO_TECHNOLOGY_LTE:14 or RIL_RADIO_TECHNOLOGY_UNKNOWN:0
* this is the value that should be used instead. A configuration value of
@@ -342,14 +349,29 @@
"ci_action_on_sys_update_extra_val_string";
/**
- * Specifies the amount of gap to be added in millis between DTMF tones. When a non-zero value
- * is specified, the UE shall wait for the specified amount of time before it sends out
- * successive DTMF tones on the network.
+ * Specifies the amount of gap to be added in millis between postdial DTMF tones. When a
+ * non-zero value is specified, the UE shall wait for the specified amount of time before it
+ * sends out successive DTMF tones on the network.
* @hide
*/
public static final String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
/**
+ * Specifies the amount of gap to be added in millis between postdial DTMF tones. When a
+ * non-zero value is specified, the UE shall wait for the specified amount of time before it
+ * sends out successive DTMF tones on the network.
+ * @hide
+ */
+ public static final String KEY_CDMA_DTMF_TONE_DELAY_INT = "cdma_dtmf_tone_delay_int";
+
+ /**
+ * Determines whether conference calls are supported by a carrier. When {@code true},
+ * conference calling is supported, {@code false otherwise}.
+ * @hide
+ */
+ public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
+
+ /**
* If this is true, the SIM card (through Customer Service Profile EF file) will be able to
* prevent manual operator selection. If false, this SIM setting will be ignored and manual
* operator selection will always be available. See CPHS4_2.WW6, CPHS B.4.7.1 for more
@@ -410,6 +432,7 @@
sDefaults.putBoolean(KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true);
sDefaults.putBoolean(KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL, true);
sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false);
+ sDefaults.putBoolean(KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true);
sDefaults.putBoolean(KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL, false);
sDefaults.putBoolean(KEY_DTMF_TYPE_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL, true);
@@ -448,6 +471,8 @@
sDefaults.putStringArray(KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_FORCE_HOME_NETWORK_BOOL, false);
sDefaults.putInt(KEY_IMS_DTMF_TONE_DELAY_INT, 0);
+ sDefaults.putInt(KEY_CDMA_DTMF_TONE_DELAY_INT, 100);
+ sDefaults.putBoolean(KEY_SUPPORT_CONFERENCE_CALL_BOOL, true);
// MMS defaults
sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 79146f3..273cc93 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1135,6 +1135,8 @@
"VI", // U.S. Virgin Islands
};
+ private static final String KOREA_ISO_COUNTRY_CODE = "KR";
+
/**
* Breaks the given number down and formats it according to the rules
* for the country the number is from.
@@ -1455,7 +1457,14 @@
String result = null;
try {
PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso);
- result = util.formatInOriginalFormat(pn, defaultCountryIso);
+ if (KOREA_ISO_COUNTRY_CODE.equals(defaultCountryIso) &&
+ (pn.getCountryCode() == util.getCountryCodeForRegion(KOREA_ISO_COUNTRY_CODE))) {
+ // Format local Korean phone numbers with country code to corresponding national
+ // format which would replace the leading +82 with 0.
+ result = util.format(pn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
+ } else {
+ result = util.formatInOriginalFormat(pn, defaultCountryIso);
+ }
} catch (NumberParseException e) {
}
return result;
diff --git a/tests/UiBench/.gitignore b/tests/UiBench/.gitignore
new file mode 100644
index 0000000..c39eac2
--- /dev/null
+++ b/tests/UiBench/.gitignore
@@ -0,0 +1,5 @@
+.gradle
+.idea
+*.iml
+build
+local.properties
diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk
new file mode 100644
index 0000000..ce9db3d
--- /dev/null
+++ b/tests/UiBench/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# omit gradle 'build' dir
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+
+# use appcompat/support lib from the tree, so improvements/
+# regressions are reflected in test data
+LOCAL_RESOURCE_DIR := \
+ frameworks/support/v7/appcompat/res
+
+LOCAL_AAPT_FLAGS := \
+ --extra-packages android.support.v7.appcompat
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-v4 \
+ android-support-v7-appcompat
+
+LOCAL_PACKAGE_NAME := UiBench
+
+include $(BUILD_PACKAGE)
diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml
new file mode 100644
index 0000000..b19e109
--- /dev/null
+++ b/tests/UiBench/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<!--
+ ~ 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
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.uibench">
+
+ <application
+ android:allowBackup="false"
+ android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
+ <uses-library android:name="android.test.runner" />
+
+ <!-- Root navigation activity -->
+ <activity
+ android:name=".MainActivity"
+ android:label="UiBench">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <!-- Tests -->
+ <activity
+ android:name=".TrivialListActivity"
+ android:label="Microbenchmarks/Trivial ListActivity" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.uibench.TEST" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/UiBench/build.gradle b/tests/UiBench/build.gradle
new file mode 100644
index 0000000..bf0ed11
--- /dev/null
+++ b/tests/UiBench/build.gradle
@@ -0,0 +1,37 @@
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.3.0'
+
+ }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "22.0.0"
+
+ defaultConfig {
+ minSdkVersion 14
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+ }
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ res.srcDirs = ['res']
+ }
+ }
+}
+
+dependencies {
+ // Dependencies enumerated specifically for platform-independent / reproducible builds.
+ compile 'com.android.support:support-v4:23.0.0'
+ compile 'com.android.support:appcompat-v7:23.0.0'
+}
diff --git a/tests/UiBench/gradle/wrapper/gradle-wrapper.jar b/tests/UiBench/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/tests/UiBench/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/tests/UiBench/gradle/wrapper/gradle-wrapper.properties b/tests/UiBench/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..12582f8
--- /dev/null
+++ b/tests/UiBench/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Aug 26 10:51:13 PDT 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
diff --git a/tests/UiBench/src/com/android/test/uibench/MainActivity.java b/tests/UiBench/src/com/android/test/uibench/MainActivity.java
new file mode 100644
index 0000000..7c3391d
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/MainActivity.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test.uibench;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.ListFragment;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MainActivity extends AppCompatActivity {
+ private static final String EXTRA_PATH = "activity_path";
+ private static final String CATEGORY_HWUI_TEST = "com.android.test.uibench.TEST";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent = getIntent();
+ String path = intent.getStringExtra(EXTRA_PATH);
+
+ if (path == null) {
+ path = "";
+ } else {
+ // not root level, display where we are in the hierarchy
+ setTitle(path);
+ }
+
+ FragmentManager fm = getSupportFragmentManager();
+ if (fm.findFragmentById(android.R.id.content) == null) {
+ ListFragment listFragment = new ListFragment() {
+ @Override
+ @SuppressWarnings({ "unchecked" })
+ public void onListItemClick(ListView l, View v, int position, long id) {
+ Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position);
+
+ Intent intent = (Intent) map.get("intent");
+ startActivity(intent);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ getListView().setTextFilterEnabled(true);
+ }
+ };
+ listFragment.setListAdapter(new SimpleAdapter(this, getData(path),
+ android.R.layout.simple_list_item_1, new String[] { "title" },
+ new int[] { android.R.id.text1 }));
+ fm.beginTransaction().add(android.R.id.content, listFragment).commit();
+ }
+ }
+
+ protected List<Map<String, Object>> getData(String prefix) {
+ List<Map<String, Object>> myData = new ArrayList<>();
+
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(CATEGORY_HWUI_TEST);
+
+ PackageManager pm = getPackageManager();
+ List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
+
+ if (null == list)
+ return myData;
+
+ String[] prefixPath;
+ String prefixWithSlash = prefix;
+
+ if (prefix.equals("")) {
+ prefixPath = null;
+ } else {
+ prefixPath = prefix.split("/");
+ prefixWithSlash = prefix + "/";
+ }
+
+ int len = list.size();
+
+ Map<String, Boolean> entries = new HashMap<>();
+
+ for (int i = 0; i < len; i++) {
+ ResolveInfo info = list.get(i);
+ CharSequence labelSeq = info.loadLabel(pm);
+ String label = labelSeq != null
+ ? labelSeq.toString()
+ : info.activityInfo.name;
+
+ if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) {
+
+ String[] labelPath = label.split("/");
+
+ String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];
+
+ if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
+ addItem(myData, nextLabel, activityIntent(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name));
+ } else {
+ if (entries.get(nextLabel) == null) {
+ addItem(myData, nextLabel, browseIntent(prefix.equals("") ?
+ nextLabel : prefix + "/" + nextLabel));
+ entries.put(nextLabel, true);
+ }
+ }
+ }
+ }
+
+ Collections.sort(myData, sDisplayNameComparator);
+
+ return myData;
+ }
+
+ private final static Comparator<Map<String, Object>> sDisplayNameComparator =
+ new Comparator<Map<String, Object>>() {
+ private final Collator collator = Collator.getInstance();
+
+ public int compare(Map<String, Object> map1, Map<String, Object> map2) {
+ return collator.compare(map1.get("title"), map2.get("title"));
+ }
+ };
+
+ protected Intent activityIntent(String pkg, String componentName) {
+ Intent result = new Intent();
+ result.setClassName(pkg, componentName);
+ return result;
+ }
+
+ protected Intent browseIntent(String path) {
+ Intent result = new Intent();
+ result.setClass(this, MainActivity.class);
+ result.putExtra(EXTRA_PATH, path);
+ return result;
+ }
+
+ protected void addItem(List<Map<String, Object>> data, String name, Intent intent) {
+ Map<String, Object> temp = new HashMap<>();
+ temp.put("title", name);
+ temp.put("intent", intent);
+ data.add(temp);
+ }
+}
diff --git a/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java b/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java
new file mode 100644
index 0000000..0af3471
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test.uibench;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.ListFragment;
+import android.support.v7.app.AppCompatActivity;
+import android.widget.ArrayAdapter;
+
+import java.util.Random;
+
+public class TrivialListActivity extends AppCompatActivity {
+ static final int STRING_LENGTH = 10;
+
+ static String[] buildStringList() {
+ String[] strings = new String[200];
+ Random random = new Random(0);
+ for (int i = 0; i < strings.length; i++) {
+ String result = "";
+ for (int j = 0; j < STRING_LENGTH; j++) {
+ // add random letter
+ result += (char)(random.nextInt(26) + 65);
+ }
+ strings[i] = result;
+ }
+ return strings;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ FragmentManager fm = getSupportFragmentManager();
+ if (fm.findFragmentById(android.R.id.content) == null) {
+ ListFragment listFragment = new ListFragment();
+ listFragment.setListAdapter(new ArrayAdapter<>(TrivialListActivity.this,
+ android.R.layout.simple_list_item_1, buildStringList()));
+ fm.beginTransaction().add(android.R.id.content, listFragment).commit();
+ }
+ }
+}
diff --git a/tools/aapt2/Files.cpp b/tools/aapt2/Files.cpp
index 8484148..b24ff6b 100644
--- a/tools/aapt2/Files.cpp
+++ b/tools/aapt2/Files.cpp
@@ -22,7 +22,7 @@
#include <string>
#include <sys/stat.h>
-#ifdef HAVE_MS_C_RUNTIME
+#ifdef _WIN32
// Windows includes.
#include <direct.h>
#endif
@@ -83,7 +83,7 @@
}
inline static int mkdirImpl(const StringPiece& path) {
-#ifdef HAVE_MS_C_RUNTIME
+#ifdef _WIN32
return _mkdir(path.toString().c_str());
#else
return mkdir(path.toString().c_str(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP);
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 62859ec..a8fd91c 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -30,6 +30,7 @@
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.util.DisplayMetrics;
+import android.view.AppTransitionAnimationSpec;
import java.lang.Override;
@@ -241,6 +242,12 @@
}
@Override
+ public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
+ IRemoteCallback callback, boolean scaleUp) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
// TODO Auto-generated method stub
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index b76ec17..567002e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -33,6 +33,7 @@
import org.xmlpull.v1.XmlPullParserException;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
@@ -227,16 +228,18 @@
* Find the background color for this bar from the theme attributes. Only relevant to StatusBar
* and NavigationBar.
* <p/>
- * Returns 0 if not found.
+ * Returns null if not found.
*
* @param colorAttrName the attribute name for the background color
* @param translucentAttrName the attribute name for the translucency property of the bar.
*
* @throws NumberFormatException if color resolved to an invalid string.
*/
- protected int getBarColor(@NonNull String colorAttrName, @NonNull String translucentAttrName) {
+ @Nullable
+ protected Integer getBarColor(@NonNull String colorAttrName,
+ @NonNull String translucentAttrName) {
if (!Config.isGreaterOrEqual(mSimulatedPlatformVersion, LOLLIPOP)) {
- return 0;
+ return null;
}
RenderResources renderResources = getContext().getRenderResources();
// First check if the bar is translucent.
@@ -251,10 +254,11 @@
if (transparent) {
return getColor(renderResources, colorAttrName);
}
- return 0;
+ return null;
}
- private static int getColor(RenderResources renderResources, String attr) {
+ @Nullable
+ private static Integer getColor(RenderResources renderResources, String attr) {
// From ?attr/foo to @color/bar. This is most likely an ItemResourceValue.
ResourceValue resource = renderResources.findItemInTheme(attr, true);
// Form @color/bar to the #AARRGGBB
@@ -275,7 +279,7 @@
}
}
}
- return 0;
+ return null;
}
private ResourceValue getResourceValue(String reference) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
index 9c89bfe2..d50ce23 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -65,8 +65,8 @@
super(context, orientation, getShortestWidth(context)>= 600 ? LAYOUT_600DP_XML : LAYOUT_XML,
"navigation_bar.xml", simulatedPlatformVersion);
- int color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
- setBackgroundColor(color == 0 ? 0xFF000000 : color);
+ Integer color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
+ setBackgroundColor(color == null ? 0xFF000000 : color);
// Cannot access the inside items through id because no R.id values have been
// created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 2dc7c65..95a5a58 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -71,8 +71,9 @@
// FIXME: use FILL_H?
setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
- int color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
- setBackgroundColor(color == 0 ? Config.getStatusBarColor(simulatedPlatformVersion) : color);
+ Integer color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
+ setBackgroundColor(
+ color == null ? Config.getStatusBarColor(simulatedPlatformVersion) : color);
// Cannot access the inside items through id because no R.id values have been
// created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index ac7c409..24e1ce7 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -421,8 +421,7 @@
gc.setComposite(AlphaComposite.Src);
gc.setColor(new Color(0x00000000, true));
- gc.fillRect(0, 0,
- mMeasuredScreenWidth, mMeasuredScreenHeight);
+ gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
// done
gc.dispose();