Merge "UsbAlsaManager: Don't reselect current USB audio device on all USB disconnects"
diff --git a/api/current.txt b/api/current.txt
index e6d088d..9c26faa 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -482,7 +482,7 @@
field public static final int dialogTitle = 16843250; // 0x10101f2
field public static final int digits = 16843110; // 0x1010166
field public static final int direction = 16843217; // 0x10101d1
- field public static final int directionDescriptions = 16843681; // 0x10103a1
+ field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
field public static final int directionPriority = 16843218; // 0x10101d2
field public static final int disableDependentsState = 16843249; // 0x10101f1
field public static final int disabledAlpha = 16842803; // 0x1010033
@@ -1200,7 +1200,7 @@
field public static final int tag = 16842961; // 0x10100d1
field public static final int targetActivity = 16843266; // 0x1010202
field public static final int targetClass = 16842799; // 0x101002f
- field public static final int targetDescriptions = 16843680; // 0x10103a0
+ field public static final deprecated int targetDescriptions = 16843680; // 0x10103a0
field public static final int targetId = 16843740; // 0x10103dc
field public static final int targetName = 16843853; // 0x101044d
field public static final int targetPackage = 16842785; // 0x1010021
@@ -12616,6 +12616,8 @@
field public static final int CAMERA_DISABLED = 1; // 0x1
field public static final int CAMERA_DISCONNECTED = 2; // 0x2
field public static final int CAMERA_ERROR = 3; // 0x3
+ field public static final int CAMERA_IN_USE = 4; // 0x4
+ field public static final int MAX_CAMERAS_IN_USE = 5; // 0x5
}
public abstract class CameraCaptureSession implements java.lang.AutoCloseable {
@@ -12756,7 +12758,10 @@
method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public void registerAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback, android.os.Handler);
+ method public void registerTorchCallback(android.hardware.camera2.CameraManager.TorchCallback, android.os.Handler);
+ method public void setTorchMode(java.lang.String, boolean) throws android.hardware.camera2.CameraAccessException;
method public void unregisterAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback);
+ method public void unregisterTorchCallback(android.hardware.camera2.CameraManager.TorchCallback);
}
public static abstract class CameraManager.AvailabilityCallback {
@@ -12765,6 +12770,13 @@
method public void onCameraUnavailable(java.lang.String);
}
+ public static abstract class CameraManager.TorchCallback {
+ ctor public CameraManager.TorchCallback();
+ method public void onTorchModeAvailable(java.lang.String);
+ method public void onTorchModeChanged(java.lang.String, boolean);
+ method public void onTorchModeUnavailable(java.lang.String);
+ }
+
public abstract class CameraMetadata {
method public java.util.List<TKey> getKeys();
field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1
@@ -16205,6 +16217,7 @@
method public void connect();
method public void disconnect();
method public android.os.Bundle getExtras();
+ method public void getMediaItem(java.lang.String, android.media.browse.MediaBrowser.MediaItemCallback);
method public java.lang.String getRoot();
method public android.content.ComponentName getServiceComponent();
method public android.media.session.MediaSession.Token getSessionToken();
@@ -16234,6 +16247,12 @@
field public static final int FLAG_PLAYABLE = 2; // 0x2
}
+ public static abstract class MediaBrowser.MediaItemCallback {
+ ctor public MediaBrowser.MediaItemCallback();
+ method public void onError();
+ method public void onMediaItemLoaded(android.media.browse.MediaBrowser.MediaItem);
+ }
+
public static abstract class MediaBrowser.SubscriptionCallback {
ctor public MediaBrowser.SubscriptionCallback();
method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -21770,6 +21789,7 @@
field public static final int KITKAT_WATCH = 20; // 0x14
field public static final int LOLLIPOP = 21; // 0x15
field public static final int LOLLIPOP_MR1 = 22; // 0x16
+ field public static final int MNC = 10000; // 0x2710
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -24813,6 +24833,8 @@
field public static final java.lang.String EMAIL = "email";
field public static final java.lang.String EMAIL_ISPRIMARY = "email_isprimary";
field public static final java.lang.String EMAIL_TYPE = "email_type";
+ field public static final java.lang.String EXTRA_ACCOUNT = "android.provider.extra.ACCOUNT";
+ field public static final java.lang.String EXTRA_DATA_SET = "android.provider.extra.DATA_SET";
field public static final java.lang.String FULL_MODE = "full_mode";
field public static final java.lang.String IM_HANDLE = "im_handle";
field public static final java.lang.String IM_ISPRIMARY = "im_isprimary";
@@ -26139,6 +26161,8 @@
}
public static final class Telephony.Threads implements android.provider.Telephony.ThreadsColumns {
+ method public static long getOrCreateThreadId(android.content.Context, java.lang.String);
+ method public static long getOrCreateThreadId(android.content.Context, java.util.Set<java.lang.String>);
field public static final int BROADCAST_THREAD = 1; // 0x1
field public static final int COMMON_THREAD = 0; // 0x0
field public static final android.net.Uri CONTENT_URI;
@@ -27344,6 +27368,7 @@
public abstract class MediaBrowserService extends android.app.Service {
ctor public MediaBrowserService();
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ method public void getMediaItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>) throws java.lang.UnsupportedOperationException;
method public android.media.session.MediaSession.Token getSessionToken();
method public void notifyChildrenChanged(java.lang.String);
method public android.os.IBinder onBind(android.content.Intent);
@@ -34080,6 +34105,7 @@
method public void setOnHoverListener(android.view.View.OnHoverListener);
method public void setOnKeyListener(android.view.View.OnKeyListener);
method public void setOnLongClickListener(android.view.View.OnLongClickListener);
+ method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener);
method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
method public void setOnTouchListener(android.view.View.OnTouchListener);
method public void setOutlineProvider(android.view.ViewOutlineProvider);
@@ -34347,6 +34373,10 @@
method public abstract boolean onLongClick(android.view.View);
}
+ public static abstract interface View.OnScrollChangeListener {
+ method public abstract void onScrollChange(android.view.View, int, int, int, int);
+ }
+
public static abstract interface View.OnSystemUiVisibilityChangeListener {
method public abstract void onSystemUiVisibilityChange(int);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index e6ddb4f..62932fd 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -554,7 +554,7 @@
field public static final int dialogTitle = 16843250; // 0x10101f2
field public static final int digits = 16843110; // 0x1010166
field public static final int direction = 16843217; // 0x10101d1
- field public static final int directionDescriptions = 16843681; // 0x10103a1
+ field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
field public static final int directionPriority = 16843218; // 0x10101d2
field public static final int disableDependentsState = 16843249; // 0x10101f1
field public static final int disabledAlpha = 16842803; // 0x1010033
@@ -1276,7 +1276,7 @@
field public static final int tag = 16842961; // 0x10100d1
field public static final int targetActivity = 16843266; // 0x1010202
field public static final int targetClass = 16842799; // 0x101002f
- field public static final int targetDescriptions = 16843680; // 0x10103a0
+ field public static final deprecated int targetDescriptions = 16843680; // 0x10103a0
field public static final int targetId = 16843740; // 0x10103dc
field public static final int targetName = 16843853; // 0x101044d
field public static final int targetPackage = 16842785; // 0x1010021
@@ -12884,6 +12884,8 @@
field public static final int CAMERA_DISABLED = 1; // 0x1
field public static final int CAMERA_DISCONNECTED = 2; // 0x2
field public static final int CAMERA_ERROR = 3; // 0x3
+ field public static final int CAMERA_IN_USE = 4; // 0x4
+ field public static final int MAX_CAMERAS_IN_USE = 5; // 0x5
}
public abstract class CameraCaptureSession implements java.lang.AutoCloseable {
@@ -13024,7 +13026,10 @@
method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public void registerAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback, android.os.Handler);
+ method public void registerTorchCallback(android.hardware.camera2.CameraManager.TorchCallback, android.os.Handler);
+ method public void setTorchMode(java.lang.String, boolean) throws android.hardware.camera2.CameraAccessException;
method public void unregisterAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback);
+ method public void unregisterTorchCallback(android.hardware.camera2.CameraManager.TorchCallback);
}
public static abstract class CameraManager.AvailabilityCallback {
@@ -13033,6 +13038,13 @@
method public void onCameraUnavailable(java.lang.String);
}
+ public static abstract class CameraManager.TorchCallback {
+ ctor public CameraManager.TorchCallback();
+ method public void onTorchModeAvailable(java.lang.String);
+ method public void onTorchModeChanged(java.lang.String, boolean);
+ method public void onTorchModeUnavailable(java.lang.String);
+ }
+
public abstract class CameraMetadata {
method public java.util.List<TKey> getKeys();
field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1
@@ -17255,6 +17267,7 @@
method public void connect();
method public void disconnect();
method public android.os.Bundle getExtras();
+ method public void getMediaItem(java.lang.String, android.media.browse.MediaBrowser.MediaItemCallback);
method public java.lang.String getRoot();
method public android.content.ComponentName getServiceComponent();
method public android.media.session.MediaSession.Token getSessionToken();
@@ -17284,6 +17297,12 @@
field public static final int FLAG_PLAYABLE = 2; // 0x2
}
+ public static abstract class MediaBrowser.MediaItemCallback {
+ ctor public MediaBrowser.MediaItemCallback();
+ method public void onError();
+ method public void onMediaItemLoaded(android.media.browse.MediaBrowser.MediaItem);
+ }
+
public static abstract class MediaBrowser.SubscriptionCallback {
ctor public MediaBrowser.SubscriptionCallback();
method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -23349,6 +23368,7 @@
field public static final int KITKAT_WATCH = 20; // 0x14
field public static final int LOLLIPOP = 21; // 0x15
field public static final int LOLLIPOP_MR1 = 22; // 0x16
+ field public static final int MNC = 10000; // 0x2710
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -26402,6 +26422,8 @@
field public static final java.lang.String EMAIL = "email";
field public static final java.lang.String EMAIL_ISPRIMARY = "email_isprimary";
field public static final java.lang.String EMAIL_TYPE = "email_type";
+ field public static final java.lang.String EXTRA_ACCOUNT = "android.provider.extra.ACCOUNT";
+ field public static final java.lang.String EXTRA_DATA_SET = "android.provider.extra.DATA_SET";
field public static final java.lang.String FULL_MODE = "full_mode";
field public static final java.lang.String IM_HANDLE = "im_handle";
field public static final java.lang.String IM_ISPRIMARY = "im_isprimary";
@@ -27728,6 +27750,8 @@
}
public static final class Telephony.Threads implements android.provider.Telephony.ThreadsColumns {
+ method public static long getOrCreateThreadId(android.content.Context, java.lang.String);
+ method public static long getOrCreateThreadId(android.content.Context, java.util.Set<java.lang.String>);
field public static final int BROADCAST_THREAD = 1; // 0x1
field public static final int COMMON_THREAD = 0; // 0x0
field public static final android.net.Uri CONTENT_URI;
@@ -28933,6 +28957,7 @@
public abstract class MediaBrowserService extends android.app.Service {
ctor public MediaBrowserService();
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ method public void getMediaItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>) throws java.lang.UnsupportedOperationException;
method public android.media.session.MediaSession.Token getSessionToken();
method public void notifyChildrenChanged(java.lang.String);
method public android.os.IBinder onBind(android.content.Intent);
@@ -30677,6 +30702,7 @@
method public android.telecom.PhoneAccountHandle getConnectionManager();
method public android.telecom.PhoneAccountHandle getDefaultOutgoingPhoneAccount(java.lang.String);
method public android.content.ComponentName getDefaultPhoneApp();
+ method public java.lang.String getLine1Number(android.telecom.PhoneAccountHandle);
method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
@@ -36278,6 +36304,7 @@
method public void setOnHoverListener(android.view.View.OnHoverListener);
method public void setOnKeyListener(android.view.View.OnKeyListener);
method public void setOnLongClickListener(android.view.View.OnLongClickListener);
+ method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener);
method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
method public void setOnTouchListener(android.view.View.OnTouchListener);
method public void setOutlineProvider(android.view.ViewOutlineProvider);
@@ -36545,6 +36572,10 @@
method public abstract boolean onLongClick(android.view.View);
}
+ public static abstract interface View.OnScrollChangeListener {
+ method public abstract void onScrollChange(android.view.View, int, int, int, int);
+ }
+
public static abstract interface View.OnSystemUiVisibilityChangeListener {
method public abstract void onSystemUiVisibilityChange(int);
}
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
index 6550d22..48a34e7 100644
--- a/cmds/bootanimation/bootanimation_main.cpp
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -16,20 +16,14 @@
#define LOG_TAG "BootAnimation"
-#include <cutils/properties.h>
-
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
-
+#include <cutils/properties.h>
+#include <sys/resource.h>
#include <utils/Log.h>
#include <utils/threads.h>
-#if defined(HAVE_PTHREADS)
-# include <pthread.h>
-# include <sys/resource.h>
-#endif
-
#include "BootAnimation.h"
using namespace android;
@@ -38,9 +32,7 @@
int main()
{
-#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
-#endif
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.nobootanimation", value, "0");
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 23b05c4..a09bca1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2373,8 +2373,10 @@
if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) {
return false;
} else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) {
- if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,
- keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE)) {
+ Window w = getWindow();
+ if (w.hasFeature(Window.FEATURE_OPTIONS_PANEL) &&
+ w.performPanelShortcut(Window.FEATURE_OPTIONS_PANEL, keyCode, event,
+ Menu.FLAG_ALWAYS_PERFORM_CLOSE)) {
return true;
}
return false;
@@ -2939,7 +2941,8 @@
* time it needs to be displayed.
*/
public void invalidateOptionsMenu() {
- if (mActionBar == null || !mActionBar.invalidateOptionsMenu()) {
+ if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL) &&
+ (mActionBar == null || !mActionBar.invalidateOptionsMenu())) {
mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
}
}
@@ -3151,7 +3154,8 @@
* open, this method does nothing.
*/
public void openOptionsMenu() {
- if (mActionBar == null || !mActionBar.openOptionsMenu()) {
+ if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL) &&
+ (mActionBar == null || !mActionBar.openOptionsMenu())) {
mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
}
}
@@ -3161,7 +3165,9 @@
* closed, this method does nothing.
*/
public void closeOptionsMenu() {
- mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
+ if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
+ mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
+ }
}
/**
@@ -3220,7 +3226,9 @@
* Programmatically closes the most recently opened context menu, if showing.
*/
public void closeContextMenu() {
- mWindow.closePanel(Window.FEATURE_CONTEXT_MENU);
+ if (mWindow.hasFeature(Window.FEATURE_CONTEXT_MENU)) {
+ mWindow.closePanel(Window.FEATURE_CONTEXT_MENU);
+ }
}
/**
@@ -4607,7 +4615,7 @@
if (Looper.myLooper() != mMainThread.getLooper()) {
throw new IllegalStateException("Must be called from main thread");
}
- mMainThread.requestRelaunchActivity(mToken, null, null, 0, false, null, false);
+ mMainThread.requestRelaunchActivity(mToken, null, null, 0, false, null, null, false);
}
/**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ea37b89..de3c95c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -293,6 +293,7 @@
boolean hideForNow;
Configuration newConfig;
Configuration createdConfig;
+ Configuration overrideConfig;
ActivityClientRecord nextIdle;
ProfilerInfo profilerInfo;
@@ -615,12 +616,13 @@
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
+ @Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
- String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
- PersistableBundle persistentState, List<ResultInfo> pendingResults,
- List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
- ProfilerInfo profilerInfo) {
+ ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
+ CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
+ int procState, Bundle state, PersistableBundle persistentState,
+ List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
+ boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
@@ -644,16 +646,19 @@
r.profilerInfo = profilerInfo;
+ r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
+ @Override
public final void scheduleRelaunchActivity(IBinder token,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
- int configChanges, boolean notResumed, Configuration config) {
+ int configChanges, boolean notResumed, Configuration config,
+ Configuration overrideConfig) {
requestRelaunchActivity(token, pendingResults, pendingNewIntents,
- configChanges, notResumed, config, true);
+ configChanges, notResumed, config, overrideConfig, true);
}
public final void scheduleNewIntent(List<ReferrerIntent> intents, IBinder token) {
@@ -887,6 +892,7 @@
sendMessage(H.LOW_MEMORY, null);
}
+ @Override
public void scheduleActivityConfigurationChanged(IBinder token) {
sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
}
@@ -1668,7 +1674,7 @@
String[] libDirs, int displayId, Configuration overrideConfiguration,
LoadedApk pkgInfo) {
return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
- displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(), null);
+ displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo());
}
final Handler getHandler() {
@@ -2353,7 +2359,8 @@
private Context createBaseContextForActivity(ActivityClientRecord r,
final Activity activity) {
- ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
+ ContextImpl appContext =
+ ContextImpl.createActivityContext(this, r.packageInfo, r.overrideConfig);
appContext.setOuterContext(activity);
Context baseContext = appContext;
@@ -3561,7 +3568,7 @@
// request all activities to relaunch for the changes to take place
for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
- requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, false);
+ requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false);
}
}
}
@@ -3805,7 +3812,7 @@
public final void requestRelaunchActivity(IBinder token,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
int configChanges, boolean notResumed, Configuration config,
- boolean fromServer) {
+ Configuration overrideConfig, boolean fromServer) {
ActivityClientRecord target = null;
synchronized (mResourcesManager) {
@@ -3854,6 +3861,9 @@
if (config != null) {
target.createdConfig = config;
}
+ if (overrideConfig != null) {
+ target.overrideConfig = overrideConfig;
+ }
target.pendingConfigChanges |= configChanges;
}
}
@@ -3966,6 +3976,7 @@
}
}
r.startsNotResumed = tmp.startsNotResumed;
+ r.overrideConfig = tmp.overrideConfig;
handleLaunchActivity(r, currentIntent);
}
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index d0d9d71..e3b27b5 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -799,6 +799,15 @@
mIsStartingTransition = false;
}
+ /**
+ * Cancels any pending transitions and returns true if there is a transition is in
+ * the middle of starting.
+ */
+ protected boolean cancelPendingTransitions() {
+ mPendingTransition = null;
+ return mIsStartingTransition;
+ }
+
protected void moveSharedElementsToOverlay() {
if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) {
return;
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 555d20b..a2bfa4e 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -22,6 +22,7 @@
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.Window;
import java.lang.ref.WeakReference;
@@ -252,7 +253,7 @@
}
}
- public boolean startExitBackTransition(Activity activity) {
+ public boolean startExitBackTransition(final Activity activity) {
if (mEnteringNames == null) {
return false;
} else {
@@ -260,10 +261,11 @@
mHasExited = true;
Transition enterViewsTransition = null;
ViewGroup decor = null;
+ boolean delayExitBack = false;
if (mEnterTransitionCoordinator != null) {
enterViewsTransition = mEnterTransitionCoordinator.getEnterViewsTransition();
decor = mEnterTransitionCoordinator.getDecor();
- mEnterTransitionCoordinator.cancelEnter();
+ delayExitBack = mEnterTransitionCoordinator.cancelEnter();
mEnterTransitionCoordinator = null;
if (enterViewsTransition != null && decor != null) {
enterViewsTransition.pause(decor);
@@ -275,7 +277,23 @@
if (enterViewsTransition != null && decor != null) {
enterViewsTransition.resume(decor);
}
- mReturnExitCoordinator.startExit(activity.mResultCode, activity.mResultData);
+ if (delayExitBack && decor != null) {
+ final ViewGroup finalDecor = decor;
+ decor.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ finalDecor.getViewTreeObserver().removeOnPreDrawListener(this);
+ if (mReturnExitCoordinator != null) {
+ mReturnExitCoordinator.startExit(activity.mResultCode,
+ activity.mResultData);
+ }
+ return true;
+ }
+ });
+ } else {
+ mReturnExitCoordinator.startExit(activity.mResultCode, activity.mResultData);
+ }
}
return true;
}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index eb3ddb2..349b66d 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -140,6 +140,10 @@
int ident = data.readInt();
ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data);
Configuration curConfig = Configuration.CREATOR.createFromParcel(data);
+ Configuration overrideConfig = null;
+ if (data.readInt() != 0) {
+ overrideConfig = Configuration.CREATOR.createFromParcel(data);
+ }
CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
String referrer = data.readString();
IVoiceInteractor voiceInteractor = IVoiceInteractor.Stub.asInterface(
@@ -153,8 +157,8 @@
boolean isForward = data.readInt() != 0;
ProfilerInfo profilerInfo = data.readInt() != 0
? ProfilerInfo.CREATOR.createFromParcel(data) : null;
- scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, referrer,
- voiceInteractor, procState, state, persistentState, ri, pi,
+ scheduleLaunchActivity(intent, b, ident, info, curConfig, overrideConfig, compatInfo,
+ referrer, voiceInteractor, procState, state, persistentState, ri, pi,
notResumed, isForward, profilerInfo);
return true;
}
@@ -167,14 +171,15 @@
List<ReferrerIntent> pi = data.createTypedArrayList(ReferrerIntent.CREATOR);
int configChanges = data.readInt();
boolean notResumed = data.readInt() != 0;
- Configuration config = null;
+ Configuration config = Configuration.CREATOR.createFromParcel(data);
+ Configuration overrideConfig = null;
if (data.readInt() != 0) {
- config = Configuration.CREATOR.createFromParcel(data);
+ overrideConfig = Configuration.CREATOR.createFromParcel(data);
}
- scheduleRelaunchActivity(b, ri, pi, configChanges, notResumed, config);
+ scheduleRelaunchActivity(b, ri, pi, configChanges, notResumed, config, overrideConfig);
return true;
}
-
+
case SCHEDULE_NEW_INTENT_TRANSACTION:
{
data.enforceInterface(IApplicationThread.descriptor);
@@ -775,11 +780,11 @@
}
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
- String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
- PersistableBundle persistentState, List<ResultInfo> pendingResults,
- List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
- ProfilerInfo profilerInfo) throws RemoteException {
+ ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
+ CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
+ int procState, Bundle state, PersistableBundle persistentState,
+ List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
+ boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
intent.writeToParcel(data, 0);
@@ -787,6 +792,12 @@
data.writeInt(ident);
info.writeToParcel(data, 0);
curConfig.writeToParcel(data, 0);
+ if (overrideConfig != null) {
+ data.writeInt(1);
+ overrideConfig.writeToParcel(data, 0);
+ } else {
+ data.writeInt(0);
+ }
compatInfo.writeToParcel(data, 0);
data.writeString(referrer);
data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null);
@@ -810,8 +821,8 @@
public final void scheduleRelaunchActivity(IBinder token,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
- int configChanges, boolean notResumed, Configuration config)
- throws RemoteException {
+ int configChanges, boolean notResumed, Configuration config,
+ Configuration overrideConfig) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
@@ -819,9 +830,10 @@
data.writeTypedList(pendingNewIntents);
data.writeInt(configChanges);
data.writeInt(notResumed ? 1 : 0);
- if (config != null) {
+ config.writeToParcel(data, 0);
+ if (overrideConfig != null) {
data.writeInt(1);
- config.writeToParcel(data, 0);
+ overrideConfig.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
@@ -1112,8 +1124,7 @@
data.recycle();
}
- public final void scheduleActivityConfigurationChanged(
- IBinder token) throws RemoteException {
+ public final void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e9df8c6..39caf0b 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2264,11 +2264,10 @@
}
static ContextImpl createActivityContext(ActivityThread mainThread,
- LoadedApk packageInfo, IBinder activityToken) {
+ LoadedApk packageInfo, Configuration overrideConfiguration) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
- if (activityToken == null) throw new IllegalArgumentException("activityInfo");
- return new ContextImpl(null, mainThread,
- packageInfo, activityToken, null, false, null, null);
+ return new ContextImpl(null, mainThread, packageInfo, null, null, false, null,
+ overrideConfiguration);
}
private ContextImpl(ContextImpl container, ActivityThread mainThread,
@@ -2303,15 +2302,14 @@
Resources resources = packageInfo.getResources(mainThread);
if (resources != null) {
- if (activityToken != null
- || displayId != Display.DEFAULT_DISPLAY
+ if (displayId != Display.DEFAULT_DISPLAY
|| overrideConfiguration != null
|| (compatInfo != null && compatInfo.applicationScale
!= resources.getCompatibilityInfo().applicationScale)) {
resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
- overrideConfiguration, compatInfo, activityToken);
+ overrideConfiguration, compatInfo);
}
}
mResources = resources;
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 12d4513..067073a 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -910,21 +910,27 @@
* @see Activity#openOptionsMenu()
*/
public void openOptionsMenu() {
- mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
+ if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
+ mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
+ }
}
-
+
/**
* @see Activity#closeOptionsMenu()
*/
public void closeOptionsMenu() {
- mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
+ if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
+ mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
+ }
}
/**
* @see Activity#invalidateOptionsMenu()
*/
public void invalidateOptionsMenu() {
- mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
+ if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
+ mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
+ }
}
/**
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index ecf19c7..c053c83 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -18,7 +18,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
-import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.ResultReceiver;
@@ -565,7 +564,12 @@
clearState();
}
- public void cancelEnter() {
+ /**
+ * Cancels the enter transition.
+ * @return True if the enter transition is still pending capturing the target state. If so,
+ * any transition started on the decor will do nothing.
+ */
+ public boolean cancelEnter() {
setGhostVisibility(View.INVISIBLE);
mHasStopped = true;
mIsCanceled = true;
@@ -576,6 +580,7 @@
}
mActivity = null;
clearState();
+ return super.cancelPendingTransitions();
}
private void makeOpaque() {
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 8bf8cd7..f2c912e 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -33,7 +33,6 @@
import android.os.RemoteException;
import android.os.IBinder;
import android.os.IInterface;
-import android.service.voice.IVoiceInteractionSession;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
@@ -59,14 +58,14 @@
throws RemoteException;
void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
- String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
- PersistableBundle persistentState, List<ResultInfo> pendingResults,
- List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
- ProfilerInfo profilerInfo) throws RemoteException;
+ ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
+ CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
+ int procState, Bundle state, PersistableBundle persistentState,
+ List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
+ boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException;
void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
- List<ReferrerIntent> pendingNewIntents, int configChanges,
- boolean notResumed, Configuration config) throws RemoteException;
+ List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed,
+ Configuration config, Configuration overrideConfig) throws RemoteException;
void scheduleNewIntent(List<ReferrerIntent> intent, IBinder token) throws RemoteException;
void scheduleDestroyActivity(IBinder token, boolean finished,
int configChanges) throws RemoteException;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 1691d8e..fac40b2 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -25,7 +25,6 @@
import android.content.res.Resources;
import android.content.res.ResourcesKey;
import android.hardware.display.DisplayManagerGlobal;
-import android.os.IBinder;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Slog;
@@ -38,8 +37,7 @@
/** @hide */
public class ResourcesManager {
static final String TAG = "ResourcesManager";
- static final boolean DEBUG_CACHE = false;
- static final boolean DEBUG_STATS = true;
+ private static final boolean DEBUG = false;
private static ResourcesManager sResourcesManager;
final ArrayMap<ResourcesKey, WeakReference<Resources> > mActiveResources
@@ -51,7 +49,6 @@
CompatibilityInfo mResCompatibilityInfo;
Configuration mResConfiguration;
- final Configuration mTmpConfig = new Configuration();
public static ResourcesManager getInstance() {
synchronized (ResourcesManager.class) {
@@ -144,30 +141,32 @@
* Creates the top level Resources for applications with the given compatibility info.
*
* @param resDir the resource directory.
+ * @param splitResDirs split resource directories.
* @param overlayDirs the resource overlay directories.
* @param libDirs the shared library resource dirs this app references.
- * @param compatInfo the compability info. Must not be null.
- * @param token the application token for determining stack bounds.
+ * @param displayId display Id.
+ * @param overrideConfiguration override configurations.
+ * @param compatInfo the compatibility info. Must not be null.
*/
public Resources getTopLevelResources(String resDir, String[] splitResDirs,
String[] overlayDirs, String[] libDirs, int displayId,
- Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
+ Configuration overrideConfiguration, CompatibilityInfo compatInfo) {
final float scale = compatInfo.applicationScale;
- ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale, token);
+ Configuration overrideConfigCopy = (overrideConfiguration != null)
+ ? new Configuration(overrideConfiguration) : null;
+ ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfigCopy, scale);
Resources r;
synchronized (this) {
// Resources is app scale dependent.
- if (false) {
- Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
- }
+ if (DEBUG) Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
+
WeakReference<Resources> wr = mActiveResources.get(key);
r = wr != null ? wr.get() : null;
//if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
if (r != null && r.getAssets().isUpToDate()) {
- if (false) {
- Slog.w(TAG, "Returning cached resources " + r + " " + resDir
- + ": appScale=" + r.getCompatibilityInfo().applicationScale);
- }
+ if (DEBUG) Slog.w(TAG, "Returning cached resources " + r + " " + resDir
+ + ": appScale=" + r.getCompatibilityInfo().applicationScale
+ + " key=" + key + " overrideConfig=" + overrideConfiguration);
return r;
}
}
@@ -213,7 +212,7 @@
//Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
DisplayMetrics dm = getDisplayMetricsLocked(displayId);
Configuration config;
- boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+ final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
final boolean hasOverrideConfig = key.hasOverrideConfiguration();
if (!isDefaultDisplay || hasOverrideConfig) {
config = new Configuration(getConfiguration());
@@ -222,16 +221,14 @@
}
if (hasOverrideConfig) {
config.updateFrom(key.mOverrideConfiguration);
+ if (DEBUG) Slog.v(TAG, "Applied overrideConfig=" + key.mOverrideConfiguration);
}
} else {
config = getConfiguration();
}
- r = new Resources(assets, dm, config, compatInfo, token);
- if (false) {
- Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
- + r.getConfiguration() + " appScale="
- + r.getCompatibilityInfo().applicationScale);
- }
+ r = new Resources(assets, dm, config, compatInfo);
+ if (DEBUG) Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
+ + r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale);
synchronized (this) {
WeakReference<Resources> wr = mActiveResources.get(key);
@@ -244,7 +241,8 @@
}
// XXX need to remove entries when weak references go away
- mActiveResources.put(key, new WeakReference<Resources>(r));
+ mActiveResources.put(key, new WeakReference<>(r));
+ if (DEBUG) Slog.v(TAG, "mActiveResources.size()=" + mActiveResources.size());
return r;
}
}
@@ -255,7 +253,7 @@
mResConfiguration = new Configuration();
}
if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
+ if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
+ mResConfiguration.seq + ", newSeq=" + config.seq);
return false;
}
@@ -287,7 +285,7 @@
ResourcesKey key = mActiveResources.keyAt(i);
Resources r = mActiveResources.valueAt(i).get();
if (r != null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
+ if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
+ r + " config to: " + config);
int displayId = key.mDisplayId;
boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index d7d9e8b..5c09b42 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3082,6 +3082,12 @@
a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
}
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestActivity_primaryUserOnly,
+ false)) {
+ a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
+ }
+
if (!receiver) {
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
@@ -3153,11 +3159,6 @@
setExported = true;
}
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_primaryUserOnly,
- false)) {
- a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
- }
}
sa.recycle();
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c931c01..6fb7299 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -141,9 +141,6 @@
private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
- @SuppressWarnings("unused")
- private WeakReference<IBinder> mToken;
-
static {
sPreloadedDrawables = new LongSparseArray[2];
sPreloadedDrawables[0] = new LongSparseArray<ConstantState>();
@@ -224,46 +221,44 @@
/**
* Create a new Resources object on top of an existing set of assets in an
* AssetManager.
- *
- * @param assets Previously created AssetManager.
- * @param metrics Current display metrics to consider when
+ *
+ * @param assets Previously created AssetManager.
+ * @param metrics Current display metrics to consider when
* selecting/computing resource values.
- * @param config Desired device configuration to consider when
+ * @param config Desired device configuration to consider when
* selecting/computing resource values (optional).
*/
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
- this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+ this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
}
/**
* Creates a new Resources object with CompatibilityInfo.
- *
- * @param assets Previously created AssetManager.
- * @param metrics Current display metrics to consider when
+ *
+ * @param assets Previously created AssetManager.
+ * @param metrics Current display metrics to consider when
* selecting/computing resource values.
- * @param config Desired device configuration to consider when
+ * @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 token The Activity token for determining stack affiliation. Usually null.
* @hide
*/
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config,
- CompatibilityInfo compatInfo, IBinder token) {
+ CompatibilityInfo compatInfo) {
mAssets = assets;
mMetrics.setToDefaults();
if (compatInfo != null) {
mCompatibilityInfo = compatInfo;
}
- mToken = new WeakReference<IBinder>(token);
updateConfiguration(config, metrics);
assets.ensureStringBlocks();
}
/**
* Return a global shared Resources object that provides access to only
- * system resources (no application resources), and is not configured for
- * the current screen (can not use dimension units, does not change based
- * on orientation, etc).
+ * system resources (no application resources), and is not configured for
+ * the current screen (can not use dimension units, does not change based
+ * on orientation, etc).
*/
public static Resources getSystem() {
synchronized (sSync) {
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 4ae3825..9548d49 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -16,27 +16,23 @@
package android.content.res;
-import android.os.IBinder;
+import java.util.Objects;
/** @hide */
public final class ResourcesKey {
- final String mResDir;
- final float mScale;
+ private final String mResDir;
+ private final float mScale;
private final int mHash;
- private final IBinder mToken;
public final int mDisplayId;
- public final Configuration mOverrideConfiguration = new Configuration();
+ public final Configuration mOverrideConfiguration;
public ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration,
- float scale, IBinder token) {
+ float scale) {
mResDir = resDir;
mDisplayId = displayId;
- if (overrideConfiguration != null) {
- mOverrideConfiguration.setTo(overrideConfiguration);
- }
+ mOverrideConfiguration = overrideConfiguration;
mScale = scale;
- mToken = token;
int hash = 17;
hash = 31 * hash + (mResDir == null ? 0 : mResDir.hashCode());
@@ -48,7 +44,8 @@
}
public boolean hasOverrideConfiguration() {
- return !Configuration.EMPTY.equals(mOverrideConfiguration);
+ return mOverrideConfiguration != null
+ && !Configuration.EMPTY.equals(mOverrideConfiguration);
}
@Override
@@ -63,17 +60,9 @@
}
ResourcesKey peer = (ResourcesKey) obj;
- if ((mResDir == null) && (peer.mResDir != null)) {
+ if (!Objects.equals(mResDir, peer.mResDir)) {
return false;
}
- if ((mResDir != null) && (peer.mResDir == null)) {
- return false;
- }
- if ((mResDir != null) && (peer.mResDir != null)) {
- if (!mResDir.equals(peer.mResDir)) {
- return false;
- }
- }
if (mDisplayId != peer.mDisplayId) {
return false;
}
diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java
index 91ef6ca..84e9912 100644
--- a/core/java/android/hardware/camera2/CameraAccessException.java
+++ b/core/java/android/hardware/camera2/CameraAccessException.java
@@ -28,16 +28,14 @@
*/
public class CameraAccessException extends AndroidException {
/**
- * The camera device is in use already
- * @hide
+ * The camera device is in use already.
*/
public static final int CAMERA_IN_USE = 4;
/**
- * The system-wide limit for number of open cameras has been reached,
- * and more camera devices cannot be opened until previous instances are
- * closed.
- * @hide
+ * The system-wide limit for number of open cameras or camera resources has
+ * been reached, and more camera devices cannot be opened or torch mode
+ * cannot be turned on until previous instances are closed.
*/
public static final int MAX_CAMERAS_IN_USE = 5;
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index b6bb33b..8af3c15 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -109,8 +109,11 @@
* of the state of individual CameraManager instances.</p>
*
* @param callback the new callback to send camera availability notices to
- * @param handler The handler on which the callback should be invoked, or
- * {@code null} to use the current thread's {@link android.os.Looper looper}.
+ * @param handler The handler on which the callback should be invoked, or {@code null} to use
+ * the current thread's {@link android.os.Looper looper}.
+ *
+ * @throws IllegalArgumentException if the handler is {@code null} but the current thread has
+ * no looper.
*/
public void registerAvailabilityCallback(AvailabilityCallback callback, Handler handler) {
if (handler == null) {
@@ -138,6 +141,42 @@
}
/**
+ * Register a callback to be notified about torch mode status.
+ *
+ * <p>Registering the same callback again will replace the handler with the
+ * new one provided.</p>
+ *
+ * <p>The first time a callback is registered, it is immediately called
+ * with the torch mode status of all currently known camera devices.</p>
+ *
+ * <p>Since this callback will be registered with the camera service, remember to unregister it
+ * once it is no longer needed; otherwise the callback will continue to receive events
+ * indefinitely and it may prevent other resources from being released. Specifically, the
+ * callbacks will be invoked independently of the general activity lifecycle and independently
+ * of the state of individual CameraManager instances.</p>
+ *
+ * @param callback The new callback to send torch mode status to
+ * @param handler The handler on which the callback should be invoked, or {@code null} to use
+ * the current thread's {@link android.os.Looper looper}.
+ *
+ * @throws IllegalArgumentException if the handler is {@code null} but the current thread has
+ * no looper.
+ */
+ public void registerTorchCallback(TorchCallback callback, Handler handler) {
+ }
+
+ /**
+ * Remove a previously-added callback; the callback will no longer receive torch mode status
+ * callbacks.
+ *
+ * <p>Removing a callback that isn't registered has no effect.</p>
+ *
+ * @param callback The callback to remove from the notification list
+ */
+ public void unregisterTorchCallback(TorchCallback callback) {
+ }
+
+ /**
* <p>Query the capabilities of a camera device. These capabilities are
* immutable for a given camera.</p>
*
@@ -384,6 +423,47 @@
}
/**
+ * Set the flash unit's torch mode of the camera of the given ID without opening the camera
+ * device.
+ *
+ * <p>Use {@link #getCameraIdList} to get the list of available camera devices and use
+ * {@link #getCameraCharacteristics} to check whether the camera device has a flash unit.
+ * Note that even if a camera device has a flash unit, turning on the torch mode may fail
+ * if the camera device or other camera resources needed to turn on the torch mode are in use.
+ * </p>
+ *
+ * <p> If {@link #setTorchMode} is called to turn on or off the torch mode successfully,
+ * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked.
+ * However, even if turning on the torch mode is successful, the application does not have the
+ * exclusive ownership of the flash unit or the camera device. The torch mode will be turned
+ * off and becomes unavailable when the camera device that the flash unit belongs to becomes
+ * unavailable ({@link CameraManager.TorchCallback#onTorchModeAvailable} will be
+ * invoked) or when other camera resources to keep the torch on become unavailable (
+ * {@link CameraManager.TorchCallback#onTorchModeUnavailable} will be invoked). Also,
+ * other applications are free to call {@link #setTorchMode} to turn off the torch mode (
+ * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked).
+ *
+ * @param cameraId
+ * The unique identifier of the camera device that the flash unit belongs to.
+ * @param enabled
+ * The desired state of the torch mode for the target camera device. Set to
+ * {@code true} to turn on the torch mode. Set to {@code false} to turn off the
+ * torch mode.
+ *
+ * @throws CameraAccessException if it failed to access the flash unit.
+ * {@link CameraAccessException#CAMERA_IN_USE} will be thrown if the camera device
+ * is in use. {@link CameraAccessException#MAX_CAMERAS_IN_USE} will be thrown if
+ * other camera resources needed to turn on the torch mode are in use.
+ *
+ * @throws IllegalArgumentException if cameraId was null, cameraId doesn't match any currently
+ * or previously available camera device, or the camera device doesn't have a
+ * flash unit.
+ */
+ public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException {
+
+ }
+
+ /**
* A callback for camera devices becoming available or
* unavailable to open.
*
@@ -428,6 +508,68 @@
}
/**
+ * A callback for camera flash torch modes becoming available, unavailable, enabled, or
+ * disabled.
+ *
+ * <p>The torch mode becomes available when the camera device it belongs to is no longer in use
+ * and other camera resources it needs are no longer busy. It becomes unavailable when the
+ * camera device it belongs to becomes unavailable or other camera resouces it needs become
+ * busy due to other higher priority camera activities. The torch mode changes when an
+ * application calls {@link #setTorchMode} successfully.
+ *
+ * <p>Extend this callback and pass an instance of the subclass to
+ * {@link CameraManager#registerTorchCallback} to be notified of such status changes.
+ * </p>
+ *
+ * @see registerTorchCallback
+ */
+ public static abstract class TorchCallback {
+ /**
+ * The torch mode of a camera has become available to use.
+ *
+ * <p>The default implementation of this method does nothing.</p>
+ *
+ * @param cameraId The unique identifier of the camera whose torch mode has become
+ * available.
+ */
+ public void onTorchModeAvailable(String cameraId) {
+ // default empty implementation
+ }
+
+ /**
+ * A previously-available torch mode of a camera has become unavailable.
+ *
+ * <p>If torch mode was previously turned on by calling {@link #setTorchMode}, it will be
+ * turned off before {@link CameraManager.TorchCallback#onTorchModeUnavailable} is
+ * invoked. {@link #setTorchMode} will fail until the flash unit becomes available again.
+ * </p>
+ *
+ * <p>The default implementation of this method does nothing.</p>
+ *
+ * @param cameraId The unique identifier of the camera whose torch mode has become
+ * unavailable.
+ */
+ public void onTorchModeUnavailable(String cameraId) {
+ // default empty implementation
+ }
+
+ /**
+ * Torch mode of a camera has been turned on or off through {@link #setTorchMode}.
+ *
+ * <p>The default implementation of this method does nothing.</p>
+ *
+ * @param cameraId The unique identifier of the camera whose torch mode has been changed.
+ *
+ * @param enabled The state that the torch mode of the camera has been changed to.
+ * {@code true} when the torch mode has been turned on. {@code false} when
+ * the torch mode has been turned off.
+ */
+ public void onTorchModeChanged(String cameraId, boolean enabled) {
+ // default empty implementation
+ }
+ }
+
+ /**
* Return or create the list of currently connected camera devices.
*
* <p>In case of errors connecting to the camera service, will return an empty list.</p>
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 03540e1..347db05 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -328,15 +328,15 @@
appendStreamConfig(availableStreamConfigs,
ImageFormat.YUV_420_888, previewSizes);
for (int format : p.getSupportedPreviewFormats()) {
- if (ImageFormat.isPublicFormat(format)) {
+ if (ImageFormat.isPublicFormat(format) && format != ImageFormat.NV21) {
appendStreamConfig(availableStreamConfigs, format, previewSizes);
- } else {
+ } else if (VERBOSE) {
/*
* Do not add any formats unknown to us
* (since it would fail runtime checks in StreamConfigurationMap)
*/
- Log.w(TAG,
- String.format("mapStreamConfigs - Skipping non-public format %x", format));
+ Log.v(TAG,
+ String.format("mapStreamConfigs - Skipping format %x", format));
}
}
@@ -389,8 +389,8 @@
int j = 0;
for (String mode : antiBandingModes) {
int convertedMode = convertAntiBandingMode(mode);
- if (convertedMode == -1) {
- Log.w(TAG, "Antibanding mode " + ((mode == null) ? "NULL" : mode) +
+ if (VERBOSE && convertedMode == -1) {
+ Log.v(TAG, "Antibanding mode " + ((mode == null) ? "NULL" : mode) +
" not supported, skipping...");
} else {
modes[j++] = convertedMode;
diff --git a/core/java/android/hardware/camera2/utils/ArrayUtils.java b/core/java/android/hardware/camera2/utils/ArrayUtils.java
index 5a78bbd..79a335c 100644
--- a/core/java/android/hardware/camera2/utils/ArrayUtils.java
+++ b/core/java/android/hardware/camera2/utils/ArrayUtils.java
@@ -117,7 +117,7 @@
// Guard against unexpected values
if (strIndex < 0) {
- Log.w(TAG, "Ignoring invalid value " + str);
+ if (VERBOSE) Log.v(TAG, "Ignoring invalid value " + str);
continue;
}
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index f64ef87..f283051 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -68,6 +68,8 @@
* accessory function is enabled
* <li> {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the
* audio source function is enabled
+ * <li> {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the
+ * MIDI function is enabled
* </ul>
*
* {@hide}
@@ -188,6 +190,14 @@
public static final String USB_FUNCTION_AUDIO_SOURCE = "audio_source";
/**
+ * Name of the MIDI USB function.
+ * Used in extras for the {@link #ACTION_USB_STATE} broadcast
+ *
+ * {@hide}
+ */
+ public static final String USB_FUNCTION_MIDI = "midi";
+
+ /**
* Name of the Accessory USB function.
* Used in extras for the {@link #ACTION_USB_STATE} broadcast
*
diff --git a/core/java/android/midi/MidiInputPort.java b/core/java/android/midi/MidiInputPort.java
index 5d806cf8..88ace5f 100644
--- a/core/java/android/midi/MidiInputPort.java
+++ b/core/java/android/midi/MidiInputPort.java
@@ -33,7 +33,7 @@
private final FileOutputStream mOutputStream;
// buffer to use for sending messages out our output stream
- private final byte[] mBuffer = new byte[MAX_PACKED_MESSAGE_SIZE];
+ private final byte[] mBuffer = new byte[MAX_PACKET_SIZE];
/* package */ MidiInputPort(ParcelFileDescriptor pfd, int portNumber) {
super(portNumber);
@@ -50,10 +50,19 @@
* {@link java.lang.System#nanoTime}
*/
public void onPost(byte[] msg, int offset, int count, long timestamp) throws IOException {
+ assert(offset >= 0 && count >= 0 && offset + count <= msg.length);
+
synchronized (mBuffer) {
- int length = packMessage(msg, offset, count, timestamp, mBuffer);
try {
- mOutputStream.write(mBuffer, 0, length);
+ while (count > 0) {
+ int length = packMessage(msg, offset, count, timestamp, mBuffer);
+ mOutputStream.write(mBuffer, 0, length);
+ int sent = getMessageSize(mBuffer, length);
+ assert(sent >= 0 && sent <= length);
+
+ offset += sent;
+ count -= sent;
+ }
} catch (IOException e) {
IoUtils.closeQuietly(mOutputStream);
// report I/O failure
diff --git a/core/java/android/midi/MidiOutputPort.java b/core/java/android/midi/MidiOutputPort.java
index b550ed4..00b7bad 100644
--- a/core/java/android/midi/MidiOutputPort.java
+++ b/core/java/android/midi/MidiOutputPort.java
@@ -45,7 +45,7 @@
private final Thread mThread = new Thread() {
@Override
public void run() {
- byte[] buffer = new byte[MAX_PACKED_MESSAGE_SIZE];
+ byte[] buffer = new byte[MAX_PACKET_SIZE];
ArrayList<MidiReceiver> deadReceivers = new ArrayList<MidiReceiver>();
try {
@@ -54,9 +54,6 @@
int count = mInputStream.read(buffer);
if (count < 0) {
break;
- } else if (count < MIN_PACKED_MESSAGE_SIZE || count > MAX_PACKED_MESSAGE_SIZE) {
- Log.e(TAG, "Number of bytes read out of range: " + count);
- continue;
}
int offset = getMessageOffset(buffer, count);
@@ -96,7 +93,6 @@
}
};
-
/* package */ MidiOutputPort(ParcelFileDescriptor pfd, int portNumber) {
super(portNumber);
mInputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
diff --git a/core/java/android/midi/MidiPort.java b/core/java/android/midi/MidiPort.java
index 1fa7946..44d1a88 100644
--- a/core/java/android/midi/MidiPort.java
+++ b/core/java/android/midi/MidiPort.java
@@ -32,16 +32,19 @@
private final int mPortNumber;
/**
- * Minimum size of packed message as sent through our ParcelFileDescriptor
- * 8 bytes for timestamp and 1 to 3 bytes for message
+ * Maximum size of a packet that can pass through our ParcelFileDescriptor
*/
- protected static final int MIN_PACKED_MESSAGE_SIZE = 9;
+ protected static final int MAX_PACKET_SIZE = 1024;
/**
- * Maximum size of packed message as sent through our ParcelFileDescriptor
- * 8 bytes for timestamp and 1 to 3 bytes for message
+ * size of message timestamp in bytes
*/
- protected static final int MAX_PACKED_MESSAGE_SIZE = 11;
+ private static final int TIMESTAMP_SIZE = 8;
+
+ /**
+ * Maximum amount of MIDI data that can be included in a packet
+ */
+ public static final int MAX_PACKET_DATA_SIZE = MAX_PACKET_SIZE - TIMESTAMP_SIZE;
/* package */ MidiPort(int portNumber) {
@@ -76,49 +79,52 @@
*/
protected static int packMessage(byte[] message, int offset, int size, long timestamp,
byte[] dest) {
- // pack variable length message first
+ if (size + TIMESTAMP_SIZE > MAX_PACKET_SIZE) {
+ size = MAX_PACKET_SIZE - TIMESTAMP_SIZE;
+ }
+ // message data goes first
System.arraycopy(message, offset, dest, 0, size);
- int destOffset = size;
- // timestamp takes 8 bytes
- for (int i = 0; i < 8; i++) {
- dest[destOffset++] = (byte)timestamp;
+
+ // followed by timestamp
+ for (int i = 0; i < TIMESTAMP_SIZE; i++) {
+ dest[size++] = (byte)timestamp;
timestamp >>= 8;
}
- return destOffset;
+ return size;
}
/**
- * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
- * returns the offet of of MIDI message in packed buffer
+ * Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
+ * returns the offset of the MIDI message in packed buffer
*/
protected static int getMessageOffset(byte[] buffer, int bufferLength) {
- // message is at start of buffer
+ // message is at the beginning
return 0;
}
/**
- * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
- * returns size of MIDI message in packed buffer
+ * Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
+ * returns size of MIDI data in packed buffer
*/
protected static int getMessageSize(byte[] buffer, int bufferLength) {
- // message length is total buffer length minus size of the timestamp and port number
- return bufferLength - 8 /* sizeof(timestamp) */;
+ // message length is total buffer length minus size of the timestamp
+ return bufferLength - TIMESTAMP_SIZE;
}
/**
- * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
+ * Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
* unpacks timestamp from packed buffer
*/
protected static long getMessageTimeStamp(byte[] buffer, int bufferLength) {
+ // timestamp is at end of the packet
+ int offset = bufferLength;
long timestamp = 0;
- // timestamp follows variable length message data
- int dataLength = getMessageSize(buffer, bufferLength);
- for (int i = dataLength + 7; i >= dataLength; i--) {
- int b = (int)buffer[i] & 0xFF;
+ for (int i = 0; i < TIMESTAMP_SIZE; i++) {
+ int b = (int)buffer[--offset] & 0xFF;
timestamp = (timestamp << 8) | b;
}
return timestamp;
- }
+ }
}
diff --git a/core/java/android/midi/MidiReceiver.java b/core/java/android/midi/MidiReceiver.java
index 0b183cc..a4e1a10 100644
--- a/core/java/android/midi/MidiReceiver.java
+++ b/core/java/android/midi/MidiReceiver.java
@@ -30,6 +30,8 @@
* NOTE: the msg array parameter is only valid within the context of this call.
* The msg bytes should be copied by the receiver rather than retaining a reference
* to this parameter.
+ * Also, modifying the contents of the msg array parameter may result in other receivers
+ * in the same application receiving incorrect values in their onPost() method.
*
* @param msg a byte array containing the MIDI message
* @param offset the offset of the first byte of the message in the byte array
diff --git a/core/java/android/midi/MidiUtils.java b/core/java/android/midi/MidiUtils.java
deleted file mode 100644
index e60e2db..0000000
--- a/core/java/android/midi/MidiUtils.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.midi;
-
-import android.util.Log;
-
-/**
- * Class containing miscellaneous MIDI utilities.
- *
- * @hide
- */
-public final class MidiUtils {
- private static final String TAG = "MidiUtils";
-
- private MidiUtils() { }
-
- /**
- * Returns data size of a MIDI message based on the message's command byte
- * @param b the message command byte
- * @return the message's data length
- */
- public static int getMessageDataSize(byte b) {
- switch (b & 0xF0) {
- case 0x80:
- case 0x90:
- case 0xA0:
- case 0xB0:
- case 0xE0:
- return 2;
- case 0xC0:
- case 0xD0:
- return 1;
- case 0xF0:
- switch (b & 0x0F) {
- case 0x00:
- Log.e(TAG, "System Exclusive not supported yet");
- return -1;
- case 0x01:
- case 0x03:
- return 1;
- case 0x02:
- return 2;
- default:
- return 0;
- }
- default:
- Log.e(TAG, "unknown MIDI command " + b);
- return -1;
- }
- }
-}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 2dfd919..e4b594a 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -597,6 +597,11 @@
* Lollipop with an extra sugar coating on the outside!
*/
public static final int LOLLIPOP_MR1 = 22;
+
+ /**
+ * M comes after L.
+ */
+ public static final int MNC = CUR_DEVELOPMENT;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d24e614..7dd559c 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8709,10 +8709,8 @@
* dialog to chose an account
* <p>
* Type: {@link Account}
- *
- * @hide
*/
- public static final String ACCOUNT = "com.android.contacts.extra.ACCOUNT";
+ public static final String EXTRA_ACCOUNT = "android.provider.extra.ACCOUNT";
/**
* Used to specify the data set within the account in which to create the
@@ -8722,10 +8720,8 @@
* created in the base account, with no data set.
* <p>
* Type: String
- *
- * @hide
*/
- public static final String DATA_SET = "com.android.contacts.extra.DATA_SET";
+ public static final String EXTRA_DATA_SET = "android.provider.extra.DATA_SET";
}
}
}
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index b18cc3b..ed2d3c6 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -19,6 +19,8 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
import android.net.SntpClient;
import android.os.SystemClock;
import android.provider.Settings;
@@ -35,10 +37,13 @@
private static final boolean LOGD = false;
private static NtpTrustedTime sSingleton;
+ private static Context sContext;
private final String mServer;
private final long mTimeout;
+ private ConnectivityManager mCM;
+
private boolean mHasCache;
private long mCachedNtpTime;
private long mCachedNtpElapsedRealtime;
@@ -67,6 +72,7 @@
final String server = secureServer != null ? secureServer : defaultServer;
sSingleton = new NtpTrustedTime(server, timeout);
+ sContext = context;
}
return sSingleton;
@@ -79,6 +85,20 @@
return false;
}
+ // We can't do this at initialization time: ConnectivityService might not be running yet.
+ synchronized (this) {
+ if (mCM == null) {
+ mCM = (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+ }
+
+ final NetworkInfo ni = mCM == null ? null : mCM.getActiveNetworkInfo();
+ if (ni == null || !ni.isConnected()) {
+ if (LOGD) Log.d(TAG, "forceRefresh: no connectivity");
+ return false;
+ }
+
+
if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
final SntpClient client = new SntpClient();
if (client.requestTime(mServer, (int) mTimeout)) {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 7b20e72..743f6b7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -81,7 +81,7 @@
void addAppToken(int addPos, IApplicationToken token, int groupId, int stackId,
int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
int configChanges, boolean voiceInteraction, boolean launchTaskBehind);
- void setAppGroupId(IBinder token, int groupId);
+ void setAppTask(IBinder token, int taskId);
void setAppOrientation(IApplicationToken token, int requestedOrientation);
int getAppOrientation(IApplicationToken token);
void setFocusedApp(IBinder token, boolean moveFocusNow);
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 7b13e84..d08ab46 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -188,9 +188,6 @@
void wallpaperCommandComplete(IBinder window, in Bundle result);
- void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
- float dsdx, float dtdx, float dsdy, float dtdy);
-
/**
* Notifies that a rectangle on the screen has been requested.
*/
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1e6f6c9..259367e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4569,11 +4569,18 @@
}
/**
- * Register a callback to be invoked when the scroll position of this view
- * changed.
+ * Register a callback to be invoked when the scroll X or Y positions of
+ * this view change.
+ * <p>
+ * <b>Note:</b> Some views handle scrolling independently from View and may
+ * have their own separate listeners for scroll-type events. For example,
+ * {@link android.widget.ListView ListView} allows clients to register an
+ * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
+ * to listen for changes in list scroll position.
*
- * @param l The callback that will run.
- * @hide Only used internally.
+ * @param l The listener to notify when the scroll X or Y position changes.
+ * @see android.view.View#getScrollX()
+ * @see android.view.View#getScrollY()
*/
public void setOnScrollChangeListener(OnScrollChangeListener l) {
getListenerInfo().mOnScrollChangeListener = l;
@@ -5896,23 +5903,6 @@
return true;
}
- /**
- * Adds the clickable rectangles withing the bounds of this view. They
- * may overlap. This method is intended for use only by the accessibility
- * layer.
- *
- * @param outRects List to which to add clickable areas.
- *
- * @hide
- */
- public void addClickableRectsForAccessibility(List<RectF> outRects) {
- if (isClickable() || isLongClickable()) {
- RectF bounds = new RectF();
- bounds.set(0, 0, getWidth(), getHeight());
- outRects.add(bounds);
- }
- }
-
static void offsetRects(List<RectF> rects, float offsetX, float offsetY) {
final int rectCount = rects.size();
for (int i = 0; i < rectCount; i++) {
@@ -9959,9 +9949,15 @@
/**
* Interface definition for a callback to be invoked when the scroll
- * position of a view changes.
+ * X or Y positions of a view change.
+ * <p>
+ * <b>Note:</b> Some views handle scrolling independently from View and may
+ * have their own separate listeners for scroll-type events. For example,
+ * {@link android.widget.ListView ListView} allows clients to register an
+ * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
+ * to listen for changes in list scroll position.
*
- * @hide Only used internally.
+ * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
*/
public interface OnScrollChangeListener {
/**
@@ -16642,6 +16638,7 @@
if (changed) {
requestLayout();
+ invalidateOutline();
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index ee9845f..49e4efa 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -857,27 +857,11 @@
// Compute the intersection between the child and the sibling.
if (siblingBounds.intersect(bounds)) {
- List<RectF> clickableRects = new ArrayList<>();
- sibling.addClickableRectsForAccessibility(clickableRects);
-
- final int clickableRectCount = clickableRects.size();
- for (int j = 0; j < clickableRectCount; j++) {
- RectF clickableRect = clickableRects.get(j);
-
- // Translate the clickable rect to our coordinates.
- offsetChildRectToMyCoords(clickableRect, sibling);
-
- // Compute the intersection between the child and the clickable rects.
- if (clickableRect.intersect(bounds)) {
- // If a clickable rect completely covers the child, done.
- if (clickableRect.equals(bounds)) {
- releaseOrderedChildIterator();
- return false;
- }
- // Keep track of the intersection rectangle.
- intersections.add(clickableRect);
- }
- }
+ // Conservatively we consider an overlapping sibling to be
+ // interactive and ignore it. This is not ideal as if the
+ // sibling completely covers the view despite handling no
+ // touch events we will not be able to click on the view.
+ intersections.add(siblingBounds);
}
}
@@ -892,54 +876,6 @@
return true;
}
- /**
- * @hide
- */
- @Override
- public void addClickableRectsForAccessibility(List<RectF> outRects) {
- int sizeBefore = outRects.size();
-
- super.addClickableRectsForAccessibility(outRects);
-
- // If we added ourselves, then no need to visit children.
- if (outRects.size() > sizeBefore) {
- return;
- }
-
- Iterator<View> iterator = obtainOrderedChildIterator();
- while (iterator.hasNext()) {
- View child = iterator.next();
-
- // Cannot click on an invisible view.
- if (!isVisible(child)) {
- continue;
- }
-
- sizeBefore = outRects.size();
-
- // Add clickable rects in the child bounds.
- child.addClickableRectsForAccessibility(outRects);
-
- // Offset the clickable rects for out children to our coordinates.
- final int sizeAfter = outRects.size();
- for (int j = sizeBefore; j < sizeAfter; j++) {
- RectF rect = outRects.get(j);
-
- // Translate the clickable rect to our coordinates.
- offsetChildRectToMyCoords(rect, child);
-
- // If a clickable rect fills the parent, done.
- if ((int) rect.left == 0 && (int) rect.top == 0
- && (int) rect.right == mRight && (int) rect.bottom == mBottom) {
- releaseOrderedChildIterator();
- return;
- }
- }
- }
-
- releaseOrderedChildIterator();
- }
-
private void offsetChildRectToMyCoords(RectF rect, View child) {
if (!child.hasIdentityMatrix()) {
child.getMatrix().mapRect(rect);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 87d9a58..151ff83 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1326,6 +1326,11 @@
}
}
+ // Non-visible windows can't hold accessibility focus.
+ if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
+ host.clearAccessibilityFocus();
+ }
+
// Execute enqueued actions on every traversal in case a detached view enqueued an action
getRunQueue().executeActions(mAttachInfo.mHandler);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 094a8a1..12b310f 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -501,13 +501,6 @@
public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24;
/**
- * Window type: Behind the universe of the real windows.
- * In multiuser systems shows on all users' windows.
- * @hide
- */
- public static final int TYPE_UNIVERSE_BACKGROUND = FIRST_SYSTEM_WINDOW+25;
-
- /**
* Window type: Display overlay window. Used to simulate secondary display devices.
* In multiuser systems shows on all users' windows.
* @hide
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index b8e94ee..ff1fde7 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -579,13 +579,6 @@
public int getMaxWallpaperLayer();
/**
- * Return the window layer at which windows appear above the normal
- * universe (that is no longer impacted by the universe background
- * transform).
- */
- public int getAboveUniverseLayer();
-
- /**
* Return the display width available after excluding any screen
* decorations that can never be removed. That is, system bar or
* button bar.
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index b5afdf7..6096d7d 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -721,7 +721,7 @@
* @return Whether the refresh succeeded.
*/
public boolean refresh() {
- return refresh(false);
+ return refresh(true);
}
/**
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index c6c979e..f1fa1b6 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -762,18 +762,6 @@
awakenScrollBars();
}
- /**
- * @hide
- */
- @Override
- public void addClickableRectsForAccessibility(List<RectF> outRects) {
- // This class always consumes touch events, therefore if it
- // covers a view we do not want to send a click over it.
- RectF bounds = new RectF();
- bounds.set(0, 0, getWidth(), getHeight());
- outRects.add(bounds);
- }
-
/** @hide */
@Override
public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index fe8b08b..d85bbb9 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -1648,19 +1648,32 @@
private void setPressedItem(View child, int position, float x, float y) {
mDrawsInPressedState = true;
- // Ordering is essential. First update the pressed state and layout
- // the children. This will ensure the selector actually gets drawn.
- setPressed(true);
- layoutChildren();
+ // Ordering is essential. First, update the container's pressed state.
+ drawableHotspotChanged(x, y);
+ if (!isPressed()) {
+ setPressed(true);
+ }
+
+ // Next, run layout if we need to stabilize child positions.
+ if (mDataChanged) {
+ layoutChildren();
+ }
// Manage the pressed view based on motion position. This allows us to
// play nicely with actual touch and scroll events.
final View motionView = getChildAt(mMotionPosition - mFirstPosition);
- if (motionView != null) {
+ if (motionView != null && motionView != child && motionView.isPressed()) {
motionView.setPressed(false);
}
mMotionPosition = position;
- child.setPressed(true);
+
+ // Offset for child coordinates.
+ final float childX = x - child.getLeft();
+ final float childY = y - child.getTop();
+ child.drawableHotspotChanged(childX, childY);
+ if (!child.isPressed()) {
+ child.setPressed(true);
+ }
// Ensure that keyboard focus starts from the last touched position.
setSelectedPositionInt(position);
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 094a712..4b061d3 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -1271,11 +1271,19 @@
@Override
protected int getVirtualViewAt(float x, float y) {
final int id;
+
+ // Calling getDegreesXY() has side-effects, so we need to cache the
+ // current inner circle value and restore after the call.
+ final boolean wasOnInnerCircle = mIsOnInnerCircle;
final int degrees = getDegreesFromXY(x, y, true);
+ final boolean isOnInnerCircle = mIsOnInnerCircle;
+ mIsOnInnerCircle = wasOnInnerCircle;
+
if (degrees != -1) {
final int snapDegrees = snapOnly30s(degrees, 0) % 360;
if (mShowHours) {
- final int hour = getHourForDegrees(snapDegrees, mIsOnInnerCircle);
+ final int hour24 = getHourForDegrees(snapDegrees, isOnInnerCircle);
+ final int hour = mIs24HourMode ? hour24 : hour24To12(hour24);
id = makeId(TYPE_HOUR, hour);
} else {
final int current = getCurrentMinute();
@@ -1404,6 +1412,16 @@
return hour24;
}
+ private int hour24To12(int hour24) {
+ if (hour24 == 0) {
+ return 12;
+ } else if (hour24 > 12) {
+ return hour24 - 12;
+ } else {
+ return hour24;
+ }
+ }
+
private void getBoundsForVirtualView(int virtualViewId, Rect bounds) {
final float radius;
final int type = getTypeFromId(virtualViewId);
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 0f35e0d..c5325c4 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -1101,18 +1101,6 @@
* @hide
*/
@Override
- public void addClickableRectsForAccessibility(List<RectF> outRects) {
- // This class always consumes touch events, therefore if it
- // covers a view we do not want to send a click over it.
- RectF bounds = new RectF();
- bounds.set(0, 0, getWidth(), getHeight());
- outRects.add(bounds);
- }
-
- /**
- * @hide
- */
- @Override
protected void onSetLayoutParams(View child, ViewGroup.LayoutParams lp) {
/*
* Apps may set ActionBar.LayoutParams on their action bar custom views when
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index e8e2c8d..7937a95 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -227,18 +227,6 @@
return true;
}
- /**
- * @hide
- */
- @Override
- public void addClickableRectsForAccessibility(List<RectF> outRects) {
- // This class always consumes touch events, therefore if it
- // covers a view we do not want to send a click over it.
- RectF bounds = new RectF();
- bounds.set(0, 0, getWidth(), getHeight());
- outRects.add(bounds);
- }
-
@Override
public boolean onHoverEvent(MotionEvent ev) {
super.onHoverEvent(ev);
diff --git a/core/java/com/android/internal/widget/FaceUnlockView.java b/core/java/com/android/internal/widget/FaceUnlockView.java
deleted file mode 100644
index 121e601..0000000
--- a/core/java/com/android/internal/widget/FaceUnlockView.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.RelativeLayout;
-
-public class FaceUnlockView extends RelativeLayout {
- private static final String TAG = "FaceUnlockView";
-
- public FaceUnlockView(Context context) {
- this(context, null);
- }
-
- public FaceUnlockView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- private int resolveMeasured(int measureSpec, int desired)
- {
- int result = 0;
- int specSize = MeasureSpec.getSize(measureSpec);
- switch (MeasureSpec.getMode(measureSpec)) {
- case MeasureSpec.UNSPECIFIED:
- result = desired;
- break;
- case MeasureSpec.AT_MOST:
- result = Math.max(specSize, desired);
- break;
- case MeasureSpec.EXACTLY:
- default:
- result = specSize;
- }
- return result;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int minimumWidth = getSuggestedMinimumWidth();
- final int minimumHeight = getSuggestedMinimumHeight();
- int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
- int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
-
- final int chosenSize = Math.min(viewWidth, viewHeight);
- final int newWidthMeasureSpec =
- MeasureSpec.makeMeasureSpec(chosenSize, MeasureSpec.AT_MOST);
- final int newHeightMeasureSpec =
- MeasureSpec.makeMeasureSpec(chosenSize, MeasureSpec.AT_MOST);
-
- super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
- }
-}
diff --git a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
deleted file mode 100644
index 5f3c5f9..0000000
--- a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import java.lang.Math;
-
-import com.android.internal.R;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.StateSet;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewGroup;
-import android.widget.RemoteViews.RemoteView;
-
-/**
- * A layout that switches between its children based on the requested layout height.
- * Each child specifies its minimum and maximum valid height. Results are undefined
- * if children specify overlapping ranges. A child may specify the maximum height
- * as 'unbounded' to indicate that it is willing to be displayed arbitrarily tall.
- *
- * <p>
- * See {@link SizeAdaptiveLayout.LayoutParams} for a full description of the
- * layout parameters used by SizeAdaptiveLayout.
- */
-@RemoteView
-public class SizeAdaptiveLayout extends ViewGroup {
-
- private static final String TAG = "SizeAdaptiveLayout";
- private static final boolean DEBUG = false;
- private static final boolean REPORT_BAD_BOUNDS = true;
- private static final long CROSSFADE_TIME = 250;
-
- // TypedArray indices
- private static final int MIN_VALID_HEIGHT =
- R.styleable.SizeAdaptiveLayout_Layout_layout_minHeight;
- private static final int MAX_VALID_HEIGHT =
- R.styleable.SizeAdaptiveLayout_Layout_layout_maxHeight;
-
- // view state
- private View mActiveChild;
- private View mLastActive;
-
- // animation state
- private AnimatorSet mTransitionAnimation;
- private AnimatorListener mAnimatorListener;
- private ObjectAnimator mFadePanel;
- private ObjectAnimator mFadeView;
- private int mCanceledAnimationCount;
- private View mEnteringView;
- private View mLeavingView;
- // View used to hide larger views under smaller ones to create a uniform crossfade
- private View mModestyPanel;
- private int mModestyPanelTop;
-
- public SizeAdaptiveLayout(Context context) {
- this(context, null);
- }
-
- public SizeAdaptiveLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public SizeAdaptiveLayout(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public SizeAdaptiveLayout(
- Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- initialize();
- }
-
- private void initialize() {
- mModestyPanel = new View(getContext());
- // If the SizeAdaptiveLayout has a solid background, use it as a transition hint.
- Drawable background = getBackground();
- if (background instanceof StateListDrawable) {
- StateListDrawable sld = (StateListDrawable) background;
- sld.setState(StateSet.WILD_CARD);
- background = sld.getCurrent();
- }
- if (background instanceof ColorDrawable) {
- mModestyPanel.setBackgroundDrawable(background);
- }
- SizeAdaptiveLayout.LayoutParams layout =
- new SizeAdaptiveLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT);
- mModestyPanel.setLayoutParams(layout);
- addView(mModestyPanel);
- mFadePanel = ObjectAnimator.ofFloat(mModestyPanel, "alpha", 0f);
- mFadeView = ObjectAnimator.ofFloat(null, "alpha", 0f);
- mAnimatorListener = new BringToFrontOnEnd();
- mTransitionAnimation = new AnimatorSet();
- mTransitionAnimation.play(mFadeView).with(mFadePanel);
- mTransitionAnimation.setDuration(CROSSFADE_TIME);
- mTransitionAnimation.addListener(mAnimatorListener);
- }
-
- /**
- * Visible for testing
- * @hide
- */
- public Animator getTransitionAnimation() {
- return mTransitionAnimation;
- }
-
- /**
- * Visible for testing
- * @hide
- */
- public View getModestyPanel() {
- return mModestyPanel;
- }
-
- @Override
- public void onAttachedToWindow() {
- mLastActive = null;
- // make sure all views start off invisible.
- for (int i = 0; i < getChildCount(); i++) {
- getChildAt(i).setVisibility(View.GONE);
- }
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (DEBUG) Log.d(TAG, this + " measure spec: " +
- MeasureSpec.toString(heightMeasureSpec));
- View model = selectActiveChild(heightMeasureSpec);
- if (model == null) {
- setMeasuredDimension(0, 0);
- return;
- }
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) model.getLayoutParams();
- if (DEBUG) Log.d(TAG, "active min: " + lp.minHeight + " max: " + lp.maxHeight);
- measureChild(model, widthMeasureSpec, heightMeasureSpec);
- int childHeight = model.getMeasuredHeight();
- int childWidth = model.getMeasuredHeight();
- int childState = combineMeasuredStates(0, model.getMeasuredState());
- if (DEBUG) Log.d(TAG, "measured child at: " + childHeight);
- int resolvedWidth = resolveSizeAndState(childWidth, widthMeasureSpec, childState);
- int resolvedHeight = resolveSizeAndState(childHeight, heightMeasureSpec, childState);
- if (DEBUG) Log.d(TAG, "resolved to: " + resolvedHeight);
- int boundedHeight = clampSizeToBounds(resolvedHeight, model);
- if (DEBUG) Log.d(TAG, "bounded to: " + boundedHeight);
- setMeasuredDimension(resolvedWidth, boundedHeight);
- }
-
- private int clampSizeToBounds(int measuredHeight, View child) {
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) child.getLayoutParams();
- int heightIn = View.MEASURED_SIZE_MASK & measuredHeight;
- int height = Math.max(heightIn, lp.minHeight);
- if (lp.maxHeight != SizeAdaptiveLayout.LayoutParams.UNBOUNDED) {
- height = Math.min(height, lp.maxHeight);
- }
-
- if (REPORT_BAD_BOUNDS && heightIn != height) {
- Log.d(TAG, this + "child view " + child + " " +
- "measured out of bounds at " + heightIn +"px " +
- "clamped to " + height + "px");
- }
-
- return height;
- }
-
- //TODO extend to width and height
- private View selectActiveChild(int heightMeasureSpec) {
- final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- View unboundedView = null;
- View tallestView = null;
- int tallestViewSize = 0;
- View smallestView = null;
- int smallestViewSize = Integer.MAX_VALUE;
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child != mModestyPanel) {
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) child.getLayoutParams();
- if (DEBUG) Log.d(TAG, "looking at " + i +
- " with min: " + lp.minHeight +
- " max: " + lp.maxHeight);
- if (lp.maxHeight == SizeAdaptiveLayout.LayoutParams.UNBOUNDED &&
- unboundedView == null) {
- unboundedView = child;
- }
- if (lp.maxHeight > tallestViewSize) {
- tallestViewSize = lp.maxHeight;
- tallestView = child;
- }
- if (lp.minHeight < smallestViewSize) {
- smallestViewSize = lp.minHeight;
- smallestView = child;
- }
- if (heightMode != MeasureSpec.UNSPECIFIED &&
- heightSize >= lp.minHeight && heightSize <= lp.maxHeight) {
- if (DEBUG) Log.d(TAG, " found exact match, finishing early");
- return child;
- }
- }
- }
- if (unboundedView != null) {
- tallestView = unboundedView;
- }
- if (heightMode == MeasureSpec.UNSPECIFIED || heightSize > tallestViewSize) {
- return tallestView;
- } else {
- return smallestView;
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (DEBUG) Log.d(TAG, this + " onlayout height: " + (bottom - top));
- mLastActive = mActiveChild;
- int measureSpec = View.MeasureSpec.makeMeasureSpec(bottom - top,
- View.MeasureSpec.EXACTLY);
- mActiveChild = selectActiveChild(measureSpec);
- if (mActiveChild == null) return;
-
- mActiveChild.setVisibility(View.VISIBLE);
-
- if (mLastActive != mActiveChild && mLastActive != null) {
- if (DEBUG) Log.d(TAG, this + " changed children from: " + mLastActive +
- " to: " + mActiveChild);
-
- mEnteringView = mActiveChild;
- mLeavingView = mLastActive;
-
- mEnteringView.setAlpha(1f);
-
- mModestyPanel.setAlpha(1f);
- mModestyPanel.bringToFront();
- mModestyPanelTop = mLeavingView.getHeight();
- mModestyPanel.setVisibility(View.VISIBLE);
- // TODO: mModestyPanel background should be compatible with mLeavingView
-
- mLeavingView.bringToFront();
-
- if (mTransitionAnimation.isRunning()) {
- mTransitionAnimation.cancel();
- }
- mFadeView.setTarget(mLeavingView);
- mFadeView.setFloatValues(0f);
- mFadePanel.setFloatValues(0f);
- mTransitionAnimation.setupStartValues();
- mTransitionAnimation.start();
- }
- final int childWidth = mActiveChild.getMeasuredWidth();
- final int childHeight = mActiveChild.getMeasuredHeight();
- // TODO investigate setting LAYER_TYPE_HARDWARE on mLastActive
- mActiveChild.layout(0, 0, childWidth, childHeight);
-
- if (DEBUG) Log.d(TAG, "got modesty offset of " + mModestyPanelTop);
- mModestyPanel.layout(0, mModestyPanelTop, childWidth, mModestyPanelTop + childHeight);
- }
-
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- if (DEBUG) Log.d(TAG, "generate layout from attrs");
- return new SizeAdaptiveLayout.LayoutParams(getContext(), attrs);
- }
-
- @Override
- protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- if (DEBUG) Log.d(TAG, "generate default layout from viewgroup");
- return new SizeAdaptiveLayout.LayoutParams(p);
- }
-
- @Override
- protected LayoutParams generateDefaultLayoutParams() {
- if (DEBUG) Log.d(TAG, "generate default layout from null");
- return new SizeAdaptiveLayout.LayoutParams();
- }
-
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof SizeAdaptiveLayout.LayoutParams;
- }
-
- /**
- * Per-child layout information associated with ViewSizeAdaptiveLayout.
- *
- * TODO extend to width and height
- *
- * @attr ref android.R.styleable#SizeAdaptiveLayout_Layout_layout_minHeight
- * @attr ref android.R.styleable#SizeAdaptiveLayout_Layout_layout_maxHeight
- */
- public static class LayoutParams extends ViewGroup.LayoutParams {
-
- /**
- * Indicates the minimum valid height for the child.
- */
- @ViewDebug.ExportedProperty(category = "layout")
- public int minHeight;
-
- /**
- * Indicates the maximum valid height for the child.
- */
- @ViewDebug.ExportedProperty(category = "layout")
- public int maxHeight;
-
- /**
- * Constant value for maxHeight that indicates there is not maximum height.
- */
- public static final int UNBOUNDED = -1;
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- if (DEBUG) {
- Log.d(TAG, "construct layout from attrs");
- for (int i = 0; i < attrs.getAttributeCount(); i++) {
- Log.d(TAG, " " + attrs.getAttributeName(i) + " = " +
- attrs.getAttributeValue(i));
- }
- }
- TypedArray a =
- c.obtainStyledAttributes(attrs,
- R.styleable.SizeAdaptiveLayout_Layout);
-
- minHeight = a.getDimensionPixelSize(MIN_VALID_HEIGHT, 0);
- if (DEBUG) Log.d(TAG, "got minHeight of: " + minHeight);
-
- try {
- maxHeight = a.getLayoutDimension(MAX_VALID_HEIGHT, UNBOUNDED);
- if (DEBUG) Log.d(TAG, "got maxHeight of: " + maxHeight);
- } catch (Exception e) {
- if (DEBUG) Log.d(TAG, "caught exception looking for maxValidHeight " + e);
- }
-
- a.recycle();
- }
-
- /**
- * Creates a new set of layout parameters with the specified width, height
- * and valid height bounds.
- *
- * @param width the width, either {@link #MATCH_PARENT},
- * {@link #WRAP_CONTENT} or a fixed size in pixels
- * @param height the height, either {@link #MATCH_PARENT},
- * {@link #WRAP_CONTENT} or a fixed size in pixels
- * @param minHeight the minimum height of this child
- * @param maxHeight the maximum height of this child
- * or {@link #UNBOUNDED} if the child can grow forever
- */
- public LayoutParams(int width, int height, int minHeight, int maxHeight) {
- super(width, height);
- this.minHeight = minHeight;
- this.maxHeight = maxHeight;
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(int width, int height) {
- this(width, height, UNBOUNDED, UNBOUNDED);
- }
-
- /**
- * Constructs a new LayoutParams with default values as defined in {@link LayoutParams}.
- */
- public LayoutParams() {
- this(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(ViewGroup.LayoutParams p) {
- super(p);
- minHeight = UNBOUNDED;
- maxHeight = UNBOUNDED;
- }
-
- public String debug(String output) {
- return output + "SizeAdaptiveLayout.LayoutParams={" +
- ", max=" + maxHeight +
- ", max=" + minHeight + "}";
- }
- }
-
- class BringToFrontOnEnd implements AnimatorListener {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mCanceledAnimationCount == 0) {
- mLeavingView.setVisibility(View.GONE);
- mModestyPanel.setVisibility(View.GONE);
- mEnteringView.bringToFront();
- mEnteringView = null;
- mLeavingView = null;
- } else {
- mCanceledAnimationCount--;
- }
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mCanceledAnimationCount++;
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- if (DEBUG) Log.d(TAG, "fade animation repeated: should never happen.");
- assert(false);
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- }
- }
-}
diff --git a/core/java/com/android/internal/widget/WaveView.java b/core/java/com/android/internal/widget/WaveView.java
deleted file mode 100644
index 9e7a649..0000000
--- a/core/java/com/android/internal/widget/WaveView.java
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import java.util.ArrayList;
-
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.drawable.BitmapDrawable;
-import android.media.AudioAttributes;
-import android.os.UserHandle;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.R;
-
-/**
- * A special widget containing a center and outer ring. Moving the center ring to the outer ring
- * causes an event that can be caught by implementing OnTriggerListener.
- */
-public class WaveView extends View implements ValueAnimator.AnimatorUpdateListener {
- private static final String TAG = "WaveView";
- private static final boolean DBG = false;
- private static final int WAVE_COUNT = 20; // default wave count
- private static final long VIBRATE_SHORT = 20; // msec
- private static final long VIBRATE_LONG = 20; // msec
-
- // Lock state machine states
- private static final int STATE_RESET_LOCK = 0;
- private static final int STATE_READY = 1;
- private static final int STATE_START_ATTEMPT = 2;
- private static final int STATE_ATTEMPTING = 3;
- private static final int STATE_UNLOCK_ATTEMPT = 4;
- private static final int STATE_UNLOCK_SUCCESS = 5;
-
- // Animation properties.
- private static final long DURATION = 300; // duration of transitional animations
- private static final long FINAL_DURATION = 200; // duration of final animations when unlocking
- private static final long RING_DELAY = 1300; // when to start fading animated rings
- private static final long FINAL_DELAY = 200; // delay for unlock success animation
- private static final long SHORT_DELAY = 100; // for starting one animation after another.
- private static final long WAVE_DURATION = 2000; // amount of time for way to expand/decay
- private static final long RESET_TIMEOUT = 3000; // elapsed time of inactivity before we reset
- private static final long DELAY_INCREMENT = 15; // increment per wave while tracking motion
- private static final long DELAY_INCREMENT2 = 12; // increment per wave while not tracking
- private static final long WAVE_DELAY = WAVE_DURATION / WAVE_COUNT; // initial propagation delay
-
- /**
- * The scale by which to multiply the unlock handle width to compute the radius
- * in which it can be grabbed when accessibility is disabled.
- */
- private static final float GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_DISABLED = 0.5f;
-
- /**
- * The scale by which to multiply the unlock handle width to compute the radius
- * in which it can be grabbed when accessibility is enabled (more generous).
- */
- private static final float GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.0f;
-
- private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- .build();
-
- private Vibrator mVibrator;
- private OnTriggerListener mOnTriggerListener;
- private ArrayList<DrawableHolder> mDrawables = new ArrayList<DrawableHolder>(3);
- private ArrayList<DrawableHolder> mLightWaves = new ArrayList<DrawableHolder>(WAVE_COUNT);
- private boolean mFingerDown = false;
- private float mRingRadius = 182.0f; // Radius of bitmap ring. Used to snap halo to it
- private int mSnapRadius = 136; // minimum threshold for drag unlock
- private int mWaveCount = WAVE_COUNT; // number of waves
- private long mWaveTimerDelay = WAVE_DELAY;
- private int mCurrentWave = 0;
- private float mLockCenterX; // center of widget as dictated by widget size
- private float mLockCenterY;
- private float mMouseX; // current mouse position as of last touch event
- private float mMouseY;
- private DrawableHolder mUnlockRing;
- private DrawableHolder mUnlockDefault;
- private DrawableHolder mUnlockHalo;
- private int mLockState = STATE_RESET_LOCK;
- private int mGrabbedState = OnTriggerListener.NO_HANDLE;
- private boolean mWavesRunning;
- private boolean mFinishWaves;
-
- public WaveView(Context context) {
- this(context, null);
- }
-
- public WaveView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- // TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WaveView);
- // mOrientation = a.getInt(R.styleable.WaveView_orientation, HORIZONTAL);
- // a.recycle();
-
- initDrawables();
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- mLockCenterX = 0.5f * w;
- mLockCenterY = 0.5f * h;
- super.onSizeChanged(w, h, oldw, oldh);
- }
-
- @Override
- protected int getSuggestedMinimumWidth() {
- // View should be large enough to contain the unlock ring + halo
- return mUnlockRing.getWidth() + mUnlockHalo.getWidth();
- }
-
- @Override
- protected int getSuggestedMinimumHeight() {
- // View should be large enough to contain the unlock ring + halo
- return mUnlockRing.getHeight() + mUnlockHalo.getHeight();
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
- int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
- int width;
- int height;
-
- if (widthSpecMode == MeasureSpec.AT_MOST) {
- width = Math.min(widthSpecSize, getSuggestedMinimumWidth());
- } else if (widthSpecMode == MeasureSpec.EXACTLY) {
- width = widthSpecSize;
- } else {
- width = getSuggestedMinimumWidth();
- }
-
- if (heightSpecMode == MeasureSpec.AT_MOST) {
- height = Math.min(heightSpecSize, getSuggestedMinimumWidth());
- } else if (heightSpecMode == MeasureSpec.EXACTLY) {
- height = heightSpecSize;
- } else {
- height = getSuggestedMinimumHeight();
- }
-
- setMeasuredDimension(width, height);
- }
-
- private void initDrawables() {
- mUnlockRing = new DrawableHolder(createDrawable(R.drawable.unlock_ring));
- mUnlockRing.setX(mLockCenterX);
- mUnlockRing.setY(mLockCenterY);
- mUnlockRing.setScaleX(0.1f);
- mUnlockRing.setScaleY(0.1f);
- mUnlockRing.setAlpha(0.0f);
- mDrawables.add(mUnlockRing);
-
- mUnlockDefault = new DrawableHolder(createDrawable(R.drawable.unlock_default));
- mUnlockDefault.setX(mLockCenterX);
- mUnlockDefault.setY(mLockCenterY);
- mUnlockDefault.setScaleX(0.1f);
- mUnlockDefault.setScaleY(0.1f);
- mUnlockDefault.setAlpha(0.0f);
- mDrawables.add(mUnlockDefault);
-
- mUnlockHalo = new DrawableHolder(createDrawable(R.drawable.unlock_halo));
- mUnlockHalo.setX(mLockCenterX);
- mUnlockHalo.setY(mLockCenterY);
- mUnlockHalo.setScaleX(0.1f);
- mUnlockHalo.setScaleY(0.1f);
- mUnlockHalo.setAlpha(0.0f);
- mDrawables.add(mUnlockHalo);
-
- BitmapDrawable wave = createDrawable(R.drawable.unlock_wave);
- for (int i = 0; i < mWaveCount; i++) {
- DrawableHolder holder = new DrawableHolder(wave);
- mLightWaves.add(holder);
- holder.setAlpha(0.0f);
- }
- }
-
- private void waveUpdateFrame(float mouseX, float mouseY, boolean fingerDown) {
- double distX = mouseX - mLockCenterX;
- double distY = mouseY - mLockCenterY;
- int dragDistance = (int) Math.ceil(Math.hypot(distX, distY));
- double touchA = Math.atan2(distX, distY);
- float ringX = (float) (mLockCenterX + mRingRadius * Math.sin(touchA));
- float ringY = (float) (mLockCenterY + mRingRadius * Math.cos(touchA));
-
- switch (mLockState) {
- case STATE_RESET_LOCK:
- if (DBG) Log.v(TAG, "State RESET_LOCK");
- mWaveTimerDelay = WAVE_DELAY;
- for (int i = 0; i < mLightWaves.size(); i++) {
- DrawableHolder holder = mLightWaves.get(i);
- holder.addAnimTo(300, 0, "alpha", 0.0f, false);
- }
- for (int i = 0; i < mLightWaves.size(); i++) {
- mLightWaves.get(i).startAnimations(this);
- }
-
- mUnlockRing.addAnimTo(DURATION, 0, "x", mLockCenterX, true);
- mUnlockRing.addAnimTo(DURATION, 0, "y", mLockCenterY, true);
- mUnlockRing.addAnimTo(DURATION, 0, "scaleX", 0.1f, true);
- mUnlockRing.addAnimTo(DURATION, 0, "scaleY", 0.1f, true);
- mUnlockRing.addAnimTo(DURATION, 0, "alpha", 0.0f, true);
-
- mUnlockDefault.removeAnimationFor("x");
- mUnlockDefault.removeAnimationFor("y");
- mUnlockDefault.removeAnimationFor("scaleX");
- mUnlockDefault.removeAnimationFor("scaleY");
- mUnlockDefault.removeAnimationFor("alpha");
- mUnlockDefault.setX(mLockCenterX);
- mUnlockDefault.setY(mLockCenterY);
- mUnlockDefault.setScaleX(0.1f);
- mUnlockDefault.setScaleY(0.1f);
- mUnlockDefault.setAlpha(0.0f);
- mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleX", 1.0f, true);
- mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleY", 1.0f, true);
- mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "alpha", 1.0f, true);
-
- mUnlockHalo.removeAnimationFor("x");
- mUnlockHalo.removeAnimationFor("y");
- mUnlockHalo.removeAnimationFor("scaleX");
- mUnlockHalo.removeAnimationFor("scaleY");
- mUnlockHalo.removeAnimationFor("alpha");
- mUnlockHalo.setX(mLockCenterX);
- mUnlockHalo.setY(mLockCenterY);
- mUnlockHalo.setScaleX(0.1f);
- mUnlockHalo.setScaleY(0.1f);
- mUnlockHalo.setAlpha(0.0f);
- mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "x", mLockCenterX, true);
- mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "y", mLockCenterY, true);
- mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "scaleX", 1.0f, true);
- mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "scaleY", 1.0f, true);
- mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "alpha", 1.0f, true);
-
- removeCallbacks(mLockTimerActions);
-
- mLockState = STATE_READY;
- break;
-
- case STATE_READY:
- if (DBG) Log.v(TAG, "State READY");
- mWaveTimerDelay = WAVE_DELAY;
- break;
-
- case STATE_START_ATTEMPT:
- if (DBG) Log.v(TAG, "State START_ATTEMPT");
- mUnlockDefault.removeAnimationFor("x");
- mUnlockDefault.removeAnimationFor("y");
- mUnlockDefault.removeAnimationFor("scaleX");
- mUnlockDefault.removeAnimationFor("scaleY");
- mUnlockDefault.removeAnimationFor("alpha");
- mUnlockDefault.setX(mLockCenterX + 182);
- mUnlockDefault.setY(mLockCenterY);
- mUnlockDefault.setScaleX(0.1f);
- mUnlockDefault.setScaleY(0.1f);
- mUnlockDefault.setAlpha(0.0f);
-
- mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleX", 1.0f, false);
- mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleY", 1.0f, false);
- mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "alpha", 1.0f, false);
-
- mUnlockRing.addAnimTo(DURATION, 0, "scaleX", 1.0f, true);
- mUnlockRing.addAnimTo(DURATION, 0, "scaleY", 1.0f, true);
- mUnlockRing.addAnimTo(DURATION, 0, "alpha", 1.0f, true);
-
- mLockState = STATE_ATTEMPTING;
- break;
-
- case STATE_ATTEMPTING:
- if (DBG) Log.v(TAG, "State ATTEMPTING (fingerDown = " + fingerDown + ")");
- if (dragDistance > mSnapRadius) {
- mFinishWaves = true; // don't start any more waves.
- if (fingerDown) {
- mUnlockHalo.addAnimTo(0, 0, "x", ringX, true);
- mUnlockHalo.addAnimTo(0, 0, "y", ringY, true);
- mUnlockHalo.addAnimTo(0, 0, "scaleX", 1.0f, true);
- mUnlockHalo.addAnimTo(0, 0, "scaleY", 1.0f, true);
- mUnlockHalo.addAnimTo(0, 0, "alpha", 1.0f, true);
- } else {
- if (DBG) Log.v(TAG, "up detected, moving to STATE_UNLOCK_ATTEMPT");
- mLockState = STATE_UNLOCK_ATTEMPT;
- }
- } else {
- // If waves have stopped, we need to kick them off again...
- if (!mWavesRunning) {
- mWavesRunning = true;
- mFinishWaves = false;
- // mWaveTimerDelay = WAVE_DELAY;
- postDelayed(mAddWaveAction, mWaveTimerDelay);
- }
- mUnlockHalo.addAnimTo(0, 0, "x", mouseX, true);
- mUnlockHalo.addAnimTo(0, 0, "y", mouseY, true);
- mUnlockHalo.addAnimTo(0, 0, "scaleX", 1.0f, true);
- mUnlockHalo.addAnimTo(0, 0, "scaleY", 1.0f, true);
- mUnlockHalo.addAnimTo(0, 0, "alpha", 1.0f, true);
- }
- break;
-
- case STATE_UNLOCK_ATTEMPT:
- if (DBG) Log.v(TAG, "State UNLOCK_ATTEMPT");
- if (dragDistance > mSnapRadius) {
- for (int n = 0; n < mLightWaves.size(); n++) {
- DrawableHolder wave = mLightWaves.get(n);
- long delay = 1000L*(6 + n - mCurrentWave)/10L;
- wave.addAnimTo(FINAL_DURATION, delay, "x", ringX, true);
- wave.addAnimTo(FINAL_DURATION, delay, "y", ringY, true);
- wave.addAnimTo(FINAL_DURATION, delay, "scaleX", 0.1f, true);
- wave.addAnimTo(FINAL_DURATION, delay, "scaleY", 0.1f, true);
- wave.addAnimTo(FINAL_DURATION, delay, "alpha", 0.0f, true);
- }
- for (int i = 0; i < mLightWaves.size(); i++) {
- mLightWaves.get(i).startAnimations(this);
- }
-
- mUnlockRing.addAnimTo(FINAL_DURATION, 0, "x", ringX, false);
- mUnlockRing.addAnimTo(FINAL_DURATION, 0, "y", ringY, false);
- mUnlockRing.addAnimTo(FINAL_DURATION, 0, "scaleX", 0.1f, false);
- mUnlockRing.addAnimTo(FINAL_DURATION, 0, "scaleY", 0.1f, false);
- mUnlockRing.addAnimTo(FINAL_DURATION, 0, "alpha", 0.0f, false);
-
- mUnlockRing.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
-
- mUnlockDefault.removeAnimationFor("x");
- mUnlockDefault.removeAnimationFor("y");
- mUnlockDefault.removeAnimationFor("scaleX");
- mUnlockDefault.removeAnimationFor("scaleY");
- mUnlockDefault.removeAnimationFor("alpha");
- mUnlockDefault.setX(ringX);
- mUnlockDefault.setY(ringY);
- mUnlockDefault.setScaleX(0.1f);
- mUnlockDefault.setScaleY(0.1f);
- mUnlockDefault.setAlpha(0.0f);
-
- mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "x", ringX, true);
- mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "y", ringY, true);
- mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "scaleX", 1.0f, true);
- mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "scaleY", 1.0f, true);
- mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "alpha", 1.0f, true);
-
- mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
- mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
- mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
-
- mUnlockHalo.addAnimTo(FINAL_DURATION, 0, "x", ringX, false);
- mUnlockHalo.addAnimTo(FINAL_DURATION, 0, "y", ringY, false);
-
- mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
- mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
- mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
-
- removeCallbacks(mLockTimerActions);
-
- postDelayed(mLockTimerActions, RESET_TIMEOUT);
-
- dispatchTriggerEvent(OnTriggerListener.CENTER_HANDLE);
- mLockState = STATE_UNLOCK_SUCCESS;
- } else {
- mLockState = STATE_RESET_LOCK;
- }
- break;
-
- case STATE_UNLOCK_SUCCESS:
- if (DBG) Log.v(TAG, "State UNLOCK_SUCCESS");
- removeCallbacks(mAddWaveAction);
- break;
-
- default:
- if (DBG) Log.v(TAG, "Unknown state " + mLockState);
- break;
- }
- mUnlockDefault.startAnimations(this);
- mUnlockHalo.startAnimations(this);
- mUnlockRing.startAnimations(this);
- }
-
- BitmapDrawable createDrawable(int resId) {
- Resources res = getResources();
- Bitmap bitmap = BitmapFactory.decodeResource(res, resId);
- return new BitmapDrawable(res, bitmap);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- waveUpdateFrame(mMouseX, mMouseY, mFingerDown);
- for (int i = 0; i < mDrawables.size(); ++i) {
- mDrawables.get(i).draw(canvas);
- }
- for (int i = 0; i < mLightWaves.size(); ++i) {
- mLightWaves.get(i).draw(canvas);
- }
- }
-
- private final Runnable mLockTimerActions = new Runnable() {
- public void run() {
- if (DBG) Log.v(TAG, "LockTimerActions");
- // reset lock after inactivity
- if (mLockState == STATE_ATTEMPTING) {
- if (DBG) Log.v(TAG, "Timer resets to STATE_RESET_LOCK");
- mLockState = STATE_RESET_LOCK;
- }
- // for prototype, reset after successful unlock
- if (mLockState == STATE_UNLOCK_SUCCESS) {
- if (DBG) Log.v(TAG, "Timer resets to STATE_RESET_LOCK after success");
- mLockState = STATE_RESET_LOCK;
- }
- invalidate();
- }
- };
-
- private final Runnable mAddWaveAction = new Runnable() {
- public void run() {
- double distX = mMouseX - mLockCenterX;
- double distY = mMouseY - mLockCenterY;
- int dragDistance = (int) Math.ceil(Math.hypot(distX, distY));
- if (mLockState == STATE_ATTEMPTING && dragDistance < mSnapRadius
- && mWaveTimerDelay >= WAVE_DELAY) {
- mWaveTimerDelay = Math.min(WAVE_DURATION, mWaveTimerDelay + DELAY_INCREMENT);
-
- DrawableHolder wave = mLightWaves.get(mCurrentWave);
- wave.setAlpha(0.0f);
- wave.setScaleX(0.2f);
- wave.setScaleY(0.2f);
- wave.setX(mMouseX);
- wave.setY(mMouseY);
-
- wave.addAnimTo(WAVE_DURATION, 0, "x", mLockCenterX, true);
- wave.addAnimTo(WAVE_DURATION, 0, "y", mLockCenterY, true);
- wave.addAnimTo(WAVE_DURATION*2/3, 0, "alpha", 1.0f, true);
- wave.addAnimTo(WAVE_DURATION, 0, "scaleX", 1.0f, true);
- wave.addAnimTo(WAVE_DURATION, 0, "scaleY", 1.0f, true);
-
- wave.addAnimTo(1000, RING_DELAY, "alpha", 0.0f, false);
- wave.startAnimations(WaveView.this);
-
- mCurrentWave = (mCurrentWave+1) % mWaveCount;
- if (DBG) Log.v(TAG, "WaveTimerDelay: start new wave in " + mWaveTimerDelay);
- } else {
- mWaveTimerDelay += DELAY_INCREMENT2;
- }
- if (mFinishWaves) {
- // sentinel used to restart the waves after they've stopped
- mWavesRunning = false;
- } else {
- postDelayed(mAddWaveAction, mWaveTimerDelay);
- }
- }
- };
-
- @Override
- public boolean onHoverEvent(MotionEvent event) {
- if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
- final int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_HOVER_ENTER:
- event.setAction(MotionEvent.ACTION_DOWN);
- break;
- case MotionEvent.ACTION_HOVER_MOVE:
- event.setAction(MotionEvent.ACTION_MOVE);
- break;
- case MotionEvent.ACTION_HOVER_EXIT:
- event.setAction(MotionEvent.ACTION_UP);
- break;
- }
- onTouchEvent(event);
- event.setAction(action);
- }
- return super.onHoverEvent(event);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- final int action = event.getAction();
- mMouseX = event.getX();
- mMouseY = event.getY();
- boolean handled = false;
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- removeCallbacks(mLockTimerActions);
- mFingerDown = true;
- tryTransitionToStartAttemptState(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_MOVE:
- tryTransitionToStartAttemptState(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_UP:
- if (DBG) Log.v(TAG, "ACTION_UP");
- mFingerDown = false;
- postDelayed(mLockTimerActions, RESET_TIMEOUT);
- setGrabbedState(OnTriggerListener.NO_HANDLE);
- // Normally the state machine is driven by user interaction causing redraws.
- // However, when there's no more user interaction and no running animations,
- // the state machine stops advancing because onDraw() never gets called.
- // The following ensures we advance to the next state in this case,
- // either STATE_UNLOCK_ATTEMPT or STATE_RESET_LOCK.
- waveUpdateFrame(mMouseX, mMouseY, mFingerDown);
- handled = true;
- break;
-
- case MotionEvent.ACTION_CANCEL:
- mFingerDown = false;
- handled = true;
- break;
- }
- invalidate();
- return handled ? true : super.onTouchEvent(event);
- }
-
- /**
- * Tries to transition to start attempt state.
- *
- * @param event A motion event.
- */
- private void tryTransitionToStartAttemptState(MotionEvent event) {
- final float dx = event.getX() - mUnlockHalo.getX();
- final float dy = event.getY() - mUnlockHalo.getY();
- float dist = (float) Math.hypot(dx, dy);
- if (dist <= getScaledGrabHandleRadius()) {
- setGrabbedState(OnTriggerListener.CENTER_HANDLE);
- if (mLockState == STATE_READY) {
- mLockState = STATE_START_ATTEMPT;
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- announceUnlockHandle();
- }
- }
- }
- }
-
- /**
- * @return The radius in which the handle is grabbed scaled based on
- * whether accessibility is enabled.
- */
- private float getScaledGrabHandleRadius() {
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- return GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_ENABLED * mUnlockHalo.getWidth();
- } else {
- return GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_DISABLED * mUnlockHalo.getWidth();
- }
- }
-
- /**
- * Announces the unlock handle if accessibility is enabled.
- */
- private void announceUnlockHandle() {
- setContentDescription(mContext.getString(R.string.description_target_unlock_tablet));
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
- setContentDescription(null);
- }
-
- /**
- * Triggers haptic feedback.
- */
- private synchronized void vibrate(long duration) {
- final boolean hapticEnabled = Settings.System.getIntForUser(
- mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
- UserHandle.USER_CURRENT) != 0;
- if (hapticEnabled) {
- if (mVibrator == null) {
- mVibrator = (android.os.Vibrator) getContext()
- .getSystemService(Context.VIBRATOR_SERVICE);
- }
- mVibrator.vibrate(duration, VIBRATION_ATTRIBUTES);
- }
- }
-
- /**
- * Registers a callback to be invoked when the user triggers an event.
- *
- * @param listener the OnDialTriggerListener to attach to this view
- */
- public void setOnTriggerListener(OnTriggerListener listener) {
- mOnTriggerListener = listener;
- }
-
- /**
- * Dispatches a trigger event to listener. Ignored if a listener is not set.
- * @param whichHandle the handle that triggered the event.
- */
- private void dispatchTriggerEvent(int whichHandle) {
- vibrate(VIBRATE_LONG);
- if (mOnTriggerListener != null) {
- mOnTriggerListener.onTrigger(this, whichHandle);
- }
- }
-
- /**
- * Sets the current grabbed state, and dispatches a grabbed state change
- * event to our listener.
- */
- private void setGrabbedState(int newState) {
- if (newState != mGrabbedState) {
- mGrabbedState = newState;
- if (mOnTriggerListener != null) {
- mOnTriggerListener.onGrabbedStateChange(this, mGrabbedState);
- }
- }
- }
-
- public interface OnTriggerListener {
- /**
- * Sent when the user releases the handle.
- */
- public static final int NO_HANDLE = 0;
-
- /**
- * Sent when the user grabs the center handle
- */
- public static final int CENTER_HANDLE = 10;
-
- /**
- * Called when the user drags the center ring beyond a threshold.
- */
- void onTrigger(View v, int whichHandle);
-
- /**
- * Called when the "grabbed state" changes (i.e. when the user either grabs or releases
- * one of the handles.)
- *
- * @param v the view that was triggered
- * @param grabbedState the new state: {@link #NO_HANDLE}, {@link #CENTER_HANDLE},
- */
- void onGrabbedStateChange(View v, int grabbedState);
- }
-
- public void onAnimationUpdate(ValueAnimator animation) {
- invalidate();
- }
-
- public void reset() {
- if (DBG) Log.v(TAG, "reset() : resets state to STATE_RESET_LOCK");
- mLockState = STATE_RESET_LOCK;
- invalidate();
- }
-}
diff --git a/core/java/com/android/internal/widget/multiwaveview/Ease.java b/core/java/com/android/internal/widget/multiwaveview/Ease.java
deleted file mode 100644
index 7f90c44..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/Ease.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.internal.widget.multiwaveview;
-
-import android.animation.TimeInterpolator;
-
-class Ease {
- private static final float DOMAIN = 1.0f;
- private static final float DURATION = 1.0f;
- private static final float START = 0.0f;
-
- static class Linear {
- public static final TimeInterpolator easeNone = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return input;
- }
- };
- }
-
- static class Cubic {
- public static final TimeInterpolator easeIn = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return DOMAIN*(input/=DURATION)*input*input + START;
- }
- };
- public static final TimeInterpolator easeOut = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return DOMAIN*((input=input/DURATION-1)*input*input + 1) + START;
- }
- };
- public static final TimeInterpolator easeInOut = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return ((input/=DURATION/2) < 1.0f) ?
- (DOMAIN/2*input*input*input + START)
- : (DOMAIN/2*((input-=2)*input*input + 2) + START);
- }
- };
- }
-
- static class Quad {
- public static final TimeInterpolator easeIn = new TimeInterpolator() {
- public float getInterpolation (float input) {
- return DOMAIN*(input/=DURATION)*input + START;
- }
- };
- public static final TimeInterpolator easeOut = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return -DOMAIN *(input/=DURATION)*(input-2) + START;
- }
- };
- public static final TimeInterpolator easeInOut = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return ((input/=DURATION/2) < 1) ?
- (DOMAIN/2*input*input + START)
- : (-DOMAIN/2 * ((--input)*(input-2) - 1) + START);
- }
- };
- }
-
- static class Quart {
- public static final TimeInterpolator easeIn = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return DOMAIN*(input/=DURATION)*input*input*input + START;
- }
- };
- public static final TimeInterpolator easeOut = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return -DOMAIN * ((input=input/DURATION-1)*input*input*input - 1) + START;
- }
- };
- public static final TimeInterpolator easeInOut = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return ((input/=DURATION/2) < 1) ?
- (DOMAIN/2*input*input*input*input + START)
- : (-DOMAIN/2 * ((input-=2)*input*input*input - 2) + START);
- }
- };
- }
-
- static class Quint {
- public static final TimeInterpolator easeIn = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return DOMAIN*(input/=DURATION)*input*input*input*input + START;
- }
- };
- public static final TimeInterpolator easeOut = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return DOMAIN*((input=input/DURATION-1)*input*input*input*input + 1) + START;
- }
- };
- public static final TimeInterpolator easeInOut = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return ((input/=DURATION/2) < 1) ?
- (DOMAIN/2*input*input*input*input*input + START)
- : (DOMAIN/2*((input-=2)*input*input*input*input + 2) + START);
- }
- };
- }
-
- static class Sine {
- public static final TimeInterpolator easeIn = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return -DOMAIN * (float) Math.cos(input/DURATION * (Math.PI/2)) + DOMAIN + START;
- }
- };
- public static final TimeInterpolator easeOut = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return DOMAIN * (float) Math.sin(input/DURATION * (Math.PI/2)) + START;
- }
- };
- public static final TimeInterpolator easeInOut = new TimeInterpolator() {
- public float getInterpolation(float input) {
- return -DOMAIN/2 * ((float)Math.cos(Math.PI*input/DURATION) - 1.0f) + START;
- }
- };
- }
-
-}
diff --git a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
deleted file mode 100644
index 11ac19e..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
+++ /dev/null
@@ -1,1383 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget.multiwaveview;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.media.AudioAttributes;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-
-/**
- * A re-usable widget containing a center, outer ring and wave animation.
- */
-public class GlowPadView extends View {
- private static final String TAG = "GlowPadView";
- private static final boolean DEBUG = false;
-
- // Wave state machine
- private static final int STATE_IDLE = 0;
- private static final int STATE_START = 1;
- private static final int STATE_FIRST_TOUCH = 2;
- private static final int STATE_TRACKING = 3;
- private static final int STATE_SNAP = 4;
- private static final int STATE_FINISH = 5;
-
- // Animation properties.
- private static final float SNAP_MARGIN_DEFAULT = 20.0f; // distance to ring before we snap to it
-
- public interface OnTriggerListener {
- int NO_HANDLE = 0;
- int CENTER_HANDLE = 1;
- public void onGrabbed(View v, int handle);
- public void onReleased(View v, int handle);
- public void onTrigger(View v, int target);
- public void onGrabbedStateChange(View v, int handle);
- public void onFinishFinalAnimation();
- }
-
- // Tuneable parameters for animation
- private static final int WAVE_ANIMATION_DURATION = 1000;
- private static final int RETURN_TO_HOME_DELAY = 1200;
- private static final int RETURN_TO_HOME_DURATION = 200;
- private static final int HIDE_ANIMATION_DELAY = 200;
- private static final int HIDE_ANIMATION_DURATION = 200;
- private static final int SHOW_ANIMATION_DURATION = 200;
- private static final int SHOW_ANIMATION_DELAY = 50;
- private static final int INITIAL_SHOW_HANDLE_DURATION = 200;
- private static final int REVEAL_GLOW_DELAY = 0;
- private static final int REVEAL_GLOW_DURATION = 0;
-
- private static final float TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.3f;
- private static final float TARGET_SCALE_EXPANDED = 1.0f;
- private static final float TARGET_SCALE_COLLAPSED = 0.8f;
- private static final float RING_SCALE_EXPANDED = 1.0f;
- private static final float RING_SCALE_COLLAPSED = 0.5f;
-
- private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- .build();
-
- private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
- private AnimationBundle mWaveAnimations = new AnimationBundle();
- private AnimationBundle mTargetAnimations = new AnimationBundle();
- private AnimationBundle mGlowAnimations = new AnimationBundle();
- private ArrayList<String> mTargetDescriptions;
- private ArrayList<String> mDirectionDescriptions;
- private OnTriggerListener mOnTriggerListener;
- private TargetDrawable mHandleDrawable;
- private TargetDrawable mOuterRing;
- private Vibrator mVibrator;
-
- private int mFeedbackCount = 3;
- private int mVibrationDuration = 0;
- private int mGrabbedState;
- private int mActiveTarget = -1;
- private float mGlowRadius;
- private float mWaveCenterX;
- private float mWaveCenterY;
- private int mMaxTargetHeight;
- private int mMaxTargetWidth;
- private float mRingScaleFactor = 1f;
- private boolean mAllowScaling;
-
- private float mOuterRadius = 0.0f;
- private float mSnapMargin = 0.0f;
- private float mFirstItemOffset = 0.0f;
- private boolean mMagneticTargets = false;
- private boolean mDragging;
- private int mNewTargetResources;
-
- private class AnimationBundle extends ArrayList<Tweener> {
- private static final long serialVersionUID = 0xA84D78726F127468L;
- private boolean mSuspended;
-
- public void start() {
- if (mSuspended) return; // ignore attempts to start animations
- final int count = size();
- for (int i = 0; i < count; i++) {
- Tweener anim = get(i);
- anim.animator.start();
- }
- }
-
- public void cancel() {
- final int count = size();
- for (int i = 0; i < count; i++) {
- Tweener anim = get(i);
- anim.animator.cancel();
- }
- clear();
- }
-
- public void stop() {
- final int count = size();
- for (int i = 0; i < count; i++) {
- Tweener anim = get(i);
- anim.animator.end();
- }
- clear();
- }
-
- public void setSuspended(boolean suspend) {
- mSuspended = suspend;
- }
- };
-
- private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
- dispatchOnFinishFinalAnimation();
- }
- };
-
- private AnimatorListener mResetListenerWithPing = new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- ping();
- switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
- dispatchOnFinishFinalAnimation();
- }
- };
-
- private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- invalidate();
- }
- };
-
- private boolean mAnimatingTargets;
- private AnimatorListener mTargetUpdateListener = new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- if (mNewTargetResources != 0) {
- internalSetTargetResources(mNewTargetResources);
- mNewTargetResources = 0;
- hideTargets(false, false);
- }
- mAnimatingTargets = false;
- }
- };
- private int mTargetResourceId;
- private int mTargetDescriptionsResourceId;
- private int mDirectionDescriptionsResourceId;
- private boolean mAlwaysTrackFinger;
- private int mHorizontalInset;
- private int mVerticalInset;
- private int mGravity = Gravity.TOP;
- private boolean mInitialLayout = true;
- private Tweener mBackgroundAnimator;
- private PointCloud mPointCloud;
- private float mInnerRadius;
- private int mPointerId;
-
- public GlowPadView(Context context) {
- this(context, null);
- }
-
- public GlowPadView(Context context, AttributeSet attrs) {
- super(context, attrs);
- Resources res = context.getResources();
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GlowPadView);
- mInnerRadius = a.getDimension(R.styleable.GlowPadView_innerRadius, mInnerRadius);
- mOuterRadius = a.getDimension(R.styleable.GlowPadView_outerRadius, mOuterRadius);
- mSnapMargin = a.getDimension(R.styleable.GlowPadView_snapMargin, mSnapMargin);
- mFirstItemOffset = (float) Math.toRadians(
- a.getFloat(R.styleable.GlowPadView_firstItemOffset,
- (float) Math.toDegrees(mFirstItemOffset)));
- mVibrationDuration = a.getInt(R.styleable.GlowPadView_vibrationDuration,
- mVibrationDuration);
- mFeedbackCount = a.getInt(R.styleable.GlowPadView_feedbackCount,
- mFeedbackCount);
- mAllowScaling = a.getBoolean(R.styleable.GlowPadView_allowScaling, false);
- TypedValue handle = a.peekValue(R.styleable.GlowPadView_handleDrawable);
- mHandleDrawable = new TargetDrawable(res, handle != null ? handle.resourceId : 0);
- mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
- mOuterRing = new TargetDrawable(res,
- getResourceId(a, R.styleable.GlowPadView_outerRingDrawable));
-
- mAlwaysTrackFinger = a.getBoolean(R.styleable.GlowPadView_alwaysTrackFinger, false);
- mMagneticTargets = a.getBoolean(R.styleable.GlowPadView_magneticTargets, mMagneticTargets);
-
- int pointId = getResourceId(a, R.styleable.GlowPadView_pointDrawable);
- Drawable pointDrawable = pointId != 0 ? context.getDrawable(pointId) : null;
- mGlowRadius = a.getDimension(R.styleable.GlowPadView_glowRadius, 0.0f);
-
- mPointCloud = new PointCloud(pointDrawable);
- mPointCloud.makePointCloud(mInnerRadius, mOuterRadius);
- mPointCloud.glowManager.setRadius(mGlowRadius);
-
- TypedValue outValue = new TypedValue();
-
- // Read array of target drawables
- if (a.getValue(R.styleable.GlowPadView_targetDrawables, outValue)) {
- internalSetTargetResources(outValue.resourceId);
- }
- if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
- throw new IllegalStateException("Must specify at least one target drawable");
- }
-
- // Read array of target descriptions
- if (a.getValue(R.styleable.GlowPadView_targetDescriptions, outValue)) {
- final int resourceId = outValue.resourceId;
- if (resourceId == 0) {
- throw new IllegalStateException("Must specify target descriptions");
- }
- setTargetDescriptionsResourceId(resourceId);
- }
-
- // Read array of direction descriptions
- if (a.getValue(R.styleable.GlowPadView_directionDescriptions, outValue)) {
- final int resourceId = outValue.resourceId;
- if (resourceId == 0) {
- throw new IllegalStateException("Must specify direction descriptions");
- }
- setDirectionDescriptionsResourceId(resourceId);
- }
-
- mGravity = a.getInt(R.styleable.GlowPadView_gravity, Gravity.TOP);
-
- a.recycle();
-
- setVibrateEnabled(mVibrationDuration > 0);
-
- assignDefaultsIfNeeded();
- }
-
- private int getResourceId(TypedArray a, int id) {
- TypedValue tv = a.peekValue(id);
- return tv == null ? 0 : tv.resourceId;
- }
-
- private void dump() {
- Log.v(TAG, "Outer Radius = " + mOuterRadius);
- Log.v(TAG, "SnapMargin = " + mSnapMargin);
- Log.v(TAG, "FeedbackCount = " + mFeedbackCount);
- Log.v(TAG, "VibrationDuration = " + mVibrationDuration);
- Log.v(TAG, "GlowRadius = " + mGlowRadius);
- Log.v(TAG, "WaveCenterX = " + mWaveCenterX);
- Log.v(TAG, "WaveCenterY = " + mWaveCenterY);
- }
-
- public void suspendAnimations() {
- mWaveAnimations.setSuspended(true);
- mTargetAnimations.setSuspended(true);
- mGlowAnimations.setSuspended(true);
- }
-
- public void resumeAnimations() {
- mWaveAnimations.setSuspended(false);
- mTargetAnimations.setSuspended(false);
- mGlowAnimations.setSuspended(false);
- mWaveAnimations.start();
- mTargetAnimations.start();
- mGlowAnimations.start();
- }
-
- @Override
- protected int getSuggestedMinimumWidth() {
- // View should be large enough to contain the background + handle and
- // target drawable on either edge.
- return (int) (Math.max(mOuterRing.getWidth(), 2 * mOuterRadius) + mMaxTargetWidth);
- }
-
- @Override
- protected int getSuggestedMinimumHeight() {
- // View should be large enough to contain the unlock ring + target and
- // target drawable on either edge
- return (int) (Math.max(mOuterRing.getHeight(), 2 * mOuterRadius) + mMaxTargetHeight);
- }
-
- /**
- * This gets the suggested width accounting for the ring's scale factor.
- */
- protected int getScaledSuggestedMinimumWidth() {
- return (int) (mRingScaleFactor * Math.max(mOuterRing.getWidth(), 2 * mOuterRadius)
- + mMaxTargetWidth);
- }
-
- /**
- * This gets the suggested height accounting for the ring's scale factor.
- */
- protected int getScaledSuggestedMinimumHeight() {
- return (int) (mRingScaleFactor * Math.max(mOuterRing.getHeight(), 2 * mOuterRadius)
- + mMaxTargetHeight);
- }
-
- private int resolveMeasured(int measureSpec, int desired)
- {
- int result = 0;
- int specSize = MeasureSpec.getSize(measureSpec);
- switch (MeasureSpec.getMode(measureSpec)) {
- case MeasureSpec.UNSPECIFIED:
- result = desired;
- break;
- case MeasureSpec.AT_MOST:
- result = Math.min(specSize, desired);
- break;
- case MeasureSpec.EXACTLY:
- default:
- result = specSize;
- }
- return result;
- }
-
- private void switchToState(int state, float x, float y) {
- switch (state) {
- case STATE_IDLE:
- deactivateTargets();
- hideGlow(0, 0, 0.0f, null);
- startBackgroundAnimation(0, 0.0f);
- mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
- mHandleDrawable.setAlpha(1.0f);
- break;
-
- case STATE_START:
- startBackgroundAnimation(0, 0.0f);
- break;
-
- case STATE_FIRST_TOUCH:
- mHandleDrawable.setAlpha(0.0f);
- deactivateTargets();
- showTargets(true);
- startBackgroundAnimation(INITIAL_SHOW_HANDLE_DURATION, 1.0f);
- setGrabbedState(OnTriggerListener.CENTER_HANDLE);
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- announceTargets();
- }
- break;
-
- case STATE_TRACKING:
- mHandleDrawable.setAlpha(0.0f);
- showGlow(REVEAL_GLOW_DURATION , REVEAL_GLOW_DELAY, 1.0f, null);
- break;
-
- case STATE_SNAP:
- // TODO: Add transition states (see list_selector_background_transition.xml)
- mHandleDrawable.setAlpha(0.0f);
- showGlow(REVEAL_GLOW_DURATION , REVEAL_GLOW_DELAY, 0.0f, null);
- break;
-
- case STATE_FINISH:
- doFinish();
- break;
- }
- }
-
- private void showGlow(int duration, int delay, float finalAlpha,
- AnimatorListener finishListener) {
- mGlowAnimations.cancel();
- mGlowAnimations.add(Tweener.to(mPointCloud.glowManager, duration,
- "ease", Ease.Cubic.easeIn,
- "delay", delay,
- "alpha", finalAlpha,
- "onUpdate", mUpdateListener,
- "onComplete", finishListener));
- mGlowAnimations.start();
- }
-
- private void hideGlow(int duration, int delay, float finalAlpha,
- AnimatorListener finishListener) {
- mGlowAnimations.cancel();
- mGlowAnimations.add(Tweener.to(mPointCloud.glowManager, duration,
- "ease", Ease.Quart.easeOut,
- "delay", delay,
- "alpha", finalAlpha,
- "x", 0.0f,
- "y", 0.0f,
- "onUpdate", mUpdateListener,
- "onComplete", finishListener));
- mGlowAnimations.start();
- }
-
- private void deactivateTargets() {
- final int count = mTargetDrawables.size();
- for (int i = 0; i < count; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- target.setState(TargetDrawable.STATE_INACTIVE);
- }
- mActiveTarget = -1;
- }
-
- /**
- * Dispatches a trigger event to listener. Ignored if a listener is not set.
- * @param whichTarget the target that was triggered.
- */
- private void dispatchTriggerEvent(int whichTarget) {
- vibrate();
- if (mOnTriggerListener != null) {
- mOnTriggerListener.onTrigger(this, whichTarget);
- }
- }
-
- private void dispatchOnFinishFinalAnimation() {
- if (mOnTriggerListener != null) {
- mOnTriggerListener.onFinishFinalAnimation();
- }
- }
-
- private void doFinish() {
- final int activeTarget = mActiveTarget;
- final boolean targetHit = activeTarget != -1;
-
- if (targetHit) {
- if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
-
- highlightSelected(activeTarget);
-
- // Inform listener of any active targets. Typically only one will be active.
- hideGlow(RETURN_TO_HOME_DURATION, RETURN_TO_HOME_DELAY, 0.0f, mResetListener);
- dispatchTriggerEvent(activeTarget);
- if (!mAlwaysTrackFinger) {
- // Force ring and targets to finish animation to final expanded state
- mTargetAnimations.stop();
- }
- } else {
- // Animate handle back to the center based on current state.
- hideGlow(HIDE_ANIMATION_DURATION, 0, 0.0f, mResetListenerWithPing);
- hideTargets(true, false);
- }
-
- setGrabbedState(OnTriggerListener.NO_HANDLE);
- }
-
- private void highlightSelected(int activeTarget) {
- // Highlight the given target and fade others
- mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
- hideUnselected(activeTarget);
- }
-
- private void hideUnselected(int active) {
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- if (i != active) {
- mTargetDrawables.get(i).setAlpha(0.0f);
- }
- }
- }
-
- private void hideTargets(boolean animate, boolean expanded) {
- mTargetAnimations.cancel();
- // Note: these animations should complete at the same time so that we can swap out
- // the target assets asynchronously from the setTargetResources() call.
- mAnimatingTargets = animate;
- final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
- final int delay = animate ? HIDE_ANIMATION_DELAY : 0;
-
- final float targetScale = expanded ?
- TARGET_SCALE_EXPANDED : TARGET_SCALE_COLLAPSED;
- final int length = mTargetDrawables.size();
- final TimeInterpolator interpolator = Ease.Cubic.easeOut;
- for (int i = 0; i < length; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- target.setState(TargetDrawable.STATE_INACTIVE);
- mTargetAnimations.add(Tweener.to(target, duration,
- "ease", interpolator,
- "alpha", 0.0f,
- "scaleX", targetScale,
- "scaleY", targetScale,
- "delay", delay,
- "onUpdate", mUpdateListener));
- }
-
- float ringScaleTarget = expanded ?
- RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED;
- ringScaleTarget *= mRingScaleFactor;
- mTargetAnimations.add(Tweener.to(mOuterRing, duration,
- "ease", interpolator,
- "alpha", 0.0f,
- "scaleX", ringScaleTarget,
- "scaleY", ringScaleTarget,
- "delay", delay,
- "onUpdate", mUpdateListener,
- "onComplete", mTargetUpdateListener));
-
- mTargetAnimations.start();
- }
-
- private void showTargets(boolean animate) {
- mTargetAnimations.stop();
- mAnimatingTargets = animate;
- final int delay = animate ? SHOW_ANIMATION_DELAY : 0;
- final int duration = animate ? SHOW_ANIMATION_DURATION : 0;
- final int length = mTargetDrawables.size();
- for (int i = 0; i < length; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- target.setState(TargetDrawable.STATE_INACTIVE);
- mTargetAnimations.add(Tweener.to(target, duration,
- "ease", Ease.Cubic.easeOut,
- "alpha", 1.0f,
- "scaleX", 1.0f,
- "scaleY", 1.0f,
- "delay", delay,
- "onUpdate", mUpdateListener));
- }
-
- float ringScale = mRingScaleFactor * RING_SCALE_EXPANDED;
- mTargetAnimations.add(Tweener.to(mOuterRing, duration,
- "ease", Ease.Cubic.easeOut,
- "alpha", 1.0f,
- "scaleX", ringScale,
- "scaleY", ringScale,
- "delay", delay,
- "onUpdate", mUpdateListener,
- "onComplete", mTargetUpdateListener));
-
- mTargetAnimations.start();
- }
-
- private void vibrate() {
- final boolean hapticEnabled = Settings.System.getIntForUser(
- mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
- UserHandle.USER_CURRENT) != 0;
- if (mVibrator != null && hapticEnabled) {
- mVibrator.vibrate(mVibrationDuration, VIBRATION_ATTRIBUTES);
- }
- }
-
- private ArrayList<TargetDrawable> loadDrawableArray(int resourceId) {
- Resources res = getContext().getResources();
- TypedArray array = res.obtainTypedArray(resourceId);
- final int count = array.length();
- ArrayList<TargetDrawable> drawables = new ArrayList<TargetDrawable>(count);
- for (int i = 0; i < count; i++) {
- TypedValue value = array.peekValue(i);
- TargetDrawable target = new TargetDrawable(res, value != null ? value.resourceId : 0);
- drawables.add(target);
- }
- array.recycle();
- return drawables;
- }
-
- private void internalSetTargetResources(int resourceId) {
- final ArrayList<TargetDrawable> targets = loadDrawableArray(resourceId);
- mTargetDrawables = targets;
- mTargetResourceId = resourceId;
-
- int maxWidth = mHandleDrawable.getWidth();
- int maxHeight = mHandleDrawable.getHeight();
- final int count = targets.size();
- for (int i = 0; i < count; i++) {
- TargetDrawable target = targets.get(i);
- maxWidth = Math.max(maxWidth, target.getWidth());
- maxHeight = Math.max(maxHeight, target.getHeight());
- }
- if (mMaxTargetWidth != maxWidth || mMaxTargetHeight != maxHeight) {
- mMaxTargetWidth = maxWidth;
- mMaxTargetHeight = maxHeight;
- requestLayout(); // required to resize layout and call updateTargetPositions()
- } else {
- updateTargetPositions(mWaveCenterX, mWaveCenterY);
- updatePointCloudPosition(mWaveCenterX, mWaveCenterY);
- }
- }
-
- /**
- * Loads an array of drawables from the given resourceId.
- *
- * @param resourceId
- */
- public void setTargetResources(int resourceId) {
- if (mAnimatingTargets) {
- // postpone this change until we return to the initial state
- mNewTargetResources = resourceId;
- } else {
- internalSetTargetResources(resourceId);
- }
- }
-
- public int getTargetResourceId() {
- return mTargetResourceId;
- }
-
- /**
- * Sets the resource id specifying the target descriptions for accessibility.
- *
- * @param resourceId The resource id.
- */
- public void setTargetDescriptionsResourceId(int resourceId) {
- mTargetDescriptionsResourceId = resourceId;
- if (mTargetDescriptions != null) {
- mTargetDescriptions.clear();
- }
- }
-
- /**
- * Gets the resource id specifying the target descriptions for accessibility.
- *
- * @return The resource id.
- */
- public int getTargetDescriptionsResourceId() {
- return mTargetDescriptionsResourceId;
- }
-
- /**
- * Sets the resource id specifying the target direction descriptions for accessibility.
- *
- * @param resourceId The resource id.
- */
- public void setDirectionDescriptionsResourceId(int resourceId) {
- mDirectionDescriptionsResourceId = resourceId;
- if (mDirectionDescriptions != null) {
- mDirectionDescriptions.clear();
- }
- }
-
- /**
- * Gets the resource id specifying the target direction descriptions.
- *
- * @return The resource id.
- */
- public int getDirectionDescriptionsResourceId() {
- return mDirectionDescriptionsResourceId;
- }
-
- /**
- * Enable or disable vibrate on touch.
- *
- * @param enabled
- */
- public void setVibrateEnabled(boolean enabled) {
- if (enabled && mVibrator == null) {
- mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
- } else {
- mVibrator = null;
- }
- }
-
- /**
- * Starts wave animation.
- *
- */
- public void ping() {
- if (mFeedbackCount > 0) {
- boolean doWaveAnimation = true;
- final AnimationBundle waveAnimations = mWaveAnimations;
-
- // Don't do a wave if there's already one in progress
- if (waveAnimations.size() > 0 && waveAnimations.get(0).animator.isRunning()) {
- long t = waveAnimations.get(0).animator.getCurrentPlayTime();
- if (t < WAVE_ANIMATION_DURATION/2) {
- doWaveAnimation = false;
- }
- }
-
- if (doWaveAnimation) {
- startWaveAnimation();
- }
- }
- }
-
- private void stopAndHideWaveAnimation() {
- mWaveAnimations.cancel();
- mPointCloud.waveManager.setAlpha(0.0f);
- }
-
- private void startWaveAnimation() {
- mWaveAnimations.cancel();
- mPointCloud.waveManager.setAlpha(1.0f);
- mPointCloud.waveManager.setRadius(mHandleDrawable.getWidth()/2.0f);
- mWaveAnimations.add(Tweener.to(mPointCloud.waveManager, WAVE_ANIMATION_DURATION,
- "ease", Ease.Quad.easeOut,
- "delay", 0,
- "radius", 2.0f * mOuterRadius,
- "onUpdate", mUpdateListener,
- "onComplete",
- new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- mPointCloud.waveManager.setRadius(0.0f);
- mPointCloud.waveManager.setAlpha(0.0f);
- }
- }));
- mWaveAnimations.start();
- }
-
- /**
- * Resets the widget to default state and cancels all animation. If animate is 'true', will
- * animate objects into place. Otherwise, objects will snap back to place.
- *
- * @param animate
- */
- public void reset(boolean animate) {
- mGlowAnimations.stop();
- mTargetAnimations.stop();
- startBackgroundAnimation(0, 0.0f);
- stopAndHideWaveAnimation();
- hideTargets(animate, false);
- hideGlow(0, 0, 0.0f, null);
- Tweener.reset();
- }
-
- private void startBackgroundAnimation(int duration, float alpha) {
- final Drawable background = getBackground();
- if (mAlwaysTrackFinger && background != null) {
- if (mBackgroundAnimator != null) {
- mBackgroundAnimator.animator.cancel();
- }
- mBackgroundAnimator = Tweener.to(background, duration,
- "ease", Ease.Cubic.easeIn,
- "alpha", (int)(255.0f * alpha),
- "delay", SHOW_ANIMATION_DELAY);
- mBackgroundAnimator.animator.start();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- final int action = event.getActionMasked();
- boolean handled = false;
- switch (action) {
- case MotionEvent.ACTION_POINTER_DOWN:
- case MotionEvent.ACTION_DOWN:
- if (DEBUG) Log.v(TAG, "*** DOWN ***");
- handleDown(event);
- handleMove(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (DEBUG) Log.v(TAG, "*** MOVE ***");
- handleMove(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- case MotionEvent.ACTION_UP:
- if (DEBUG) Log.v(TAG, "*** UP ***");
- handleMove(event);
- handleUp(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_CANCEL:
- if (DEBUG) Log.v(TAG, "*** CANCEL ***");
- handleMove(event);
- handleCancel(event);
- handled = true;
- break;
-
- }
- invalidate();
- return handled ? true : super.onTouchEvent(event);
- }
-
- private void updateGlowPosition(float x, float y) {
- float dx = x - mOuterRing.getX();
- float dy = y - mOuterRing.getY();
- dx *= 1f / mRingScaleFactor;
- dy *= 1f / mRingScaleFactor;
- mPointCloud.glowManager.setX(mOuterRing.getX() + dx);
- mPointCloud.glowManager.setY(mOuterRing.getY() + dy);
- }
-
- private void handleDown(MotionEvent event) {
- int actionIndex = event.getActionIndex();
- float eventX = event.getX(actionIndex);
- float eventY = event.getY(actionIndex);
- switchToState(STATE_START, eventX, eventY);
- if (!trySwitchToFirstTouchState(eventX, eventY)) {
- mDragging = false;
- } else {
- mPointerId = event.getPointerId(actionIndex);
- updateGlowPosition(eventX, eventY);
- }
- }
-
- private void handleUp(MotionEvent event) {
- if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
- int actionIndex = event.getActionIndex();
- if (event.getPointerId(actionIndex) == mPointerId) {
- switchToState(STATE_FINISH, event.getX(actionIndex), event.getY(actionIndex));
- }
- }
-
- private void handleCancel(MotionEvent event) {
- if (DEBUG && mDragging) Log.v(TAG, "** Handle CANCEL");
-
- // Drop the active target if canceled.
- mActiveTarget = -1;
-
- int actionIndex = event.findPointerIndex(mPointerId);
- actionIndex = actionIndex == -1 ? 0 : actionIndex;
- switchToState(STATE_FINISH, event.getX(actionIndex), event.getY(actionIndex));
- }
-
- private void handleMove(MotionEvent event) {
- int activeTarget = -1;
- final int historySize = event.getHistorySize();
- ArrayList<TargetDrawable> targets = mTargetDrawables;
- int ntargets = targets.size();
- float x = 0.0f;
- float y = 0.0f;
- float activeAngle = 0.0f;
- int actionIndex = event.findPointerIndex(mPointerId);
-
- if (actionIndex == -1) {
- return; // no data for this pointer
- }
-
- for (int k = 0; k < historySize + 1; k++) {
- float eventX = k < historySize ? event.getHistoricalX(actionIndex, k)
- : event.getX(actionIndex);
- float eventY = k < historySize ? event.getHistoricalY(actionIndex, k)
- : event.getY(actionIndex);
- // tx and ty are relative to wave center
- float tx = eventX - mWaveCenterX;
- float ty = eventY - mWaveCenterY;
- float touchRadius = (float) Math.hypot(tx, ty);
- final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
- float limitX = tx * scale;
- float limitY = ty * scale;
- double angleRad = Math.atan2(-ty, tx);
-
- if (!mDragging) {
- trySwitchToFirstTouchState(eventX, eventY);
- }
-
- if (mDragging) {
- // For multiple targets, snap to the one that matches
- final float snapRadius = mRingScaleFactor * mOuterRadius - mSnapMargin;
- final float snapDistance2 = snapRadius * snapRadius;
- // Find first target in range
- for (int i = 0; i < ntargets; i++) {
- TargetDrawable target = targets.get(i);
-
- double targetMinRad = mFirstItemOffset + (i - 0.5) * 2 * Math.PI / ntargets;
- double targetMaxRad = mFirstItemOffset + (i + 0.5) * 2 * Math.PI / ntargets;
- if (target.isEnabled()) {
- boolean angleMatches =
- (angleRad > targetMinRad && angleRad <= targetMaxRad) ||
- (angleRad + 2 * Math.PI > targetMinRad &&
- angleRad + 2 * Math.PI <= targetMaxRad) ||
- (angleRad - 2 * Math.PI > targetMinRad &&
- angleRad - 2 * Math.PI <= targetMaxRad);
- if (angleMatches && (dist2(tx, ty) > snapDistance2)) {
- activeTarget = i;
- activeAngle = (float) -angleRad;
- }
- }
- }
- }
- x = limitX;
- y = limitY;
- }
-
- if (!mDragging) {
- return;
- }
-
- if (activeTarget != -1) {
- switchToState(STATE_SNAP, x,y);
- updateGlowPosition(x, y);
- } else {
- switchToState(STATE_TRACKING, x, y);
- updateGlowPosition(x, y);
- }
-
- if (mActiveTarget != activeTarget) {
- // Defocus the old target
- if (mActiveTarget != -1) {
- TargetDrawable target = targets.get(mActiveTarget);
- if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
- target.setState(TargetDrawable.STATE_INACTIVE);
- }
- if (mMagneticTargets) {
- updateTargetPosition(mActiveTarget, mWaveCenterX, mWaveCenterY);
- }
- }
- // Focus the new target
- if (activeTarget != -1) {
- TargetDrawable target = targets.get(activeTarget);
- if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
- target.setState(TargetDrawable.STATE_FOCUSED);
- }
- if (mMagneticTargets) {
- updateTargetPosition(activeTarget, mWaveCenterX, mWaveCenterY, activeAngle);
- }
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- String targetContentDescription = getTargetDescription(activeTarget);
- announceForAccessibility(targetContentDescription);
- }
- }
- }
- mActiveTarget = activeTarget;
- }
-
- @Override
- public boolean onHoverEvent(MotionEvent event) {
- if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
- final int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_HOVER_ENTER:
- event.setAction(MotionEvent.ACTION_DOWN);
- break;
- case MotionEvent.ACTION_HOVER_MOVE:
- event.setAction(MotionEvent.ACTION_MOVE);
- break;
- case MotionEvent.ACTION_HOVER_EXIT:
- event.setAction(MotionEvent.ACTION_UP);
- break;
- }
- onTouchEvent(event);
- event.setAction(action);
- }
- super.onHoverEvent(event);
- return true;
- }
-
- /**
- * Sets the current grabbed state, and dispatches a grabbed state change
- * event to our listener.
- */
- private void setGrabbedState(int newState) {
- if (newState != mGrabbedState) {
- if (newState != OnTriggerListener.NO_HANDLE) {
- vibrate();
- }
- mGrabbedState = newState;
- if (mOnTriggerListener != null) {
- if (newState == OnTriggerListener.NO_HANDLE) {
- mOnTriggerListener.onReleased(this, OnTriggerListener.CENTER_HANDLE);
- } else {
- mOnTriggerListener.onGrabbed(this, OnTriggerListener.CENTER_HANDLE);
- }
- mOnTriggerListener.onGrabbedStateChange(this, newState);
- }
- }
- }
-
- private boolean trySwitchToFirstTouchState(float x, float y) {
- final float tx = x - mWaveCenterX;
- final float ty = y - mWaveCenterY;
- if (mAlwaysTrackFinger || dist2(tx,ty) <= getScaledGlowRadiusSquared()) {
- if (DEBUG) Log.v(TAG, "** Handle HIT");
- switchToState(STATE_FIRST_TOUCH, x, y);
- updateGlowPosition(tx, ty);
- mDragging = true;
- return true;
- }
- return false;
- }
-
- private void assignDefaultsIfNeeded() {
- if (mOuterRadius == 0.0f) {
- mOuterRadius = Math.max(mOuterRing.getWidth(), mOuterRing.getHeight())/2.0f;
- }
- if (mSnapMargin == 0.0f) {
- mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
- }
- if (mInnerRadius == 0.0f) {
- mInnerRadius = mHandleDrawable.getWidth() / 10.0f;
- }
- }
-
- private void computeInsets(int dx, int dy) {
- final int layoutDirection = getLayoutDirection();
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-
- switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- mHorizontalInset = 0;
- break;
- case Gravity.RIGHT:
- mHorizontalInset = dx;
- break;
- case Gravity.CENTER_HORIZONTAL:
- default:
- mHorizontalInset = dx / 2;
- break;
- }
- switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
- case Gravity.TOP:
- mVerticalInset = 0;
- break;
- case Gravity.BOTTOM:
- mVerticalInset = dy;
- break;
- case Gravity.CENTER_VERTICAL:
- default:
- mVerticalInset = dy / 2;
- break;
- }
- }
-
- /**
- * Given the desired width and height of the ring and the allocated width and height, compute
- * how much we need to scale the ring.
- */
- private float computeScaleFactor(int desiredWidth, int desiredHeight,
- int actualWidth, int actualHeight) {
-
- // Return unity if scaling is not allowed.
- if (!mAllowScaling) return 1f;
-
- final int layoutDirection = getLayoutDirection();
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-
- float scaleX = 1f;
- float scaleY = 1f;
-
- // We use the gravity as a cue for whether we want to scale on a particular axis.
- // We only scale to fit horizontally if we're not pinned to the left or right. Likewise,
- // we only scale to fit vertically if we're not pinned to the top or bottom. In these
- // cases, we want the ring to hang off the side or top/bottom, respectively.
- switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- case Gravity.RIGHT:
- break;
- case Gravity.CENTER_HORIZONTAL:
- default:
- if (desiredWidth > actualWidth) {
- scaleX = (1f * actualWidth - mMaxTargetWidth) /
- (desiredWidth - mMaxTargetWidth);
- }
- break;
- }
- switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
- case Gravity.TOP:
- case Gravity.BOTTOM:
- break;
- case Gravity.CENTER_VERTICAL:
- default:
- if (desiredHeight > actualHeight) {
- scaleY = (1f * actualHeight - mMaxTargetHeight) /
- (desiredHeight - mMaxTargetHeight);
- }
- break;
- }
- return Math.min(scaleX, scaleY);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int minimumWidth = getSuggestedMinimumWidth();
- final int minimumHeight = getSuggestedMinimumHeight();
- int computedWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
- int computedHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
-
- mRingScaleFactor = computeScaleFactor(minimumWidth, minimumHeight,
- computedWidth, computedHeight);
-
- int scaledWidth = getScaledSuggestedMinimumWidth();
- int scaledHeight = getScaledSuggestedMinimumHeight();
-
- computeInsets(computedWidth - scaledWidth, computedHeight - scaledHeight);
- setMeasuredDimension(computedWidth, computedHeight);
- }
-
- private float getRingWidth() {
- return mRingScaleFactor * Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
- }
-
- private float getRingHeight() {
- return mRingScaleFactor * Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- final int width = right - left;
- final int height = bottom - top;
-
- // Target placement width/height. This puts the targets on the greater of the ring
- // width or the specified outer radius.
- final float placementWidth = getRingWidth();
- final float placementHeight = getRingHeight();
- float newWaveCenterX = mHorizontalInset
- + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
- float newWaveCenterY = mVerticalInset
- + Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
-
- if (mInitialLayout) {
- stopAndHideWaveAnimation();
- hideTargets(false, false);
- mInitialLayout = false;
- }
-
- mOuterRing.setPositionX(newWaveCenterX);
- mOuterRing.setPositionY(newWaveCenterY);
-
- mPointCloud.setScale(mRingScaleFactor);
-
- mHandleDrawable.setPositionX(newWaveCenterX);
- mHandleDrawable.setPositionY(newWaveCenterY);
-
- updateTargetPositions(newWaveCenterX, newWaveCenterY);
- updatePointCloudPosition(newWaveCenterX, newWaveCenterY);
- updateGlowPosition(newWaveCenterX, newWaveCenterY);
-
- mWaveCenterX = newWaveCenterX;
- mWaveCenterY = newWaveCenterY;
-
- if (DEBUG) dump();
- }
-
- private void updateTargetPosition(int i, float centerX, float centerY) {
- final float angle = getAngle(getSliceAngle(), i);
- updateTargetPosition(i, centerX, centerY, angle);
- }
-
- private void updateTargetPosition(int i, float centerX, float centerY, float angle) {
- final float placementRadiusX = getRingWidth() / 2;
- final float placementRadiusY = getRingHeight() / 2;
- if (i >= 0) {
- ArrayList<TargetDrawable> targets = mTargetDrawables;
- final TargetDrawable targetIcon = targets.get(i);
- targetIcon.setPositionX(centerX);
- targetIcon.setPositionY(centerY);
- targetIcon.setX(placementRadiusX * (float) Math.cos(angle));
- targetIcon.setY(placementRadiusY * (float) Math.sin(angle));
- }
- }
-
- private void updateTargetPositions(float centerX, float centerY) {
- updateTargetPositions(centerX, centerY, false);
- }
-
- private void updateTargetPositions(float centerX, float centerY, boolean skipActive) {
- final int size = mTargetDrawables.size();
- final float alpha = getSliceAngle();
- // Reposition the target drawables if the view changed.
- for (int i = 0; i < size; i++) {
- if (!skipActive || i != mActiveTarget) {
- updateTargetPosition(i, centerX, centerY, getAngle(alpha, i));
- }
- }
- }
-
- private float getAngle(float alpha, int i) {
- return mFirstItemOffset + alpha * i;
- }
-
- private float getSliceAngle() {
- return (float) (-2.0f * Math.PI / mTargetDrawables.size());
- }
-
- private void updatePointCloudPosition(float centerX, float centerY) {
- mPointCloud.setCenter(centerX, centerY);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- mPointCloud.draw(canvas);
- mOuterRing.draw(canvas);
- final int ntargets = mTargetDrawables.size();
- for (int i = 0; i < ntargets; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- if (target != null) {
- target.draw(canvas);
- }
- }
- mHandleDrawable.draw(canvas);
- }
-
- public void setOnTriggerListener(OnTriggerListener listener) {
- mOnTriggerListener = listener;
- }
-
- private float square(float d) {
- return d * d;
- }
-
- private float dist2(float dx, float dy) {
- return dx*dx + dy*dy;
- }
-
- private float getScaledGlowRadiusSquared() {
- final float scaledTapRadius;
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- scaledTapRadius = TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED * mGlowRadius;
- } else {
- scaledTapRadius = mGlowRadius;
- }
- return square(scaledTapRadius);
- }
-
- private void announceTargets() {
- StringBuilder utterance = new StringBuilder();
- final int targetCount = mTargetDrawables.size();
- for (int i = 0; i < targetCount; i++) {
- String targetDescription = getTargetDescription(i);
- String directionDescription = getDirectionDescription(i);
- if (!TextUtils.isEmpty(targetDescription)
- && !TextUtils.isEmpty(directionDescription)) {
- String text = String.format(directionDescription, targetDescription);
- utterance.append(text);
- }
- }
- if (utterance.length() > 0) {
- announceForAccessibility(utterance.toString());
- }
- }
-
- private String getTargetDescription(int index) {
- if (mTargetDescriptions == null || mTargetDescriptions.isEmpty()) {
- mTargetDescriptions = loadDescriptions(mTargetDescriptionsResourceId);
- if (mTargetDrawables.size() != mTargetDescriptions.size()) {
- Log.w(TAG, "The number of target drawables must be"
- + " equal to the number of target descriptions.");
- return null;
- }
- }
- return mTargetDescriptions.get(index);
- }
-
- private String getDirectionDescription(int index) {
- if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) {
- mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId);
- if (mTargetDrawables.size() != mDirectionDescriptions.size()) {
- Log.w(TAG, "The number of target drawables must be"
- + " equal to the number of direction descriptions.");
- return null;
- }
- }
- return mDirectionDescriptions.get(index);
- }
-
- private ArrayList<String> loadDescriptions(int resourceId) {
- TypedArray array = getContext().getResources().obtainTypedArray(resourceId);
- final int count = array.length();
- ArrayList<String> targetContentDescriptions = new ArrayList<String>(count);
- for (int i = 0; i < count; i++) {
- String contentDescription = array.getString(i);
- targetContentDescriptions.add(contentDescription);
- }
- array.recycle();
- return targetContentDescriptions;
- }
-
- public int getResourceIdForTarget(int index) {
- final TargetDrawable drawable = mTargetDrawables.get(index);
- return drawable == null ? 0 : drawable.getResourceId();
- }
-
- public void setEnableTarget(int resourceId, boolean enabled) {
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- final TargetDrawable target = mTargetDrawables.get(i);
- if (target.getResourceId() == resourceId) {
- target.setEnabled(enabled);
- break; // should never be more than one match
- }
- }
- }
-
- /**
- * Gets the position of a target in the array that matches the given resource.
- * @param resourceId
- * @return the index or -1 if not found
- */
- public int getTargetPosition(int resourceId) {
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- final TargetDrawable target = mTargetDrawables.get(i);
- if (target.getResourceId() == resourceId) {
- return i; // should never be more than one match
- }
- }
- return -1;
- }
-
- private boolean replaceTargetDrawables(Resources res, int existingResourceId,
- int newResourceId) {
- if (existingResourceId == 0 || newResourceId == 0) {
- return false;
- }
-
- boolean result = false;
- final ArrayList<TargetDrawable> drawables = mTargetDrawables;
- final int size = drawables.size();
- for (int i = 0; i < size; i++) {
- final TargetDrawable target = drawables.get(i);
- if (target != null && target.getResourceId() == existingResourceId) {
- target.setDrawable(res, newResourceId);
- result = true;
- }
- }
-
- if (result) {
- requestLayout(); // in case any given drawable's size changes
- }
-
- return result;
- }
-
- /**
- * Searches the given package for a resource to use to replace the Drawable on the
- * target with the given resource id
- * @param component of the .apk that contains the resource
- * @param name of the metadata in the .apk
- * @param existingResId the resource id of the target to search for
- * @return true if found in the given package and replaced at least one target Drawables
- */
- public boolean replaceTargetDrawablesIfPresent(ComponentName component, String name,
- int existingResId) {
- if (existingResId == 0) return false;
-
- boolean replaced = false;
- if (component != null) {
- try {
- PackageManager packageManager = mContext.getPackageManager();
- // Look for the search icon specified in the activity meta-data
- Bundle metaData = packageManager.getActivityInfo(
- component, PackageManager.GET_META_DATA).metaData;
- if (metaData != null) {
- int iconResId = metaData.getInt(name);
- if (iconResId != 0) {
- Resources res = packageManager.getResourcesForActivity(component);
- replaced = replaceTargetDrawables(res, existingResId, iconResId);
- }
- }
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Failed to swap drawable; "
- + component.flattenToShortString() + " not found", e);
- } catch (Resources.NotFoundException nfe) {
- Log.w(TAG, "Failed to swap drawable from "
- + component.flattenToShortString(), nfe);
- }
- }
- if (!replaced) {
- // Restore the original drawable
- replaceTargetDrawables(mContext.getResources(), existingResId, existingResId);
- }
- return replaced;
- }
-}
diff --git a/core/java/com/android/internal/widget/multiwaveview/PointCloud.java b/core/java/com/android/internal/widget/multiwaveview/PointCloud.java
deleted file mode 100644
index 6f26b99..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/PointCloud.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget.multiwaveview;
-
-import java.util.ArrayList;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-
-public class PointCloud {
- private static final float MIN_POINT_SIZE = 2.0f;
- private static final float MAX_POINT_SIZE = 4.0f;
- private static final int INNER_POINTS = 8;
- private static final String TAG = "PointCloud";
- private ArrayList<Point> mPointCloud = new ArrayList<Point>();
- private Drawable mDrawable;
- private float mCenterX;
- private float mCenterY;
- private Paint mPaint;
- private float mScale = 1.0f;
- private static final float PI = (float) Math.PI;
-
- // These allow us to have multiple concurrent animations.
- WaveManager waveManager = new WaveManager();
- GlowManager glowManager = new GlowManager();
- private float mOuterRadius;
-
- public class WaveManager {
- private float radius = 50;
- private float alpha = 0.0f;
-
- public void setRadius(float r) {
- radius = r;
- }
-
- public float getRadius() {
- return radius;
- }
-
- public void setAlpha(float a) {
- alpha = a;
- }
-
- public float getAlpha() {
- return alpha;
- }
- };
-
- public class GlowManager {
- private float x;
- private float y;
- private float radius = 0.0f;
- private float alpha = 0.0f;
-
- public void setX(float x1) {
- x = x1;
- }
-
- public float getX() {
- return x;
- }
-
- public void setY(float y1) {
- y = y1;
- }
-
- public float getY() {
- return y;
- }
-
- public void setAlpha(float a) {
- alpha = a;
- }
-
- public float getAlpha() {
- return alpha;
- }
-
- public void setRadius(float r) {
- radius = r;
- }
-
- public float getRadius() {
- return radius;
- }
- }
-
- class Point {
- float x;
- float y;
- float radius;
-
- public Point(float x2, float y2, float r) {
- x = (float) x2;
- y = (float) y2;
- radius = r;
- }
- }
-
- public PointCloud(Drawable drawable) {
- mPaint = new Paint();
- mPaint.setFilterBitmap(true);
- mPaint.setColor(Color.rgb(255, 255, 255)); // TODO: make configurable
- mPaint.setAntiAlias(true);
- mPaint.setDither(true);
-
- mDrawable = drawable;
- if (mDrawable != null) {
- drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
- }
- }
-
- public void setCenter(float x, float y) {
- mCenterX = x;
- mCenterY = y;
- }
-
- public void makePointCloud(float innerRadius, float outerRadius) {
- if (innerRadius == 0) {
- Log.w(TAG, "Must specify an inner radius");
- return;
- }
- mOuterRadius = outerRadius;
- mPointCloud.clear();
- final float pointAreaRadius = (outerRadius - innerRadius);
- final float ds = (2.0f * PI * innerRadius / INNER_POINTS);
- final int bands = (int) Math.round(pointAreaRadius / ds);
- final float dr = pointAreaRadius / bands;
- float r = innerRadius;
- for (int b = 0; b <= bands; b++, r += dr) {
- float circumference = 2.0f * PI * r;
- final int pointsInBand = (int) (circumference / ds);
- float eta = PI/2.0f;
- float dEta = 2.0f * PI / pointsInBand;
- for (int i = 0; i < pointsInBand; i++) {
- float x = r * (float) Math.cos(eta);
- float y = r * (float) Math.sin(eta);
- eta += dEta;
- mPointCloud.add(new Point(x, y, r));
- }
- }
- }
-
- public void setScale(float scale) {
- mScale = scale;
- }
-
- public float getScale() {
- return mScale;
- }
-
- public int getAlphaForPoint(Point point) {
- // Contribution from positional glow
- float glowDistance = (float) Math.hypot(glowManager.x - point.x, glowManager.y - point.y);
- float glowAlpha = 0.0f;
- if (glowDistance < glowManager.radius) {
- float cosf = (float) Math.cos(PI * 0.25f * glowDistance / glowManager.radius);
- glowAlpha = glowManager.alpha * Math.max(0.0f, (float) Math.pow(cosf, 10.0f));
- }
-
- // Compute contribution from Wave
- float radius = (float) Math.hypot(point.x, point.y);
- float waveAlpha = 0.0f;
- if (radius < waveManager.radius * 2) {
- float distanceToWaveRing = (radius - waveManager.radius);
- float cosf = (float) Math.cos(PI * 0.5f * distanceToWaveRing / waveManager.radius);
- waveAlpha = waveManager.alpha * Math.max(0.0f, (float) Math.pow(cosf, 6.0f));
- }
- return (int) (Math.max(glowAlpha, waveAlpha) * 255);
- }
-
- private float interp(float min, float max, float f) {
- return min + (max - min) * f;
- }
-
- public void draw(Canvas canvas) {
- ArrayList<Point> points = mPointCloud;
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- canvas.scale(mScale, mScale, mCenterX, mCenterY);
- for (int i = 0; i < points.size(); i++) {
- Point point = points.get(i);
- final float pointSize = interp(MAX_POINT_SIZE, MIN_POINT_SIZE,
- point.radius / mOuterRadius);
- final float px = point.x + mCenterX;
- final float py = point.y + mCenterY;
- int alpha = getAlphaForPoint(point);
-
- if (alpha == 0) continue;
-
- if (mDrawable != null) {
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- final float cx = mDrawable.getIntrinsicWidth() * 0.5f;
- final float cy = mDrawable.getIntrinsicHeight() * 0.5f;
- final float s = pointSize / MAX_POINT_SIZE;
- canvas.scale(s, s, px, py);
- canvas.translate(px - cx, py - cy);
- mDrawable.setAlpha(alpha);
- mDrawable.draw(canvas);
- canvas.restore();
- } else {
- mPaint.setAlpha(alpha);
- canvas.drawCircle(px, py, pointSize, mPaint);
- }
- }
- canvas.restore();
- }
-
-}
diff --git a/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java b/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java
deleted file mode 100644
index 5a4c441..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * 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.internal.widget.multiwaveview;
-
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
-import android.util.Log;
-
-public class TargetDrawable {
- private static final String TAG = "TargetDrawable";
- private static final boolean DEBUG = false;
-
- public static final int[] STATE_ACTIVE =
- { android.R.attr.state_enabled, android.R.attr.state_active };
- public static final int[] STATE_INACTIVE =
- { android.R.attr.state_enabled, -android.R.attr.state_active };
- public static final int[] STATE_FOCUSED =
- { android.R.attr.state_enabled, -android.R.attr.state_active,
- android.R.attr.state_focused };
-
- private float mTranslationX = 0.0f;
- private float mTranslationY = 0.0f;
- private float mPositionX = 0.0f;
- private float mPositionY = 0.0f;
- private float mScaleX = 1.0f;
- private float mScaleY = 1.0f;
- private float mAlpha = 1.0f;
- private Drawable mDrawable;
- private boolean mEnabled = true;
- private final int mResourceId;
-
- public TargetDrawable(Resources res, int resId) {
- mResourceId = resId;
- setDrawable(res, resId);
- }
-
- public void setDrawable(Resources res, int resId) {
- // Note we explicitly don't set mResourceId to resId since we allow the drawable to be
- // swapped at runtime and want to re-use the existing resource id for identification.
- Drawable drawable = resId == 0 ? null : res.getDrawable(resId);
- // Mutate the drawable so we can animate shared drawable properties.
- mDrawable = drawable != null ? drawable.mutate() : null;
- resizeDrawables();
- setState(STATE_INACTIVE);
- }
-
- public TargetDrawable(TargetDrawable other) {
- mResourceId = other.mResourceId;
- // Mutate the drawable so we can animate shared drawable properties.
- mDrawable = other.mDrawable != null ? other.mDrawable.mutate() : null;
- resizeDrawables();
- setState(STATE_INACTIVE);
- }
-
- public void setState(int [] state) {
- if (mDrawable instanceof StateListDrawable) {
- StateListDrawable d = (StateListDrawable) mDrawable;
- d.setState(state);
- }
- }
-
- public boolean hasState(int [] state) {
- if (mDrawable instanceof StateListDrawable) {
- StateListDrawable d = (StateListDrawable) mDrawable;
- // TODO: this doesn't seem to work
- return d.getStateDrawableIndex(state) != -1;
- }
- return false;
- }
-
- /**
- * Returns true if the drawable is a StateListDrawable and is in the focused state.
- *
- * @return
- */
- public boolean isActive() {
- if (mDrawable instanceof StateListDrawable) {
- StateListDrawable d = (StateListDrawable) mDrawable;
- int[] states = d.getState();
- for (int i = 0; i < states.length; i++) {
- if (states[i] == android.R.attr.state_focused) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns true if this target is enabled. Typically an enabled target contains a valid
- * drawable in a valid state. Currently all targets with valid drawables are valid.
- *
- * @return
- */
- public boolean isEnabled() {
- return mDrawable != null && mEnabled;
- }
-
- /**
- * Makes drawables in a StateListDrawable all the same dimensions.
- * If not a StateListDrawable, then justs sets the bounds to the intrinsic size of the
- * drawable.
- */
- private void resizeDrawables() {
- if (mDrawable instanceof StateListDrawable) {
- StateListDrawable d = (StateListDrawable) mDrawable;
- int maxWidth = 0;
- int maxHeight = 0;
- for (int i = 0; i < d.getStateCount(); i++) {
- Drawable childDrawable = d.getStateDrawable(i);
- maxWidth = Math.max(maxWidth, childDrawable.getIntrinsicWidth());
- maxHeight = Math.max(maxHeight, childDrawable.getIntrinsicHeight());
- }
- if (DEBUG) Log.v(TAG, "union of childDrawable rects " + d + " to: "
- + maxWidth + "x" + maxHeight);
- d.setBounds(0, 0, maxWidth, maxHeight);
- for (int i = 0; i < d.getStateCount(); i++) {
- Drawable childDrawable = d.getStateDrawable(i);
- if (DEBUG) Log.v(TAG, "sizing drawable " + childDrawable + " to: "
- + maxWidth + "x" + maxHeight);
- childDrawable.setBounds(0, 0, maxWidth, maxHeight);
- }
- } else if (mDrawable != null) {
- mDrawable.setBounds(0, 0,
- mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
- }
- }
-
- public void setX(float x) {
- mTranslationX = x;
- }
-
- public void setY(float y) {
- mTranslationY = y;
- }
-
- public void setScaleX(float x) {
- mScaleX = x;
- }
-
- public void setScaleY(float y) {
- mScaleY = y;
- }
-
- public void setAlpha(float alpha) {
- mAlpha = alpha;
- }
-
- public float getX() {
- return mTranslationX;
- }
-
- public float getY() {
- return mTranslationY;
- }
-
- public float getScaleX() {
- return mScaleX;
- }
-
- public float getScaleY() {
- return mScaleY;
- }
-
- public float getAlpha() {
- return mAlpha;
- }
-
- public void setPositionX(float x) {
- mPositionX = x;
- }
-
- public void setPositionY(float y) {
- mPositionY = y;
- }
-
- public float getPositionX() {
- return mPositionX;
- }
-
- public float getPositionY() {
- return mPositionY;
- }
-
- public int getWidth() {
- return mDrawable != null ? mDrawable.getIntrinsicWidth() : 0;
- }
-
- public int getHeight() {
- return mDrawable != null ? mDrawable.getIntrinsicHeight() : 0;
- }
-
- public void draw(Canvas canvas) {
- if (mDrawable == null || !mEnabled) {
- return;
- }
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- canvas.scale(mScaleX, mScaleY, mPositionX, mPositionY);
- canvas.translate(mTranslationX + mPositionX, mTranslationY + mPositionY);
- canvas.translate(-0.5f * getWidth(), -0.5f * getHeight());
- mDrawable.setAlpha((int) Math.round(mAlpha * 255f));
- mDrawable.draw(canvas);
- canvas.restore();
- }
-
- public void setEnabled(boolean enabled) {
- mEnabled = enabled;
- }
-
- public int getResourceId() {
- return mResourceId;
- }
-}
diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
deleted file mode 100644
index d559d9d..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.internal.widget.multiwaveview;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map.Entry;
-
-import android.animation.Animator.AnimatorListener;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.util.Log;
-
-class Tweener {
- private static final String TAG = "Tweener";
- private static final boolean DEBUG = false;
-
- ObjectAnimator animator;
- private static HashMap<Object, Tweener> sTweens = new HashMap<Object, Tweener>();
-
- public Tweener(ObjectAnimator anim) {
- animator = anim;
- }
-
- private static void remove(Animator animator) {
- Iterator<Entry<Object, Tweener>> iter = sTweens.entrySet().iterator();
- while (iter.hasNext()) {
- Entry<Object, Tweener> entry = iter.next();
- if (entry.getValue().animator == animator) {
- if (DEBUG) Log.v(TAG, "Removing tweener " + sTweens.get(entry.getKey())
- + " sTweens.size() = " + sTweens.size());
- iter.remove();
- break; // an animator can only be attached to one object
- }
- }
- }
-
- public static Tweener to(Object object, long duration, Object... vars) {
- long delay = 0;
- AnimatorUpdateListener updateListener = null;
- AnimatorListener listener = null;
- TimeInterpolator interpolator = null;
-
- // Iterate through arguments and discover properties to animate
- ArrayList<PropertyValuesHolder> props = new ArrayList<PropertyValuesHolder>(vars.length/2);
- for (int i = 0; i < vars.length; i+=2) {
- if (!(vars[i] instanceof String)) {
- throw new IllegalArgumentException("Key must be a string: " + vars[i]);
- }
- String key = (String) vars[i];
- Object value = vars[i+1];
- if ("simultaneousTween".equals(key)) {
- // TODO
- } else if ("ease".equals(key)) {
- interpolator = (TimeInterpolator) value; // TODO: multiple interpolators?
- } else if ("onUpdate".equals(key) || "onUpdateListener".equals(key)) {
- updateListener = (AnimatorUpdateListener) value;
- } else if ("onComplete".equals(key) || "onCompleteListener".equals(key)) {
- listener = (AnimatorListener) value;
- } else if ("delay".equals(key)) {
- delay = ((Number) value).longValue();
- } else if ("syncWith".equals(key)) {
- // TODO
- } else if (value instanceof float[]) {
- props.add(PropertyValuesHolder.ofFloat(key,
- ((float[])value)[0], ((float[])value)[1]));
- } else if (value instanceof int[]) {
- props.add(PropertyValuesHolder.ofInt(key,
- ((int[])value)[0], ((int[])value)[1]));
- } else if (value instanceof Number) {
- float floatValue = ((Number)value).floatValue();
- props.add(PropertyValuesHolder.ofFloat(key, floatValue));
- } else {
- throw new IllegalArgumentException(
- "Bad argument for key \"" + key + "\" with value " + value.getClass());
- }
- }
-
- // Re-use existing tween, if present
- Tweener tween = sTweens.get(object);
- ObjectAnimator anim = null;
- if (tween == null) {
- anim = ObjectAnimator.ofPropertyValuesHolder(object,
- props.toArray(new PropertyValuesHolder[props.size()]));
- tween = new Tweener(anim);
- sTweens.put(object, tween);
- if (DEBUG) Log.v(TAG, "Added new Tweener " + tween);
- } else {
- anim = sTweens.get(object).animator;
- replace(props, object); // Cancel all animators for given object
- }
-
- if (interpolator != null) {
- anim.setInterpolator(interpolator);
- }
-
- // Update animation with properties discovered in loop above
- anim.setStartDelay(delay);
- anim.setDuration(duration);
- if (updateListener != null) {
- anim.removeAllUpdateListeners(); // There should be only one
- anim.addUpdateListener(updateListener);
- }
- if (listener != null) {
- anim.removeAllListeners(); // There should be only one.
- anim.addListener(listener);
- }
- anim.addListener(mCleanupListener);
-
- return tween;
- }
-
- Tweener from(Object object, long duration, Object... vars) {
- // TODO: for v of vars
- // toVars[v] = object[v]
- // object[v] = vars[v]
- return Tweener.to(object, duration, vars);
- }
-
- // Listener to watch for completed animations and remove them.
- private static AnimatorListener mCleanupListener = new AnimatorListenerAdapter() {
-
- @Override
- public void onAnimationEnd(Animator animation) {
- remove(animation);
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- remove(animation);
- }
- };
-
- public static void reset() {
- if (DEBUG) {
- Log.v(TAG, "Reset()");
- if (sTweens.size() > 0) {
- Log.v(TAG, "Cleaning up " + sTweens.size() + " animations");
- }
- }
- sTweens.clear();
- }
-
- private static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
- for (final Object killobject : args) {
- Tweener tween = sTweens.get(killobject);
- if (tween != null) {
- tween.animator.cancel();
- if (props != null) {
- tween.animator.setValues(
- props.toArray(new PropertyValuesHolder[props.size()]));
- } else {
- sTweens.remove(tween);
- }
- }
- }
- }
-}
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 9996ce1..9ea63aa 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -511,18 +511,15 @@
///////////////////////////////////////////////////////////////////////////////
-static bool computeAllocationSize(const SkImageInfo& info, size_t* size, size_t* rowBytes) {
- int32_t rowBytes32 = SkToS32(info.minRowBytes());
- int64_t bigSize = (int64_t)info.height() * rowBytes32;
- if (rowBytes32 < 0 || !sk_64_isS32(bigSize)) {
- return false; // allocation will be too large
- }
+static bool computeAllocationSize(const SkBitmap& bitmap, size_t* size) {
+ int32_t rowBytes32 = SkToS32(bitmap.rowBytes());
+ int64_t bigSize = (int64_t)bitmap.height() * rowBytes32;
+ if (rowBytes32 < 0 || !sk_64_isS32(bigSize)) {
+ return false; // allocation will be too large
+ }
- *size = sk_64_asS32(bigSize);
- *rowBytes = rowBytes32;
-
- SkASSERT(*size >= info.getSafeSize(*rowBytes));
- return true;
+ *size = sk_64_asS32(bigSize);
+ return true;
}
jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
@@ -533,11 +530,15 @@
return NULL;
}
- size_t size, rowBytes;
- if (!computeAllocationSize(info, &size, &rowBytes)) {
+ size_t size;
+ if (!computeAllocationSize(*bitmap, &size)) {
return NULL;
}
+ // we must respect the rowBytes value already set on the bitmap instead of
+ // attempting to compute our own.
+ const size_t rowBytes = bitmap->rowBytes();
+
jbyteArray arrayObj = (jbyteArray) env->CallObjectMethod(gVMRuntime,
gVMRuntime_newNonMovableArray,
gByte_class, size);
@@ -580,11 +581,15 @@
return NULL;
}
- size_t size, rowBytes;
- if (!computeAllocationSize(info, &size, &rowBytes)) {
+ size_t size;
+ if (!computeAllocationSize(*bitmap, &size)) {
return false;
}
+ // we must respect the rowBytes value already set on the bitmap instead of
+ // attempting to compute our own.
+ const size_t rowBytes = bitmap->rowBytes();
+
void* addr = sk_malloc_flags(size, 0);
if (NULL == addr) {
return false;
diff --git a/core/jni/android/graphics/NinePatchPeeker.cpp b/core/jni/android/graphics/NinePatchPeeker.cpp
index 2644888..6c32a21 100644
--- a/core/jni/android/graphics/NinePatchPeeker.cpp
+++ b/core/jni/android/graphics/NinePatchPeeker.cpp
@@ -24,7 +24,9 @@
if (!strcmp("npTc", tag) && length >= sizeof(Res_png_9patch)) {
Res_png_9patch* patch = (Res_png_9patch*) data;
size_t patchSize = patch->serializedSize();
- assert(length == patchSize);
+ if (length != patchSize) {
+ return false;
+ }
// You have to copy the data because it is owned by the png reader
Res_png_9patch* patchNew = (Res_png_9patch*) malloc(patchSize);
memcpy(patchNew, patch, patchSize);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 085cc81..6094fd1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -183,8 +183,6 @@
<protected-broadcast android:name="android.intent.action.HEADSET_PLUG" />
<protected-broadcast android:name="android.media.action.HDMI_AUDIO_PLUG" />
- <protected-broadcast android:name="android.media.action.USB_AUDIO_ACCESSORY_PLUG" />
- <protected-broadcast android:name="android.media.action.USB_AUDIO_DEVICE_PLUG" />
<protected-broadcast android:name="android.media.AUDIO_BECOMING_NOISY" />
<protected-broadcast android:name="android.media.RINGER_MODE_CHANGED" />
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index 3fdcaf7..ea22b15 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -16,12 +16,9 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
>
<include layout="@layout/notification_template_icon_group"
android:layout_width="@dimen/notification_large_icon_width"
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index 935424a..2a3ee90 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -16,12 +16,9 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="unbounded"
>
<include layout="@layout/notification_template_icon_group"
android:layout_width="@dimen/notification_large_icon_width"
diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml
index 302e651..f1a9549 100644
--- a/core/res/res/layout/notification_template_material_big_picture.xml
+++ b/core/res/res/layout/notification_template_material_big_picture.xml
@@ -16,12 +16,9 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="unbounded"
>
<ImageView
android:id="@+id/big_picture"
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index d0c10b2..f657f04 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -16,12 +16,9 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="unbounded"
>
<include layout="@layout/notification_template_icon_group"
android:layout_width="@dimen/notification_large_icon_width"
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index ac448ee..d292d4e 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -16,12 +16,9 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="unbounded"
>
<include layout="@layout/notification_template_icon_group"
android:layout_width="@dimen/notification_large_icon_width"
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index 69020a4..0292d28 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -16,14 +16,11 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="64dp"
android:orientation="horizontal"
android:background="#00000000"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
>
<include layout="@layout/notification_template_icon_group"
android:layout_width="@dimen/notification_large_icon_width"
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
new file mode 100644
index 0000000..3435474
--- /dev/null
+++ b/core/res/res/values-television/config.xml
@@ -0,0 +1,26 @@
+<?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 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for TV products. Do not translate. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Flags enabling default window features. See Window.java -->
+ <bool name="config_defaultWindowFeatureOptionsPanel">false</bool>
+</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 551c044..39c42ee 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7034,75 +7034,16 @@
<!-- =============================== -->
<eat-comment />
<declare-styleable name="GlowPadView">
- <!-- Reference to an array resource that be shown as targets around a circle. -->
- <attr name="targetDrawables" format="reference" />
-
- <!-- Reference to an array resource that be used as description for the targets around the circle. -->
+ <!-- Reference to an array resource that be used as description for the targets around the circle.
+ {@deprecated Removed.} -->
<attr name="targetDescriptions" format="reference" />
- <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
+ <!-- Reference to an array resource that be used to announce the directions with targets around the circle.
+ {@deprecated Removed.}-->
<attr name="directionDescriptions" format="reference" />
-
- <!-- Sets a drawable as the center. -->
- <attr name="handleDrawable" format="reference" />
-
- <!-- Drawable to use for wave ripple animation. -->
- <attr name="outerRingDrawable" format="reference"/>
-
- <!-- Drawble used for drawing points -->
- <attr name="pointDrawable" format="reference" />
-
- <!-- Inner radius of glow area. -->
- <attr name="innerRadius"/>
-
- <!-- Outer radius of glow area. Target icons will be drawn on this circle. -->
- <attr name="outerRadius" format="dimension" />
-
- <!-- Radius of glow under finger. -->
- <attr name="glowRadius" format="dimension" />
-
- <!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
- <attr name="vibrationDuration" format="integer" />
-
- <!-- How close we need to be before snapping to a target. -->
- <attr name="snapMargin" format="dimension" />
-
- <!-- Number of waves/chevrons to show in animation. -->
- <attr name="feedbackCount" format="integer" />
-
- <!-- Used when the handle shouldn't wait to be hit before following the finger -->
- <attr name="alwaysTrackFinger" format="boolean" />
-
- <!-- Location along the circle of the first item, in degrees.-->
- <attr name="firstItemOffset" format="float" />
-
- <!-- Causes targets to snap to the finger location on activation. -->
- <attr name="magneticTargets" format="boolean" />
-
- <attr name="gravity" />
-
- <!-- Determine whether the glow pad is allowed to scale to fit the bounds indicated
- by its parent. If this is set to false, no scaling will occur. If this is set to true
- scaling will occur to fit for any axis in which gravity is set to center. -->
- <attr name="allowScaling" format="boolean" />
</declare-styleable>
<!-- =============================== -->
- <!-- SizeAdaptiveLayout class attributes -->
- <!-- =============================== -->
- <eat-comment />
- <declare-styleable name="SizeAdaptiveLayout_Layout">
- <!-- The maximum valid height for this item. -->
- <attr name="layout_maxHeight" format="dimension">
- <!-- Indicates that the view may be resized arbitrarily large. -->
- <enum name="unbounded" value="-1" />
- </attr>
- <!-- The minimum valid height for this item. -->
- <attr name="layout_minHeight" format="dimension" />
- </declare-styleable>
- <declare-styleable name="SizeAdaptiveLayout" />
-
- <!-- =============================== -->
<!-- Location package class attributes -->
<!-- =============================== -->
<eat-comment />
@@ -7509,11 +7450,6 @@
<enum name="pageDeleteDropTarget" value="7" />
</attr>
- <declare-styleable name="SlidingChallengeLayout_Layout">
- <attr name="layout_childType" />
- <attr name="layout_maxHeight" />
- </declare-styleable>
-
<!-- Attributes that can be used with <code><FragmentBreadCrumbs></code>
tags. -->
<declare-styleable name="FragmentBreadCrumbs">
@@ -7522,27 +7458,6 @@
<attr name="itemColor" format="color|reference" />
</declare-styleable>
- <declare-styleable name="MultiPaneChallengeLayout">
- <!-- Influences how layout_centerWithinArea behaves -->
- <attr name="orientation" />
- </declare-styleable>
-
- <declare-styleable name="MultiPaneChallengeLayout_Layout">
- <!-- Percentage of the screen this child should consume or center within.
- If 0/default, the view will be measured by standard rules
- as if this were a FrameLayout. -->
- <attr name="layout_centerWithinArea" format="float" />
- <attr name="layout_childType" />
- <attr name="layout_gravity" />
- <attr name="layout_maxWidth" format="dimension" />
- <attr name="layout_maxHeight" />
- </declare-styleable>
-
- <declare-styleable name="KeyguardSecurityViewFlipper_Layout">
- <attr name="layout_maxWidth" />
- <attr name="layout_maxHeight" />
- </declare-styleable>
-
<declare-styleable name="Toolbar">
<attr name="titleTextAppearance" format="reference" />
<attr name="subtitleTextAppearance" format="reference" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 68c1046..f2d9de8 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -424,6 +424,10 @@
<!-- Integer indicating wpa_supplicant scan interval in milliseconds -->
<integer translatable="false" name="config_wifi_supplicant_scan_interval">15000</integer>
+ <!-- Integer indicating amount of time failed networks areblacklisted for the purpose
+ of network switching in milliseconds -->
+ <integer translatable="false" name="config_wifi_network_switching_blacklist_time">172800000</integer>
+
<!-- Integer indicating wpa_supplicant scan interval when p2p is connected in milliseconds -->
<integer translatable="false" name="config_wifi_scan_interval_p2p_connected">60000</integer>
@@ -2021,4 +2025,7 @@
<!-- Use ERI text for network name on CDMA LTE -->
<bool name="config_LTE_eri_for_network_name">true</bool>
+
+ <!-- Whether to start in touch mode -->
+ <bool name="config_defaultInTouchMode">true</bool>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9f49b08..9945c63 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1759,7 +1759,9 @@
<public type="attr" name="actionModeSplitBackground" id="0x0101039d" />
<public type="attr" name="textAppearanceListItem" id="0x0101039e" />
<public type="attr" name="textAppearanceListItemSmall" id="0x0101039f" />
+ <!-- @deprecated Removed. -->
<public type="attr" name="targetDescriptions" id="0x010103a0" />
+ <!-- @deprecated Removed. -->
<public type="attr" name="directionDescriptions" id="0x010103a1" />
<public type="attr" name="overridesImplicitlyEnabledSubtype" id="0x010103a2" />
<public type="attr" name="listPreferredItemPaddingLeft" id="0x010103a3" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f51e82c9..efdc3c8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5188,4 +5188,9 @@
<string name="stk_cc_ss_to_ussd">SS request is modified to USSD request.</string>
<string name="stk_cc_ss_to_ss">SS request is modified to new SS request.</string>
+ <!-- Manufacturer name for USB MIDI Peripheral port -->
+ <string name="usb_midi_peripheral_manufacturer_name">Android</string>
+ <!-- Model name for USB MIDI Peripheral port -->
+ <string name="usb_midi_peripheral_model_name">USB Peripheral Port</string>
+
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 574c099..607744f 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -327,6 +327,7 @@
<java-symbol type="integer" name="config_wifi_framework_scan_result_rssi_level_patchup_value" />
<java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
<java-symbol type="string" name="config_wifi_random_mac_oui" />
+ <java-symbol type="integer" name="config_wifi_network_switching_blacklist_time" />
<java-symbol type="bool" name="editable_voicemailnumber" />
@@ -2154,4 +2155,8 @@
<java-symbol type="bool" name="config_use_sim_language_file" />
<java-symbol type="bool" name="config_LTE_eri_for_network_name" />
+ <java-symbol type="bool" name="config_defaultInTouchMode" />
+
+ <java-symbol type="string" name="usb_midi_peripheral_manufacturer_name" />
+ <java-symbol type="string" name="usb_midi_peripheral_model_name" />
</resources>
diff --git a/core/tests/coretests/res/layout/size_adaptive.xml b/core/tests/coretests/res/layout/size_adaptive.xml
deleted file mode 100644
index 03d0574..0000000
--- a/core/tests/coretests/res/layout/size_adaptive.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:id="@+id/multi1"
- android:layout_width="match_parent"
- android:layout_height="64dp" >
-
- <include
- android:id="@+id/one_u"
- layout="@layout/size_adaptive_one_u"
- android:layout_width="fill_parent"
- android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
- />
-
- <include
- android:id="@+id/four_u"
- layout="@layout/size_adaptive_four_u"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_color.xml b/core/tests/coretests/res/layout/size_adaptive_color.xml
deleted file mode 100644
index cdb7a59..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_color.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:background="#ffffff"
- android:id="@+id/multi1"
- android:layout_width="match_parent"
- android:layout_height="64dp" >
-
- <include
- android:id="@+id/one_u"
- layout="@layout/size_adaptive_one_u"
- android:layout_width="fill_parent"
- android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
- />
-
- <include
- android:id="@+id/four_u"
- layout="@layout/size_adaptive_four_u"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_color_statelist.xml b/core/tests/coretests/res/layout/size_adaptive_color_statelist.xml
deleted file mode 100644
index d24df5b..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_color_statelist.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:background="@drawable/size_adaptive_statelist"
- android:id="@+id/multi1"
- android:layout_width="match_parent"
- android:layout_height="64dp" >
-
- <include
- android:id="@+id/one_u"
- layout="@layout/size_adaptive_one_u"
- android:layout_width="fill_parent"
- android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
- />
-
- <include
- android:id="@+id/four_u"
- layout="@layout/size_adaptive_four_u"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_four_u.xml b/core/tests/coretests/res/layout/size_adaptive_four_u.xml
deleted file mode 100644
index 232b921..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_four_u.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/gridLayout4"
- android:layout_width="match_parent"
- android:layout_height="256dp"
- android:background="#000000"
- android:columnCount="2"
- android:padding="1dp" >
-
- <ImageView
- android:id="@+id/actor"
- android:layout_width="62dp"
- android:layout_height="62dp"
- android:layout_row="0"
- android:layout_column="0"
- android:layout_rowSpan="2"
- android:contentDescription="@string/actor"
- android:src="@drawable/abe" />
-
- <TextView
- android:layout_width="0dp"
- android:id="@+id/name"
- android:layout_row="0"
- android:layout_column="1"
- android:layout_gravity="fill_horizontal"
- android:padding="3dp"
- android:text="@string/actor"
- android:textColor="#ffffff"
- android:textStyle="bold" />
-
- <ImageView
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_row="1"
- android:layout_column="1"
- android:layout_gravity="fill_horizontal"
- android:padding="5dp"
- android:adjustViewBounds="true"
- android:background="#555555"
- android:scaleType="centerCrop"
- android:src="@drawable/gettysburg"
- android:contentDescription="@string/caption" />
-
- <TextView
- android:layout_width="0dp"
- android:id="@+id/note"
- android:layout_row="2"
- android:layout_column="1"
- android:layout_gravity="fill_horizontal"
- android:padding="3dp"
- android:singleLine="true"
- android:text="@string/first"
- android:textColor="#ffffff" />
-</GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml b/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml
deleted file mode 100644
index 93a10de..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/gridLayout4"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="#000000"
- android:columnCount="2"
- android:padding="1dp"
- android:orientation="horizontal" >
-
- <ImageView
- android:id="@+id/actor"
- android:layout_width="62dp"
- android:layout_height="62dp"
- android:layout_row="0"
- android:layout_column="0"
- android:layout_rowSpan="2"
- android:contentDescription="@string/actor"
- android:src="@drawable/abe" />
-
- <TextView
- android:layout_width="0dp"
- android:id="@+id/name"
- android:layout_row="0"
- android:layout_column="1"
- android:layout_gravity="fill_horizontal"
- android:padding="3dp"
- android:text="@string/actor"
- android:textColor="#ffffff"
- android:textStyle="bold" />
-
- <TextView
- android:id="@+id/note"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_column="1"
- android:layout_gravity="fill_horizontal"
- android:layout_marginTop="5dp"
- android:layout_row="1"
- android:padding="3dp"
- android:singleLine="false"
- android:text="@string/first"
- android:textColor="#ffffff" />
-
- </GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_gappy.xml b/core/tests/coretests/res/layout/size_adaptive_gappy.xml
deleted file mode 100644
index d5e3b41..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_gappy.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:id="@+id/multi_with_gap"
- android:layout_width="match_parent"
- android:layout_height="64dp" >
-
- <include
- android:id="@+id/one_u"
- layout="@layout/size_adaptive_one_u"
- android:layout_width="fill_parent"
- android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
- />
-
- <include
- android:id="@+id/four_u"
- layout="@layout/size_adaptive_four_u"
- android:layout_width="fill_parent"
- android:layout_height="256dp"
- internal:layout_minHeight="128dp"
- internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_large_only.xml b/core/tests/coretests/res/layout/size_adaptive_large_only.xml
deleted file mode 100644
index cf58265..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_large_only.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:id="@+id/large_only_multi"
- android:layout_width="match_parent"
- android:layout_height="64dp" >
-
- <include
- android:id="@+id/four_u"
- layout="@layout/size_adaptive_four_u"
- android:layout_width="fill_parent"
- android:layout_height="256dp"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_lies.xml b/core/tests/coretests/res/layout/size_adaptive_lies.xml
deleted file mode 100644
index 7de892e..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_lies.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:id="@+id/multi1"
- android:layout_width="match_parent"
- android:layout_height="64dp" >
-
- <include
- android:id="@+id/one_u"
- layout="@layout/size_adaptive_one_u"
- android:layout_width="fill_parent"
- android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
- />
-
- <include
- android:id="@+id/four_u"
- layout="@layout/size_adaptive_one_u"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_one_u.xml b/core/tests/coretests/res/layout/size_adaptive_one_u.xml
deleted file mode 100644
index b6fe4a0..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_one_u.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/gridLayout1"
- android:layout_width="match_parent"
- android:layout_height="64dp"
- android:background="#000000"
- android:columnCount="3"
- android:padding="1dp"
- android:rowCount="2" >
-
- <ImageView
- android:id="@+id/actor"
- android:layout_width="62dp"
- android:layout_height="62dp"
- android:layout_column="0"
- android:layout_row="0"
- android:layout_rowSpan="2"
- android:contentDescription="@string/actor"
- android:src="@drawable/abe" />
-
- <TextView
- android:id="@+id/name"
- android:layout_gravity="fill"
- android:padding="3dp"
- android:text="@string/actor"
- android:textColor="#ffffff"
- android:textStyle="bold" />
-
- <ImageView
- android:layout_width="62dp"
- android:layout_height="62dp"
- android:layout_gravity="fill_vertical"
- android:layout_rowSpan="2"
- android:adjustViewBounds="true"
- android:background="#555555"
- android:padding="2dp"
- android:scaleType="fitXY"
- android:src="@drawable/gettysburg"
- android:contentDescription="@string/caption" />
-
- <TextView
- android:id="@+id/note"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_gravity="fill"
- android:layout_marginTop="5dp"
- android:padding="3dp"
- android:singleLine="true"
- android:text="@string/first"
- android:textColor="#ffffff" />
-
-</GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml b/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml
deleted file mode 100644
index df54eb6..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/gridLayout1"
- android:layout_width="match_parent"
- android:layout_height="64dp"
- android:background="#000000"
- android:columnCount="2"
- android:padding="1dp"
- android:rowCount="2" >
-
- <ImageView
- android:id="@+id/actor"
- android:layout_width="62dp"
- android:layout_height="62dp"
- android:layout_column="0"
- android:layout_row="0"
- android:layout_rowSpan="2"
- android:contentDescription="@string/actor"
- android:src="@drawable/abe" />
-
- <TextView
- android:id="@+id/name"
- android:layout_gravity="fill"
- android:padding="3dp"
- android:text="@string/actor"
- android:textColor="#ffffff"
- android:textStyle="bold" />
-
- <TextView
- android:id="@+id/note"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_gravity="fill"
- android:layout_marginTop="5dp"
- android:padding="3dp"
- android:singleLine="true"
- android:text="@string/first"
- android:textColor="#ffffff" />
-
-</GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_overlapping.xml b/core/tests/coretests/res/layout/size_adaptive_overlapping.xml
deleted file mode 100644
index 4abe8b0..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_overlapping.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:id="@+id/multi_with_overlap"
- android:layout_width="match_parent"
- android:layout_height="64dp" >
-
- <include
- android:id="@+id/one_u"
- layout="@layout/size_adaptive_one_u"
- android:layout_width="fill_parent"
- android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
- />
-
- <include
- android:id="@+id/four_u"
- layout="@layout/size_adaptive_four_u"
- android:layout_width="fill_parent"
- android:layout_height="256dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="256dp"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_singleton.xml b/core/tests/coretests/res/layout/size_adaptive_singleton.xml
deleted file mode 100644
index eba387f..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_singleton.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:layout_width="match_parent"
- android:layout_height="64dp" >
-
- <include
- android:id="@+id/one_u"
- layout="@layout/size_adaptive_one_u_text"
- android:layout_width="fill_parent"
- android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
- />
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_text.xml b/core/tests/coretests/res/layout/size_adaptive_text.xml
deleted file mode 100644
index a9f0ba9..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_text.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:id="@+id/multi1"
- android:layout_width="match_parent"
- android:layout_height="64dp" >
-
- <include
- android:id="@+id/one_u"
- layout="@layout/size_adaptive_one_u_text"
- android:layout_width="fill_parent"
- android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
- />
-
- <include
- android:id="@+id/four_u"
- layout="@layout/size_adaptive_four_u_text"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_three_way.xml b/core/tests/coretests/res/layout/size_adaptive_three_way.xml
deleted file mode 100644
index 1eb5396..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_three_way.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
- android:id="@+id/three_way_multi"
- android:layout_width="match_parent"
- android:layout_height="64dp" >
-
- <include
- android:id="@+id/one_u"
- layout="@layout/size_adaptive_one_u"
- android:layout_width="fill_parent"
- android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
- />
-
- <include
- android:id="@+id/two_u"
- layout="@layout/size_adaptive_four_u"
- android:layout_width="fill_parent"
- android:layout_height="128dp"
- internal:layout_minHeight="65dp"
- internal:layout_maxHeight="128dp"/>
-
- <include
- android:id="@+id/four_u"
- layout="@layout/size_adaptive_four_u"
- android:layout_width="fill_parent"
- android:layout_height="256dp"
- internal:layout_minHeight="129dp"
- internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
deleted file mode 100644
index 18411b0..0000000
--- a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import com.android.frameworks.coretests.R;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.internal.widget.SizeAdaptiveLayout;
-
-
-public class SizeAdaptiveLayoutTest extends AndroidTestCase {
-
- private LayoutInflater mInflater;
- private int mOneU;
- private int mFourU;
- private SizeAdaptiveLayout mSizeAdaptiveLayout;
- private View mSmallView;
- private View mMediumView;
- private View mLargeView;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- // inflate the layout
- final Context context = getContext();
- mInflater = LayoutInflater.from(context);
- mOneU = 64;
- mFourU = 4 * mOneU;
- }
-
- private void inflate(int resource){
- mSizeAdaptiveLayout = (SizeAdaptiveLayout) mInflater.inflate(resource, null);
- mSizeAdaptiveLayout.onAttachedToWindow();
-
- mSmallView = mSizeAdaptiveLayout.findViewById(R.id.one_u);
- mMediumView = mSizeAdaptiveLayout.findViewById(R.id.two_u);
- mLargeView = mSizeAdaptiveLayout.findViewById(R.id.four_u);
- }
-
- /**
- * The name 'test preconditions' is a convention to signal that if this
- * test doesn't pass, the test case was not set up properly and it might
- * explain any and all failures in other tests. This is not guaranteed
- * to run before other tests, as junit uses reflection to find the tests.
- */
- @SmallTest
- public void testPreconditions() {
- assertNotNull(mInflater);
-
- inflate(R.layout.size_adaptive);
- assertNotNull(mSizeAdaptiveLayout);
- assertNotNull(mSmallView);
- assertNotNull(mLargeView);
- }
-
- @SmallTest
- public void testOpenLarge() {
- inflate(R.layout.size_adaptive);
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- int height = (int) lp.minHeight + 10;
-
- measureAndLayout(height);
-
- assertEquals("4U should be visible",
- View.VISIBLE,
- mLargeView.getVisibility());
- assertEquals("1U should be gone",
- View.GONE,
- mSmallView.getVisibility());
- }
-
- @SmallTest
- public void testOpenSmall() {
- inflate(R.layout.size_adaptive);
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
- int height = (int) lp.minHeight;
-
- measureAndLayout(height);
-
- assertEquals("1U should be visible",
- View.VISIBLE,
- mSmallView.getVisibility());
- assertEquals("4U should be gone",
- View.GONE,
- mLargeView.getVisibility());
- }
-
- @SmallTest
- public void testOpenTooSmall() {
- inflate(R.layout.size_adaptive);
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
- int height = (int) lp.minHeight - 10;
-
- measureAndLayout(height);
-
- assertEquals("1U should be visible",
- View.VISIBLE,
- mSmallView.getVisibility());
- assertEquals("4U should be gone",
- View.GONE,
- mLargeView.getVisibility());
- }
-
- @SmallTest
- public void testOpenTooBig() {
- inflate(R.layout.size_adaptive);
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- lp.maxHeight = 500;
- mLargeView.setLayoutParams(lp);
- int height = (int) (lp.minHeight + 10);
-
- measureAndLayout(height);
-
- assertEquals("4U should be visible",
- View.VISIBLE,
- mLargeView.getVisibility());
- assertEquals("1U should be gone",
- View.GONE,
- mSmallView.getVisibility());
- }
-
- @SmallTest
- public void testOpenWrapContent() {
- inflate(R.layout.size_adaptive_text);
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- int height = (int) lp.minHeight + 10;
-
- // manually measure it, and lay it out
- int measureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
- mSizeAdaptiveLayout.measure(500, measureSpec);
- assertTrue("should not be forced to 4U",
- mSizeAdaptiveLayout.getMeasuredHeight() < mFourU);
- }
-
- @SmallTest
- public void testOpenOneUOnlySmall() {
- inflate(R.layout.size_adaptive_singleton);
- assertNull("largeView should be NULL in the singleton layout", mLargeView);
-
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
- int height = (int) lp.minHeight - 10;
-
- measureAndLayout(height);
-
- assertEquals("1U should be visible",
- View.VISIBLE,
- mSmallView.getVisibility());
- }
-
- @SmallTest
- public void testOpenOneUOnlyLarge() {
- inflate(R.layout.size_adaptive_singleton);
- assertNull("largeView should be NULL in the singleton layout", mLargeView);
-
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
- int height = (int) lp.maxHeight + 10;
-
- measureAndLayout(height);
-
- assertEquals("1U should be visible",
- View.VISIBLE,
- mSmallView.getVisibility());
- }
-
- @SmallTest
- public void testOpenOneUOnlyJustRight() {
- inflate(R.layout.size_adaptive_singleton);
- assertNull("largeView should be NULL in the singleton layout", mLargeView);
-
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
- int height = (int) lp.minHeight;
-
- measureAndLayout(height);
-
- assertEquals("1U should be visible",
- View.VISIBLE,
- mSmallView.getVisibility());
- }
-
- @SmallTest
- public void testOpenFourUOnlySmall() {
- inflate(R.layout.size_adaptive_large_only);
- assertNull("smallView should be NULL in the singleton layout", mSmallView);
-
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- int height = (int) lp.minHeight - 10;
-
- measureAndLayout(height);
-
- assertEquals("4U should be visible",
- View.VISIBLE,
- mLargeView.getVisibility());
- }
-
- @SmallTest
- public void testOpenFourUOnlyLarge() {
- inflate(R.layout.size_adaptive_large_only);
- assertNull("smallView should be NULL in the singleton layout", mSmallView);
-
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- int height = (int) lp.maxHeight + 10;
-
- measureAndLayout(height);
-
- assertEquals("4U should be visible",
- View.VISIBLE,
- mLargeView.getVisibility());
- }
-
- @SmallTest
- public void testOpenFourUOnlyJustRight() {
- inflate(R.layout.size_adaptive_large_only);
- assertNull("smallView should be NULL in the singleton layout", mSmallView);
-
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- int height = (int) lp.minHeight;
-
- measureAndLayout(height);
-
- assertEquals("4U should be visible",
- View.VISIBLE,
- mLargeView.getVisibility());
- }
-
- @SmallTest
- public void testOpenIntoAGap() {
- inflate(R.layout.size_adaptive_gappy);
-
- SizeAdaptiveLayout.LayoutParams smallParams =
- (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
- SizeAdaptiveLayout.LayoutParams largeParams =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- assertTrue("gappy layout should have a gap",
- smallParams.maxHeight + 10 < largeParams.minHeight);
- int height = (int) smallParams.maxHeight + 10;
-
- measureAndLayout(height);
-
- assertTrue("one and only one view should be visible",
- mLargeView.getVisibility() != mSmallView.getVisibility());
- // behavior is undefined in this case.
- }
-
- @SmallTest
- public void testOpenIntoAnOverlap() {
- inflate(R.layout.size_adaptive_overlapping);
-
- SizeAdaptiveLayout.LayoutParams smallParams =
- (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
- SizeAdaptiveLayout.LayoutParams largeParams =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- assertEquals("overlapping layout should overlap",
- smallParams.minHeight,
- largeParams.minHeight);
- int height = (int) smallParams.maxHeight;
-
- measureAndLayout(height);
-
- assertTrue("one and only one view should be visible",
- mLargeView.getVisibility() != mSmallView.getVisibility());
- assertEquals("1U should get priority in an overlap because it is first",
- View.VISIBLE,
- mSmallView.getVisibility());
- }
-
- @SmallTest
- public void testOpenThreeWayViewSmall() {
- inflate(R.layout.size_adaptive_three_way);
- assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView);
-
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
- int height = (int) lp.minHeight;
-
- measureAndLayout(height);
-
- assertEquals("1U should be visible",
- View.VISIBLE,
- mSmallView.getVisibility());
- assertEquals("2U should be gone",
- View.GONE,
- mMediumView.getVisibility());
- assertEquals("4U should be gone",
- View.GONE,
- mLargeView.getVisibility());
- }
-
- @SmallTest
- public void testOpenThreeWayViewMedium() {
- inflate(R.layout.size_adaptive_three_way);
- assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView);
-
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mMediumView.getLayoutParams();
- int height = (int) lp.minHeight;
-
- measureAndLayout(height);
-
- assertEquals("1U should be gone",
- View.GONE,
- mSmallView.getVisibility());
- assertEquals("2U should be visible",
- View.VISIBLE,
- mMediumView.getVisibility());
- assertEquals("4U should be gone",
- View.GONE,
- mLargeView.getVisibility());
- }
-
- @SmallTest
- public void testOpenThreeWayViewLarge() {
- inflate(R.layout.size_adaptive_three_way);
- assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView);
-
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- int height = (int) lp.minHeight;
-
- measureAndLayout(height);
-
- assertEquals("1U should be gone",
- View.GONE,
- mSmallView.getVisibility());
- assertEquals("2U should be gone",
- View.GONE,
- mMediumView.getVisibility());
- assertEquals("4U should be visible",
- View.VISIBLE,
- mLargeView.getVisibility());
- }
-
- @SmallTest
- public void testResizeWithoutAnimation() {
- inflate(R.layout.size_adaptive);
-
- SizeAdaptiveLayout.LayoutParams largeParams =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- int startHeight = (int) largeParams.minHeight + 10;
- int endHeight = (int) largeParams.minHeight + 10;
-
- measureAndLayout(startHeight);
-
- assertEquals("4U should be visible",
- View.VISIBLE,
- mLargeView.getVisibility());
- assertFalse("There should be no animation on initial rendering.",
- mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
-
- measureAndLayout(endHeight);
-
- assertEquals("4U should still be visible",
- View.VISIBLE,
- mLargeView.getVisibility());
- assertFalse("There should be no animation on scale within a view.",
- mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
- }
-
- @SmallTest
- public void testResizeWithAnimation() {
- inflate(R.layout.size_adaptive);
-
- SizeAdaptiveLayout.LayoutParams smallParams =
- (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
- SizeAdaptiveLayout.LayoutParams largeParams =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- int startHeight = (int) largeParams.minHeight + 10;
- int endHeight = (int) smallParams.maxHeight;
-
- measureAndLayout(startHeight);
-
- assertEquals("4U should be visible",
- View.VISIBLE,
- mLargeView.getVisibility());
- assertFalse("There should be no animation on initial rendering.",
- mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
-
- measureAndLayout(endHeight);
-
- assertEquals("1U should now be visible",
- View.VISIBLE,
- mSmallView.getVisibility());
- assertTrue("There should be an animation on scale between views.",
- mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
- }
-
- @SmallTest
- public void testModestyPanelChangesColorWhite() {
- inflate(R.layout.size_adaptive_color);
- View panel = mSizeAdaptiveLayout.getModestyPanel();
- assertTrue("ModestyPanel should have a ColorDrawable background",
- panel.getBackground() instanceof ColorDrawable);
- ColorDrawable panelColor = (ColorDrawable) panel.getBackground();
- ColorDrawable salColor = (ColorDrawable) mSizeAdaptiveLayout.getBackground();
- assertEquals("ModestyPanel color should match the SizeAdaptiveLayout",
- panelColor.getColor(), salColor.getColor());
- }
-
- @SmallTest
- public void testModestyPanelTracksStateListColor() {
- inflate(R.layout.size_adaptive_color_statelist);
- View panel = mSizeAdaptiveLayout.getModestyPanel();
- assertEquals("ModestyPanel should have a ColorDrawable background" ,
- panel.getBackground().getClass(), ColorDrawable.class);
- ColorDrawable panelColor = (ColorDrawable) panel.getBackground();
- assertEquals("ModestyPanel color should match the SizeAdaptiveLayout",
- panelColor.getColor(), Color.RED);
- }
- @SmallTest
- public void testOpenSmallEvenWhenLargeIsActuallySmall() {
- inflate(R.layout.size_adaptive_lies);
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
- int height = (int) lp.minHeight;
-
- measureAndLayout(height);
-
- assertEquals("1U should be visible",
- View.VISIBLE,
- mSmallView.getVisibility());
- assertTrue("1U should also have been measured",
- mSmallView.getMeasuredHeight() > 0);
- }
-
- @SmallTest
- public void testOpenLargeEvenWhenLargeIsActuallySmall() {
- inflate(R.layout.size_adaptive_lies);
- SizeAdaptiveLayout.LayoutParams lp =
- (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
- int height = (int) lp.minHeight;
-
- measureAndLayout(height);
-
- assertEquals("4U should be visible",
- View.VISIBLE,
- mLargeView.getVisibility());
- assertTrue("4U should also have been measured",
- mLargeView.getMeasuredHeight() > 0);
- }
-
- private void measureAndLayout(int height) {
- // manually measure it, and lay it out
- int measureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
- mSizeAdaptiveLayout.measure(500, measureSpec);
- mSizeAdaptiveLayout.layout(0, 0, 500, mSizeAdaptiveLayout.getMeasuredHeight());
- }
-}
diff --git a/docs/html/google/play-services/ads.jd b/docs/html/google/play-services/ads.jd
index e4f0b2c..2f915f3 100644
--- a/docs/html/google/play-services/ads.jd
+++ b/docs/html/google/play-services/ads.jd
@@ -98,10 +98,8 @@
serve banner and interstitial ads using the Google Mobile Ads APIs.</p>
<h4>3. Read the documentation</h4>
- <p>Read the <a class="external-link" href="https://www.google.com/adsense/localized-terms">AdSense
- Terms of Service</a> and the <a class="external-link"
- href="https://support.google.com/admob/topic/1307235?hl=en&ref_topic=1307209">AdMob
- publisher guidelines and policies</a>.</p>
+ <p>Your use of the Google Mobile Ads SDK is governed by the terms between you and Google that
+ govern your use of the Google product (AdSense/AdMob, AdX or DFP) with which you use the SDK.</p>
<p>For quick access while developing your Android apps, the <a
href="{@docRoot}reference/gms-packages.html">Google Mobile Ads API reference</a> is available here on
developer.android.com.</p>
diff --git a/docs/html/images/transitions/transition_sample_video.mp4 b/docs/html/images/transitions/transition_sample_video.mp4
new file mode 100644
index 0000000..37ae685
--- /dev/null
+++ b/docs/html/images/transitions/transition_sample_video.mp4
Binary files differ
diff --git a/docs/html/images/transitions/transition_sample_video.ogv b/docs/html/images/transitions/transition_sample_video.ogv
new file mode 100644
index 0000000..5598814
--- /dev/null
+++ b/docs/html/images/transitions/transition_sample_video.ogv
Binary files differ
diff --git a/docs/html/images/transitions/transition_sample_video.webm b/docs/html/images/transitions/transition_sample_video.webm
new file mode 100644
index 0000000..346ba8c
--- /dev/null
+++ b/docs/html/images/transitions/transition_sample_video.webm
Binary files differ
diff --git a/docs/html/images/transitions/transitions_diagram.png b/docs/html/images/transitions/transitions_diagram.png
new file mode 100644
index 0000000..9363940
--- /dev/null
+++ b/docs/html/images/transitions/transitions_diagram.png
Binary files differ
diff --git a/docs/html/tools/building/plugin-for-gradle.jd b/docs/html/tools/building/plugin-for-gradle.jd
index 77cbfda..54a03fd 100644
--- a/docs/html/tools/building/plugin-for-gradle.jd
+++ b/docs/html/tools/building/plugin-for-gradle.jd
@@ -321,7 +321,7 @@
machine and on other machines where Android Studio is not installed.</p>
<p class="caution"><strong>Caution:</strong> When you create a project, only use the Gradle wrapper
-scripts and JAR from a trusted source, such as those generated by Android Studio. /p>
+scripts and JAR from a trusted source, such as those generated by Android Studio. </p>
<h2 id="buildVariants"> Build variants</h2>
diff --git a/docs/html/training/location/display-address.jd b/docs/html/training/location/display-address.jd
index 621b082..516f14f 100644
--- a/docs/html/training/location/display-address.jd
+++ b/docs/html/training/location/display-address.jd
@@ -1,280 +1,468 @@
page.title=Displaying a Location Address
-
trainingnavtop=true
-
@jd:body
-
-
<div id="tb-wrapper">
-<div id="tb">
+ <div id="tb">
-<h2>This lesson teaches you to</h2>
-<ol>
- <li><a href="#DefineTask">Define the Address Lookup Task</a></li>
- <li><a href="#DisplayResults">Define a Method to Display the Results</a></li>
- <li><a href="#RunTask">Run the Lookup Task</a></li>
-</ol>
+ <h2>This lesson teaches you how to</h2>
+ <ol>
+ <li><a href="#connect">Get a Geographic Location</a></li>
+ <li><a href="#fetch-address">Define an Intent Service to Fetch the
+ Address</a></li>
+ <li><a href="#start-intent">Start the Intent Service</a></li>
+ <li><a href="#result-receiver">Receive the Geocoding Results</a></li>
+ </ol>
-<h2>You should also read</h2>
-<ul>
- <li>
- <a href="{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a>
- </li>
- <li>
- <a href="retrieve-current.html">Retrieving the Current Location</a>
- </li>
- <li>
- <a href="receive-location-updates.html">Receiving Location Updates</a>
- </li>
-</ul>
-<h2>Try it out</h2>
+ <h2>You should also read</h2>
+ <ul>
+ <li>
+ <a href="{@docRoot}google/play-services/setup.html">Setting up Google
+ Play Services</a>
+ </li>
+ <li>
+ <a href="retrieve-current.html">Getting the Last Known Location</a>
+ </li>
+ <li>
+ <a href="receive-location-updates.html">Receiving Location Updates</a>
+ </li>
+ </ul>
+ <h2>Try it out</h2>
-<div class="download-box">
-<a href="http://developer.android.com/shareables/training/LocationUpdates.zip" class="button">Download
- the sample app</a>
-<p class="filename">LocationUpdates.zip</p>
+ <ul>
+ <li>
+ <a href="https://github.com/googlesamples/android-play-location/tree/master/LocationAddress" class="external-link">LocationAddress</a>
+ </li>
+ </ul>
+ </div>
</div>
-</div>
-</div>
+<p>The lessons <a href="retrieve-current.html">Getting the Last Known
+ Location</a> and <a href="receive-location-updates.html">Receiving Location
+ Updates</a> describe how to get the user's location in the form of a
+ {@link android.location.Location} object that contains latitude and longitude
+ coordinates. Although latitude and longitude are useful for calculating
+ distance or displaying a map position, in many cases the address of the
+ location is more useful. For example, if you want to let your users know where
+ they are or what is close by, a street address is more meaningful than the
+ geographic coordinates (latitude/longitude) of the location.</p>
-<p>
- The lessons <a href="retrieve-current.html">Retrieving the Current Location</a> and
- <a href="receive-location-updates.html">Receiving Location Updates</a> describe how to get the
- user's current location in the form of a {@link android.location.Location} object that
- contains latitude and longitude coordinates. Although latitude and longitude are useful for
- calculating distance or displaying a map position, in many cases the address of the location is
- more useful.
-</p>
-<p>
- The Android platform API provides a feature that returns an estimated street addresses for
- latitude and longitude values. This lesson shows you how to use this address lookup feature.
-</p>
-<p class="note">
- <strong>Note:</strong> Address lookup requires a backend service that is not included in the
- core Android framework. If this backend service is not available,
- {@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()} returns an empty
- list. The helper method {@link android.location.Geocoder#isPresent isPresent()}, available
- in API level 9 and later, checks to see if the backend service is available.
-</p>
-<p>
- The snippets in the following sections assume that your app has already retrieved the
- current location and stored it as a {@link android.location.Location} object in the global
- variable {@code mLocation}.
-</p>
-<!--
- Define the address lookup task
--->
-<h2 id="DefineTask">Define the Address Lookup Task</h2>
-<p>
-To get an address for a given latitude and longitude, call
-{@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()}, which returns a
-list of addresses. The method is synchronous, and may take a long time to do its work, so you
-should call the method from the {@link android.os.AsyncTask#doInBackground
-doInBackground()} method of an {@link android.os.AsyncTask}.
-</p>
-<p>
-While your app is getting the address, display an indeterminate activity
-indicator to show that your app is working in the background. Set the indicator's initial state
-to {@code android:visibility="gone"}, to make it invisible and remove it from the layout
-hierarchy. When you start the address lookup, you set its visibility to "visible".
-</p>
-<p>
-The following snippet shows how to add an indeterminate {@link android.widget.ProgressBar} to
-your layout file:
-</p>
+<p>Using the {@link android.location.Geocoder} class in the Android framework
+ location APIs, you can convert an address to the corresponding geographic
+ coordinates. This process is called <em>geocoding</em>. Alternatively, you can
+ convert a geographic location to an address. The address lookup feature is
+ also known as <em>reverse geocoding</em>.</p>
+
+<p>This lesson shows you how to use the
+ {@link android.location.Geocoder#getFromLocation getFromLocation()} method to
+ convert a geographic location to an address. The method returns an estimated
+ street address corresponding to a given latitude and longitude.</p>
+
+<h2 id="connect">Get a Geographic Location</h2>
+
+<p>The last known location of the device is a useful starting point for the
+ address lookup feature. The lesson on
+ <a href="retrieve-current.html">Getting the Last Known Location</a> shows you
+ how to use the
+ <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>
+ method provided by the
+ <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused
+ location provider</a> to find the latest location of the device.</p>
+
+<p>To access the fused location provider, you need to create an instance of the
+ Google Play services API client. To learn how to connect your client, see
+ <a href="{@docRoot}training/location/retrieve-current.html#play-services">Connect
+ to Google Play Services</a>.</p>
+
+<p>In order for the fused location provider to retrieve a precise street
+ address, set the location permission in your app manifest to
+ {@code ACCESS_FINE_LOCATION}, as shown in the following example:</p>
+
<pre>
-<ProgressBar
-android:id="@+id/address_progress"
-android:layout_width="wrap_content"
-android:layout_height="wrap_content"
-android:layout_centerHorizontal="true"
-android:indeterminate="true"
-android:visibility="gone" />
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.gms.location.sample.locationupdates" >
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+</manifest>
</pre>
-<p>
-To create the background task, define a subclass of {@link android.os.AsyncTask} that calls
-{@link android.location.Geocoder#getFromLocation getFromLocation()} and returns an address.
-Define a {@link android.widget.TextView} object {@code mAddress} to contain the returned
-address, and a {@link android.widget.ProgressBar} object that allows you to control the
-indeterminate activity indicator. For example:
-</p>
+
+<h2 id="fetch-address">Define an Intent Service to Fetch the Address</h2>
+
+<p>The {@link android.location.Geocoder#getFromLocation getFromLocation()}
+ method provided by the {@link android.location.Geocoder} class accepts a
+ latitude and longitude, and returns a list of addresses. The method is
+ synchronous, and may take a long time to do its work, so you should not call
+ it from the main, user interface (UI) thread of your app.</p>
+
+<p>The {@link android.app.IntentService IntentService} class provides a
+ structure for running a task on a background thread. Using this class, you can
+ handle a long-running operation without affecting your UI's responsiveness.
+ Note that the {@link android.os.AsyncTask AsyncTask} class also allows you to
+ perform background operations, but it's designed for short operations. An
+ {@link android.os.AsyncTask AsyncTask} shouldn't keep a reference to the UI if
+ the activity is recreated, for example when the device is rotated. In
+ contrast, an {@link android.app.IntentService IntentService} doesn't need to
+ be cancelled when the activity is rebuilt.</p>
+
+<p>Define a {@code FetchAddressIntentService} class that extends
+ {@link android.app.IntentService}. This class is your address lookup service.
+ The intent service handles an intent asynchronously on a worker thread, and
+ stops itself when it runs out of work. The intent extras provide the data
+ needed by the service, including a {@link android.location.Location} object
+ for conversion to an address, and a {@link android.os.ResultReceiver} object
+ to handle the results of the address lookup. The service uses a {@link
+ android.location.Geocoder} to fetch the address for the location, and sends
+ the results to the {@link android.os.ResultReceiver}.</p>
+
+<h3>Define the Intent Service in your App Manifest</h3>
+
+<p>Add an entry to your app manifest defining the intent service:</p>
+
<pre>
-public class MainActivity extends FragmentActivity {
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.gms.location.sample.locationaddress" >
+ <application
+ ...
+ <service
+ android:name=".FetchAddressIntentService"
+ android:exported="false"/>
+ </application>
...
- private TextView mAddress;
- private ProgressBar mActivityIndicator;
+</manifest>
+</pre>
+
+<p class="note"><strong>Note:</strong> The {@code <service>} element in
+ the manifest doesn't need to include an intent filter, because your main
+ activity creates an explicit intent by specifying the name of the class to use
+ for the intent.</p>
+
+<h3>Create a Geocoder</h3>
+
+<p>The process of converting a geographic location to an address is called
+ <em>reverse geocoding</em>. To perform the main work of the intent service,
+ that is, your reverse geocoding request, implement
+ {@link android.app.IntentService#onHandleIntent onHandleIntent()} within the
+ {@code FetchAddressIntentService} class. Create a
+ {@link android.location.Geocoder} object to handle the reverse geocoding.</p>
+
+<p>A locale represents a specific geographical or linguistic region. Locale
+ objects are used to adjust the presentation of information, such as numbers or
+ dates, to suit the conventions in the region represented by the locale. Pass a
+ <a href="{@docRoot}reference/java/util/Locale.html">{@code Locale}</a> object
+ to the {@link android.location.Geocoder} object, to ensure that the resulting
+ address is localized to the user's geographic region.</p>
+
+<pre>
+@Override
+protected void onHandleIntent(Intent intent) {
+ Geocoder geocoder = new Geocoder(this, Locale.getDefault());
+ ...
+}
+</pre>
+
+<h3 id="retrieve-street-address">Retrieve the street address data</h3>
+
+<p>The next step is to retrieve the street address from the geocoder, handle
+ any errors that may occur, and send the results back to the activity that
+ requested the address. To report the results of the geocoding
+ process, you need two numeric constants that indicate success or failure.
+ Define a {@code Constants} class to contain the values, as shown in this code
+ snippet:</p>
+
+<pre>
+public final class Constants {
+ public static final int SUCCESS_RESULT = 0;
+ public static final int FAILURE_RESULT = 1;
+ public static final String PACKAGE_NAME =
+ "com.google.android.gms.location.sample.locationaddress";
+ public static final String RECEIVER = PACKAGE_NAME + ".RECEIVER";
+ public static final String RESULT_DATA_KEY = PACKAGE_NAME +
+ ".RESULT_DATA_KEY";
+ public static final String LOCATION_DATA_EXTRA = PACKAGE_NAME +
+ ".LOCATION_DATA_EXTRA";
+}
+</pre>
+
+<p>To get a street address corresponding to a geographical location, call
+ {@link android.location.Geocoder#getFromLocation getFromLocation()},
+ passing it the latitude and longitude from the location object, and the
+ maximum number of addresses you want returned. In this case, you want just one
+ address. The geocoder returns an array of addresses. If no addresses were
+ found to match the given location, it returns an empty list. If there is no
+ backend geocoding service available, the geocoder returns null.</p>
+
+<p>Check for the following errors as shown in the code sample below. If an error
+ occurs, place the corresponding error message in the {@code errorMessage}
+ variable, so you can send it back to the requesting activity:</p>
+
+<ul>
+ <li><strong>No location data provided</strong> - The intent extras do not
+ include the {@link android.location.Location} object required for reverse
+ geocoding.</li>
+ <li><strong>Invalid latitude or longitude used</strong> - The latitude
+ and/or longitude values provided in the {@link android.location.Location}
+ object are invalid.</li>
+ <li><strong>No geocoder available</strong> - The background geocoding service
+ is not available, due to a network error or IO exception.</li>
+ <li><strong>Sorry, no address found</strong> - The geocoder could not find an
+ address for the given latitude/longitude.</li>
+</ul>
+
+<p>To get the individual lines of an address object, use the
+ {@link android.location.Address#getAddressLine getAddressLine()}
+ method provided by the {@link android.location.Address} class. Then join the
+ lines into a list of address fragments ready to return to the activity that
+ requested the address.</p>
+
+<p>To send the results back to the requesting activity, call the
+ {@code deliverResultToReceiver()} method (defined in
+ <a href="#return-address">Return the address to the requestor</a>). The
+ results consist of the previously-mentioned numeric success/failure code and
+ a string. In the case of a successful reverse geocoding, the string contains
+ the address. In the case of a failure, the string contains the error message,
+ as shown in the code sample below:</p>
+
+<pre>
+@Override
+protected void onHandleIntent(Intent intent) {
+ String errorMessage = "";
+
+ // Get the location passed to this service through an extra.
+ Location location = intent.getParcelableExtra(
+ Constants.LOCATION_DATA_EXTRA);
+
+ ...
+
+ List<Address> addresses = null;
+
+ try {
+ addresses = geocoder.getFromLocation(
+ location.getLatitude(),
+ location.getLongitude(),
+ // In this sample, get just a single address.
+ 1);
+ } catch (IOException ioException) {
+ // Catch network or other I/O problems.
+ errorMessage = getString(R.string.service_not_available);
+ Log.e(TAG, errorMessage, ioException);
+ } catch (IllegalArgumentException illegalArgumentException) {
+ // Catch invalid latitude or longitude values.
+ errorMessage = getString(R.string.invalid_lat_long_used);
+ Log.e(TAG, errorMessage + ". " +
+ "Latitude = " + location.getLatitude() +
+ ", Longitude = " +
+ location.getLongitude(), illegalArgumentException);
+ }
+
+ // Handle case where no address was found.
+ if (addresses == null || addresses.size() == 0) {
+ if (errorMessage.isEmpty()) {
+ errorMessage = getString(R.string.no_address_found);
+ Log.e(TAG, errorMessage);
+ }
+ deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
+ } else {
+ Address address = addresses.get(0);
+ ArrayList<String> addressFragments = new ArrayList<String>();
+
+ // Fetch the address lines using {@code getAddressLine},
+ // join them, and send them to the thread.
+ for(int i = 0; i < address.getMaxAddressLineIndex(); i++) {
+ addressFragments.add(address.getAddressLine(i));
+ }
+ Log.i(TAG, getString(R.string.address_found));
+ deliverResultToReceiver(Constants.SUCCESS_RESULT,
+ TextUtils.join(System.getProperty("line.separator"),
+ addressFragments));
+ }
+}
+</pre>
+
+<h3 id="return-address">Return the address to the requestor</h3>
+
+<p>The final thing the intent service must do is send the address back to a
+ {@link android.os.ResultReceiver} in the activity that started the service.
+ The {@link android.os.ResultReceiver} class allows you to send a
+ numeric result code as well as a message containing the result data. The
+ numeric code is useful for reporting the success or failure of the geocoding
+ request. In the case of a successful reverse geocoding, the message contains
+ the address. In the case of a failure, the message contains some text
+ describing the reason for failure.</p>
+
+<p>You have already retrieved the address from the geocoder, trapped any errors
+ that may occur, and called the {@code deliverResultToReceiver()} method. Now
+ you need to define the {@code deliverResultToReceiver()} method that sends
+ a result code and message bundle to the result receiver.</p>
+
+<p>For the result code, use the value that you've passed to the
+ {@code deliverResultToReceiver()} method in the {@code resultCode} parameter.
+ To construct the message bundle, concatenate the {@code RESULT_DATA_KEY}
+ constant from your {@code Constants} class (defined in
+ <a href="#retrieve-street-address">Retrieve the street address data</a>) and
+ the value in the {@code message} parameter passed to the
+ {@code deliverResultToReceiver()} method, as shown in the following sample:
+</p>
+
+<pre>
+public class FetchAddressIntentService extends IntentService {
+ protected ResultReceiver mReceiver;
+ ...
+ private void deliverResultToReceiver(int resultCode, String message) {
+ Bundle bundle = new Bundle();
+ bundle.putString(Constants.RESULT_DATA_KEY, message);
+ mReceiver.send(resultCode, bundle);
+ }
+}
+</pre>
+
+<h2 id="start-intent">Start the Intent Service</h2>
+
+<p>The intent service, as defined in the previous section, runs in the
+ background and is responsible for fetching the address corresponding to a
+ given geographic location. When you start the service, the Android framework
+ instantiates and starts the service if it isn't already running, and creates a
+ process if needed. If the service is already running then it remains running.
+ Because the service extends {@link android.app.IntentService IntentService},
+ it shuts down automatically when all intents have been processed.</p>
+
+<p>Start the service from your app's main activity,
+ and create an {@link android.content.Intent} to pass data to the service. You
+ need an <em>explicit</em> intent, because you want only your service
+ to respond to the intent. For more information, see
+ <a href="{@docRoot}guide/components/intents-filters.html#Types">Intent
+ Types</a>.</p>
+
+<p>To create an explicit intent, specify the name of the
+ class to use for the service: {@code FetchAddressIntentService.class}.
+ Pass two pieces of information in the intent extras:</p>
+
+<ul>
+ <li>A {@link android.os.ResultReceiver} to handle the results of the address
+ lookup.</li>
+ <li>A {@link android.location.Location} object containing the latitude and
+ longitude that you want to convert to an address.</li>
+</ul>
+
+<p>The following code sample shows you how to start the intent service:</p>
+
+<pre>
+public class MainActivity extends ActionBarActivity implements
+ ConnectionCallbacks, OnConnectionFailedListener {
+
+ protected Location mLastLocation;
+ private AddressResultReceiver mResultReceiver;
+ ...
+
+ protected void startIntentService() {
+ Intent intent = new Intent(this, FetchAddressIntentService.class);
+ intent.putExtra(Constants.RECEIVER, mResultReceiver);
+ intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
+ startService(intent);
+ }
+}
+</pre>
+
+<p>Call the above {@code startIntentService()} method when the
+ user takes an action that requires a geocoding address lookup. For example,
+ the user may press a <em>Fetch address</em> button on your app's UI. Before
+ starting the intent service, you need to check that the connection to Google
+ Play services is present. The following code snippet shows the call to the
+ {@code startIntentService()} method in the button handler:</p>
+
+<pre>
+public void fetchAddressButtonHandler(View view) {
+ // Only start the service to fetch the address if GoogleApiClient is
+ // connected.
+ if (mGoogleApiClient.isConnected() && mLastLocation != null) {
+ startIntentService();
+ }
+ // If GoogleApiClient isn't connected, process the user's request by
+ // setting mAddressRequested to true. Later, when GoogleApiClient connects,
+ // launch the service to fetch the address. As far as the user is
+ // concerned, pressing the Fetch Address button
+ // immediately kicks off the process of getting the address.
+ mAddressRequested = true;
+ updateUIWidgets();
+}
+</pre>
+
+<p>You must also start the intent service when the connection to Google Play
+ services is established, if the user has already clicked the button on your
+ app's UI. The following code snippet shows the call to the
+ {@code startIntentService()} method in the
+ <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a>
+ callback provided by the Google API Client:</p>
+
+<pre>
+public class MainActivity extends ActionBarActivity implements
+ ConnectionCallbacks, OnConnectionFailedListener {
...
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- ...
- mAddress = (TextView) findViewById(R.id.address);
- mActivityIndicator =
- (ProgressBar) findViewById(R.id.address_progress);
- }
- ...
- /**
- * A subclass of AsyncTask that calls getFromLocation() in the
- * background. The class definition has these generic types:
- * Location - A {@link android.location.Location} object containing
- * the current location.
- * Void - indicates that progress units are not used
- * String - An address passed to onPostExecute()
- */
- private class GetAddressTask extends
- AsyncTask<Location, Void, String> {
- Context mContext;
- public GetAddressTask(Context context) {
- super();
- mContext = context;
- }
- ...
- /**
- * Get a Geocoder instance, get the latitude and longitude
- * look up the address, and return it
- *
- * @params params One or more Location objects
- * @return A string containing the address of the current
- * location, or an empty string if no address can be found,
- * or an error message
- */
- @Override
- protected String doInBackground(Location... params) {
- Geocoder geocoder =
- new Geocoder(mContext, Locale.getDefault());
- // Get the current location from the input parameter list
- Location loc = params[0];
- // Create a list to contain the result address
- List<Address> addresses = null;
- try {
- /*
- * Return 1 address.
- */
- addresses = geocoder.getFromLocation(loc.getLatitude(),
- loc.getLongitude(), 1);
- } catch (IOException e1) {
- Log.e("LocationSampleActivity",
- "IO Exception in getFromLocation()");
- e1.printStackTrace();
- return ("IO Exception trying to get address");
- } catch (IllegalArgumentException e2) {
- // Error message to post in the log
- String errorString = "Illegal arguments " +
- Double.toString(loc.getLatitude()) +
- " , " +
- Double.toString(loc.getLongitude()) +
- " passed to address service";
- Log.e("LocationSampleActivity", errorString);
- e2.printStackTrace();
- return errorString;
+ public void onConnected(Bundle connectionHint) {
+ // Gets the best and most recent location currently available,
+ // which may be null in rare cases when a location is not available.
+ mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
+ mGoogleApiClient);
+
+ if (mLastLocation != null) {
+ // Determine whether a Geocoder is available.
+ if (!Geocoder.isPresent()) {
+ Toast.makeText(this, R.string.no_geocoder_available,
+ Toast.LENGTH_LONG).show();
+ return;
}
- // If the reverse geocode returned an address
- if (addresses != null && addresses.size() > 0) {
- // Get the first address
- Address address = addresses.get(0);
- /*
- * Format the first line of address (if available),
- * city, and country name.
- */
- String addressText = String.format(
- "%s, %s, %s",
- // If there's a street address, add it
- address.getMaxAddressLineIndex() > 0 ?
- address.getAddressLine(0) : "",
- // Locality is usually a city
- address.getLocality(),
- // The country of the address
- address.getCountryName());
- // Return the text
- return addressText;
- } else {
- return "No address found";
+
+ if (mAddressRequested) {
+ startIntentService();
}
}
- ...
}
- ...
}
</pre>
-<p>
-The next section shows you how to display the address in the user interface.
-</p>
-<!-- Define a method to display the address -->
-<h2 id="DisplayResults">Define a Method to Display the Results</h2>
-<p>
- {@link android.os.AsyncTask#doInBackground doInBackground()} returns the result of the address
- lookup as a {@link java.lang.String}. This value is passed to
- {@link android.os.AsyncTask#onPostExecute onPostExecute()}, where you do further processing
- on the results. Since {@link android.os.AsyncTask#onPostExecute onPostExecute()}
- runs on the UI thread, it can update the user interface; for example, it can turn off the
- activity indicator and display the results to the user:
-</p>
+
+<h2 id="result-receiver">Receive the Geocoding Results</h2>
+
+<p>The intent service has handled the geocoding request, and uses a
+ {@link android.os.ResultReceiver} to return the results to the activity that
+ made the request. In the activity that makes the request, define an
+ {@code AddressResultReceiver} that extends {@link android.os.ResultReceiver}
+ to handle the response from {@code FetchAddressIntentService}.</p>
+
+<p>The result includes a numeric result code (<code>resultCode</code>) as well
+ as a message containing the result data (<code>resultData</code>). If the
+ reverse geocoding process was successful, the <code>resultData</code> contains
+ the address. In the case of a failure, the <code>resultData</code> contains
+ text describing the reason for failure. For details of the possible errors,
+ see <a href="#return-address">Return the address to the requestor</a>.</p>
+
+<p>Override the
+ {@link android.os.ResultReceiver#onReceiveResult onReceiveResult()} method
+ to handle the results delivered to the result receiver, as shown in the
+ following code sample:</p>
+
<pre>
- private class GetAddressTask extends
- AsyncTask<Location, Void, String> {
- ...
- /**
- * A method that's called once doInBackground() completes. Turn
- * off the indeterminate activity indicator and set
- * the text of the UI element that shows the address. If the
- * lookup failed, display the error message.
- */
+public class MainActivity extends ActionBarActivity implements
+ ConnectionCallbacks, OnConnectionFailedListener {
+ ...
+ class AddressResultReceiver extends ResultReceiver {
+ public AddressResultReceiver(Handler handler) {
+ super(handler);
+ }
+
@Override
- protected void onPostExecute(String address) {
- // Set activity indicator visibility to "gone"
- mActivityIndicator.setVisibility(View.GONE);
- // Display the results of the lookup.
- mAddress.setText(address);
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+
+ // Display the address string
+ // or an error message sent from the intent service.
+ mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
+ displayAddressOutput();
+
+ // Show a toast message if an address was found.
+ if (resultCode == Constants.SUCCESS_RESULT) {
+ showToast(getString(R.string.address_found));
+ }
+
}
- ...
}
-</pre>
-<p>
- The final step is to run the address lookup.
-</p>
-<!-- Get and display the address -->
-<h2 id="RunTask">Run the Lookup Task</h2>
-<p>
- To get the address, call {@link android.os.AsyncTask#execute execute()}. For example, the
- following snippet starts the address lookup when the user clicks the "Get Address" button:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity {
- ...
- /**
- * The "Get Address" button in the UI is defined with
- * android:onClick="getAddress". The method is invoked whenever the
- * user clicks the button.
- *
- * @param v The view object associated with this method,
- * in this case a Button.
- */
- public void getAddress(View v) {
- // Ensure that a Geocoder services is available
- if (Build.VERSION.SDK_INT >=
- Build.VERSION_CODES.GINGERBREAD
- &&
- Geocoder.isPresent()) {
- // Show the activity indicator
- mActivityIndicator.setVisibility(View.VISIBLE);
- /*
- * Reverse geocoding is long-running and synchronous.
- * Run it on a background thread.
- * Pass the current location to the background task.
- * When the task finishes,
- * onPostExecute() displays the address.
- */
- (new GetAddressTask(this)).execute(mLocation);
- }
- ...
- }
- ...
}
</pre>
-<p>
- The next lesson, <a href="geofencing.html">Creating and Monitoring Geofences</a>, demonstrates
- how to define locations of interest called <b>geofences</b> and how to use geofence monitoring
- to detect the user's proximity to a location of interest.
-</p>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 0fcfb9c..f5999a5 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -437,6 +437,35 @@
</li>
</ul>
</li>
+
+ <li class="nav-section">
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot?>training/transitions/index.html"
+ description=
+ "How to animate state changes in a view hierarchy using transitions."
+ >Animating Views Using Scenes and Transitions</a>
+ </div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>training/transitions/overview.html">
+ The Transitions Framework
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/transitions/scenes.html">
+ Creating a Scene
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/transitions/transitions.html">
+ Applying a Transition
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/transitions/custom-transitions.html">
+ Creating Custom Transitions
+ </a>
+ </li>
+
+ </ul>
+ </li>
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/animation/index.html"
description=
diff --git a/docs/html/training/transitions/custom-transitions.jd b/docs/html/training/transitions/custom-transitions.jd
new file mode 100644
index 0000000..b64daaeb
--- /dev/null
+++ b/docs/html/training/transitions/custom-transitions.jd
@@ -0,0 +1,189 @@
+page.title=Creating Custom Transitions
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#Extend">Extend the Transition Class</a></li>
+ <li><a href="#CaptureProperties">Capture View Property Values</a></li>
+ <li><a href="#CreateAnimator">Create a Custom Animator</a></li>
+ <li><a href="#Apply">Apply a Custom Transition</a></li>
+</ol>
+</div>
+</div>
+
+<p>A custom transition enables you to create an animation that is not available from any of
+the built-in transition classes. For example, you can define a custom transition that turns
+the foreground color of text and input fields to gray to indicate that the fields are disabled
+in the new screen. This type of change helps users see the fields you disabled.</p>
+
+<p>A custom transition, like one of the built-in transition types, applies animations to
+child views of both the starting and ending scenes. Unlike built-in transition types,
+however, you have to provide the code that captures property values and generates animations.
+You may also want to define a subset of target views for your animation.</p>
+
+<p>This lesson teaches you to capture property values and generate animations to create
+custom transitions.</p>
+
+
+
+<h2 id="Extend">Extend the Transition Class</h2>
+
+<p>To create a custom transition, add a class to your project that extends the {@link
+android.transition.Transition} class and override the methods shown in the following snippet:</p>
+
+<pre>
+public class CustomTransition extends Transition {
+
+ @Override
+ public void captureStartValues(TransitionValues values) {}
+
+ @Override
+ public void captureEndValues(TransitionValues values) {}
+
+ @Override
+ public Animator createAnimator(ViewGroup sceneRoot,
+ TransitionValues startValues,
+ TransitionValues endValues) {}
+}
+</pre>
+
+<p>The following sections explain how to override these methods.</p>
+
+
+
+<h2 id="CaptureProperties">Capture View Property Values</h2>
+
+<p>Transition animations use the property animation system described in
+<a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>. Property
+animations change a view property between a starting and ending value over a specified
+period of time, so the framework needs to have both the starting and ending value of
+the property to construct the animation.</p>
+
+<p>However, a property animation usually needs only a small subset of all the view's property
+values. For example, a color animation needs color property values, while a movement
+animation needs position property values. Since the property values needed for an animation
+are specific to a transition, the transitions framework does not provide every property value
+to a transition. Instead, the framework invokes callback methods that allow a transition to
+capture only the property values it needs and store them in the framework.</p>
+
+
+<h3 id="StartingValues">Capturing Starting Values</h3>
+
+<p>To pass the starting view values to the framework, implement the
+{@link android.transition.Transition#captureStartValues captureStartValues(transitionValues)}
+method. The framework calls this method for every view in the starting scene. The method
+argument is a {@link android.transition.TransitionValues} object that contains a reference
+to the view and a {@link java.util.Map} instance in which you can store the view values you
+want. In your implementation, retrieve these property values and pass them back to the
+framework by storing them in the map.</p>
+
+<p>To ensure that the key for a property value does not conflict with other {@link
+android.transition.TransitionValues} keys, use the following naming scheme:</p>
+
+<pre>
+package_name:transition_name:property_name
+</pre>
+
+<p>The following snippet shows an implementation of the {@link
+android.transition.Transition#captureStartValues captureStartValues()} method:</p>
+
+<pre>
+public class CustomTransition extends Transition {
+
+ // Define a key for storing a property value in
+ // TransitionValues.values with the syntax
+ // package_name:transition_class:property_name to avoid collisions
+ private static final String PROPNAME_BACKGROUND =
+ "com.example.android.customtransition:CustomTransition:background";
+
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ // Call the convenience method captureValues
+ captureValues(transitionValues);
+ }
+
+
+ // For the view in transitionValues.view, get the values you
+ // want and put them in transitionValues.values
+ private void captureValues(TransitionValues transitionValues) {
+ // Get a reference to the view
+ View view = transitionValues.view;
+ // Store its background property in the values map
+ transitionValues.values.put(PROPNAME_BACKGROUND, view.getBackground());
+ }
+ ...
+}
+</pre>
+
+
+<h3 id="EndingValues">Capture Ending Values</h3>
+
+<p>The framework calls the {@link android.transition.Transition#captureEndValues} method
+once for every target view in the ending scene. In all other respects, {@link
+android.transition.Transition#captureEndValues captureEndValues()} works the same as {@link
+android.transition.Transition#captureStartValues captureStartValues()}.</p>
+
+<p>The following code snippet shows an implementation of the {@link
+android.transition.Transition#captureEndValues captureEndValues()} method:</p>
+
+<pre>
+@Override
+public void captureEndValues(TransitionValues transitionValues) {
+ captureValues(transitionValues);
+}
+</pre>
+
+<p>In this example, both the {@link android.transition.Transition#captureStartValues
+captureStartValues()} and {@link android.transition.Transition#captureEndValues captureEndValues()}
+methods invoke <code>captureValues()</code> to retrieve and store values. The view property
+that <code>captureValues()</code> retrieves is the same, but it has different values in the
+starting and ending scenes. The framework maintains separate maps for the starting and ending
+states of a view.</p>
+
+
+
+<h2 id="CreateAnimator">Create a Custom Animator</h2>
+
+<p>To animate the changes to a view between its state in the starting scene and its state in
+the ending scene, you provide an animator by overriding the {@link
+android.transition.Transition#createAnimator createAnimator()} method. When the
+framework calls this method, it passes in the scene root view and the {@link
+android.transition.TransitionValues} objects that contain the starting and ending values
+you captured.</p>
+
+<p>The number of times the framework calls the {@link
+android.transition.Transition#createAnimator createAnimator()} method depends on the changes that
+occur between the starting and ending scenes. For example, consider a fade out/fade in animation
+implemented as a custom transition. If the starting scene has five targets of which two are
+removed from the ending scene, and the ending scene has the three targets from the starting
+scene plus a new target, then the framework calls {@link
+android.transition.Transition#createAnimator createAnimator()} six times: three of the calls
+animate the fading out and fading in of the targets that stay in both scene objects; two more calls
+animate the fading out of the targets removed from the ending scene; and one call
+animates the fading in of the new target in the ending scene.</p>
+
+<p>For target views that exist on both the starting and ending scenes, the framework provides
+a {@link android.transition.TransitionValues} object for both the <code>startValues</code> and
+<code>endValues</code> arguments. For target views that only exist in the starting or the
+ending scene, the framework provides a {@link android.transition.TransitionValues} object
+for the corresponding argument and <code>null</code> for the other.</p>
+
+<p>To implement the {@link android.transition.Transition#createAnimator} method when you create
+a custom transition, use the view property values you captured to create an {@link
+android.animation.Animator} object and return it to the framework. For an example implementation,
+see the <a
+href="{@docRoot}samples/CustomTransition/src/com.example.android.customtransition/ChangeColor.html">
+<code>ChangeColor</code></a> class in the <a href="{@docRoot}samples/CustomTransition/index.html">
+CustomTransition</a> sample. For more information about property animators, see
+<a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>.</p>
+
+
+
+<h2 id="Apply">Apply a Custom Transition</h2>
+
+<p>Custom transitions work the same as built-in transitions. You can apply a custom transition
+using a transition manager, as described in <a
+href="{@docRoot}training/transitions/transitions.html#Apply">Applying a Transition</a>.</p>
diff --git a/docs/html/training/transitions/index.jd b/docs/html/training/transitions/index.jd
new file mode 100644
index 0000000..53faa01
--- /dev/null
+++ b/docs/html/training/transitions/index.jd
@@ -0,0 +1,80 @@
+page.title=Animating Views Using Scenes and Transitions
+
+@jd:body
+
+<!-- Sidebox -->
+<div id="tb-wrapper">
+<div id="tb">
+ <h2>Dependencies and Prerequisites</h2>
+ <ul>
+ <li>Android 4.4.2 (API level 19) or higher</li>
+ </ul>
+ <h2>You should also read</h2>
+ <ul>
+ <li><a href="{@docRoot}guide/topics/ui/how-android-draws.html">
+ How Android Draws Views</a></li>
+ </ul>
+ <h2>Try it out</h2>
+ <ul>
+ <li><a href="{@docRoot}samples/BasicTransition/index.html">BasicTransition</a> sample</li>
+ <li><a href="{@docRoot}samples/CustomTransition/index.html">CustomTransition</a> sample</li>
+ </ul>
+</div>
+</div>
+
+<!-- Video box -->
+<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=S3H7nJ4QaD8">
+<div>
+ <h3>Video</h3>
+ <p>DevBytes: Android 4.4 Transitions</p>
+</div>
+</a>
+
+<p>The user interface of an activity often changes in response to user input and other events.
+For example, an activity that contains a form where users can type search queries can hide
+the form when the user submits it and show a list of search results in its place.</p>
+
+<p>To provide visual continuity in these situations, you can animate changes between
+different view hierarchies in your user interface. These animations give users feedback on
+their actions and help them learn how your app works.</p>
+
+<p>Android includes the <em>transitions framework</em>, which enables you to easily
+animate changes between two view hierarchies. The framework animates the views at runtime by
+changing some of their property values over time. The framework includes built-in animations
+for common effects and lets you create custom animations and transition lifecycle callbacks.</p>
+
+<p>This class teaches you to use the built-in animations in the transitions framework to
+animate changes between view hierarchies. This class also covers how to create custom
+animations.</p>
+
+<p class="note"><strong>Note:</strong> For Android versions earlier than 4.4.2 (API level 19)
+but greater than or equal to Android 4.0 (API level 14), use the <code>animateLayoutChanges</code>
+attribute to animate layouts. To learn more, see
+<a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a> and
+<a href="{@docRoot}training/animation/layout.html">Animating Layout Changes</a>.</p>
+
+
+<h2>Lessons</h2>
+
+<dl>
+<dt><a href="{@docRoot}training/transitions/overview.html">
+The Transitions Framework</a></dt>
+<dd>
+ Learn the main features and components of the transitions framework.
+</dd>
+<dt><a href="{@docRoot}training/transitions/scenes.html">
+Creating a Scene</a></dt>
+<dd>
+ Learn how to create a scene to store the state of a view hierarchy.
+</dd>
+<dt><a href="{@docRoot}training/transitions/transitions.html">
+Applying a Transition</a></dt>
+<dd>
+ Learn how to apply a transition between two scenes of a view hierarchy.
+</dd>
+<dt><a href="{@docRoot}training/transitions/custom-transitions.html">
+Creating Custom Transitions</a></dt>
+<dd>
+ Learn how to create other animation effects not included in the transitions framework.
+</dd>
+</dl>
diff --git a/docs/html/training/transitions/overview.jd b/docs/html/training/transitions/overview.jd
new file mode 100644
index 0000000..044cf16
--- /dev/null
+++ b/docs/html/training/transitions/overview.jd
@@ -0,0 +1,165 @@
+page.title=The Transitions Framework
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson covers</h2>
+<ol>
+ <li><a href="#Overview">Overview</a></li>
+ <li><a href="#Scenes">Scenes</a></li>
+ <li><a href="#Transitions">Transitions</a></li>
+ <li><a href="#Limitations">Limitations</a></li>
+</ol>
+</div>
+</div>
+
+<p>Animating your app's user interface provides more than just visual appeal. Animations
+highlight changes and provide visual cues that help users learn how your app works.</p>
+
+<p>To help you animate a change between one view hierarchy and another, Android provides the
+transitions framework. This framework applies one or more animations to all the views in the
+hierarchies as it changes between them.</p>
+
+<p>The framework has the following features:</p>
+
+<dl>
+<dt><em>Group-level animations</em></dt>
+<dd>Applies one or more animation effects to all of the views in a view hierarchy.</dd>
+<dt><em>Transition-based animation</em></dt>
+<dd>Runs animations based on the changes between starting and ending view property values.</dd>
+<dt><em>Built-in animations</em></dt>
+<dd>Includes predefined animations for common effects such as fade out or movement.</dd>
+
+<!-- Figure 1 - Transitions video -->
+<div style="float:right;margin-left:30px;margin-top:10px">
+<div class="framed-nexus5-port-span-5" style="clear:left;">
+<video class="play-on-hover" height="442" autoplay="" poster="">
+<source src="{@docRoot}images/transitions/transition_sample_video.mp4" type="video/mp4">
+<source src="{@docRoot}images/transitions/transition_sample_video.ogv" type="video/ogg">
+<source src="{@docRoot}images/transitions/transition_sample_video.webm" type="video/webm">
+</video>
+</div>
+<p class="img-caption" style="margin-top:7px;margin-bottom:0px">
+<strong>Figure 1.</strong> Visual cues using user interface animation.</p>
+<div style="margin-top:5px;margin-bottom:20px;font-size:10pt" class="video-instructions"> </div>
+</div>
+
+<dt><em>Resource file support</em></dt>
+<dd>Loads view hierarchies and built-in animations from layout resource files.</dd>
+<dt><em>Lifecycle callbacks</em></dt>
+<dd>Defines callbacks that provide finer control over the animation and hierarchy change
+process.</dd>
+</dl>
+
+
+
+<h2 id="Overview">Overview</h2>
+
+<p>The example in Figure 1 shows how an animation provides visual cues to help the user. As the
+app changes from its search entry screen to its search results screen, it fades out views that
+are no longer in use and fades in new views.</p>
+
+<p>This animation is an example of using the transitions framework. The framework
+animates changes to all the views in two view hierarchies. A view hierarchy can be as simple
+as a single view or as complex as a {@link android.view.ViewGroup} containing an elaborate
+tree of views. The framework animates each view by changing one or more of its property values
+over time between the initial or <em>starting</em> view hierarchy and the final or <em>ending</em>
+view hierarchy.</p>
+
+<p>The transitions framework works in parallel with view hierarchies and animations. The
+purpose of the framework is to store the state of view hierarchies, change between these
+hierarchies in order to modify the appearance of the device screen, and animate the change by
+storing and applying animation definitions.</p>
+
+<p>The diagram in Figure 2 illustrates the relationship between view hierarchies, framework
+objects, and animations:</p>
+
+<!-- Figure 2 - diagram -->
+<img src="{@docRoot}images/transitions/transitions_diagram.png"
+ width="506" height="234" alt="" style="margin-top:7px" />
+<p class="img-caption"><strong>Figure 2.</strong> Relationships in the transitions framework.</p>
+
+<p>The transitions framework provides abstractions for scenes, transitions, and transition
+managers. These are described in detail in the following sections. To use the framework, you
+create scenes for the view hierarchies in your app that you plan to change between. Next, you
+create a transition for each animation you want to use. To start the animation between two
+view hierarchies, you use a transition manager specifying the transition to use and the ending
+scene. This procedure is described in detail in the remaining lessons in this class.</p>
+
+
+
+<h2 id="Scenes">Scenes</h2>
+
+<p>A scene stores the state of a view hierarchy, including all its views and their property
+values. A view hierarchy can be a simple view or a complex tree of views and child layouts.
+Storing the view hierarchy state in a scene enables you to transition into that state from
+another scene. The framework provides the {@link android.transition.Scene} class to represent
+a scene.</p>
+
+<p>The transitions framework lets you create scenes from layout resource files or from
+{@link android.view.ViewGroup} objects in your code. Creating a scene in your code is useful
+if you generated a view hierarchy dynamically or if you are modifying it at runtime.</p>
+
+<p>In most cases, you do not create a starting scene explicitly. If you have applied a
+transition, the framework uses the previous ending scene as the starting scene for any
+subsequent transitions. If you have not applied a transition, the framework collects information
+about the views from the current state of the screen.</p>
+
+<p>A scene can also define its own actions that run when you make a scene change. For example,
+this feature is useful for cleaning up view settings after you transition to a scene.</p>
+
+<p>In addition to the view hierarchy and its property values, a scene also stores a reference
+to the parent of the view hierarchy. This root view is called a <strong>scene root</strong>.
+Changes to the scene and animations that affect the scene occur within the scene root.</p>
+
+<p>To learn how to create scenes, see
+<a href="{@docRoot}training/transitions/scenes.html">Creating a Scene</a>.</p>
+
+
+
+<h2 id="Transitions">Transitions</h2>
+
+<p>In the transitions framework, animations create a series of frames that depict a change
+between the view hierarchies in the starting and ending scenes. Information about the animation
+is stored in a {@link android.transition.Transition} object. To run the animation, you apply the
+transition using a {@link android.transition.TransitionManager} instance. The framework can
+transition between two different scenes or transition to a different state for the current
+scene.</p>
+
+<p>The framework includes a set of built-in transitions for commonly-used animation effects,
+such as fading and resizing views. You can also define your own custom transitions to create
+an animation effect using the APIs in the animations framework. The transitions framework also
+enables you to combine different animation effects in a transition set that contains a group
+of individual built-in or custom transitions.</p>
+
+<p>The transition lifecycle is similar to the activity lifecycle, and it represents the
+transition states that the framework monitors between the start and the completion of an
+animation. At important lifecycle states, the framework invokes callback methods that you can
+implement to make adjustments to your user interface at different phases of the transition.</p>
+
+<p>To learn more about transitions, see
+<a href="{@docRoot}training/transitions/transitions.html">Applying a Transition</a> and
+<a href="{@docRoot}training/transitions/custom-transitions.html">Creating Custom
+Transitions</a>.</p>
+
+
+
+<h2 id="Limitations">Limitations</h2>
+
+<p>This section lists some known limitations of the transitions framework:</p>
+
+<ul>
+<li>Animations applied to a {@link android.view.SurfaceView} may not appear correctly.
+{@link android.view.SurfaceView} instances are updated from a non-UI thread, so the updates
+may be out of sync with the animations of other views.</li>
+<li>Some specific transition types may not produce the desired animation effect when applied
+to a {@link android.view.TextureView}.</li>
+<li>Classes that extend {@link android.widget.AdapterView}, such as
+{@link android.widget.ListView}, manage their child views in ways that are incompatible with
+the transitions framework. If you try to animate a view based on
+{@link android.widget.AdapterView}, the device display may hang.</li>
+<li>If you try to resize a {@link android.widget.TextView} with an animation, the text will
+pop to a new location before the object has completely resized. To avoid this problem, do not
+animate the resizing of views that contain text.</li>
+</ul>
diff --git a/docs/html/training/transitions/scenes.jd b/docs/html/training/transitions/scenes.jd
new file mode 100644
index 0000000..4bf7d0e
--- /dev/null
+++ b/docs/html/training/transitions/scenes.jd
@@ -0,0 +1,211 @@
+page.title=Creating a Scene
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#FromLayout">Create a Scene From a Layout Resource</a></li>
+ <li><a href="#FromCode">Create a Scene in Your Code</a></li>
+ <li><a href="#Actions">Create Scene Actions</a></li>
+</ol>
+</div>
+</div>
+
+<p>Scenes store the state of a view hierarchy, including all its views and their property
+values. The transitions framework can run animations between a starting and an ending scene.
+The starting scene is often determined automatically from the current state of the user
+interface. For the ending scene, the framework enables you to create a scene from a layout
+resource file or from a group of views in your code.</p>
+
+<p>This lesson shows you how to create scenes in your app and how to define scene actions.
+The next lesson shows you how to transition between two scenes.</p>
+
+<p class="note"><strong>Note:</strong> The framework can animate changes in a single view
+hierarchy without using scenes, as described in
+<a href="{@docRoot}training/transitions/transitions.html#NoScenes">Apply a Transition Without
+Scenes</a>. However, understanding this lesson is essential to work with transitions.</p>
+
+
+
+<h2 id="FromLayout">Create a Scene From a Layout Resource</h2>
+
+<p>You can create a {@link android.transition.Scene} instance directly from a layout resource
+file. Use this technique when the view hierarchy in the file is mostly static. The resulting
+scene represents the state of the view hierarchy at the time you created the
+{@link android.transition.Scene} instance. If you change the view hierarchy, you have to
+recreate the scene. The framework creates the scene from the entire view hierarchy in the
+file; you can not create a scene from part of a layout file.</p>
+
+<p>To create a {@link android.transition.Scene} instance from a layout resource file, retrieve
+the scene root from your layout as a {@link android.view.ViewGroup} instance and then call the
+{@link android.transition.Scene#getSceneForLayout Scene.getSceneForLayout()} method with the
+scene root and the resource ID of the layout file that contains the view hierarchy for the
+scene.</p>
+
+<h3>Define Layouts for Scenes</h3>
+
+<p>The code snippets in the rest of this section show you how to create two different scenes
+with the same scene root element. The snippets also demonstrate that you can load multiple
+unrelated {@link android.transition.Scene} objects without implying that they are related to
+each other.</p>
+
+<p>The example consists of the following layout definitions:</p>
+
+<ul>
+<li>The main layout of an activity with a text label and a child layout.</li>
+<li>A relative layout for the first scene with two text fields.</li>
+<li>A relative layout for the second scene with the same two text fields in different order.</li>
+</ul>
+
+<p>The example is designed so that all of the animation occurs within the child layout of the
+main layout for the activity. The text label in the main layout remains static.</p>
+
+<p>The main layout for the activity is defined as follows:</p>
+
+<p class="code-caption">res/layout/activity_main.xml</p>
+
+<pre>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/master_layout">
+ <TextView
+ android:id="@+id/title"
+ ...
+ android:text="Title"/>
+ <FrameLayout
+ android:id="@+id/scene_root">
+ <include layout="@layout/a_scene" />
+ </FrameLayout>
+</LinearLayout>
+</pre>
+
+<p>This layout definition contains a text field and a child layout for the scene root. The
+layout for the first scene is included in the main layout file. This allows the app to display
+it as part of the initial user interface and also to load it into a scene, since the framework
+can load only a whole layout file into a scene.</p>
+
+<p>The layout for the first scene is defined as follows:</p>
+
+<p class="code-caption">res/layout/a_scene.xml</p>
+
+<pre>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/scene_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ <TextView
+ android:id="@+id/text_view1
+ android:text="Text Line 1" />
+ <TextView
+ android:id="@+id/text_view2
+ android:text="Text Line 2" />
+</RelativeLayout>
+</pre>
+
+<p>The layout for the second scene contains the same two text fields (with the same IDs)
+placed in a different order and is defined as follows:</p>
+
+<p class="code-caption">res/layout/another_scene.xml</p>
+
+<pre>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/scene_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ <TextView
+ android:id="@+id/text_view2
+ android:text="Text Line 2" />
+ <TextView
+ android:id="@+id/text_view1
+ android:text="Text Line 1" />
+</RelativeLayout>
+</pre>
+
+<h3>Generate Scenes from Layouts</h3>
+
+<p>After you create definitions for the two relative layouts, you can obtain an scene for
+each of them. This enables you to later transition between the two UI configurations.
+To obtain a scene, you need a reference to the scene root and the layout resource ID.</p>
+
+<p>The following code snippet shows you how to get a reference to the scene root and create
+two {@link android.transition.Scene} objects from the layout files:</p>
+
+<pre>
+Scene mAScene;
+Scene mAnotherScene;
+
+// Create the scene root for the scenes in this app
+mSceneRoot = (ViewGroup) findViewById(R.id.scene_root);
+
+// Create the scenes
+mAScene = Scene.getSceneForLayout(mSceneRoot, R.layout.a_scene, this);
+mAnotherScene =
+ Scene.getSceneForLayout(mSceneRoot, R.layout.another_scene, this);
+</pre>
+
+<p>In the app, there are now two {@link android.transition.Scene} objects based on view
+hierarchies. Both scenes use the scene root defined by the
+{@link android.widget.FrameLayout} element in <code>res/layout/activity_main.xml</code>.</p>
+
+
+
+<h2 id="FromCode">Create a Scene in Your Code</h2>
+
+<p>You can also create a {@link android.transition.Scene} instance in your code from a
+{@link android.view.ViewGroup} object. Use this technique when you modify the view hierarchies
+directly in your code or when you generate them dynamically.</p>
+
+<p>To create a scene from a view hierarchy in your code, use the
+{@link android.transition.Scene#Scene(android.view.ViewGroup, android.view.View) Scene(sceneRoot, viewHierarchy)}
+constructor. Calling this constructor is equivalent to calling the
+{@link android.transition.Scene#getSceneForLayout Scene.getSceneForLayout()} method when you
+have already inflated a layout file.</p>
+
+<p>The following code snippet demonstrates how to create a {@link android.transition.Scene}
+instance from the scene root element and the view hierarchy for the scene in your code:</p>
+
+<pre>
+Scene mScene;
+
+// Obtain the scene root element
+mSceneRoot = (ViewGroup) mSomeLayoutElement;
+
+// Obtain the view hierarchy to add as a child of
+// the scene root when this scene is entered
+mViewHierarchy = (ViewGroup) someOtherLayoutElement;
+
+// Create a scene
+mScene = new Scene(mSceneRoot, mViewHierarchy);
+</pre>
+
+
+
+<h2 id="Actions">Create Scene Actions</h2>
+
+<p>The framework enables you to define custom scene actions that the system runs when entering
+or exiting a scene. In many cases, defining custom scene actions is not necessary, since the
+framework animates the change between scenes automatically.</p>
+
+<p>Scene actions are useful for handling these cases:</p>
+
+<ul>
+<li>Animate views that are not in the same hierarchy. You can animate views for both the
+starting and ending scenes using exit and entry scene actions.</li>
+<li>Animate views that the transitions framework cannot animate automatically, such as
+{@link android.widget.ListView} objects. For more information, see
+<a href="{@docRoot}training/transitions/overview.html#Limitations">Limitations</a>.</li>
+</ul>
+
+<p>To provide custom scene actions, define your actions as {@link java.lang.Runnable} objects
+and pass them to the {@link android.transition.Scene#setExitAction Scene.setExitAction()} or
+{@link android.transition.Scene#setEnterAction Scene.setEnterAction()} methods. The framework
+calls the {@link android.transition.Scene#setExitAction setExitAction()} method on the starting
+scene before running the transition animation and the {@link
+android.transition.Scene#setEnterAction setEnterAction()} method on the ending scene after
+running the transition animation.</p>
+
+<p class="note"><strong>Note:</strong> Do not use scene actions to pass data between views in
+the starting and ending scenes. For more information, see
+<a href="{@docRoot}training/transitions/transitions.html#Callbacks">Defining Transition
+Lifecycle Callbacks</a>.</p>
diff --git a/docs/html/training/transitions/transitions.jd b/docs/html/training/transitions/transitions.jd
new file mode 100644
index 0000000..489e291
--- /dev/null
+++ b/docs/html/training/transitions/transitions.jd
@@ -0,0 +1,315 @@
+page.title=Applying a Transition
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#Create">Create a Transition</a></li>
+ <li><a href="#Apply">Apply a Transition</a></li>
+ <li><a href="#Targets">Choose Specific Target Views</a></li>
+ <li><a href="#Multiple">Specify Multiple Transitions</a></li>
+ <li><a href="#NoScenes">Apply a Transition Without Scenes</a></li>
+ <li><a href="#Callbacks">Define Transition Lifecycle Callbacks</a></li>
+</ol>
+</div>
+</div>
+
+<p>In the transitions framework, animations create a series of frames that depict a change
+between the view hierarchies in the starting and ending scenes. The framework represents
+these animations as transition objects, which contain information about an animation. To
+run an animation, you provide the transition to use and the ending scene to a transition
+manager.</p>
+
+<p>This lesson teaches you run an animation between two scenes using built-in transitions
+to move, resize, and fade views. The next lesson shows you how to define custom transitions.</p>
+
+
+
+<h2 id="Create">Create a Transition</h2>
+
+<p>In the previous lesson, you learned how to create scenes that represent the state of
+different view hierarchies. Once you have defined the starting scene and the ending scene you
+want to change between, you need to create a {@link android.transition.Transition} object
+that defines an animation. The framework enables you to specify a built-in transition in a
+resource file and inflate it in your code or to create an instance of a built-in transition
+directly in your code.</p>
+
+<!-- Built in transition table -->
+<p class="table-caption" id="table1"><strong>Table 1.</strong> Built-in transition types.</p>
+<table>
+<tr>
+ <th scope="col">Class</th>
+ <th scope="col">Tag</th>
+ <th scope="col">Attributes</th>
+ <th scope="col">Effect</th>
+</tr>
+<tr>
+ <td><code><a href="/reference/android/transition/AutoTransition.html">AutoTransition</a></code></td>
+ <td><autoTransition/></td>
+ <td style="text-align=center;"> - </td>
+ <td>Default transition. Fade out, move and resize, and fade in views, in that order.</td>
+</tr>
+<tr>
+ <td><code><a href="/reference/android/transition/Fade.html">Fade</a></code></td>
+ <td><fade/></td>
+ <td><code>android:fadingMode="[fade_in |<br> fade_out |<br> fade_in_out]"</code></td>
+ <td>
+ <code>fade_in</code> fades in views<br>
+ <code>fade_out</code> fades out views<br>
+ <code>fade_in_out</code> (default) does a <code>fade_out</code> followed by a <code>fade_in</code>.
+ </td>
+</tr>
+<tr>
+ <td><code><a href="/reference/android/transition/ChangeBounds.html">ChangeBounds</a></code></td>
+ <td><changeBounds/></td>
+ <td style="text-align=center;"> - </td>
+ <td>Moves and resizes views.</td>
+</tr>
+</table>
+
+
+<h3 id="FromFile">Create a transition instance from a resource file</h3>
+
+<p>This technique enables you to modify your transition definition without having to change
+the code of your activity. This technique is also useful to separate complex transition
+definitions from your application code, as shown in <a href="#Multiple">Specify Multiple
+Transitions</a>.</p>
+
+<p>To specify a built-in transition in a resource file, follow these steps:</p>
+
+<ol>
+<li>Add the <code>res/transition/</code> directory to your project.</li>
+<li>Create a new XML resource file inside this directory.</li>
+<li>Add an XML node for one of the built-in transitions.</li>
+</ol>
+
+<p>For example, the following resource file specifies the {@link android.transition.Fade}
+transition:</p>
+
+<p class="code-caption">res/transition/fade_transition.xml</p>
+
+<pre>
+<fade xmlns:android="http://schemas.android.com/apk/res/android" />
+</pre>
+
+<p>The following code snippet shows how to inflate a {@link android.transition.Transition}
+instance inside your activity from a resource file:</p>
+
+<pre>
+Transition mFadeTransition =
+ TransitionInflater.from(this).
+ inflateTransition(R.transition.fade_transition);
+</pre>
+
+
+<h3 id="FromCode">Create a transition instance in your code</h3>
+
+<p>This technique is useful for creating transition objects dynamically if you modify the user
+interface in your code, and to create simple built-in transition instances with few or
+no parameters.</p>
+
+<p>To create an instance of a built-in transition, invoke one of the public constructors in
+the subclasses of the {@link android.transition.Transition} class. For example, the following
+code snippet creates an instance of the {@link android.transition.Fade} transition:</p>
+
+<pre>
+Transition mFadeTransition = new Fade();
+</pre>
+
+
+
+<h2 id="Apply">Apply a Transition</h2>
+
+<p>You typically apply a transition to change between different view hierarchies in response
+to an event, such as a user action. For example, consider a search app: when the user enters
+a search term and clicks the search button, the app changes to the scene that represents the
+results layout while applying a transition that fades out the search button and fades in the
+search results.</p>
+
+<p>To make a scene change while applying a transition in response to some event in your
+activity, call the {@link android.transition.TransitionManager#go TransitionManager.go()}
+static method with the ending scene and the transition instance to use for the animation,
+as shown in the following snippet:</p>
+
+<pre>
+TransitionManager.go(mEndingScene, mFadeTransition);
+</pre>
+
+<p>The framework changes the view hierarchy inside the scene root with the view hierarchy
+from the ending scene while running the animation specified by the transition instance. The
+starting scene is the ending scene from the last transition. If there was no previous
+transition, the starting scene is determined automatically from the current state of the
+user interface.</p>
+
+<p>If you do not specify a transition instance, the transition manager can apply an automatic
+transition that does something reasonable for most situations. For more information, see the
+API reference for the {@link android.transition.TransitionManager} class.</p>
+
+
+
+<h2 id="Targets">Choose Specific Target Views</h2>
+
+<p>The framework applies transitions to all views in the starting and ending scenes by
+default. In some cases, you may only want to apply an animation to a subset of views in a
+scene. For example, the framework does not support animating changes to
+{@link android.widget.ListView} objects, so you should not try to animate them during a
+transition. The framework enables you to select specific views you want to animate.</p>
+
+<p>Each view that the transition animates is called a <em>target</em>. You can only
+select targets that are part of the view hierarchy associated with a scene.</p>
+
+<p>To remove one or more views from the list of targets, call the {@link
+android.transition.Transition#removeTarget removeTarget()} method before starting
+the transition. To add only the views you specify to the list of targets, call the
+{@link android.transition.Transition#addTarget addTarget()} method. For more
+information, see the API reference for the {@link android.transition.Transition} class.</p>
+
+
+
+<h2 id="Multiple">Specify Multiple Transitions</h2>
+
+<p>To get the most impact from an animation, you should match it to the type of changes
+that occur between the scenes. For example, if you are removing some views and adding others
+between scenes, a fade out/fade in animation provides a noticeable indication that some views
+are no longer available. If you are moving views to different points on the screen, a better
+choice would be to animate the movement so that users notice the new location of the views.</p>
+
+<p>You do not have to choose only one animation, since the transitions framework enables you
+to combine animation effects in a transition set that contains a group of individual built-in
+or custom transitions.</p>
+
+<p>To define a transition set from a collection of transitions in XML, create a resource file
+in the <code>res/transitions/</code> directory and list the transitions under the
+<code>transitionSet</code> element. For example, the following snippet shows how to specify a
+transition set that has the same behaviour as the {@link android.transition.AutoTransition}
+class:</p>
+
+<pre>
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+ android:transitionOrdering="sequential">
+ <fade android:fadingMode="fade_out" />
+ <changeBounds />
+ <fade android:fadingMode="fade_in" />
+</transitionSet>
+</pre>
+
+<p>To inflate the transition set into a {@link android.transition.TransitionSet} object in
+your code, call the {@link android.transition.TransitionInflater#from TransitionInflater.from()}
+method in your activity. The {@link android.transition.TransitionSet} class extends from the
+{@link android.transition.Transition} class, so you can use it with a transition manager just
+like any other {@link android.transition.Transition} instance.</p>
+
+
+
+<h2 id="NoScenes">Apply a Transition Without Scenes</h2>
+
+<p>Changing view hierarchies is not the only way to modify your user interface. You can also
+make changes by adding, modifying, and removing child views within the current hierarchy. For
+example, you can implement a search interaction with just a single layout. Start with the
+layout showing a search entry field and a search icon. To change the user interface to show
+the results, remove the search button when the user clicks it by calling the {@link
+android.view.ViewGroup#removeView ViewGroup.removeView()} method, and add the search results by
+calling {@link android.view.ViewGroup#addView ViewGroup.addView()} method.</p>
+
+<p>You may want to use this approach if the alternative is to have two hierarchies that are
+nearly identical. Rather than having to create and maintain two separate layout files for a
+minor difference in the user interface, you can have one layout file containing a view
+hierarchy that you modify in code.</p>
+
+<p>If you make changes within the current view hierarchy in this fashion, you do not need to
+create a scene. Instead, you can create and apply a transition between two states of a view
+hierarchy using a <em>delayed transition</em>. This feature of the transitions framework
+starts with the current view hierarchy state, records changes you make to its views, and applies
+a transition that animates the changes when the system redraws the user interface.</p>
+
+<p>To create a delayed transition within a single view hierarchy, follow these steps:</p>
+
+<ol>
+<li>When the event that triggers the transition occurs, call the {@link
+android.transition.TransitionManager#beginDelayedTransition
+TransitionManager.beginDelayedTransition()} method providing the parent view of all the views
+you want to change and the transition to use. The framework stores the current state of the
+child views and their property values.</li>
+<li>Make changes to the child views as required by your use case. The framework records
+the changes you make to the child views and their properties.</li>
+<li>When the system redraws the user interface according to your changes, the framework
+animates the changes between the original state and the new state.</li>
+</ol>
+
+<p>The following example shows how to animate the addition of a text view to a view hierarchy
+using a delayed transition. The first snippet shows the layout definition file:</p>
+
+<p class="code-caption">res/layout/activity_main.xml</p>
+
+<pre>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/mainLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ <EditText
+ android:id="@+id/inputText"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ ...
+</RelativeLayout>
+</pre>
+
+<p>The next snippet shows the code that animates the addition of the text view:</p>
+
+<p class="code-caption">MainActivity.java</p>
+
+<pre>
+private TextView mLabelText;
+private Fade mFade;
+private ViewGroup mRootView;
+...
+
+// Load the layout
+this.setContentView(R.layout.activity_main);
+...
+
+// Create a new TextView and set some View properties
+mLabelText = new TextView();
+mLabelText.setText("Label").setId("1");
+
+// Get the root view and create a transition
+mRootView = (ViewGroup) findViewById(R.id.mainLayout);
+mFade = new Fade(IN);
+
+// Start recording changes to the view hierarchy
+TransitionManager.beginDelayedTransition(mRootView, mFade);
+
+// Add the new TextView to the view hierarchy
+mRootView.addView(mLabelText);
+
+// When the system redraws the screen to show this update,
+// the framework will animate the addition as a fade in
+</pre>
+
+
+
+<h2 id="Callbacks">Define Transition Lifecycle Callbacks</h2>
+
+<p>The transition lifecycle is similar to the activity lifecycle. It represents the transition
+states that the framework monitors during the time between a call to the {@link
+android.transition.TransitionManager#go TransitionManager.go()} method and the completion of
+the animation. At important lifecycle states, the framework invokes callbacks defined by
+the {@link android.transition.Transition.TransitionListener TransitionListener}
+interface.</p>
+
+<p>Transition lifecycle callbacks are useful, for example, for copying a view property value
+from the starting view hierarchy to the ending view hierarchy during a scene change. You
+cannot simply copy the value from its starting view to the view in the ending view hierarchy,
+because the ending view hierarchy is not inflated until the transition is completed.
+Instead, you need to store the value in a variable and then copy it into the ending view
+hierarchy when the framework has finished the transition. To get notified when the transition
+is completed, you can implement the {@link
+android.transition.Transition.TransitionListener#onTransitionEnd
+TransitionListener.onTransitionEnd()} method in your activity.</p>
+
+<p>For more information, see the API reference for the {@link
+android.transition.Transition.TransitionListener TransitionListener} class.</p>
diff --git a/docs/html/training/wearables/data-layer/data-items.jd b/docs/html/training/wearables/data-layer/data-items.jd
index 12babbf..49a8d32 100644
--- a/docs/html/training/wearables/data-layer/data-items.jd
+++ b/docs/html/training/wearables/data-layer/data-items.jd
@@ -46,7 +46,7 @@
</ol>
<p>
-However, instead of working with raw bytes using <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])">setData()</a>,
+However, instead of working with raw bytes using <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])"><code>setData()</code></a>,
we recommend you <a href="#SyncData">use a data map</a>, which exposes
a data item in an easy-to-use {@link android.os.Bundle}-like interface.
</p>
@@ -88,39 +88,121 @@
</li>
</ol>
-<p>The following example shows how to create a data map and put data on it:</p>
+<p>The <code>increaseCounter()</code> method in the following example shows how to create a
+data map and put data in it:</p>
<pre>
-PutDataMapRequest dataMap = PutDataMapRequest.create("/count");
-dataMap.getDataMap().putInt(COUNT_KEY, count++);
-PutDataRequest request = dataMap.asPutDataRequest();
-PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi
- .putDataItem(mGoogleApiClient, request);
-</pre>
+public class MainActivity extends Activity implements
+ DataApi.DataListener,
+ GoogleApiClient.ConnectionCallbacks,
+ GoogleApiClient.OnConnectionFailedListener {
-<h2 id="ListenEvents">Listen for Data Item Events</h2>
-If one side of the data layer connection changes a data item, you probably want
-to be notified of any changes on the other side of the connection.
-You can do this by implementing a listener for data item events.
+ private static final String COUNT_KEY = "com.example.key.count";
-<p>For example, here's what a typical callback looks like to carry out certain actions
-when data changes:</p>
+ private GoogleApiClient mGoogleApiClient;
+ private int count = 0;
-<pre>
-@Override
-public void onDataChanged(DataEventBuffer dataEvents) {
- for (DataEvent event : dataEvents) {
- if (event.getType() == DataEvent.TYPE_DELETED) {
- Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
- } else if (event.getType() == DataEvent.TYPE_CHANGED) {
- Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
- }
+ ...
+
+ // Create a data map and put data in it
+ private void <strong>increaseCounter</strong>() {
+ PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
+ putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
+ PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
+ PendingResult<DataApi.DataItemResult> pendingResult =
+ Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
}
+
+ ...
}
</pre>
-<p>
-This is just a snippet that requires more implementation details. Learn about
-how to implement a full listener service or activity in
+
+<p>For more information about handling the
+<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">
+<code>PendingResult</code></a> object, see
+<a href="{@docRoot}training/wearables/data-layer/events.html#Wait">Wait for the Status of Data
+Layer Calls</a>.</p>
+
+
+<h2 id="ListenEvents">Listen for Data Item Events</h2>
+
+<p>If one side of the data layer connection changes a data item, you probably want
+to be notified of any changes on the other side of the connection.
+You can do this by implementing a listener for data item events.</p>
+
+<p>The code snippet in the following example notifies your app when the value of the
+counter defined in the previous example changes:</p>
+
+<pre>
+public class MainActivity extends Activity implements
+ DataApi.DataListener,
+ GoogleApiClient.ConnectionCallbacks,
+ GoogleApiClient.OnConnectionFailedListener {
+
+ private static final String COUNT_KEY = "com.example.key.count";
+
+ private GoogleApiClient mGoogleApiClient;
+ private int count = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .build();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onStart();
+ mGoogleApiClient.connect();
+ }
+
+ @Override
+ public void onConnected(Bundle bundle) {
+ <strong>Wearable.DataApi.addListener</strong>(mGoogleApiClient, this);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ <strong>Wearable.DataApi.removeListener</strong>(mGoogleApiClient, this);
+ mGoogleApiClient.disconnect();
+ }
+
+ @Override
+ public void <strong>onDataChanged</strong>(DataEventBuffer dataEvents) {
+ for (DataEvent event : dataEvents) {
+ if (event.getType() == DataEvent.TYPE_CHANGED) {
+ // DataItem changed
+ DataItem item = event.getDataItem();
+ if (item.getUri().getPath().compareTo("/count") == 0) {
+ DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
+ updateCount(dataMap.getInt(COUNT_KEY));
+ }
+ } else if (event.getType() == DataEvent.TYPE_DELETED) {
+ // DataItem deleted
+ }
+ }
+ }
+
+ // Our method to update the count
+ private void updateCount(int c) { ... }
+
+ ...
+}
+</pre>
+
+<p>This activity implements the
+<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html">
+<code>DataItem.DataListener</code></a> interface. This activity adds itself as a listener
+for data item events inside the <code>onConnected()</code> method and removes the listener
+in the <code>onPause()</code> method.</p>
+
+<p>You can also implement the listener as a service. For more information, see
<a href="{@docRoot}training/wearables/data-layer/events.html#Listen">Listen for Data Layer
-Events</a>.
-</p>
\ No newline at end of file
+Events</a>.</p>
diff --git a/docs/html/training/wearables/data-layer/events.jd b/docs/html/training/wearables/data-layer/events.jd
index 6a3949a..c797f68 100644
--- a/docs/html/training/wearables/data-layer/events.jd
+++ b/docs/html/training/wearables/data-layer/events.jd
@@ -267,6 +267,8 @@
public class MainActivity extends Activity implements
DataApi.DataListener, ConnectionCallbacks, OnConnectionFailedListener {
+ private GoogleApiClient mGoogleApiClient;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -314,4 +316,5 @@
}
}
}
+}
</pre>
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 8b70a08..488ee4c 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -34,7 +34,6 @@
import android.graphics.Outline;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
-import android.graphics.drawable.Drawable.ConstantState;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -60,28 +59,49 @@
public class InsetDrawable extends Drawable implements Drawable.Callback {
private final Rect mTmpRect = new Rect();
- private final InsetState mState;
+ private InsetState mState;
+ private Drawable mDrawable;
private boolean mMutated;
- /*package*/ InsetDrawable() {
- this(null, null);
+ /**
+ * No-arg constructor used by drawable inflation.
+ */
+ InsetDrawable() {
+ this(new InsetState(), null);
}
+ /**
+ * Creates a new inset drawable with the specified inset.
+ *
+ * @param drawable The drawable to inset.
+ * @param inset Inset in pixels around the drawable.
+ */
public InsetDrawable(Drawable drawable, int inset) {
this(drawable, inset, inset, inset, inset);
}
- public InsetDrawable(Drawable drawable, int insetLeft, int insetTop,
- int insetRight, int insetBottom) {
- this(null, null);
+ /**
+ * Creates a new inset drawable with the specified insets.
+ *
+ * @param drawable The drawable to inset.
+ * @param insetLeft Left inset in pixels.
+ * @param insetTop Top inset in pixels.
+ * @param insetRight Right inset in pixels.
+ * @param insetBottom Bottom inset in pixels.
+ */
+ public InsetDrawable(Drawable drawable, int insetLeft, int insetTop,int insetRight,
+ int insetBottom) {
+ this(new InsetState(), null);
- mState.mDrawable = drawable;
+ mState.mDrawableState = drawable == null ? null : drawable.getConstantState();
mState.mInsetLeft = insetLeft;
mState.mInsetTop = insetTop;
mState.mInsetRight = insetRight;
mState.mInsetBottom = insetBottom;
+ mDrawable = drawable;
+
if (drawable != null) {
drawable.setCallback(this);
}
@@ -93,10 +113,6 @@
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable);
super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible);
- // Reset mDrawable to preserve old multiple-inflate behavior. This is
- // silly, but we have CTS tests that rely on it.
- mState.mDrawable = null;
-
updateStateFromTypedArray(a);
inflateChildElements(r, parser, attrs, theme);
verifyRequiredAttributes(a);
@@ -106,25 +122,26 @@
private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
Theme theme) throws XmlPullParserException, IOException {
// Load inner XML elements.
- if (mState.mDrawable == null) {
+ if (mDrawable == null) {
int type;
while ((type=parser.next()) == XmlPullParser.TEXT) {
}
if (type != XmlPullParser.START_TAG) {
- throw new XmlPullParserException(
- parser.getPositionDescription()
- + ": <inset> tag requires a 'drawable' attribute or "
- + "child tag defining a drawable");
+ throw new XmlPullParserException(parser.getPositionDescription()
+ + ": <inset> tag requires a 'drawable' attribute or "
+ + "child tag defining a drawable");
}
+
final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
- mState.mDrawable = dr;
+ mState.mDrawableState = dr.getConstantState();
+ mDrawable = dr;
dr.setCallback(this);
}
}
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
// If we're not waiting on a theme, verify required attributes.
- if (mState.mDrawable == null && (mState.mThemeAttrs == null
+ if (mDrawable == null && (mState.mThemeAttrs == null
|| mState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) {
throw new XmlPullParserException(a.getPositionDescription()
+ ": <inset> tag requires a 'drawable' attribute or "
@@ -148,7 +165,8 @@
case R.styleable.InsetDrawable_drawable:
final Drawable dr = a.getDrawable(attr);
if (dr != null) {
- state.mDrawable = dr;
+ mState.mDrawableState = dr.getConstantState();
+ mDrawable = dr;
dr.setCallback(this);
}
break;
@@ -198,8 +216,8 @@
}
}
- if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
- state.mDrawable.applyTheme(t);
+ if (mDrawable != null && mDrawable.canApplyTheme()) {
+ mDrawable.applyTheme(t);
}
}
@@ -234,27 +252,27 @@
@Override
public void draw(Canvas canvas) {
- mState.mDrawable.draw(canvas);
+ mDrawable.draw(canvas);
}
@Override
public int getChangingConfigurations() {
return super.getChangingConfigurations()
| mState.mChangingConfigurations
- | mState.mDrawable.getChangingConfigurations();
+ | mDrawable.getChangingConfigurations();
}
@Override
public boolean getPadding(Rect padding) {
- boolean pad = mState.mDrawable.getPadding(padding);
+ final boolean pad = mDrawable.getPadding(padding);
padding.left += mState.mInsetLeft;
padding.right += mState.mInsetRight;
padding.top += mState.mInsetTop;
padding.bottom += mState.mInsetBottom;
- return pad || (mState.mInsetLeft | mState.mInsetRight |
- mState.mInsetTop | mState.mInsetBottom) != 0;
+ return pad || (mState.mInsetLeft | mState.mInsetRight
+ | mState.mInsetTop | mState.mInsetBottom) != 0;
}
/** @hide */
@@ -269,61 +287,61 @@
@Override
public void setHotspot(float x, float y) {
- mState.mDrawable.setHotspot(x, y);
+ mDrawable.setHotspot(x, y);
}
@Override
public void setHotspotBounds(int left, int top, int right, int bottom) {
- mState.mDrawable.setHotspotBounds(left, top, right, bottom);
+ mDrawable.setHotspotBounds(left, top, right, bottom);
}
/** @hide */
@Override
public void getHotspotBounds(Rect outRect) {
- mState.mDrawable.getHotspotBounds(outRect);
+ mDrawable.getHotspotBounds(outRect);
}
@Override
public boolean setVisible(boolean visible, boolean restart) {
- mState.mDrawable.setVisible(visible, restart);
+ mDrawable.setVisible(visible, restart);
return super.setVisible(visible, restart);
}
@Override
public void setAlpha(int alpha) {
- mState.mDrawable.setAlpha(alpha);
+ mDrawable.setAlpha(alpha);
}
@Override
public int getAlpha() {
- return mState.mDrawable.getAlpha();
+ return mDrawable.getAlpha();
}
@Override
public void setColorFilter(ColorFilter cf) {
- mState.mDrawable.setColorFilter(cf);
+ mDrawable.setColorFilter(cf);
}
@Override
public void setTintList(ColorStateList tint) {
- mState.mDrawable.setTintList(tint);
+ mDrawable.setTintList(tint);
}
@Override
public void setTintMode(Mode tintMode) {
- mState.mDrawable.setTintMode(tintMode);
+ mDrawable.setTintMode(tintMode);
}
/** {@hide} */
@Override
public void setLayoutDirection(int layoutDirection) {
- mState.mDrawable.setLayoutDirection(layoutDirection);
+ mDrawable.setLayoutDirection(layoutDirection);
}
@Override
public int getOpacity() {
final InsetState state = mState;
- final int opacity = state.mDrawable.getOpacity();
+ final int opacity = mDrawable.getOpacity();
if (opacity == PixelFormat.OPAQUE && (state.mInsetLeft > 0 || state.mInsetTop > 0
|| state.mInsetRight > 0 || state.mInsetBottom > 0)) {
return PixelFormat.TRANSLUCENT;
@@ -333,19 +351,19 @@
@Override
public boolean isStateful() {
- return mState.mDrawable.isStateful();
+ return mDrawable.isStateful();
}
@Override
protected boolean onStateChange(int[] state) {
- boolean changed = mState.mDrawable.setState(state);
+ final boolean changed = mDrawable.setState(state);
onBoundsChange(getBounds());
return changed;
}
@Override
protected boolean onLevelChange(int level) {
- return mState.mDrawable.setLevel(level);
+ return mDrawable.setLevel(level);
}
@Override
@@ -358,24 +376,22 @@
r.right -= mState.mInsetRight;
r.bottom -= mState.mInsetBottom;
- mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
+ mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
}
@Override
public int getIntrinsicWidth() {
- return mState.mDrawable.getIntrinsicWidth()
- + mState.mInsetLeft + mState.mInsetRight;
+ return mDrawable.getIntrinsicWidth() + mState.mInsetLeft + mState.mInsetRight;
}
@Override
public int getIntrinsicHeight() {
- return mState.mDrawable.getIntrinsicHeight()
- + mState.mInsetTop + mState.mInsetBottom;
+ return mDrawable.getIntrinsicHeight() + mState.mInsetTop + mState.mInsetBottom;
}
@Override
public void getOutline(@NonNull Outline outline) {
- mState.mDrawable.getOutline(outline);
+ mDrawable.getOutline(outline);
}
@Override
@@ -390,7 +406,8 @@
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
- mState.mDrawable.mutate();
+ mState = new InsetState(mState);
+ mDrawable.mutate();
mMutated = true;
}
return this;
@@ -401,7 +418,7 @@
*/
public void clearMutated() {
super.clearMutated();
- mState.mDrawable.clearMutated();
+ mDrawable.clearMutated();
mMutated = false;
}
@@ -409,51 +426,53 @@
* Returns the drawable wrapped by this InsetDrawable. May be null.
*/
public Drawable getDrawable() {
- return mState.mDrawable;
+ return mDrawable;
}
- final static class InsetState extends ConstantState {
+ private static final class InsetState extends ConstantState {
int[] mThemeAttrs;
int mChangingConfigurations;
- Drawable mDrawable;
+ ConstantState mDrawableState;
int mInsetLeft = 0;
int mInsetTop = 0;
int mInsetRight = 0;
int mInsetBottom = 0;
- private boolean mCheckedConstantState;
- private boolean mCanConstantState;
+ public InsetState() {
+ // Empty constructor.
+ }
- InsetState(InsetState orig, InsetDrawable owner, Resources res) {
+ public InsetState(InsetState orig) {
if (orig != null) {
mThemeAttrs = orig.mThemeAttrs;
mChangingConfigurations = orig.mChangingConfigurations;
- if (res != null) {
- mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
- } else {
- mDrawable = orig.mDrawable.getConstantState().newDrawable();
- }
- mDrawable.setCallback(owner);
- mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
- mDrawable.setBounds(orig.mDrawable.getBounds());
- mDrawable.setLevel(orig.mDrawable.getLevel());
+ mDrawableState = orig.mDrawableState;
mInsetLeft = orig.mInsetLeft;
mInsetTop = orig.mInsetTop;
mInsetRight = orig.mInsetRight;
mInsetBottom = orig.mInsetBottom;
- mCheckedConstantState = mCanConstantState = true;
}
}
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+ return mThemeAttrs != null
+ || (mDrawableState != null && mDrawableState.canApplyTheme())
|| super.canApplyTheme();
}
@Override
+ public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
+ final ConstantState state = mDrawableState;
+ if (state != null) {
+ return state.addAtlasableBitmaps(atlasList);
+ }
+ return 0;
+ }
+
+ @Override
public Drawable newDrawable() {
return new InsetDrawable(this, null);
}
@@ -468,27 +487,30 @@
return mChangingConfigurations;
}
- boolean canConstantState() {
- if (!mCheckedConstantState) {
- mCanConstantState = mDrawable.getConstantState() != null;
- mCheckedConstantState = true;
- }
-
- return mCanConstantState;
- }
-
- @Override
- public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
- final ConstantState state = mDrawable.getConstantState();
- if (state != null) {
- return state.addAtlasableBitmaps(atlasList);
- }
- return 0;
+ public boolean canConstantState() {
+ return mDrawableState != null;
}
}
+ /**
+ * The one constructor to rule them all. This is called by all public
+ * constructors to set the state and initialize local properties.
+ */
private InsetDrawable(InsetState state, Resources res) {
- mState = new InsetState(state, this, res);
+ mState = state;
+
+ updateLocalState(res);
+ }
+
+ /**
+ * Initializes local dynamic properties from state. This should be called
+ * after significant state changes, e.g. from the One True Constructor and
+ * after inflating or applying a theme.
+ */
+ private void updateLocalState(Resources res) {
+ if (mState.mDrawableState != null) {
+ mDrawable = mState.mDrawableState.newDrawable(res);
+ }
}
}
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 421c5c1..8673219 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -118,9 +118,9 @@
yDivsOffset(0), colorsOffset(0) { }
int8_t wasDeserialized;
- int8_t numXDivs;
- int8_t numYDivs;
- int8_t numColors;
+ uint8_t numXDivs;
+ uint8_t numYDivs;
+ uint8_t numColors;
// The offset (from the start of this structure) to the xDivs & yDivs
// array for this 9patch. To get a pointer to this array, call
diff --git a/libs/hwui/Android.common.mk b/libs/hwui/Android.common.mk
index b1673fe..7c1a724 100644
--- a/libs/hwui/Android.common.mk
+++ b/libs/hwui/Android.common.mk
@@ -5,12 +5,24 @@
-Wno-gnu-static-float-init
LOCAL_SRC_FILES := \
+ font/CacheTexture.cpp \
+ font/Font.cpp \
+ renderstate/MeshState.cpp \
+ renderstate/PixelBufferState.cpp \
+ renderstate/RenderState.cpp \
+ renderstate/Scissor.cpp \
+ renderstate/Stencil.cpp \
+ renderthread/CanvasContext.cpp \
+ renderthread/DrawFrameTask.cpp \
+ renderthread/EglManager.cpp \
+ renderthread/RenderProxy.cpp \
+ renderthread/RenderTask.cpp \
+ renderthread/RenderThread.cpp \
+ renderthread/TimeLord.cpp \
+ thread/TaskManager.cpp \
utils/Blur.cpp \
utils/GLUtils.cpp \
utils/SortedListImpl.cpp \
- thread/TaskManager.cpp \
- font/CacheTexture.cpp \
- font/Font.cpp \
AmbientShadow.cpp \
AnimationContext.cpp \
Animator.cpp \
@@ -48,29 +60,17 @@
RenderBufferCache.cpp \
RenderNode.cpp \
RenderProperties.cpp \
- RenderState.cpp \
ResourceCache.cpp \
ShadowTessellator.cpp \
SkiaCanvas.cpp \
SkiaShader.cpp \
Snapshot.cpp \
SpotShadow.cpp \
- Stencil.cpp \
TessellationCache.cpp \
Texture.cpp \
TextureCache.cpp \
TextDropShadowCache.cpp
-# RenderThread stuff
-LOCAL_SRC_FILES += \
- renderthread/CanvasContext.cpp \
- renderthread/DrawFrameTask.cpp \
- renderthread/EglManager.cpp \
- renderthread/RenderProxy.cpp \
- renderthread/RenderTask.cpp \
- renderthread/RenderThread.cpp \
- renderthread/TimeLord.cpp
-
intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,)
LOCAL_C_INCLUDES += \
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 107eb08..1fb8092 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -16,24 +16,23 @@
#define LOG_TAG "OpenGLRenderer"
+#include "Caches.h"
+
+#include "DisplayListRenderer.h"
+#include "GammaFontRenderer.h"
+#include "LayerRenderer.h"
+#include "Properties.h"
+#include "renderstate/RenderState.h"
+#include "ShadowTessellator.h"
+
#include <utils/Log.h>
#include <utils/String8.h>
-#include "Caches.h"
-#include "DisplayListRenderer.h"
-#include "GammaFontRenderer.h"
-#include "Properties.h"
-#include "LayerRenderer.h"
-#include "ShadowTessellator.h"
-#include "RenderState.h"
-
namespace android {
-
-using namespace uirenderer;
-ANDROID_SINGLETON_STATIC_INSTANCE(Caches);
-
namespace uirenderer {
+Caches* Caches::sInstance = nullptr;
+
///////////////////////////////////////////////////////////////////////////////
// Macros
///////////////////////////////////////////////////////////////////////////////
@@ -48,8 +47,12 @@
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-Caches::Caches(): Singleton<Caches>(),
- mExtensions(Extensions::getInstance()), mInitialized(false), mRenderState(nullptr) {
+Caches::Caches(RenderState& renderState)
+ : patchCache(renderState)
+ , mRenderState(&renderState)
+ , mExtensions(Extensions::getInstance())
+ , mInitialized(false) {
+ INIT_LOGD("Creating OpenGL renderer caches");
init();
initFont();
initConstraints();
@@ -59,7 +62,8 @@
initTempProperties();
mDebugLevel = readDebugLevel();
- ALOGD("Enabling debug mode %d", mDebugLevel);
+ ALOGD_IF(mDebugLevel != kDebugDisabled,
+ "Enabling debug mode %d", mDebugLevel);
}
bool Caches::init() {
@@ -67,29 +71,10 @@
ATRACE_NAME("Caches::init");
- glGenBuffers(1, &meshBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
- glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
-
- mCurrentBuffer = meshBuffer;
- mCurrentIndicesBuffer = 0;
- mCurrentPositionPointer = this;
- mCurrentPositionStride = 0;
- mCurrentTexCoordsPointer = this;
- mCurrentPixelBuffer = 0;
-
- mTexCoordsArrayEnabled = false;
-
- glDisable(GL_SCISSOR_TEST);
- scissorEnabled = false;
- mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
-
glActiveTexture(gTextureUnits[0]);
mTextureUnit = 0;
mRegionMesh = nullptr;
- mMeshIndices = 0;
- mShadowStripsIndices = 0;
blend = false;
lastSrcMode = GL_ZERO;
lastDstMode = GL_ZERO;
@@ -101,11 +86,12 @@
debugOverdraw = false;
debugStencilClip = kStencilHide;
- patchCache.init(*this);
+ patchCache.init();
mInitialized = true;
resetBoundTextures();
+ mPixelBufferState.reset(new PixelBufferState());
return true;
}
@@ -219,17 +205,8 @@
void Caches::terminate() {
if (!mInitialized) return;
-
- glDeleteBuffers(1, &meshBuffer);
- mCurrentBuffer = 0;
-
- glDeleteBuffers(1, &mMeshIndices);
- mMeshIndices = 0;
mRegionMesh.release();
- glDeleteBuffers(1, &mShadowStripsIndices);
- mShadowStripsIndices = 0;
-
fboCache.clear();
programCache.clear();
@@ -239,6 +216,8 @@
clearGarbage();
+ mPixelBufferState.release();
+
mInitialized = false;
}
@@ -271,7 +250,7 @@
layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount());
if (mRenderState) {
int memused = 0;
- for (std::set<const Layer*>::iterator it = mRenderState->mActiveLayers.begin();
+ for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin();
it != mRenderState->mActiveLayers.end(); it++) {
const Layer* layer = *it;
log.appendFormat(" Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n",
@@ -369,155 +348,9 @@
}
///////////////////////////////////////////////////////////////////////////////
-// VBO
+// Textures
///////////////////////////////////////////////////////////////////////////////
-bool Caches::bindMeshBuffer() {
- return bindMeshBuffer(meshBuffer);
-}
-
-bool Caches::bindMeshBuffer(const GLuint buffer) {
- if (mCurrentBuffer != buffer) {
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- mCurrentBuffer = buffer;
- return true;
- }
- return false;
-}
-
-bool Caches::unbindMeshBuffer() {
- if (mCurrentBuffer) {
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- mCurrentBuffer = 0;
- return true;
- }
- return false;
-}
-
-bool Caches::bindIndicesBufferInternal(const GLuint buffer) {
- if (mCurrentIndicesBuffer != buffer) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
- mCurrentIndicesBuffer = buffer;
- return true;
- }
- return false;
-}
-
-bool Caches::bindQuadIndicesBuffer() {
- if (!mMeshIndices) {
- std::unique_ptr<uint16_t[]> regionIndices(new uint16_t[gMaxNumberOfQuads * 6]);
- for (uint32_t i = 0; i < gMaxNumberOfQuads; i++) {
- uint16_t quad = i * 4;
- int index = i * 6;
- regionIndices[index ] = quad; // top-left
- regionIndices[index + 1] = quad + 1; // top-right
- regionIndices[index + 2] = quad + 2; // bottom-left
- regionIndices[index + 3] = quad + 2; // bottom-left
- regionIndices[index + 4] = quad + 1; // top-right
- regionIndices[index + 5] = quad + 3; // bottom-right
- }
-
- glGenBuffers(1, &mMeshIndices);
- bool force = bindIndicesBufferInternal(mMeshIndices);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, gMaxNumberOfQuads * 6 * sizeof(uint16_t),
- regionIndices.get(), GL_STATIC_DRAW);
- return force;
- }
-
- return bindIndicesBufferInternal(mMeshIndices);
-}
-
-bool Caches::bindShadowIndicesBuffer() {
- if (!mShadowStripsIndices) {
- std::unique_ptr<uint16_t[]> shadowIndices(new uint16_t[MAX_SHADOW_INDEX_COUNT]);
- ShadowTessellator::generateShadowIndices(shadowIndices.get());
- glGenBuffers(1, &mShadowStripsIndices);
- bool force = bindIndicesBufferInternal(mShadowStripsIndices);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_SHADOW_INDEX_COUNT * sizeof(uint16_t),
- shadowIndices.get(), GL_STATIC_DRAW);
- return force;
- }
-
- return bindIndicesBufferInternal(mShadowStripsIndices);
-}
-
-bool Caches::unbindIndicesBuffer() {
- if (mCurrentIndicesBuffer) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- mCurrentIndicesBuffer = 0;
- return true;
- }
- return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// PBO
-///////////////////////////////////////////////////////////////////////////////
-
-bool Caches::bindPixelBuffer(const GLuint buffer) {
- if (mCurrentPixelBuffer != buffer) {
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
- mCurrentPixelBuffer = buffer;
- return true;
- }
- return false;
-}
-
-bool Caches::unbindPixelBuffer() {
- if (mCurrentPixelBuffer) {
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- mCurrentPixelBuffer = 0;
- return true;
- }
- return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Meshes and textures
-///////////////////////////////////////////////////////////////////////////////
-
-void Caches::bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
- if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
- GLuint slot = currentProgram->position;
- glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
- mCurrentPositionPointer = vertices;
- mCurrentPositionStride = stride;
- }
-}
-
-void Caches::bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
- if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
- GLuint slot = currentProgram->texCoords;
- glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
- mCurrentTexCoordsPointer = vertices;
- mCurrentTexCoordsStride = stride;
- }
-}
-
-void Caches::resetVertexPointers() {
- mCurrentPositionPointer = this;
- mCurrentTexCoordsPointer = this;
-}
-
-void Caches::resetTexCoordsVertexPointer() {
- mCurrentTexCoordsPointer = this;
-}
-
-void Caches::enableTexCoordsVertexArray() {
- if (!mTexCoordsArrayEnabled) {
- glEnableVertexAttribArray(Program::kBindingTexCoords);
- mCurrentTexCoordsPointer = this;
- mTexCoordsArrayEnabled = true;
- }
-}
-
-void Caches::disableTexCoordsVertexArray() {
- if (mTexCoordsArrayEnabled) {
- glDisableVertexAttribArray(Program::kBindingTexCoords);
- mTexCoordsArrayEnabled = false;
- }
-}
-
void Caches::activeTexture(GLuint textureUnit) {
if (mTextureUnit != textureUnit) {
glActiveTexture(gTextureUnits[textureUnit]);
@@ -579,71 +412,6 @@
}
///////////////////////////////////////////////////////////////////////////////
-// Scissor
-///////////////////////////////////////////////////////////////////////////////
-
-bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
- if (scissorEnabled && (x != mScissorX || y != mScissorY ||
- width != mScissorWidth || height != mScissorHeight)) {
-
- if (x < 0) {
- width += x;
- x = 0;
- }
- if (y < 0) {
- height += y;
- y = 0;
- }
- if (width < 0) {
- width = 0;
- }
- if (height < 0) {
- height = 0;
- }
- glScissor(x, y, width, height);
-
- mScissorX = x;
- mScissorY = y;
- mScissorWidth = width;
- mScissorHeight = height;
-
- return true;
- }
- return false;
-}
-
-bool Caches::enableScissor() {
- if (!scissorEnabled) {
- glEnable(GL_SCISSOR_TEST);
- scissorEnabled = true;
- resetScissor();
- return true;
- }
- return false;
-}
-
-bool Caches::disableScissor() {
- if (scissorEnabled) {
- glDisable(GL_SCISSOR_TEST);
- scissorEnabled = false;
- return true;
- }
- return false;
-}
-
-void Caches::setScissorEnabled(bool enabled) {
- if (scissorEnabled != enabled) {
- if (enabled) glEnable(GL_SCISSOR_TEST);
- else glDisable(GL_SCISSOR_TEST);
- scissorEnabled = enabled;
- }
-}
-
-void Caches::resetScissor() {
- mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
// Tiling
///////////////////////////////////////////////////////////////////////////////
@@ -682,7 +450,7 @@
TextureVertex* Caches::getRegionMesh() {
// Create the mesh, 2 triangles and 4 vertices per rectangle in the region
if (!mRegionMesh) {
- mRegionMesh.reset(new TextureVertex[gMaxNumberOfQuads * 4]);
+ mRegionMesh.reset(new TextureVertex[kMaxNumberOfQuads * 4]);
}
return mRegionMesh.get();
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index b0eebd7..8d23833 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -21,7 +21,27 @@
#define LOG_TAG "OpenGLRenderer"
#endif
+
+#include "AssetAtlas.h"
+#include "Dither.h"
+#include "Extensions.h"
+#include "FboCache.h"
+#include "GradientCache.h"
+#include "LayerCache.h"
+#include "PatchCache.h"
+#include "ProgramCache.h"
+#include "PathCache.h"
+#include "RenderBufferCache.h"
+#include "renderstate/PixelBufferState.h"
+#include "ResourceCache.h"
+#include "TessellationCache.h"
+#include "TextDropShadowCache.h"
+#include "TextureCache.h"
+#include "thread/TaskProcessor.h"
+#include "thread/TaskManager.h"
+
#include <vector>
+#include <memory>
#include <GLES3/gl3.h>
@@ -33,25 +53,6 @@
#include <SkPath.h>
-#include "thread/TaskProcessor.h"
-#include "thread/TaskManager.h"
-
-#include "AssetAtlas.h"
-#include "Extensions.h"
-#include "TextureCache.h"
-#include "LayerCache.h"
-#include "RenderBufferCache.h"
-#include "GradientCache.h"
-#include "PatchCache.h"
-#include "ProgramCache.h"
-#include "PathCache.h"
-#include "TessellationCache.h"
-#include "TextDropShadowCache.h"
-#include "FboCache.h"
-#include "ResourceCache.h"
-#include "Stencil.h"
-#include "Dither.h"
-
namespace android {
namespace uirenderer {
@@ -64,29 +65,6 @@
// GL ES 2.0 defines that at least 16 texture units must be supported
#define REQUIRED_TEXTURE_UNITS_COUNT 3
-// Maximum number of quads that pre-allocated meshes can draw
-static const uint32_t gMaxNumberOfQuads = 2048;
-
-// Generates simple and textured vertices
-#define FV(x, y, u, v) { x, y, u, v }
-
-// This array is never used directly but used as a memcpy source in the
-// OpenGLRenderer constructor
-static const TextureVertex gMeshVertices[] = {
- FV(0.0f, 0.0f, 0.0f, 0.0f),
- FV(1.0f, 0.0f, 1.0f, 0.0f),
- FV(0.0f, 1.0f, 0.0f, 1.0f),
- FV(1.0f, 1.0f, 1.0f, 1.0f)
-};
-static const GLsizei gMeshStride = sizeof(TextureVertex);
-static const GLsizei gVertexStride = sizeof(Vertex);
-static const GLsizei gAlphaVertexStride = sizeof(AlphaVertex);
-static const GLsizei gMeshTextureOffset = 2 * sizeof(float);
-static const GLsizei gVertexAlphaOffset = 2 * sizeof(float);
-static const GLsizei gVertexAAWidthOffset = 2 * sizeof(float);
-static const GLsizei gVertexAALengthOffset = 3 * sizeof(float);
-static const GLsizei gMeshCount = 4;
-
// Must define as many texture units as specified by REQUIRED_TEXTURE_UNITS_COUNT
static const GLenum gTextureUnits[] = {
GL_TEXTURE0,
@@ -95,28 +73,31 @@
};
///////////////////////////////////////////////////////////////////////////////
-// Debug
-///////////////////////////////////////////////////////////////////////////////
-
-struct CacheLogger {
- CacheLogger() {
- INIT_LOGD("Creating OpenGL renderer caches");
- }
-}; // struct CacheLogger
-
-///////////////////////////////////////////////////////////////////////////////
// Caches
///////////////////////////////////////////////////////////////////////////////
class RenderNode;
class RenderState;
-class ANDROID_API Caches: public Singleton<Caches> {
- Caches();
+class ANDROID_API Caches {
+public:
+ static Caches& createInstance(RenderState& renderState) {
+ LOG_ALWAYS_FATAL_IF(sInstance, "double create of Caches attempted");
+ sInstance = new Caches(renderState);
+ return *sInstance;
+ }
- friend class Singleton<Caches>;
+ static Caches& getInstance() {
+ LOG_ALWAYS_FATAL_IF(!sInstance, "instance not yet created");
+ return *sInstance;
+ }
- CacheLogger mLogger;
+ static bool hasInstance() {
+ return sInstance != 0;
+ }
+private:
+ Caches(RenderState& renderState);
+ static Caches* sInstance;
public:
enum FlushMode {
@@ -135,8 +116,6 @@
*/
bool initProperties();
- void setRenderState(RenderState* renderState) { mRenderState = renderState; }
-
/**
* Flush the cache.
*
@@ -175,59 +154,6 @@
*/
void deleteLayerDeferred(Layer* layer);
- /**
- * Binds the VBO used to render simple textured quads.
- */
- bool bindMeshBuffer();
-
- /**
- * Binds the specified VBO if needed.
- */
- bool bindMeshBuffer(const GLuint buffer);
-
- /**
- * Unbinds the VBO used to render simple textured quads.
- */
- bool unbindMeshBuffer();
-
- /**
- * Binds a global indices buffer that can draw up to
- * gMaxNumberOfQuads quads.
- */
- bool bindQuadIndicesBuffer();
- bool bindShadowIndicesBuffer();
- bool unbindIndicesBuffer();
-
- /**
- * Binds the specified buffer as the current GL unpack pixel buffer.
- */
- bool bindPixelBuffer(const GLuint buffer);
-
- /**
- * Resets the current unpack pixel buffer to 0 (default value.)
- */
- bool unbindPixelBuffer();
-
- /**
- * Binds an attrib to the specified float vertex pointer.
- * Assumes a stride of gMeshStride and a size of 2.
- */
- void bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride = gMeshStride);
-
- /**
- * Binds an attrib to the specified float vertex pointer.
- * Assumes a stride of gMeshStride and a size of 2.
- */
- void bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride = gMeshStride);
-
- /**
- * Resets the vertex pointers.
- */
- void resetVertexPointers();
- void resetTexCoordsVertexPointer();
-
- void enableTexCoordsVertexArray();
- void disableTexCoordsVertexArray();
/**
* Activate the specified texture unit. The texture unit must
@@ -272,20 +198,6 @@
*/
void unbindTexture(GLuint texture);
- /**
- * Sets the scissor for the current surface.
- */
- bool setScissor(GLint x, GLint y, GLint width, GLint height);
-
- /**
- * Resets the scissor state.
- */
- void resetScissor();
-
- bool enableScissor();
- bool disableScissor();
- void setScissorEnabled(bool enabled);
-
void startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool discard);
void endTiling();
@@ -310,14 +222,10 @@
GLenum lastSrcMode;
GLenum lastDstMode;
Program* currentProgram;
- bool scissorEnabled;
bool drawDeferDisabled;
bool drawReorderDisabled;
- // VBO to draw with
- GLuint meshBuffer;
-
// Misc
GLint maxTextureSize;
@@ -348,7 +256,6 @@
TaskManager tasks;
Dither dither;
- Stencil stencil;
bool gpuPixelBuffersEnabled;
@@ -371,6 +278,8 @@
int propertyAmbientShadowStrength;
int propertySpotShadowStrength;
+ PixelBufferState& pixelBuffer() { return *mPixelBufferState; }
+
private:
enum OverdrawColorSet {
kColorSet_Default = 0,
@@ -382,8 +291,6 @@
void initConstraints();
void initStaticProperties();
- bool bindIndicesBufferInternal(const GLuint buffer);
-
static void eventMarkNull(GLsizei length, const GLchar* marker) { }
static void startMarkNull(GLsizei length, const GLchar* marker) { }
static void endMarkNull() { }
@@ -396,32 +303,17 @@
if (label) *label = '\0';
}
- GLuint mCurrentBuffer;
- GLuint mCurrentIndicesBuffer;
- GLuint mCurrentPixelBuffer;
- const void* mCurrentPositionPointer;
- GLsizei mCurrentPositionStride;
- const void* mCurrentTexCoordsPointer;
- GLsizei mCurrentTexCoordsStride;
+ RenderState* mRenderState;
- bool mTexCoordsArrayEnabled;
+ std::unique_ptr<PixelBufferState> mPixelBufferState; // TODO: move to RenderState
GLuint mTextureUnit;
- GLint mScissorX;
- GLint mScissorY;
- GLint mScissorWidth;
- GLint mScissorHeight;
-
Extensions& mExtensions;
// Used to render layers
std::unique_ptr<TextureVertex[]> mRegionMesh;
- // Global index buffer
- GLuint mMeshIndices;
- GLuint mShadowStripsIndices;
-
mutable Mutex mGarbageLock;
Vector<Layer*> mLayerGarbage;
@@ -434,8 +326,6 @@
GLuint mBoundTextures[REQUIRED_TEXTURE_UNITS_COUNT];
OverdrawColorSet mOverdrawDebugColorSet;
-
- RenderState* mRenderState;
}; // class Caches
}; // namespace uirenderer
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 36c14c4..d128ffe 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -17,13 +17,6 @@
#ifndef ANDROID_HWUI_DISPLAY_OPERATION_H
#define ANDROID_HWUI_DISPLAY_OPERATION_H
-#include <SkColor.h>
-#include <SkPath.h>
-#include <SkPathOps.h>
-#include <SkXfermode.h>
-
-#include <private/hwui/DrawGlInfo.h>
-
#include "OpenGLRenderer.h"
#include "AssetAtlas.h"
#include "DeferredDisplayList.h"
@@ -31,11 +24,18 @@
#include "GammaFontRenderer.h"
#include "Patch.h"
#include "RenderNode.h"
-#include "RenderState.h"
+#include "renderstate/RenderState.h"
#include "UvMapper.h"
#include "utils/LinearAllocator.h"
#include "utils/PaintUtils.h"
+#include <SkColor.h>
+#include <SkPath.h>
+#include <SkPathOps.h>
+#include <SkXfermode.h>
+
+#include <private/hwui/DrawGlInfo.h>
+
// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
#define OP_LOGS(s) OP_LOG("%s", (s))
#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index a0bc7b0..193474f 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -14,7 +14,17 @@
* limitations under the License.
*/
-#define LOG_TAG "OpenGLRenderer"
+#include "FontRenderer.h"
+
+#include "Caches.h"
+#include "Debug.h"
+#include "Extensions.h"
+#include "OpenGLRenderer.h"
+#include "PixelBuffer.h"
+#include "Rect.h"
+#include "renderstate/RenderState.h"
+#include "utils/Blur.h"
+#include "utils/Timing.h"
#include <SkGlyph.h>
#include <SkUtils.h>
@@ -27,17 +37,6 @@
#include <RenderScript.h>
#endif
-#include "utils/Blur.h"
-#include "utils/Timing.h"
-
-#include "Caches.h"
-#include "Debug.h"
-#include "Extensions.h"
-#include "FontRenderer.h"
-#include "OpenGLRenderer.h"
-#include "PixelBuffer.h"
-#include "Rect.h"
-
namespace android {
namespace uirenderer {
@@ -47,9 +46,7 @@
///////////////////////////////////////////////////////////////////////////////
// TextSetupFunctor
///////////////////////////////////////////////////////////////////////////////
-status_t TextSetupFunctor::operator ()(int what, void* data) {
- Data* typedData = reinterpret_cast<Data*>(data);
- GLenum glyphFormat = typedData ? typedData->glyphFormat : GL_ALPHA;
+status_t TextSetupFunctor::setup(GLenum glyphFormat) {
renderer->setupDraw();
renderer->setupDrawTextGamma(paint);
@@ -397,7 +394,7 @@
CacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format,
bool allocate) {
- CacheTexture* cacheTexture = new CacheTexture(width, height, format, gMaxNumberOfQuads);
+ CacheTexture* cacheTexture = new CacheTexture(width, height, format, kMaxNumberOfQuads);
if (allocate) {
Caches::getInstance().activeTexture(0);
@@ -473,7 +470,7 @@
checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId);
// Unbind any PBO we might have used to update textures
- caches.unbindPixelBuffer();
+ caches.pixelBuffer().unbind();
// Reset to default unpack row length to avoid affecting texture
// uploads in other parts of the renderer
@@ -485,26 +482,29 @@
}
void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) {
- Caches& caches = Caches::getInstance();
+ if (!mFunctor) return;
+
+ Caches& caches = mFunctor->renderer->getCaches();
+ RenderState& renderState = mFunctor->renderer->renderState();
+
bool first = true;
- bool force = false;
+ bool forceRebind = false;
for (uint32_t i = 0; i < cacheTextures.size(); i++) {
CacheTexture* texture = cacheTextures[i];
if (texture->canDraw()) {
if (first) {
if (mFunctor) {
- TextSetupFunctor::Data functorData(texture->getFormat());
- (*mFunctor)(0, &functorData);
+ mFunctor->setup(texture->getFormat());
}
checkTextureUpdate();
- caches.bindQuadIndicesBuffer();
+ renderState.meshState().bindQuadIndicesBuffer();
if (!mDrawn) {
// If returns true, a VBO was bound and we must
// rebind our vertex attrib pointers even if
// they have the same values as the current pointers
- force = caches.unbindMeshBuffer();
+ forceRebind = renderState.meshState().unbindMeshBuffer();
}
caches.activeTexture(0);
@@ -515,14 +515,16 @@
texture->setLinearFiltering(mLinearFiltering, false);
TextureVertex* mesh = texture->mesh();
- caches.bindPositionVertexPointer(force, &mesh[0].x);
- caches.bindTexCoordsVertexPointer(force, &mesh[0].u);
- force = false;
+ MeshState& meshState = renderState.meshState();
+ Program* program = caches.currentProgram;
+ meshState.bindPositionVertexPointer(program, forceRebind, &mesh[0].x);
+ meshState.bindTexCoordsVertexPointer(program, forceRebind, &mesh[0].u);
glDrawElements(GL_TRIANGLES, texture->meshElementCount(),
GL_UNSIGNED_SHORT, texture->indices());
texture->resetMesh();
+ forceRebind = false;
}
}
}
@@ -647,7 +649,7 @@
Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, nullptr, positions);
// Unbind any PBO we might have used
- Caches::getInstance().unbindPixelBuffer();
+ Caches::getInstance().pixelBuffer().unbind();
blurImage(&dataBuffer, paddedWidth, paddedHeight, radius);
}
@@ -661,7 +663,7 @@
return image;
}
-void FontRenderer::initRender(const Rect* clip, Rect* bounds, Functor* functor) {
+void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor) {
checkInit();
mDrawn = false;
@@ -689,7 +691,7 @@
bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const char *text,
uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y,
- const float* positions, Rect* bounds, Functor* functor, bool forceFinish) {
+ const float* positions, Rect* bounds, TextSetupFunctor* functor, bool forceFinish) {
if (!mCurrentFont) {
ALOGE("No font set");
return false;
@@ -707,7 +709,7 @@
bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text,
uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path,
- float hOffset, float vOffset, Rect* bounds, Functor* functor) {
+ float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor) {
if (!mCurrentFont) {
ALOGE("No font set");
return false;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 668ee64..cb63684 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -17,7 +17,12 @@
#ifndef ANDROID_HWUI_FONT_RENDERER_H
#define ANDROID_HWUI_FONT_RENDERER_H
-#include <utils/Functor.h>
+#include "font/FontUtil.h"
+#include "font/CacheTexture.h"
+#include "font/CachedGlyphInfo.h"
+#include "font/Font.h"
+#include "utils/SortedList.h"
+
#include <utils/LruCache.h>
#include <utils/Vector.h>
#include <utils/StrongPointer.h>
@@ -26,12 +31,6 @@
#include <GLES2/gl2.h>
-#include "font/FontUtil.h"
-#include "font/CacheTexture.h"
-#include "font/CachedGlyphInfo.h"
-#include "font/Font.h"
-#include "utils/SortedList.h"
-
#ifdef ANDROID_ENABLE_RENDERSCRIPT
#include "RenderScript.h"
namespace RSC {
@@ -47,26 +46,20 @@
class OpenGLRenderer;
-///////////////////////////////////////////////////////////////////////////////
-// TextSetupFunctor
-///////////////////////////////////////////////////////////////////////////////
-class TextSetupFunctor: public Functor {
+class TextSetupFunctor {
public:
- struct Data {
- Data(GLenum glyphFormat) : glyphFormat(glyphFormat) {
- }
-
- GLenum glyphFormat;
- };
-
TextSetupFunctor(OpenGLRenderer* renderer, float x, float y, bool pureTranslate,
- int alpha, SkXfermode::Mode mode, const SkPaint* paint): Functor(),
- renderer(renderer), x(x), y(y), pureTranslate(pureTranslate),
- alpha(alpha), mode(mode), paint(paint) {
+ int alpha, SkXfermode::Mode mode, const SkPaint* paint)
+ : renderer(renderer)
+ , x(x)
+ , y(y)
+ , pureTranslate(pureTranslate)
+ , alpha(alpha)
+ , mode(mode)
+ , paint(paint) {
}
- ~TextSetupFunctor() { }
- status_t operator ()(int what, void* data) override;
+ status_t setup(GLenum glyphFormat);
OpenGLRenderer* renderer;
float x;
@@ -77,10 +70,6 @@
const SkPaint* paint;
};
-///////////////////////////////////////////////////////////////////////////////
-// FontRenderer
-///////////////////////////////////////////////////////////////////////////////
-
class FontRenderer {
public:
FontRenderer();
@@ -101,22 +90,14 @@
// bounds is an out parameter
bool renderPosText(const SkPaint* paint, const Rect* clip, const char *text,
uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions,
- Rect* bounds, Functor* functor, bool forceFinish = true);
+ Rect* bounds, TextSetupFunctor* functor, bool forceFinish = true);
// bounds is an out parameter
bool renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text,
uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path,
- float hOffset, float vOffset, Rect* bounds, Functor* functor);
+ float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor);
struct DropShadow {
- DropShadow() { };
-
- DropShadow(const DropShadow& dropShadow):
- width(dropShadow.width), height(dropShadow.height),
- image(dropShadow.image), penX(dropShadow.penX),
- penY(dropShadow.penY) {
- }
-
uint32_t width;
uint32_t height;
uint8_t* image;
@@ -152,7 +133,7 @@
void flushAllAndInvalidate();
void checkInit();
- void initRender(const Rect* clip, Rect* bounds, Functor* functor);
+ void initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor);
void finishRender();
void issueDrawCommand(Vector<CacheTexture*>& cacheTextures);
@@ -193,7 +174,7 @@
bool mUploadTexture;
- Functor* mFunctor;
+ TextSetupFunctor* mFunctor;
const Rect* mClip;
Rect* mBounds;
bool mDrawn;
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 9176c76..1714e6d 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_HWUI_GRADIENT_CACHE_H
#define ANDROID_HWUI_GRADIENT_CACHE_H
+#include <memory>
+
#include <GLES3/gl3.h>
#include <SkShader.h>
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 7388e3c..7a4b830 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -16,17 +16,18 @@
#define LOG_TAG "OpenGLRenderer"
-#include <utils/Log.h>
+#include "Layer.h"
#include "Caches.h"
#include "DeferredDisplayList.h"
-#include "Layer.h"
#include "LayerRenderer.h"
#include "OpenGLRenderer.h"
#include "RenderNode.h"
-#include "RenderState.h"
+#include "renderstate/RenderState.h"
#include "utils/TraceUtils.h"
+#include <utils/Log.h>
+
#define ATRACE_LAYER_WORK(label) \
ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \
label, \
@@ -67,15 +68,23 @@
}
Layer::~Layer() {
- renderState.requireGLContext();
renderState.unregisterLayer(this);
SkSafeUnref(colorFilter);
- removeFbo();
- deleteTexture();
+
+ if (stencil || fbo || texture.id) {
+ renderState.requireGLContext();
+ removeFbo();
+ deleteTexture();
+ }
delete[] mesh;
}
+void Layer::onGlContextLost() {
+ removeFbo();
+ deleteTexture();
+}
+
uint32_t Layer::computeIdealWidth(uint32_t layerWidth) {
return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE);
}
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 3b4f293..84ff021 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -288,6 +288,12 @@
void postDecStrong();
/**
+ * Lost the GL context but the layer is still around, mark it invalid internally
+ * so the dtor knows not to do any GL work
+ */
+ void onGlContextLost();
+
+ /**
* Bounds of the layer.
*/
Rect layer;
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 6ad1b197..076251f 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -17,18 +17,19 @@
#define LOG_TAG "OpenGLRenderer"
#define ATRACE_TAG ATRACE_TAG_VIEW
-#include <ui/Rect.h>
-
-#include <private/hwui/DrawGlInfo.h>
-
-#include "RenderState.h"
#include "LayerCache.h"
#include "LayerRenderer.h"
#include "Matrix.h"
#include "Properties.h"
#include "Rect.h"
+#include "renderstate/RenderState.h"
#include "utils/TraceUtils.h"
+#include <ui/Rect.h>
+
+#include <private/hwui/DrawGlInfo.h>
+
+
namespace android {
namespace uirenderer {
@@ -48,7 +49,7 @@
bool opaque) {
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
- renderState().bindFramebuffer(mLayer->getFbo());
+ mRenderState.bindFramebuffer(mLayer->getFbo());
const float width = mLayer->layer.getWidth();
const float height = mLayer->layer.getHeight();
@@ -70,10 +71,10 @@
void LayerRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
if (mLayer->isDirty()) {
- getCaches().disableScissor();
+ mRenderState.scissor().setEnabled(false);
glClear(GL_COLOR_BUFFER_BIT);
- getCaches().resetScissor();
+ mRenderState.scissor().reset();
mLayer->setDirty(false);
} else {
OpenGLRenderer::clear(left, top, right, bottom, opaque);
@@ -436,7 +437,7 @@
renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
bitmap->width(), bitmap->height(), !layer->isBlend());
- caches.disableScissor();
+ renderState.scissor().setEnabled(false);
renderer.translate(0.0f, bitmap->height());
renderer.scale(1.0f, -1.0f);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 82f6ddd..42b246c 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -16,6 +16,25 @@
#define LOG_TAG "OpenGLRenderer"
+#include "OpenGLRenderer.h"
+
+#include "DeferredDisplayList.h"
+#include "DisplayListRenderer.h"
+#include "Fence.h"
+#include "GammaFontRenderer.h"
+#include "Patch.h"
+#include "PathTessellator.h"
+#include "Properties.h"
+#include "RenderNode.h"
+#include "renderstate/RenderState.h"
+#include "ShadowTessellator.h"
+#include "SkiaShader.h"
+#include "Vector.h"
+#include "VertexBuffer.h"
+#include "utils/GLUtils.h"
+#include "utils/PaintUtils.h"
+#include "utils/TraceUtils.h"
+
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
@@ -32,24 +51,6 @@
#include <ui/Rect.h>
-#include "OpenGLRenderer.h"
-#include "DeferredDisplayList.h"
-#include "DisplayListRenderer.h"
-#include "Fence.h"
-#include "GammaFontRenderer.h"
-#include "Patch.h"
-#include "PathTessellator.h"
-#include "Properties.h"
-#include "RenderNode.h"
-#include "RenderState.h"
-#include "ShadowTessellator.h"
-#include "SkiaShader.h"
-#include "Vector.h"
-#include "VertexBuffer.h"
-#include "utils/GLUtils.h"
-#include "utils/PaintUtils.h"
-#include "utils/TraceUtils.h"
-
#if DEBUG_DETAILED_EVENTS
#define EVENT_LOGD(...) eventMarkDEBUG(__VA_ARGS__)
#else
@@ -135,10 +136,10 @@
OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
: mState(*this)
- , mFrameStarted(false)
, mCaches(Caches::getInstance())
, mExtensions(Extensions::getInstance())
, mRenderState(renderState)
+ , mFrameStarted(false)
, mScissorOptimizationDisabled(false)
, mSuppressTiling(false)
, mFirstFrameAfterResize(true)
@@ -151,7 +152,7 @@
memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
mDrawModifiers.mOverrideLayerAlpha = 1.0f;
- memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
+ memcpy(mMeshVertices, kMeshVertices, sizeof(kMeshVertices));
}
OpenGLRenderer::~OpenGLRenderer() {
@@ -256,14 +257,14 @@
void OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
if (!opaque) {
- mCaches.enableScissor();
- mCaches.setScissor(left, getViewportHeight() - bottom, right - left, bottom - top);
+ mRenderState.scissor().setEnabled(true);
+ mRenderState.scissor().set(left, getViewportHeight() - bottom, right - left, bottom - top);
glClear(GL_COLOR_BUFFER_BIT);
mDirty = true;
return;
}
- mCaches.resetScissor();
+ mRenderState.scissor().reset();
}
void OpenGLRenderer::syncState() {
@@ -347,7 +348,7 @@
mRenderState.bindFramebuffer(currentSnapshot()->fbo);
debugOverdraw(true, false);
- mCaches.resetScissor();
+ mRenderState.scissor().reset();
dirtyClip();
}
@@ -378,7 +379,7 @@
if (mState.getDirtyClip()) {
setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
}
- if (mCaches.enableScissor() || prevDirtyClip) {
+ if (mRenderState.scissor().setEnabled(true) || prevDirtyClip) {
setScissorFromClip();
}
@@ -428,27 +429,29 @@
if (mCaches.debugOverdraw && onGetTargetFbo() == 0) {
const Rect* clip = &mTilingClip;
- mCaches.enableScissor();
- mCaches.setScissor(clip->left, mState.firstSnapshot()->getViewportHeight() - clip->bottom,
- clip->right - clip->left, clip->bottom - clip->top);
+ mRenderState.scissor().setEnabled(true);
+ mRenderState.scissor().set(clip->left,
+ mState.firstSnapshot()->getViewportHeight() - clip->bottom,
+ clip->right - clip->left,
+ clip->bottom - clip->top);
// 1x overdraw
- mCaches.stencil.enableDebugTest(2);
+ mRenderState.stencil().enableDebugTest(2);
drawColor(mCaches.getOverdrawColor(1), SkXfermode::kSrcOver_Mode);
// 2x overdraw
- mCaches.stencil.enableDebugTest(3);
+ mRenderState.stencil().enableDebugTest(3);
drawColor(mCaches.getOverdrawColor(2), SkXfermode::kSrcOver_Mode);
// 3x overdraw
- mCaches.stencil.enableDebugTest(4);
+ mRenderState.stencil().enableDebugTest(4);
drawColor(mCaches.getOverdrawColor(3), SkXfermode::kSrcOver_Mode);
// 4x overdraw and higher
- mCaches.stencil.enableDebugTest(4, true);
+ mRenderState.stencil().enableDebugTest(4, true);
drawColor(mCaches.getOverdrawColor(4), SkXfermode::kSrcOver_Mode);
- mCaches.stencil.disable();
+ mRenderState.stencil().disable();
}
}
@@ -835,8 +838,8 @@
startTilingCurrentClip(true, true);
// Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
- mCaches.enableScissor();
- mCaches.setScissor(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
+ mRenderState.scissor().setEnabled(true);
+ mRenderState.scissor().set(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
glClear(GL_COLOR_BUFFER_BIT);
@@ -863,7 +866,7 @@
bool clipRequired = false;
mState.calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom,
&clipRequired, nullptr, false); // safely ignore return, should never be rejected
- mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired);
+ mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
if (fboLayer) {
endTiling();
@@ -891,7 +894,7 @@
layer->setAlpha(255);
}
- mCaches.unbindMeshBuffer();
+ mRenderState.meshState().unbindMeshBuffer();
mCaches.activeTexture(0);
@@ -960,7 +963,7 @@
setupDrawTextureTransformUniforms(layer->getTexTransform());
setupDrawMesh(&mMeshVertices[0].x, &mMeshVertices[0].u);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
}
void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
@@ -1002,7 +1005,7 @@
drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
layer->getTexture(), &layerPaint, blend,
&mMeshVertices[0].x, &mMeshVertices[0].u,
- GL_TRIANGLE_STRIP, gMeshCount, swap, swap || simpleTransform);
+ GL_TRIANGLE_STRIP, kMeshCount, swap, swap || simpleTransform);
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
}
@@ -1168,7 +1171,7 @@
numQuads++;
- if (numQuads >= gMaxNumberOfQuads) {
+ if (numQuads >= kMaxNumberOfQuads) {
DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
GL_UNSIGNED_SHORT, nullptr));
numQuads = 0;
@@ -1261,7 +1264,7 @@
void OpenGLRenderer::issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount) {
GLsizei elementsCount = quadsCount * 6;
while (elementsCount > 0) {
- GLsizei drawCount = min(elementsCount, (GLsizei) gMaxNumberOfQuads * 6);
+ GLsizei drawCount = min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
setupDrawIndexedVertices(&mesh[0].x);
glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr);
@@ -1286,7 +1289,7 @@
// The list contains bounds that have already been clipped
// against their initial clip rect, and the current clip
// is likely different so we need to disable clipping here
- bool scissorChanged = mCaches.disableScissor();
+ bool scissorChanged = mRenderState.scissor().setEnabled(false);
Vertex mesh[count * 4];
Vertex* vertex = mesh;
@@ -1317,7 +1320,7 @@
issueIndexedQuadDraw(&mesh[0], count);
- if (scissorChanged) mCaches.enableScissor();
+ if (scissorChanged) mRenderState.scissor().setEnabled(true);
} else {
mLayers.clear();
}
@@ -1406,7 +1409,8 @@
writableSnapshot()->setClip(0, 0, mState.getWidth(), mState.getHeight());
}
dirtyClip();
- mCaches.setScissorEnabled(clipRect != nullptr || mScissorOptimizationDisabled);
+ bool enableScissor = (clipRect != nullptr) || mScissorOptimizationDisabled;
+ mRenderState.scissor().setEnabled(enableScissor);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1417,7 +1421,7 @@
Rect clip(mState.currentClipRect());
clip.snapToPixelBoundaries();
- if (mCaches.setScissor(clip.left, getViewportHeight() - clip.bottom,
+ if (mRenderState.scissor().set(clip.left, getViewportHeight() - clip.bottom,
clip.getWidth(), clip.getHeight())) {
mState.setDirtyClip(false);
}
@@ -1491,7 +1495,7 @@
}
}
- mCaches.setScissor(scissorBox.left, getViewportHeight() - scissorBox.bottom,
+ mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom,
scissorBox.getWidth(), scissorBox.getHeight());
const SkPaint* paint = nullptr;
@@ -1533,17 +1537,17 @@
incrementThreshold = 0;
}
- mCaches.stencil.enableWrite(incrementThreshold);
+ mRenderState.stencil().enableWrite(incrementThreshold);
// Clean and update the stencil, but first make sure we restrict drawing
// to the region's bounds
- bool resetScissor = mCaches.enableScissor();
+ bool resetScissor = mRenderState.scissor().setEnabled(true);
if (resetScissor) {
// The scissor was not set so we now need to update it
setScissorFromClip();
}
- mCaches.stencil.clear();
+ mRenderState.stencil().clear();
// stash and disable the outline clip state, since stencil doesn't account for outline
bool storedSkipOutlineClip = mSkipOutlineClip;
@@ -1564,10 +1568,10 @@
// so we don't want to dirty the current layer, if any
drawRegionRects(clipArea.getClipRegion(), paint, false);
}
- if (resetScissor) mCaches.disableScissor();
+ if (resetScissor) mRenderState.scissor().setEnabled(false);
mSkipOutlineClip = storedSkipOutlineClip;
- mCaches.stencil.enableTest(incrementThreshold);
+ mRenderState.stencil().enableTest(incrementThreshold);
// Draw the region used to generate the stencil if the appropriate debug
// mode is enabled
@@ -1580,7 +1584,7 @@
}
} else {
EVENT_LOGD("setStencilFromClip - disabling");
- mCaches.stencil.disable();
+ mRenderState.stencil().disable();
}
}
}
@@ -1611,7 +1615,7 @@
}
// not quick rejected, so enable the scissor if clipRequired
- mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired);
+ mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
mSkipOutlineClip = !roundRectClipRequired;
return false;
}
@@ -1638,7 +1642,7 @@
// Make sure setScissor & setStencil happen at the beginning of
// this method
if (mState.getDirtyClip()) {
- if (mCaches.scissorEnabled) {
+ if (mRenderState.scissor().isEnabled()) {
setScissorFromClip();
}
@@ -1657,7 +1661,7 @@
// the stencil buffer and if stencil highlight debugging is on
mDescription.hasDebugHighlight = !mCaches.debugOverdraw &&
mCaches.debugStencilClip == Caches::kStencilShowHighlight &&
- mCaches.stencil.isTestEnabled();
+ mRenderState.stencil().isTestEnabled();
}
void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
@@ -1676,7 +1680,7 @@
}
void OpenGLRenderer::setupDrawNoTexture() {
- mCaches.disableTexCoordsVertexArray();
+ mRenderState.meshState().disableTexCoordsVertexArray();
}
void OpenGLRenderer::setupDrawVertexAlpha(bool useShadowAlphaInterp) {
@@ -1888,21 +1892,21 @@
}
void OpenGLRenderer::setupDrawSimpleMesh() {
- bool force = mCaches.bindMeshBuffer();
- mCaches.bindPositionVertexPointer(force, nullptr);
- mCaches.unbindIndicesBuffer();
+ bool force = mRenderState.meshState().bindMeshBuffer();
+ mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram, force, nullptr);
+ mRenderState.meshState().unbindIndicesBuffer();
}
void OpenGLRenderer::setupDrawTexture(GLuint texture) {
if (texture) bindTexture(texture);
mTextureUnit++;
- mCaches.enableTexCoordsVertexArray();
+ mRenderState.meshState().enableTexCoordsVertexArray();
}
void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) {
bindExternalTexture(texture);
mTextureUnit++;
- mCaches.enableTexCoordsVertexArray();
+ mRenderState.meshState().enableTexCoordsVertexArray();
}
void OpenGLRenderer::setupDrawTextureTransform() {
@@ -1918,27 +1922,29 @@
const GLvoid* texCoords, GLuint vbo) {
bool force = false;
if (!vertices || vbo) {
- force = mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
+ force = mRenderState.meshState().bindMeshBuffer(vbo);
} else {
- force = mCaches.unbindMeshBuffer();
+ force = mRenderState.meshState().unbindMeshBuffer();
}
- mCaches.bindPositionVertexPointer(force, vertices);
+ mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram, force, vertices);
if (mCaches.currentProgram->texCoords >= 0) {
- mCaches.bindTexCoordsVertexPointer(force, texCoords);
+ mRenderState.meshState().bindTexCoordsVertexPointer(mCaches.currentProgram, force, texCoords);
}
- mCaches.unbindIndicesBuffer();
+ mRenderState.meshState().unbindIndicesBuffer();
}
void OpenGLRenderer::setupDrawMesh(const GLvoid* vertices,
const GLvoid* texCoords, const GLvoid* colors) {
- bool force = mCaches.unbindMeshBuffer();
+ bool force = mRenderState.meshState().unbindMeshBuffer();
GLsizei stride = sizeof(ColorTextureVertex);
- mCaches.bindPositionVertexPointer(force, vertices, stride);
+ mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram, force,
+ vertices, stride);
if (mCaches.currentProgram->texCoords >= 0) {
- mCaches.bindTexCoordsVertexPointer(force, texCoords, stride);
+ mRenderState.meshState().bindTexCoordsVertexPointer(mCaches.currentProgram, force,
+ texCoords, stride);
}
int slot = mCaches.currentProgram->getAttrib("colors");
if (slot >= 0) {
@@ -1946,7 +1952,7 @@
glVertexAttribPointer(slot, 4, GL_FLOAT, GL_FALSE, stride, colors);
}
- mCaches.unbindIndicesBuffer();
+ mRenderState.meshState().unbindIndicesBuffer();
}
void OpenGLRenderer::setupDrawMeshIndices(const GLvoid* vertices,
@@ -1954,24 +1960,26 @@
bool force = false;
// If vbo is != 0 we want to treat the vertices parameter as an offset inside
// a VBO. However, if vertices is set to NULL and vbo == 0 then we want to
- // use the default VBO found in Caches
+ // use the default VBO found in RenderState
if (!vertices || vbo) {
- force = mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
+ force = mRenderState.meshState().bindMeshBuffer(vbo);
} else {
- force = mCaches.unbindMeshBuffer();
+ force = mRenderState.meshState().unbindMeshBuffer();
}
- mCaches.bindQuadIndicesBuffer();
+ mRenderState.meshState().bindQuadIndicesBuffer();
- mCaches.bindPositionVertexPointer(force, vertices);
+ mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram, force, vertices);
if (mCaches.currentProgram->texCoords >= 0) {
- mCaches.bindTexCoordsVertexPointer(force, texCoords);
+ mRenderState.meshState().bindTexCoordsVertexPointer(mCaches.currentProgram,
+ force, texCoords);
}
}
void OpenGLRenderer::setupDrawIndexedVertices(GLvoid* vertices) {
- bool force = mCaches.unbindMeshBuffer();
- mCaches.bindQuadIndicesBuffer();
- mCaches.bindPositionVertexPointer(force, vertices, gVertexStride);
+ bool force = mRenderState.meshState().unbindMeshBuffer();
+ mRenderState.meshState().bindQuadIndicesBuffer();
+ mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram, force,
+ vertices, kVertexStride);
}
///////////////////////////////////////////////////////////////////////////////
@@ -2030,8 +2038,8 @@
// No need to check for a UV mapper on the texture object, only ARGB_8888
// bitmaps get packed in the atlas
drawAlpha8TextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
- paint, (GLvoid*) nullptr, (GLvoid*) gMeshTextureOffset,
- GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
+ paint, (GLvoid*) nullptr, (GLvoid*) kMeshTextureOffset,
+ GL_TRIANGLE_STRIP, kMeshCount, ignoreTransform);
}
/**
@@ -2094,7 +2102,7 @@
}
// TODO: use quickReject on bounds from vertices
- mCaches.enableScissor();
+ mRenderState.scissor().setEnabled(true);
float left = FLT_MAX;
float top = FLT_MAX;
@@ -2224,7 +2232,7 @@
getMapper(texture).map(u1, v1, u2, v2);
- mCaches.unbindMeshBuffer();
+ mRenderState.meshState().unbindMeshBuffer();
resetDrawTextureTexCoords(u1, v1, u2, v2);
texture->setWrap(GL_CLAMP_TO_EDGE, true);
@@ -2271,12 +2279,12 @@
drawAlpha8TextureMesh(dstLeft, dstTop, dstRight, dstBottom,
texture->id, paint,
&mMeshVertices[0].x, &mMeshVertices[0].u,
- GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
+ GL_TRIANGLE_STRIP, kMeshCount, ignoreTransform);
} else {
drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom,
texture->id, paint, texture->blend,
&mMeshVertices[0].x, &mMeshVertices[0].u,
- GL_TRIANGLE_STRIP, gMeshCount, false, ignoreTransform);
+ GL_TRIANGLE_STRIP, kMeshCount, false, ignoreTransform);
}
if (CC_UNLIKELY(useScaleTransform)) {
@@ -2408,33 +2416,34 @@
setupDrawShaderUniforms(getShader(paint));
const void* vertices = vertexBuffer.getBuffer();
- mCaches.unbindMeshBuffer();
- mCaches.bindPositionVertexPointer(true, vertices, isAA ? gAlphaVertexStride : gVertexStride);
- mCaches.resetTexCoordsVertexPointer();
+ mRenderState.meshState().unbindMeshBuffer();
+ mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram,
+ true, vertices, isAA ? kAlphaVertexStride : kVertexStride);
+ mRenderState.meshState().resetTexCoordsVertexPointer();
int alphaSlot = -1;
if (isAA) {
- void* alphaCoords = ((GLbyte*) vertices) + gVertexAlphaOffset;
+ void* alphaCoords = ((GLbyte*) vertices) + kVertexAlphaOffset;
alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha");
// TODO: avoid enable/disable in back to back uses of the alpha attribute
glEnableVertexAttribArray(alphaSlot);
- glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords);
+ glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, kAlphaVertexStride, alphaCoords);
}
const VertexBuffer::Mode mode = vertexBuffer.getMode();
if (mode == VertexBuffer::kStandard) {
- mCaches.unbindIndicesBuffer();
+ mRenderState.meshState().unbindIndicesBuffer();
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount());
} else if (mode == VertexBuffer::kOnePolyRingShadow) {
- mCaches.bindShadowIndicesBuffer();
+ mRenderState.meshState().bindShadowIndicesBuffer();
glDrawElements(GL_TRIANGLE_STRIP, ONE_POLY_RING_SHADOW_INDEX_COUNT,
GL_UNSIGNED_SHORT, nullptr);
} else if (mode == VertexBuffer::kTwoPolyRingShadow) {
- mCaches.bindShadowIndicesBuffer();
+ mRenderState.meshState().bindShadowIndicesBuffer();
glDrawElements(GL_TRIANGLE_STRIP, TWO_POLY_RING_SHADOW_INDEX_COUNT,
GL_UNSIGNED_SHORT, nullptr);
} else if (mode == VertexBuffer::kIndices) {
- mCaches.unbindIndicesBuffer();
+ mRenderState.meshState().unbindIndicesBuffer();
glDrawElements(GL_TRIANGLE_STRIP, vertexBuffer.getIndexCount(),
GL_UNSIGNED_SHORT, vertexBuffer.getIndices());
}
@@ -2716,9 +2725,9 @@
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawShaderUniforms(getShader(paint));
- setupDrawMesh(nullptr, (GLvoid*) gMeshTextureOffset);
+ setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
}
bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
@@ -2738,7 +2747,7 @@
return;
}
- mCaches.enableScissor();
+ mRenderState.scissor().setEnabled(true);
float x = 0.0f;
float y = 0.0f;
@@ -2868,8 +2877,6 @@
mState.setClippingRoundRect(allocator, rect, radius, highPriority);
}
-
-
void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y,
const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
DrawOpMode drawOpMode) {
@@ -2964,7 +2971,7 @@
}
// TODO: avoid scissor by calculating maximum bounds using path bounds + font metrics
- mCaches.enableScissor();
+ mRenderState.scissor().setEnabled(true);
FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
fontRenderer.setFont(paint, SkMatrix::I());
@@ -3038,7 +3045,7 @@
updateLayer(layer, true);
- mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired);
+ mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
mCaches.activeTexture(0);
if (CC_LIKELY(!layer->region.isEmpty())) {
@@ -3074,7 +3081,7 @@
GLsizei elementsCount = layer->meshElementCount;
while (elementsCount > 0) {
- GLsizei drawCount = min(elementsCount, (GLsizei) gMaxNumberOfQuads * 6);
+ GLsizei drawCount = min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
@@ -3152,9 +3159,9 @@
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawShaderUniforms(getShader(paint));
- setupDrawMesh(nullptr, (GLvoid*) gMeshTextureOffset);
+ setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
}
// Same values used by Skia
@@ -3220,7 +3227,7 @@
if (mState.currentlyIgnored()) return;
// TODO: use quickRejectWithScissor. For now, always force enable scissor.
- mCaches.enableScissor();
+ mRenderState.scissor().setEnabled(true);
SkPaint paint;
paint.setAntiAlias(true); // want to use AlphaVertex
@@ -3333,7 +3340,7 @@
setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawSimpleMesh();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
}
void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
@@ -3341,7 +3348,7 @@
texture->setWrap(GL_CLAMP_TO_EDGE, true);
GLvoid* vertices = (GLvoid*) nullptr;
- GLvoid* texCoords = (GLvoid*) gMeshTextureOffset;
+ GLvoid* texCoords = (GLvoid*) kMeshTextureOffset;
if (texture->uvMapper) {
vertices = &mMeshVertices[0].x;
@@ -3360,11 +3367,11 @@
texture->setFilter(GL_NEAREST, true);
drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
paint, texture->blend, vertices, texCoords,
- GL_TRIANGLE_STRIP, gMeshCount, false, true);
+ GL_TRIANGLE_STRIP, kMeshCount, false, true);
} else {
texture->setFilter(getFilter(paint), true);
drawTextureMesh(left, top, right, bottom, texture->id, paint,
- texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, gMeshCount);
+ texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, kMeshCount);
}
if (texture->uvMapper) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 76ad6ce..94054ff 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -222,6 +222,10 @@
return mCaches;
}
+ RenderState& renderState() {
+ return mRenderState;
+ }
+
int getViewportWidth() { return mState.getViewportWidth(); }
int getViewportHeight() { return mState.getViewportHeight(); }
@@ -523,9 +527,10 @@
return false;
}
- inline RenderState& renderState() { return mRenderState; }
-
CanvasState mState;
+ Caches& mCaches;
+ Extensions& mExtensions; // TODO: move to RenderState
+ RenderState& mRenderState;
private:
/**
@@ -1027,11 +1032,6 @@
DrawModifiers mDrawModifiers;
SkPaint mFilteredPaint;
- // Various caches
- Caches& mCaches;
- Extensions& mExtensions;
- RenderState& mRenderState;
-
// List of rectangles to clear after saveLayer() is invoked
std::vector<Rect> mLayers;
// List of layers to update at the beginning of a frame
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index eb88bc0..af403b4 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -23,6 +23,7 @@
#include "Patch.h"
#include "PatchCache.h"
#include "Properties.h"
+#include "renderstate/RenderState.h"
namespace android {
namespace uirenderer {
@@ -31,9 +32,13 @@
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-PatchCache::PatchCache():
- mSize(0), mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity),
- mMeshBuffer(0), mFreeBlocks(nullptr), mGenerationId(0) {
+PatchCache::PatchCache(RenderState& renderState)
+ : mRenderState(renderState)
+ , mSize(0)
+ , mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity)
+ , mMeshBuffer(0)
+ , mFreeBlocks(nullptr)
+ , mGenerationId(0) {
char property[PROPERTY_VALUE_MAX];
if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, nullptr) > 0) {
INIT_LOGD(" Setting patch cache size to %skB", property);
@@ -48,15 +53,15 @@
clear();
}
-void PatchCache::init(Caches& caches) {
+void PatchCache::init() {
bool created = false;
if (!mMeshBuffer) {
glGenBuffers(1, &mMeshBuffer);
created = true;
}
- caches.bindMeshBuffer(mMeshBuffer);
- caches.resetVertexPointers();
+ mRenderState.meshState().bindMeshBuffer(mMeshBuffer);
+ mRenderState.meshState().resetVertexPointers();
if (created) {
createVertexBuffer();
@@ -85,7 +90,7 @@
clearCache();
if (mMeshBuffer) {
- Caches::getInstance().unbindMeshBuffer();
+ mRenderState.meshState().unbindMeshBuffer();
glDeleteBuffers(1, &mMeshBuffer);
mMeshBuffer = 0;
mSize = 0;
@@ -187,7 +192,7 @@
*/
void PatchCache::setupMesh(Patch* newMesh, TextureVertex* vertices) {
// This call ensures the VBO exists and that it is bound
- init(Caches::getInstance());
+ init();
// If we're running out of space, let's clear the entire cache
uint32_t size = newMesh->getSize();
@@ -219,7 +224,7 @@
// Copy the 9patch mesh in the VBO
newMesh->offset = (GLintptr) (block->offset);
- newMesh->textureOffset = newMesh->offset + gMeshTextureOffset;
+ newMesh->textureOffset = newMesh->offset + kMeshTextureOffset;
glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
// Remove the block since we've used it entirely
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 4cb5338..e038720 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -51,9 +51,9 @@
class PatchCache {
public:
- PatchCache();
+ PatchCache(RenderState& renderState);
~PatchCache();
- void init(Caches& caches);
+ void init();
const Patch* get(const AssetAtlas::Entry* entry,
const uint32_t bitmapWidth, const uint32_t bitmapHeight,
@@ -168,6 +168,7 @@
void dumpFreeBlocks(const char* prefix);
#endif
+ RenderState& mRenderState;
uint32_t mMaxSize;
uint32_t mSize;
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index c564b87..cc7f88d 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -31,7 +31,6 @@
#include "PathCache.h"
#include "thread/Signal.h"
-#include "thread/Task.h"
#include "thread/TaskProcessor.h"
namespace android {
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index ecd3712..7378018 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -17,21 +17,22 @@
#ifndef ANDROID_HWUI_PATH_CACHE_H
#define ANDROID_HWUI_PATH_CACHE_H
-#include <GLES2/gl2.h>
+#include "Debug.h"
+#include "Texture.h"
+#include "thread/Task.h"
+#include "thread/TaskProcessor.h"
+#include "utils/Macros.h"
+#include "utils/Pair.h"
+#include <GLES2/gl2.h>
+#include <SkPath.h>
#include <utils/LruCache.h>
#include <utils/Mutex.h>
#include <utils/Vector.h>
-#include "Debug.h"
-#include "Texture.h"
-#include "utils/Macros.h"
-#include "utils/Pair.h"
-
class SkBitmap;
class SkCanvas;
class SkPaint;
-class SkPath;
struct SkRect;
namespace android {
diff --git a/libs/hwui/PixelBuffer.cpp b/libs/hwui/PixelBuffer.cpp
index efa271e..62eb68c 100644
--- a/libs/hwui/PixelBuffer.cpp
+++ b/libs/hwui/PixelBuffer.cpp
@@ -16,13 +16,14 @@
#define LOG_TAG "OpenGLRenderer"
-#include <utils/Log.h>
+#include "PixelBuffer.h"
-#include "Caches.h"
#include "Debug.h"
#include "Extensions.h"
-#include "PixelBuffer.h"
#include "Properties.h"
+#include "renderstate/RenderState.h"
+
+#include <utils/Log.h>
namespace android {
namespace uirenderer {
@@ -93,14 +94,16 @@
Caches& mCaches;
};
-GpuPixelBuffer::GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
+GpuPixelBuffer::GpuPixelBuffer(GLenum format,
+ uint32_t width, uint32_t height)
: PixelBuffer(format, width, height)
, mMappedPointer(nullptr)
- , mCaches(Caches::getInstance()) {
+ , mCaches(Caches::getInstance()){
glGenBuffers(1, &mBuffer);
- mCaches.bindPixelBuffer(mBuffer);
+
+ mCaches.pixelBuffer().bind(mBuffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), nullptr, GL_DYNAMIC_DRAW);
- mCaches.unbindPixelBuffer();
+ mCaches.pixelBuffer().unbind();
}
GpuPixelBuffer::~GpuPixelBuffer() {
@@ -109,7 +112,7 @@
uint8_t* GpuPixelBuffer::map(AccessMode mode) {
if (mAccessMode == kAccessMode_None) {
- mCaches.bindPixelBuffer(mBuffer);
+ mCaches.pixelBuffer().bind(mBuffer);
mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
#if DEBUG_OPENGL
if (!mMappedPointer) {
@@ -128,7 +131,7 @@
void GpuPixelBuffer::unmap() {
if (mAccessMode != kAccessMode_None) {
if (mMappedPointer) {
- mCaches.bindPixelBuffer(mBuffer);
+ mCaches.pixelBuffer().bind(mBuffer);
GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
if (status == GL_FALSE) {
ALOGE("Corrupted GPU pixel buffer");
@@ -145,7 +148,7 @@
void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
// If the buffer is not mapped, unmap() will not bind it
- mCaches.bindPixelBuffer(mBuffer);
+ mCaches.pixelBuffer().bind(mBuffer);
unmap();
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
@@ -155,7 +158,8 @@
// Factory
///////////////////////////////////////////////////////////////////////////////
-PixelBuffer* PixelBuffer::create(GLenum format, uint32_t width, uint32_t height, BufferType type) {
+PixelBuffer* PixelBuffer::create(GLenum format,
+ uint32_t width, uint32_t height, BufferType type) {
if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) {
return new GpuPixelBuffer(format, width, height);
}
diff --git a/libs/hwui/PixelBuffer.h b/libs/hwui/PixelBuffer.h
index 04225a2..aac5ec4 100644
--- a/libs/hwui/PixelBuffer.h
+++ b/libs/hwui/PixelBuffer.h
@@ -18,6 +18,7 @@
#define ANDROID_HWUI_PIXEL_BUFFER_H
#include <GLES3/gl3.h>
+#include <cutils/log.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/Vector.h b/libs/hwui/Vector.h
index aa6acc9..7c3f2fd 100644
--- a/libs/hwui/Vector.h
+++ b/libs/hwui/Vector.h
@@ -17,6 +17,9 @@
#ifndef ANDROID_HWUI_VECTOR_H
#define ANDROID_HWUI_VECTOR_H
+#include <math.h>
+#include <utils/Log.h>
+
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp
new file mode 100644
index 0000000..7820a66
--- /dev/null
+++ b/libs/hwui/renderstate/MeshState.cpp
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+#include "renderstate/MeshState.h"
+
+#include "Program.h"
+
+#include "ShadowTessellator.h"
+
+namespace android {
+namespace uirenderer {
+
+MeshState::MeshState()
+ : mCurrentPositionPointer(this)
+ , mCurrentPositionStride(0)
+ , mCurrentTexCoordsPointer(this)
+ , mCurrentTexCoordsStride(0)
+ , mTexCoordsArrayEnabled(false) {
+
+ glGenBuffers(1, &meshBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(kMeshVertices), kMeshVertices, GL_STATIC_DRAW);
+
+ mCurrentBuffer = meshBuffer;
+ mCurrentIndicesBuffer = 0;
+ mCurrentPixelBuffer = 0;
+
+ mQuadListIndices = 0;
+ mShadowStripsIndices = 0;
+}
+
+MeshState::~MeshState() {
+ glDeleteBuffers(1, &meshBuffer);
+ mCurrentBuffer = 0;
+
+ glDeleteBuffers(1, &mQuadListIndices);
+ mQuadListIndices = 0;
+
+ glDeleteBuffers(1, &mShadowStripsIndices);
+ mShadowStripsIndices = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Buffer Objects
+///////////////////////////////////////////////////////////////////////////////
+
+bool MeshState::bindMeshBuffer() {
+ return bindMeshBuffer(meshBuffer);
+}
+
+bool MeshState::bindMeshBuffer(GLuint buffer) {
+ if (!buffer) buffer = meshBuffer;
+ if (mCurrentBuffer != buffer) {
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ mCurrentBuffer = buffer;
+ return true;
+ }
+ return false;
+}
+
+bool MeshState::unbindMeshBuffer() {
+ if (mCurrentBuffer) {
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ mCurrentBuffer = 0;
+ return true;
+ }
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Vertices
+///////////////////////////////////////////////////////////////////////////////
+
+void MeshState::bindPositionVertexPointer(const Program* currentProgram, bool force,
+ const GLvoid* vertices, GLsizei stride) {
+ if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
+ GLuint slot = currentProgram->position;
+ glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
+ mCurrentPositionPointer = vertices;
+ mCurrentPositionStride = stride;
+ }
+}
+
+void MeshState::bindTexCoordsVertexPointer(const Program* currentProgram, bool force,
+ const GLvoid* vertices, GLsizei stride) {
+ if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
+ GLuint slot = currentProgram->texCoords;
+ glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
+ mCurrentTexCoordsPointer = vertices;
+ mCurrentTexCoordsStride = stride;
+ }
+}
+
+void MeshState::resetVertexPointers() {
+ mCurrentPositionPointer = this;
+ mCurrentTexCoordsPointer = this;
+}
+
+void MeshState::resetTexCoordsVertexPointer() {
+ mCurrentTexCoordsPointer = this;
+}
+
+void MeshState::enableTexCoordsVertexArray() {
+ if (!mTexCoordsArrayEnabled) {
+ glEnableVertexAttribArray(Program::kBindingTexCoords);
+ mCurrentTexCoordsPointer = this;
+ mTexCoordsArrayEnabled = true;
+ }
+}
+
+void MeshState::disableTexCoordsVertexArray() {
+ if (mTexCoordsArrayEnabled) {
+ glDisableVertexAttribArray(Program::kBindingTexCoords);
+ mTexCoordsArrayEnabled = false;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Indices
+///////////////////////////////////////////////////////////////////////////////
+
+bool MeshState::bindIndicesBufferInternal(const GLuint buffer) {
+ if (mCurrentIndicesBuffer != buffer) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
+ mCurrentIndicesBuffer = buffer;
+ return true;
+ }
+ return false;
+}
+
+bool MeshState::bindQuadIndicesBuffer() {
+ if (!mQuadListIndices) {
+ std::unique_ptr<uint16_t[]> regionIndices(new uint16_t[kMaxNumberOfQuads * 6]);
+ for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) {
+ uint16_t quad = i * 4;
+ int index = i * 6;
+ regionIndices[index ] = quad; // top-left
+ regionIndices[index + 1] = quad + 1; // top-right
+ regionIndices[index + 2] = quad + 2; // bottom-left
+ regionIndices[index + 3] = quad + 2; // bottom-left
+ regionIndices[index + 4] = quad + 1; // top-right
+ regionIndices[index + 5] = quad + 3; // bottom-right
+ }
+
+ glGenBuffers(1, &mQuadListIndices);
+ bool force = bindIndicesBufferInternal(mQuadListIndices);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, kMaxNumberOfQuads * 6 * sizeof(uint16_t),
+ regionIndices.get(), GL_STATIC_DRAW);
+ return force;
+ }
+
+ return bindIndicesBufferInternal(mQuadListIndices);
+}
+
+bool MeshState::bindShadowIndicesBuffer() {
+ if (!mShadowStripsIndices) {
+ std::unique_ptr<uint16_t[]> shadowIndices(new uint16_t[MAX_SHADOW_INDEX_COUNT]);
+ ShadowTessellator::generateShadowIndices(shadowIndices.get());
+ glGenBuffers(1, &mShadowStripsIndices);
+ bool force = bindIndicesBufferInternal(mShadowStripsIndices);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_SHADOW_INDEX_COUNT * sizeof(uint16_t),
+ shadowIndices.get(), GL_STATIC_DRAW);
+ return force;
+ }
+
+ return bindIndicesBufferInternal(mShadowStripsIndices);
+}
+
+bool MeshState::unbindIndicesBuffer() {
+ if (mCurrentIndicesBuffer) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ mCurrentIndicesBuffer = 0;
+ return true;
+ }
+ return false;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/renderstate/MeshState.h b/libs/hwui/renderstate/MeshState.h
new file mode 100644
index 0000000..76f73d4
--- /dev/null
+++ b/libs/hwui/renderstate/MeshState.h
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+#ifndef RENDERSTATE_MESHSTATE_H
+#define RENDERSTATE_MESHSTATE_H
+
+#include "Vertex.h"
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <memory>
+
+namespace android {
+namespace uirenderer {
+
+class Program;
+
+// Maximum number of quads that pre-allocated meshes can draw
+const uint32_t kMaxNumberOfQuads = 2048;
+
+// This array is never used directly but used as a memcpy source in the
+// OpenGLRenderer constructor
+const TextureVertex kMeshVertices[] = {
+ { 0, 0, 0, 0 },
+ { 1, 0, 1, 0 },
+ { 0, 1, 0, 1 },
+ { 1, 1, 1, 1 },
+};
+
+const GLsizei kVertexStride = sizeof(Vertex);
+const GLsizei kAlphaVertexStride = sizeof(AlphaVertex);
+const GLsizei kTextureVertexStride = sizeof(TextureVertex);
+
+const GLsizei kMeshTextureOffset = 2 * sizeof(float);
+const GLsizei kVertexAlphaOffset = 2 * sizeof(float);
+const GLsizei kVertexAAWidthOffset = 2 * sizeof(float);
+const GLsizei kVertexAALengthOffset = 3 * sizeof(float);
+const GLsizei kMeshCount = 4;
+
+class MeshState {
+private:
+ friend class RenderState;
+
+public:
+ ~MeshState();
+ ///////////////////////////////////////////////////////////////////////////////
+ // Buffer objects
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * Binds the VBO used to render simple textured quads.
+ */
+ bool bindMeshBuffer();
+
+ /**
+ * Binds the specified VBO if needed. If buffer == 0, binds default simple textured quad.
+ */
+ bool bindMeshBuffer(GLuint buffer);
+
+ /**
+ * Unbinds the VBO used to render simple textured quads.
+ */
+ bool unbindMeshBuffer();
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Vertices
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * Binds an attrib to the specified float vertex pointer.
+ * Assumes a stride of gTextureVertexStride and a size of 2.
+ */
+ void bindPositionVertexPointer(const Program* currentProgram, bool force,
+ const GLvoid* vertices, GLsizei stride = kTextureVertexStride);
+
+ /**
+ * Binds an attrib to the specified float vertex pointer.
+ * Assumes a stride of gTextureVertexStride and a size of 2.
+ */
+ void bindTexCoordsVertexPointer(const Program* currentProgram, bool force,
+ const GLvoid* vertices, GLsizei stride = kTextureVertexStride);
+
+ /**
+ * Resets the vertex pointers.
+ */
+ void resetVertexPointers();
+ void resetTexCoordsVertexPointer();
+
+ void enableTexCoordsVertexArray();
+ void disableTexCoordsVertexArray();
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Indices
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * Binds a global indices buffer that can draw up to
+ * gMaxNumberOfQuads quads.
+ */
+ bool bindQuadIndicesBuffer();
+ bool bindShadowIndicesBuffer();
+ bool unbindIndicesBuffer();
+
+private:
+ MeshState();
+ bool bindIndicesBufferInternal(const GLuint buffer);
+
+ // VBO to draw with
+ GLuint meshBuffer;
+
+ GLuint mCurrentBuffer;
+ GLuint mCurrentIndicesBuffer;
+ GLuint mCurrentPixelBuffer;
+
+ const void* mCurrentPositionPointer;
+ GLsizei mCurrentPositionStride;
+ const void* mCurrentTexCoordsPointer;
+ GLsizei mCurrentTexCoordsStride;
+
+ bool mTexCoordsArrayEnabled;
+
+ // Global index buffer
+ GLuint mQuadListIndices;
+ GLuint mShadowStripsIndices;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif // RENDERSTATE_MESHSTATE_H
diff --git a/libs/hwui/renderstate/PixelBufferState.cpp b/libs/hwui/renderstate/PixelBufferState.cpp
new file mode 100644
index 0000000..c23af52
--- /dev/null
+++ b/libs/hwui/renderstate/PixelBufferState.cpp
@@ -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.
+ */
+#include "renderstate/PixelBufferState.h"
+
+namespace android {
+namespace uirenderer {
+
+PixelBufferState::PixelBufferState()
+ : mCurrentPixelBuffer(0) {
+}
+
+bool PixelBufferState::bind(GLuint buffer) {
+ if (mCurrentPixelBuffer != buffer) {
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
+ mCurrentPixelBuffer = buffer;
+ return true;
+ }
+ return false;
+}
+
+bool PixelBufferState::unbind() {
+ if (mCurrentPixelBuffer) {
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ mCurrentPixelBuffer = 0;
+ return true;
+ }
+ return false;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/renderstate/PixelBufferState.h b/libs/hwui/renderstate/PixelBufferState.h
new file mode 100644
index 0000000..8dab21d
--- /dev/null
+++ b/libs/hwui/renderstate/PixelBufferState.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+#ifndef RENDERSTATE_PIXELBUFFERSTATE_H
+#define RENDERSTATE_PIXELBUFFERSTATE_H
+
+#include <GLES3/gl3.h>
+
+namespace android {
+namespace uirenderer {
+
+class PixelBufferState {
+ friend class Caches; // TODO: move to RenderState
+public:
+ bool bind(GLuint buffer);
+ bool unbind();
+private:
+ PixelBufferState();
+ GLuint mCurrentPixelBuffer;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif // RENDERSTATE_PIXELBUFFERSTATE_H
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
similarity index 81%
rename from libs/hwui/RenderState.cpp
rename to libs/hwui/renderstate/RenderState.cpp
index 45a97fb..e4c8745 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include "RenderState.h"
+#include "renderstate/RenderState.h"
#include "renderthread/CanvasContext.h"
#include "renderthread/EglManager.h"
@@ -24,6 +24,9 @@
RenderState::RenderState(renderthread::RenderThread& thread)
: mRenderThread(thread)
, mCaches(nullptr)
+ , mMeshState(nullptr)
+ , mScissor(nullptr)
+ , mStencil(nullptr)
, mViewportWidth(0)
, mViewportHeight(0)
, mFramebuffer(0) {
@@ -31,16 +34,27 @@
}
RenderState::~RenderState() {
+ LOG_ALWAYS_FATAL_IF(mMeshState || mScissor || mStencil,
+ "State object lifecycle not managed correctly");
}
void RenderState::onGLContextCreated() {
+ LOG_ALWAYS_FATAL_IF(mMeshState || mScissor || mStencil,
+ "State object lifecycle not managed correctly");
+ mMeshState = new MeshState();
+ mScissor = new Scissor();
+ mStencil = new Stencil();
+
// This is delayed because the first access of Caches makes GL calls
- mCaches = &Caches::getInstance();
+ mCaches = &Caches::createInstance(*this);
mCaches->init();
- mCaches->setRenderState(this);
mCaches->textureCache.setAssetAtlas(&mAssetAtlas);
}
+static void layerLostGlContext(Layer* layer) {
+ layer->onGlContextLost();
+}
+
void RenderState::onGLContextDestroyed() {
/*
size_t size = mActiveLayers.size();
@@ -73,7 +87,17 @@
LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size);
}
*/
+
+ // TODO: reset all cached state in state objects
+ std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext);
mAssetAtlas.terminate();
+
+ delete mMeshState;
+ mMeshState = nullptr;
+ delete mScissor;
+ mScissor = nullptr;
+ delete mStencil;
+ mStencil = nullptr;
}
void RenderState::setViewport(GLsizei width, GLsizei height) {
@@ -109,10 +133,10 @@
}
}
mCaches->resetActiveTexture();
- mCaches->unbindMeshBuffer();
- mCaches->unbindIndicesBuffer();
- mCaches->resetVertexPointers();
- mCaches->disableTexCoordsVertexArray();
+ meshState().unbindMeshBuffer();
+ meshState().unbindIndicesBuffer();
+ meshState().resetVertexPointers();
+ meshState().disableTexCoordsVertexArray();
debugOverdraw(false, false);
}
@@ -123,9 +147,7 @@
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- mCaches->scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
- mCaches->enableScissor();
- mCaches->resetScissor();
+ scissor().invalidate();
mCaches->activeTexture(0);
mCaches->resetBoundTextures();
@@ -139,13 +161,13 @@
void RenderState::debugOverdraw(bool enable, bool clear) {
if (mCaches->debugOverdraw && mFramebuffer == 0) {
if (clear) {
- mCaches->disableScissor();
- mCaches->stencil.clear();
+ scissor().setEnabled(false);
+ stencil().clear();
}
if (enable) {
- mCaches->stencil.enableDebugWrite();
+ stencil().enableDebugWrite();
} else {
- mCaches->stencil.disable();
+ stencil().disable();
}
}
}
diff --git a/libs/hwui/RenderState.h b/libs/hwui/renderstate/RenderState.h
similarity index 85%
rename from libs/hwui/RenderState.h
rename to libs/hwui/renderstate/RenderState.h
index 629fe0d..d1ee64a 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -27,6 +27,10 @@
#include "AssetAtlas.h"
#include "Caches.h"
+#include "renderstate/MeshState.h"
+#include "renderstate/PixelBufferState.h"
+#include "renderstate/Scissor.h"
+#include "renderstate/Stencil.h"
#include "utils/Macros.h"
namespace android {
@@ -58,10 +62,10 @@
void debugOverdraw(bool enable, bool clear);
- void registerLayer(const Layer* layer) {
+ void registerLayer(Layer* layer) {
mActiveLayers.insert(layer);
}
- void unregisterLayer(const Layer* layer) {
+ void unregisterLayer(Layer* layer) {
mActiveLayers.erase(layer);
}
@@ -80,7 +84,9 @@
void postDecStrong(VirtualLightRefBase* object);
AssetAtlas& assetAtlas() { return mAssetAtlas; }
-
+ MeshState& meshState() { return *mMeshState; }
+ Scissor& scissor() { return *mScissor; }
+ Stencil& stencil() { return *mStencil; }
private:
friend class renderthread::RenderThread;
friend class Caches;
@@ -92,10 +98,16 @@
RenderState(renderthread::RenderThread& thread);
~RenderState();
+
renderthread::RenderThread& mRenderThread;
Caches* mCaches;
+
+ MeshState* mMeshState;
+ Scissor* mScissor;
+ Stencil* mStencil;
+
AssetAtlas mAssetAtlas;
- std::set<const Layer*> mActiveLayers;
+ std::set<Layer*> mActiveLayers;
std::set<renderthread::CanvasContext*> mRegisteredContexts;
GLsizei mViewportWidth;
diff --git a/libs/hwui/renderstate/Scissor.cpp b/libs/hwui/renderstate/Scissor.cpp
new file mode 100644
index 0000000..66c31a2
--- /dev/null
+++ b/libs/hwui/renderstate/Scissor.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+#include "renderstate/Scissor.h"
+
+namespace android {
+namespace uirenderer {
+
+Scissor::Scissor()
+ : mEnabled(false)
+ , mScissorX(0)
+ , mScissorY(0)
+ , mScissorWidth(0)
+ , mScissorHeight(0) {
+}
+
+bool Scissor::setEnabled(bool enabled) {
+ if (mEnabled != enabled) {
+ if (enabled) {
+ glEnable(GL_SCISSOR_TEST);
+ } else {
+ glDisable(GL_SCISSOR_TEST);
+ }
+ mEnabled = enabled;
+ return true;
+ }
+ return false;
+}
+
+bool Scissor::set(GLint x, GLint y, GLint width, GLint height) {
+ if (mEnabled && (x != mScissorX || y != mScissorY
+ || width != mScissorWidth || height != mScissorHeight)) {
+
+ if (x < 0) {
+ width += x;
+ x = 0;
+ }
+ if (y < 0) {
+ height += y;
+ y = 0;
+ }
+ if (width < 0) {
+ width = 0;
+ }
+ if (height < 0) {
+ height = 0;
+ }
+ glScissor(x, y, width, height);
+
+ mScissorX = x;
+ mScissorY = y;
+ mScissorWidth = width;
+ mScissorHeight = height;
+
+ return true;
+ }
+ return false;
+}
+
+void Scissor::reset() {
+ mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
+}
+
+void Scissor::invalidate() {
+ mEnabled = glIsEnabled(GL_SCISSOR_TEST);
+ setEnabled(true);
+ reset();
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/renderstate/Scissor.h b/libs/hwui/renderstate/Scissor.h
new file mode 100644
index 0000000..cc8b3dd
--- /dev/null
+++ b/libs/hwui/renderstate/Scissor.h
@@ -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.
+ */
+#ifndef RENDERSTATE_SCISSOR_H
+#define RENDERSTATE_SCISSOR_H
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+namespace android {
+namespace uirenderer {
+
+class Scissor {
+ friend class RenderState;
+public:
+ bool setEnabled(bool enabled);
+ bool set(GLint x, GLint y, GLint width, GLint height);
+ void reset();
+ bool isEnabled() { return mEnabled; }
+private:
+ Scissor();
+ void invalidate();
+ bool mEnabled;
+ GLint mScissorX;
+ GLint mScissorY;
+ GLint mScissorWidth;
+ GLint mScissorHeight;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif // RENDERSTATE_SCISSOR_H
diff --git a/libs/hwui/Stencil.cpp b/libs/hwui/renderstate/Stencil.cpp
similarity index 98%
rename from libs/hwui/Stencil.cpp
rename to libs/hwui/renderstate/Stencil.cpp
index f56a02e..acbed14 100644
--- a/libs/hwui/Stencil.cpp
+++ b/libs/hwui/renderstate/Stencil.cpp
@@ -17,7 +17,7 @@
#include "Debug.h"
#include "Extensions.h"
#include "Properties.h"
-#include "Stencil.h"
+#include "renderstate/Stencil.h"
#include <GLES2/gl2ext.h>
diff --git a/libs/hwui/Stencil.h b/libs/hwui/renderstate/Stencil.h
similarity index 100%
rename from libs/hwui/Stencil.h
rename to libs/hwui/renderstate/Stencil.h
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 71ecba5..6346479 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -16,19 +16,19 @@
#include "CanvasContext.h"
-#include <algorithm>
-#include <private/hwui/DrawGlInfo.h>
-#include <strings.h>
-
#include "EglManager.h"
#include "RenderThread.h"
#include "../AnimationContext.h"
#include "../Caches.h"
#include "../DeferredLayerUpdater.h"
-#include "../RenderState.h"
+#include "../renderstate/RenderState.h"
+#include "../renderstate/Stencil.h"
#include "../LayerRenderer.h"
#include "../OpenGLRenderer.h"
-#include "../Stencil.h"
+
+#include <algorithm>
+#include <private/hwui/DrawGlInfo.h>
+#include <strings.h>
#define TRIM_MEMORY_COMPLETE 80
#define TRIM_MEMORY_UI_HIDDEN 20
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 0aa0439..c4feb41 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -16,13 +16,13 @@
#include "EglManager.h"
+#include "../Caches.h"
+#include "../renderstate/RenderState.h"
+#include "RenderThread.h"
+
#include <cutils/log.h>
#include <cutils/properties.h>
-#include "../Caches.h"
-#include "../RenderState.h"
-#include "RenderThread.h"
-
#define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions"
#define GLES_VERSION 2
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index a2f0625..9a0fbad 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -16,17 +16,15 @@
#include "RenderThread.h"
-#if defined(HAVE_PTHREADS)
-#include <sys/resource.h>
-#endif
-#include <gui/DisplayEventReceiver.h>
-#include <utils/Log.h>
-
-#include "../RenderState.h"
+#include "../renderstate/RenderState.h"
#include "CanvasContext.h"
#include "EglManager.h"
#include "RenderProxy.h"
+#include <gui/DisplayEventReceiver.h>
+#include <sys/resource.h>
+#include <utils/Log.h>
+
namespace android {
using namespace uirenderer::renderthread;
ANDROID_SINGLETON_STATIC_INSTANCE(RenderThread);
@@ -250,9 +248,7 @@
}
bool RenderThread::threadLoop() {
-#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
-#endif
initThreadLocals();
int timeoutMillis = -1;
diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp
index cb5401c..3c30aab 100644
--- a/libs/hwui/thread/TaskManager.cpp
+++ b/libs/hwui/thread/TaskManager.cpp
@@ -14,10 +14,8 @@
* limitations under the License.
*/
-#include <sys/sysinfo.h>
-#if defined(HAVE_PTHREADS)
#include <sys/resource.h>
-#endif
+#include <sys/sysinfo.h>
#include "TaskManager.h"
#include "Task.h"
@@ -83,9 +81,7 @@
///////////////////////////////////////////////////////////////////////////////
status_t TaskManager::WorkerThread::readyToRun() {
-#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND);
-#endif
return NO_ERROR;
}
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
index 5b7c87c..fe43fdb 100644
--- a/libs/hwui/utils/Macros.h
+++ b/libs/hwui/utils/Macros.h
@@ -18,8 +18,8 @@
#define PREVENT_COPY_AND_ASSIGN(Type) \
private: \
- Type(const Type&); \
- void operator=(const Type&)
+ Type(const Type&) = delete; \
+ void operator=(const Type&) = delete
#define DESCRIPTION_TYPE(Type) \
int compare(const Type& rhs) const { return memcmp(this, &rhs, sizeof(Type));} \
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 766a837..0ffa5fc 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -4711,7 +4711,7 @@
synchronized (mLastDeviceConnectMsgTime) {
long time = SystemClock.uptimeMillis();
if (mLastDeviceConnectMsgTime > time) {
- delay = (int)(mLastDeviceConnectMsgTime - time);
+ delay = (int)(mLastDeviceConnectMsgTime - time) + 30;
}
}
}
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 0d6b91a..53ab264 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -214,6 +214,11 @@
* the underlying data could be mapped as a pointer in JNI without doing
* any copies with {@code GetDirectBufferAddress}.</p>
*
+ * <p>For raw formats, each plane is only guaranteed to contain data
+ * up to the last pixel in the last row. In other words, the stride
+ * after the last row may not be mapped into the buffer. This is a
+ * necessary requirement for any interleaved format.</p>
+ *
* @return the byte buffer containing the image data for this plane.
*/
public abstract ByteBuffer getBuffer();
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 4f74bdd..32d5b82 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -543,11 +543,6 @@
public int load(String path, int priority)
{
- // pass network streams to player
- if (path.startsWith("http:"))
- return _load(path, priority);
-
- // try local path
int id = 0;
try {
File f = new File(path);
@@ -562,6 +557,7 @@
return id;
}
+ @Override
public int load(Context context, int resId, int priority) {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
int id = 0;
@@ -576,6 +572,7 @@
return id;
}
+ @Override
public int load(AssetFileDescriptor afd, int priority) {
if (afd != null) {
long len = afd.getLength();
@@ -588,16 +585,17 @@
}
}
+ @Override
public int load(FileDescriptor fd, long offset, long length, int priority) {
return _load(fd, offset, length, priority);
}
- private native final int _load(String uri, int priority);
-
private native final int _load(FileDescriptor fd, long offset, long length, int priority);
+ @Override
public native final boolean unload(int soundID);
+ @Override
public final int play(int soundID, float leftVolume, float rightVolume,
int priority, int loop, float rate) {
if (isRestricted()) {
@@ -620,16 +618,22 @@
}
}
+ @Override
public native final void pause(int streamID);
+ @Override
public native final void resume(int streamID);
+ @Override
public native final void autoPause();
+ @Override
public native final void autoResume();
+ @Override
public native final void stop(int streamID);
+ @Override
public final void setVolume(int streamID, float leftVolume, float rightVolume) {
if (isRestricted()) {
return;
@@ -639,16 +643,21 @@
private native final void _setVolume(int streamID, float leftVolume, float rightVolume);
+ @Override
public void setVolume(int streamID, float volume) {
setVolume(streamID, volume, volume);
}
+ @Override
public native final void setPriority(int streamID, int priority);
+ @Override
public native final void setLoop(int streamID, int loop);
+ @Override
public native final void setRate(int streamID, float rate);
+ @Override
public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener)
{
synchronized(mLock) {
@@ -729,52 +738,69 @@
return 0;
}
+ @Override
public int load(Context context, int resId, int priority) {
return 0;
}
+ @Override
public int load(AssetFileDescriptor afd, int priority) {
return 0;
}
+ @Override
public int load(FileDescriptor fd, long offset, long length, int priority) {
return 0;
}
+ @Override
public final boolean unload(int soundID) {
return true;
}
+ @Override
public final int play(int soundID, float leftVolume, float rightVolume,
int priority, int loop, float rate) {
return 0;
}
+ @Override
public final void pause(int streamID) { }
+ @Override
public final void resume(int streamID) { }
+ @Override
public final void autoPause() { }
+ @Override
public final void autoResume() { }
+ @Override
public final void stop(int streamID) { }
+ @Override
public final void setVolume(int streamID,
float leftVolume, float rightVolume) { }
+ @Override
public void setVolume(int streamID, float volume) {
}
+ @Override
public final void setPriority(int streamID, int priority) { }
+ @Override
public final void setLoop(int streamID, int loop) { }
+ @Override
public final void setRate(int streamID, float rate) { }
+ @Override
public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener) {
}
+ @Override
public final void release() { }
}
}
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index e82567c..ef8d169 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -33,6 +33,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.service.media.MediaBrowserService;
import android.service.media.IMediaBrowserService;
import android.service.media.IMediaBrowserServiceCallbacks;
@@ -347,8 +348,8 @@
*/
public void unsubscribe(@NonNull String parentId) {
// Check arguments.
- if (parentId == null) {
- throw new IllegalArgumentException("parentId is null");
+ if (TextUtils.isEmpty(parentId)) {
+ throw new IllegalArgumentException("parentId is empty.");
}
// Remove from our list.
@@ -367,6 +368,60 @@
}
/**
+ * Retrieves a specific {@link MediaItem} from the connected service. Not
+ * all services may support this, so falling back to subscribing to the
+ * parent's id should be used when unavailable.
+ *
+ * @param mediaId The id of the item to retrieve.
+ * @param cb The callback to receive the result on.
+ */
+ public void getMediaItem(@NonNull String mediaId, @NonNull final MediaItemCallback cb) {
+ if (TextUtils.isEmpty(mediaId)) {
+ throw new IllegalArgumentException("mediaId is empty.");
+ }
+ if (cb == null) {
+ throw new IllegalArgumentException("cb is null.");
+ }
+ if (mState != CONNECT_STATE_CONNECTED) {
+ Log.i(TAG, "Not connected, unable to retrieve the MediaItem.");
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ cb.onError();
+ }
+ });
+ return;
+ }
+ ResultReceiver receiver = new ResultReceiver(mHandler) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode != 0 || resultData == null
+ || !resultData.containsKey(MediaBrowserService.KEY_MEDIA_ITEM)) {
+ cb.onError();
+ return;
+ }
+ Parcelable item = resultData.getParcelable(MediaBrowserService.KEY_MEDIA_ITEM);
+ if (!(item instanceof MediaItem)) {
+ cb.onError();
+ }
+ cb.onMediaItemLoaded((MediaItem) resultData.getParcelable(
+ MediaBrowserService.KEY_MEDIA_ITEM));
+ }
+ };
+ try {
+ mServiceBinder.getMediaItem(mediaId, receiver);
+ } catch (RemoteException e) {
+ Log.i(TAG, "Remote error getting media item.");
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ cb.onError();
+ }
+ });
+ }
+ }
+
+ /**
* For debugging.
*/
private static String getStateLabel(int state) {
@@ -690,6 +745,27 @@
}
/**
+ * Callback for receiving the result of {@link #getMediaItem}.
+ */
+ public static abstract class MediaItemCallback {
+
+ /**
+ * Called when the item has been returned by the browser service.
+ *
+ * @param item The item that was returned or null if it doesn't exist.
+ */
+ public void onMediaItemLoaded(MediaItem item) {
+ }
+
+ /**
+ * Called when the id doesn't exist or there was an error retrieving the
+ * item.
+ */
+ public void onError() {
+ }
+ }
+
+ /**
* ServiceConnection to the other app.
*/
private class MediaServiceConnection implements ServiceConnection {
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 8c478ed..f29be0d 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -310,7 +310,9 @@
public void run() {
try {
if (DEBUG) Log.d(TAG, "notifySessionEvent(" + eventType + ")");
- mSessionCallback.onSessionEvent(eventType, eventArgs);
+ if (mSessionCallback != null) {
+ mSessionCallback.onSessionEvent(eventType, eventArgs);
+ }
} catch (RemoteException e) {
Log.w(TAG, "error in sending event (event=" + eventType + ")");
}
@@ -329,7 +331,9 @@
public void run() {
try {
if (DEBUG) Log.d(TAG, "notifyChannelRetuned");
- mSessionCallback.onChannelRetuned(channelUri);
+ if (mSessionCallback != null) {
+ mSessionCallback.onChannelRetuned(channelUri);
+ }
} catch (RemoteException e) {
Log.w(TAG, "error in notifyChannelRetuned");
}
@@ -366,7 +370,9 @@
public void run() {
try {
if (DEBUG) Log.d(TAG, "notifyTracksChanged");
- mSessionCallback.onTracksChanged(tracks);
+ if (mSessionCallback != null) {
+ mSessionCallback.onTracksChanged(tracks);
+ }
} catch (RemoteException e) {
Log.w(TAG, "error in notifyTracksChanged");
}
@@ -394,7 +400,9 @@
public void run() {
try {
if (DEBUG) Log.d(TAG, "notifyTrackSelected");
- mSessionCallback.onTrackSelected(type, trackId);
+ if (mSessionCallback != null) {
+ mSessionCallback.onTrackSelected(type, trackId);
+ }
} catch (RemoteException e) {
Log.w(TAG, "error in notifyTrackSelected");
}
@@ -415,7 +423,9 @@
public void run() {
try {
if (DEBUG) Log.d(TAG, "notifyVideoAvailable");
- mSessionCallback.onVideoAvailable();
+ if (mSessionCallback != null) {
+ mSessionCallback.onVideoAvailable();
+ }
} catch (RemoteException e) {
Log.w(TAG, "error in notifyVideoAvailable");
}
@@ -447,7 +457,9 @@
public void run() {
try {
if (DEBUG) Log.d(TAG, "notifyVideoUnavailable");
- mSessionCallback.onVideoUnavailable(reason);
+ if (mSessionCallback != null) {
+ mSessionCallback.onVideoUnavailable(reason);
+ }
} catch (RemoteException e) {
Log.w(TAG, "error in notifyVideoUnavailable");
}
@@ -486,7 +498,9 @@
public void run() {
try {
if (DEBUG) Log.d(TAG, "notifyContentAllowed");
- mSessionCallback.onContentAllowed();
+ if (mSessionCallback != null) {
+ mSessionCallback.onContentAllowed();
+ }
} catch (RemoteException e) {
Log.w(TAG, "error in notifyContentAllowed");
}
@@ -526,7 +540,9 @@
public void run() {
try {
if (DEBUG) Log.d(TAG, "notifyContentBlocked");
- mSessionCallback.onContentBlocked(rating.flattenToString());
+ if (mSessionCallback != null) {
+ mSessionCallback.onContentBlocked(rating.flattenToString());
+ }
} catch (RemoteException e) {
Log.w(TAG, "error in notifyContentBlocked");
}
@@ -557,7 +573,9 @@
try {
if (DEBUG) Log.d(TAG, "layoutSurface (l=" + left + ", t=" + top + ", r="
+ right + ", b=" + bottom + ",)");
- mSessionCallback.onLayoutSurface(left, top, right, bottom);
+ if (mSessionCallback != null) {
+ mSessionCallback.onLayoutSurface(left, top, right, bottom);
+ }
} catch (RemoteException e) {
Log.w(TAG, "error in layoutSurface");
}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 13cdc69..5d9355a 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -88,6 +88,10 @@
Files.FileColumns._ID, // 0
Files.FileColumns.DATA, // 1
};
+ private static final String[] FORMAT_PROJECTION = new String[] {
+ Files.FileColumns._ID, // 0
+ Files.FileColumns.FORMAT, // 1
+ };
private static final String[] PATH_FORMAT_PROJECTION = new String[] {
Files.FileColumns._ID, // 0
Files.FileColumns.DATA, // 1
@@ -597,6 +601,7 @@
MtpConstants.PROPERTY_PARENT_OBJECT,
MtpConstants.PROPERTY_PERSISTENT_UID,
MtpConstants.PROPERTY_NAME,
+ MtpConstants.PROPERTY_DISPLAY_NAME,
MtpConstants.PROPERTY_DATE_ADDED,
};
@@ -669,43 +674,6 @@
MtpConstants.PROPERTY_DESCRIPTION,
};
- static final int[] ALL_PROPERTIES = {
- // NOTE must match FILE_PROPERTIES above
- MtpConstants.PROPERTY_STORAGE_ID,
- MtpConstants.PROPERTY_OBJECT_FORMAT,
- MtpConstants.PROPERTY_PROTECTION_STATUS,
- MtpConstants.PROPERTY_OBJECT_SIZE,
- MtpConstants.PROPERTY_OBJECT_FILE_NAME,
- MtpConstants.PROPERTY_DATE_MODIFIED,
- MtpConstants.PROPERTY_PARENT_OBJECT,
- MtpConstants.PROPERTY_PERSISTENT_UID,
- MtpConstants.PROPERTY_NAME,
- MtpConstants.PROPERTY_DISPLAY_NAME,
- MtpConstants.PROPERTY_DATE_ADDED,
-
- // image specific properties
- MtpConstants.PROPERTY_DESCRIPTION,
-
- // audio specific properties
- MtpConstants.PROPERTY_ARTIST,
- MtpConstants.PROPERTY_ALBUM_NAME,
- MtpConstants.PROPERTY_ALBUM_ARTIST,
- MtpConstants.PROPERTY_TRACK,
- MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
- MtpConstants.PROPERTY_DURATION,
- MtpConstants.PROPERTY_GENRE,
- MtpConstants.PROPERTY_COMPOSER,
-
- // video specific properties
- MtpConstants.PROPERTY_ARTIST,
- MtpConstants.PROPERTY_ALBUM_NAME,
- MtpConstants.PROPERTY_DURATION,
- MtpConstants.PROPERTY_DESCRIPTION,
-
- // image specific properties
- MtpConstants.PROPERTY_DESCRIPTION,
- };
-
private int[] getSupportedObjectProperties(int format) {
switch (format) {
case MtpConstants.FORMAT_MP3:
@@ -723,8 +691,6 @@
case MtpConstants.FORMAT_PNG:
case MtpConstants.FORMAT_BMP:
return IMAGE_PROPERTIES;
- case 0:
- return ALL_PROPERTIES;
default:
return FILE_PROPERTIES;
}
@@ -749,6 +715,10 @@
MtpPropertyGroup propertyGroup;
if (property == 0xFFFFFFFFL) {
+ if (format == 0 && handle > 0) {
+ // return properties based on the object's format
+ format = getObjectFormat((int)handle);
+ }
propertyGroup = mPropertyGroupsByFormat.get(format);
if (propertyGroup == null) {
int[] propertyList = getSupportedObjectProperties(format);
@@ -988,6 +958,26 @@
}
}
+ private int getObjectFormat(int handle) {
+ Cursor c = null;
+ try {
+ c = mMediaProvider.query(mPackageName, mObjectsUri, FORMAT_PROJECTION,
+ ID_WHERE, new String[] { Integer.toString(handle) }, null, null);
+ if (c != null && c.moveToNext()) {
+ return c.getInt(1);
+ } else {
+ return -1;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in getObjectFilePath", e);
+ return -1;
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ }
+
private int deleteFile(int handle) {
mDatabaseModified = true;
String path = null;
diff --git a/media/java/android/mtp/MtpPropertyGroup.java b/media/java/android/mtp/MtpPropertyGroup.java
index 781988d..c80adfa 100644
--- a/media/java/android/mtp/MtpPropertyGroup.java
+++ b/media/java/android/mtp/MtpPropertyGroup.java
@@ -172,6 +172,17 @@
column = Images.ImageColumns.DESCRIPTION;
type = MtpConstants.TYPE_STR;
break;
+ case MtpConstants.PROPERTY_AUDIO_WAVE_CODEC:
+ case MtpConstants.PROPERTY_AUDIO_BITRATE:
+ case MtpConstants.PROPERTY_SAMPLE_RATE:
+ // these are special cased
+ type = MtpConstants.TYPE_UINT32;
+ break;
+ case MtpConstants.PROPERTY_BITRATE_TYPE:
+ case MtpConstants.PROPERTY_NUMBER_OF_CHANNELS:
+ // these are special cased
+ type = MtpConstants.TYPE_UINT16;
+ break;
default:
type = MtpConstants.TYPE_UNDEFINED;
Log.e(TAG, "unsupported property " + code);
@@ -420,6 +431,17 @@
result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
}
break;
+ case MtpConstants.PROPERTY_AUDIO_WAVE_CODEC:
+ case MtpConstants.PROPERTY_AUDIO_BITRATE:
+ case MtpConstants.PROPERTY_SAMPLE_RATE:
+ // we don't have these in our database, so return 0
+ result.append(handle, propertyCode, MtpConstants.TYPE_UINT32, 0);
+ break;
+ case MtpConstants.PROPERTY_BITRATE_TYPE:
+ case MtpConstants.PROPERTY_NUMBER_OF_CHANNELS:
+ // we don't have these in our database, so return 0
+ result.append(handle, propertyCode, MtpConstants.TYPE_UINT16, 0);
+ break;
default:
if (property.type == MtpConstants.TYPE_STR) {
result.append(handle, propertyCode, c.getString(column));
diff --git a/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
index 01285ee..f01fc07 100644
--- a/media/java/android/service/media/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -6,6 +6,7 @@
import android.service.media.IMediaBrowserServiceCallbacks;
import android.net.Uri;
import android.os.Bundle;
+import android.os.ResultReceiver;
/**
* Media API allows clients to browse through hierarchy of a user’s media collection,
@@ -18,4 +19,5 @@
void addSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
void removeSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
+ void getMediaItem(String uri, in ResultReceiver cb);
}
\ No newline at end of file
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 47cb94b..8287344 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -32,8 +32,10 @@
import android.os.IBinder;
import android.os.Handler;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.service.media.IMediaBrowserService;
import android.service.media.IMediaBrowserServiceCallbacks;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -74,6 +76,13 @@
@SdkConstant(SdkConstantType.SERVICE_ACTION)
public static final String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
+ /**
+ * A key for passing the MediaItem to the ResultReceiver in getMediaItem.
+ *
+ * @hide
+ */
+ public static final String KEY_MEDIA_ITEM = "media_item";
+
private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap();
private final Handler mHandler = new Handler();
private ServiceBinder mBinder;
@@ -261,6 +270,33 @@
}
});
}
+
+ @Override
+ public void getMediaItem(final String mediaId, final ResultReceiver receiver) {
+ if (TextUtils.isEmpty(mediaId) || receiver == null) {
+ return;
+ }
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ final Result<MediaBrowser.MediaItem> result
+ = new Result<MediaBrowser.MediaItem>(mediaId) {
+ @Override
+ void onResultSent(MediaBrowser.MediaItem item) {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(KEY_MEDIA_ITEM, item);
+ receiver.send(0, bundle);
+ }
+ };
+ try {
+ MediaBrowserService.this.getMediaItem(mediaId, result);
+ } catch (UnsupportedOperationException e) {
+ receiver.send(-1, null);
+ }
+ }
+ });
+ }
}
@Override
@@ -284,20 +320,21 @@
/**
* Called to get the root information for browsing by a particular client.
* <p>
- * The implementation should verify that the client package has
- * permission to access browse media information before returning
- * the root id; it should return null if the client is not
- * allowed to access this information.
+ * The implementation should verify that the client package has permission
+ * to access browse media information before returning the root id; it
+ * should return null if the client is not allowed to access this
+ * information.
* </p>
*
- * @param clientPackageName The package name of the application
- * which is requesting access to browse media.
- * @param clientUid The uid of the application which is requesting
- * access to browse media.
+ * @param clientPackageName The package name of the application which is
+ * requesting access to browse media.
+ * @param clientUid The uid of the application which is requesting access to
+ * browse media.
* @param rootHints An optional bundle of service-specific arguments to send
- * to the media browse service when connecting and retrieving the root id
- * for browsing, or null if none. The contents of this bundle may affect
- * the information returned when browsing.
+ * to the media browse service when connecting and retrieving the
+ * root id for browsing, or null if none. The contents of this
+ * bundle may affect the information returned when browsing.
+ * @return The {@link BrowserRoot} for accessing this app's content or null.
*/
public abstract @Nullable BrowserRoot onGetRoot(@NonNull String clientPackageName,
int clientUid, @Nullable Bundle rootHints);
@@ -305,24 +342,51 @@
/**
* Called to get information about the children of a media item.
* <p>
- * Implementations must call result.{@link Result#sendResult result.sendResult} with the list
- * of children. If loading the children will be an expensive operation that should be performed
- * on another thread, result.{@link Result#detach result.detach} may be called before returning
- * from this function, and then {@link Result#sendResult result.sendResult} called when
- * the loading is complete.
+ * Implementations must call {@link Result#sendResult result.sendResult}
+ * with the list of children. If loading the children will be an expensive
+ * operation that should be performed on another thread,
+ * {@link Result#detach result.detach} may be called before returning from
+ * this function, and then {@link Result#sendResult result.sendResult}
+ * called when the loading is complete.
*
- * @param parentId The id of the parent media item whose
- * children are to be queried.
- * @return The list of children, or null if the id is invalid.
+ * @param parentId The id of the parent media item whose children are to be
+ * queried.
+ * @param result The Result to send the list of children to, or null if the
+ * id is invalid.
*/
public abstract void onLoadChildren(@NonNull String parentId,
@NonNull Result<List<MediaBrowser.MediaItem>> result);
/**
+ * Called to get a specific media item. The mediaId should be the same id
+ * that would be returned for this item when it is in a list of child items.
+ * <p>
+ * Implementations must call {@link Result#sendResult result.sendResult}. If
+ * loading the item will be an expensive operation {@link Result#detach
+ * result.detach} may be called before returning from this function, and
+ * then {@link Result#sendResult result.sendResult} called when the item has
+ * been loaded.
+ * <p>
+ * The default implementation throws an exception.
+ *
+ * @param mediaId The id for the specific
+ * {@link android.media.browse.MediaBrowser.MediaItem}.
+ * @param result The Result to send the item to, or null if the id is
+ * invalid.
+ * @throws UnsupportedOperationException
+ */
+ public void getMediaItem(String mediaId, Result<MediaBrowser.MediaItem> result)
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("getMediaItem is not supported.");
+ }
+
+ /**
* Call to set the media session.
* <p>
* This should be called as soon as possible during the service's startup.
* It may only be called once.
+ *
+ * @param token The token for the service's {@link MediaSession}.
*/
public void setSessionToken(final MediaSession.Token token) {
if (token == null) {
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 7e68c78..5406130 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -351,7 +351,7 @@
int bytesPerPixel = 0;
dataSize = ySize = cSize = cStride = 0;
- int32_t fmt = buffer->format;
+ int32_t fmt = buffer->flexFormat;
bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, readerFormat);
fmt = applyFormatOverrides(fmt, readerFormat);
@@ -363,18 +363,21 @@
(idx == 1) ?
buffer->dataCb :
buffer->dataCr;
+ // only map until last pixel
if (idx == 0) {
- dataSize = buffer->stride * buffer->height;
+ dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
} else {
- dataSize = buffer->chromaStride * buffer->height / 2;
+ dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
+ buffer->chromaStep * (buffer->width / 2 - 1) + 1;
}
break;
// NV21
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
cr = buffer->data + (buffer->stride * buffer->height);
cb = cr + 1;
- ySize = buffer->width * buffer->height;
- cSize = buffer->width * buffer->height / 2;
+ // only map until last pixel
+ ySize = buffer->width * (buffer->height - 1) + buffer->width;
+ cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
pData =
(idx == 0) ?
@@ -488,7 +491,7 @@
int pixelStride = 0;
ALOG_ASSERT(buffer != NULL, "buffer is NULL");
- int32_t fmt = buffer->format;
+ int32_t fmt = buffer->flexFormat;
fmt = applyFormatOverrides(fmt, readerFormat);
@@ -548,7 +551,7 @@
int rowStride = 0;
ALOG_ASSERT(buffer != NULL, "buffer is NULL");
- int32_t fmt = buffer->format;
+ int32_t fmt = buffer->flexFormat;
fmt = applyFormatOverrides(fmt, readerFormat);
@@ -796,7 +799,7 @@
return ACQUIRE_NO_BUFFERS;
}
- if (buffer->format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+ if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
jniThrowException(env, "java/lang/UnsupportedOperationException",
"NV21 format is not supported by ImageReader");
return -1;
@@ -825,8 +828,10 @@
}
int bufFmt = buffer->format;
+ if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ bufFmt = buffer->flexFormat;
+ }
if (imgReaderFmt != bufFmt) {
-
if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt ==
HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) {
// Special casing for when producer switches to a format compatible with flexible YUV
@@ -848,7 +853,7 @@
String8 msg;
msg.appendFormat("The producer output buffer format 0x%x doesn't "
"match the ImageReader's configured buffer format 0x%x.",
- buffer->format, ctx->getBufferFormat());
+ bufFmt, ctx->getBufferFormat());
jniThrowException(env, "java/lang/UnsupportedOperationException",
msg.string());
return -1;
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 803ab05..713f28c 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -934,6 +934,11 @@
{ MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
{ MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
{ MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
+ { MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_TYPE_UINT32 },
+ { MTP_PROPERTY_BITRATE_TYPE, MTP_TYPE_UINT16 },
+ { MTP_PROPERTY_AUDIO_BITRATE, MTP_TYPE_UINT32 },
+ { MTP_PROPERTY_NUMBER_OF_CHANNELS,MTP_TYPE_UINT16 },
+ { MTP_PROPERTY_SAMPLE_RATE, MTP_TYPE_UINT32 },
};
static const PropertyTableEntry kDevicePropertyTable[] = {
diff --git a/media/jni/soundpool/Android.mk b/media/jni/soundpool/Android.mk
index 3382512..71ab013 100644
--- a/media/jni/soundpool/Android.mk
+++ b/media/jni/soundpool/Android.mk
@@ -2,7 +2,9 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- android_media_SoundPool_SoundPoolImpl.cpp
+ android_media_SoundPool_SoundPoolImpl.cpp \
+ SoundPool.cpp \
+ SoundPoolThread.cpp
LOCAL_SHARED_LIBRARIES := \
liblog \
@@ -10,7 +12,9 @@
libutils \
libandroid_runtime \
libnativehelper \
- libmedia
+ libmedia \
+ libmediandk \
+ libbinder
LOCAL_MODULE:= libsoundpool
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
new file mode 100644
index 0000000..a8b91d2
--- /dev/null
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -0,0 +1,1018 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPool"
+
+#include <inttypes.h>
+
+#include <utils/Log.h>
+
+#define USE_SHARED_MEM_BUFFER
+
+#include <media/AudioTrack.h>
+#include <media/IMediaHTTPService.h>
+#include <media/mediaplayer.h>
+#include <media/stagefright/MediaExtractor.h>
+#include "SoundPool.h"
+#include "SoundPoolThread.h"
+#include <media/AudioPolicyHelper.h>
+#include <ndk/NdkMediaCodec.h>
+#include <ndk/NdkMediaExtractor.h>
+#include <ndk/NdkMediaFormat.h>
+
+namespace android
+{
+
+int kDefaultBufferCount = 4;
+uint32_t kMaxSampleRate = 48000;
+uint32_t kDefaultSampleRate = 44100;
+uint32_t kDefaultFrameCount = 1200;
+size_t kDefaultHeapSize = 1024 * 1024; // 1MB
+
+
+SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes)
+{
+ ALOGV("SoundPool constructor: maxChannels=%d, attr.usage=%d, attr.flags=0x%x, attr.tags=%s",
+ maxChannels, pAttributes->usage, pAttributes->flags, pAttributes->tags);
+
+ // check limits
+ mMaxChannels = maxChannels;
+ if (mMaxChannels < 1) {
+ mMaxChannels = 1;
+ }
+ else if (mMaxChannels > 32) {
+ mMaxChannels = 32;
+ }
+ ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels);
+
+ mQuit = false;
+ mDecodeThread = 0;
+ memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
+ mAllocated = 0;
+ mNextSampleID = 0;
+ mNextChannelID = 0;
+
+ mCallback = 0;
+ mUserData = 0;
+
+ mChannelPool = new SoundChannel[mMaxChannels];
+ for (int i = 0; i < mMaxChannels; ++i) {
+ mChannelPool[i].init(this);
+ mChannels.push_back(&mChannelPool[i]);
+ }
+
+ // start decode thread
+ startThreads();
+}
+
+SoundPool::~SoundPool()
+{
+ ALOGV("SoundPool destructor");
+ mDecodeThread->quit();
+ quit();
+
+ Mutex::Autolock lock(&mLock);
+
+ mChannels.clear();
+ if (mChannelPool)
+ delete [] mChannelPool;
+ // clean up samples
+ ALOGV("clear samples");
+ mSamples.clear();
+
+ if (mDecodeThread)
+ delete mDecodeThread;
+}
+
+void SoundPool::addToRestartList(SoundChannel* channel)
+{
+ Mutex::Autolock lock(&mRestartLock);
+ if (!mQuit) {
+ mRestart.push_back(channel);
+ mCondition.signal();
+ }
+}
+
+void SoundPool::addToStopList(SoundChannel* channel)
+{
+ Mutex::Autolock lock(&mRestartLock);
+ if (!mQuit) {
+ mStop.push_back(channel);
+ mCondition.signal();
+ }
+}
+
+int SoundPool::beginThread(void* arg)
+{
+ SoundPool* p = (SoundPool*)arg;
+ return p->run();
+}
+
+int SoundPool::run()
+{
+ mRestartLock.lock();
+ while (!mQuit) {
+ mCondition.wait(mRestartLock);
+ ALOGV("awake");
+ if (mQuit) break;
+
+ while (!mStop.empty()) {
+ SoundChannel* channel;
+ ALOGV("Getting channel from stop list");
+ List<SoundChannel* >::iterator iter = mStop.begin();
+ channel = *iter;
+ mStop.erase(iter);
+ mRestartLock.unlock();
+ if (channel != 0) {
+ Mutex::Autolock lock(&mLock);
+ channel->stop();
+ }
+ mRestartLock.lock();
+ if (mQuit) break;
+ }
+
+ while (!mRestart.empty()) {
+ SoundChannel* channel;
+ ALOGV("Getting channel from list");
+ List<SoundChannel*>::iterator iter = mRestart.begin();
+ channel = *iter;
+ mRestart.erase(iter);
+ mRestartLock.unlock();
+ if (channel != 0) {
+ Mutex::Autolock lock(&mLock);
+ channel->nextEvent();
+ }
+ mRestartLock.lock();
+ if (mQuit) break;
+ }
+ }
+
+ mStop.clear();
+ mRestart.clear();
+ mCondition.signal();
+ mRestartLock.unlock();
+ ALOGV("goodbye");
+ return 0;
+}
+
+void SoundPool::quit()
+{
+ mRestartLock.lock();
+ mQuit = true;
+ mCondition.signal();
+ mCondition.wait(mRestartLock);
+ ALOGV("return from quit");
+ mRestartLock.unlock();
+}
+
+bool SoundPool::startThreads()
+{
+ createThreadEtc(beginThread, this, "SoundPool");
+ if (mDecodeThread == NULL)
+ mDecodeThread = new SoundPoolThread(this);
+ return mDecodeThread != NULL;
+}
+
+SoundChannel* SoundPool::findChannel(int channelID)
+{
+ for (int i = 0; i < mMaxChannels; ++i) {
+ if (mChannelPool[i].channelID() == channelID) {
+ return &mChannelPool[i];
+ }
+ }
+ return NULL;
+}
+
+SoundChannel* SoundPool::findNextChannel(int channelID)
+{
+ for (int i = 0; i < mMaxChannels; ++i) {
+ if (mChannelPool[i].nextChannelID() == channelID) {
+ return &mChannelPool[i];
+ }
+ }
+ return NULL;
+}
+
+int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused)
+{
+ ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d",
+ fd, offset, length, priority);
+ Mutex::Autolock lock(&mLock);
+ sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length);
+ mSamples.add(sample->sampleID(), sample);
+ doLoad(sample);
+ return sample->sampleID();
+}
+
+void SoundPool::doLoad(sp<Sample>& sample)
+{
+ ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID());
+ sample->startLoad();
+ mDecodeThread->loadSample(sample->sampleID());
+}
+
+bool SoundPool::unload(int sampleID)
+{
+ ALOGV("unload: sampleID=%d", sampleID);
+ Mutex::Autolock lock(&mLock);
+ return mSamples.removeItem(sampleID);
+}
+
+int SoundPool::play(int sampleID, float leftVolume, float rightVolume,
+ int priority, int loop, float rate)
+{
+ ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
+ sampleID, leftVolume, rightVolume, priority, loop, rate);
+ sp<Sample> sample;
+ SoundChannel* channel;
+ int channelID;
+
+ Mutex::Autolock lock(&mLock);
+
+ if (mQuit) {
+ return 0;
+ }
+ // is sample ready?
+ sample = findSample(sampleID);
+ if ((sample == 0) || (sample->state() != Sample::READY)) {
+ ALOGW(" sample %d not READY", sampleID);
+ return 0;
+ }
+
+ dump();
+
+ // allocate a channel
+ channel = allocateChannel_l(priority);
+
+ // no channel allocated - return 0
+ if (!channel) {
+ ALOGV("No channel allocated");
+ return 0;
+ }
+
+ channelID = ++mNextChannelID;
+
+ ALOGV("play channel %p state = %d", channel, channel->state());
+ channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
+ return channelID;
+}
+
+SoundChannel* SoundPool::allocateChannel_l(int priority)
+{
+ List<SoundChannel*>::iterator iter;
+ SoundChannel* channel = NULL;
+
+ // allocate a channel
+ if (!mChannels.empty()) {
+ iter = mChannels.begin();
+ if (priority >= (*iter)->priority()) {
+ channel = *iter;
+ mChannels.erase(iter);
+ ALOGV("Allocated active channel");
+ }
+ }
+
+ // update priority and put it back in the list
+ if (channel) {
+ channel->setPriority(priority);
+ for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
+ if (priority < (*iter)->priority()) {
+ break;
+ }
+ }
+ mChannels.insert(iter, channel);
+ }
+ return channel;
+}
+
+// move a channel from its current position to the front of the list
+void SoundPool::moveToFront_l(SoundChannel* channel)
+{
+ for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
+ if (*iter == channel) {
+ mChannels.erase(iter);
+ mChannels.push_front(channel);
+ break;
+ }
+ }
+}
+
+void SoundPool::pause(int channelID)
+{
+ ALOGV("pause(%d)", channelID);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->pause();
+ }
+}
+
+void SoundPool::autoPause()
+{
+ ALOGV("autoPause()");
+ Mutex::Autolock lock(&mLock);
+ for (int i = 0; i < mMaxChannels; ++i) {
+ SoundChannel* channel = &mChannelPool[i];
+ channel->autoPause();
+ }
+}
+
+void SoundPool::resume(int channelID)
+{
+ ALOGV("resume(%d)", channelID);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->resume();
+ }
+}
+
+void SoundPool::autoResume()
+{
+ ALOGV("autoResume()");
+ Mutex::Autolock lock(&mLock);
+ for (int i = 0; i < mMaxChannels; ++i) {
+ SoundChannel* channel = &mChannelPool[i];
+ channel->autoResume();
+ }
+}
+
+void SoundPool::stop(int channelID)
+{
+ ALOGV("stop(%d)", channelID);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->stop();
+ } else {
+ channel = findNextChannel(channelID);
+ if (channel)
+ channel->clearNextEvent();
+ }
+}
+
+void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume)
+{
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->setVolume(leftVolume, rightVolume);
+ }
+}
+
+void SoundPool::setPriority(int channelID, int priority)
+{
+ ALOGV("setPriority(%d, %d)", channelID, priority);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->setPriority(priority);
+ }
+}
+
+void SoundPool::setLoop(int channelID, int loop)
+{
+ ALOGV("setLoop(%d, %d)", channelID, loop);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->setLoop(loop);
+ }
+}
+
+void SoundPool::setRate(int channelID, float rate)
+{
+ ALOGV("setRate(%d, %f)", channelID, rate);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->setRate(rate);
+ }
+}
+
+// call with lock held
+void SoundPool::done_l(SoundChannel* channel)
+{
+ ALOGV("done_l(%d)", channel->channelID());
+ // if "stolen", play next event
+ if (channel->nextChannelID() != 0) {
+ ALOGV("add to restart list");
+ addToRestartList(channel);
+ }
+
+ // return to idle state
+ else {
+ ALOGV("move to front");
+ moveToFront_l(channel);
+ }
+}
+
+void SoundPool::setCallback(SoundPoolCallback* callback, void* user)
+{
+ Mutex::Autolock lock(&mCallbackLock);
+ mCallback = callback;
+ mUserData = user;
+}
+
+void SoundPool::notify(SoundPoolEvent event)
+{
+ Mutex::Autolock lock(&mCallbackLock);
+ if (mCallback != NULL) {
+ mCallback(event, this, mUserData);
+ }
+}
+
+void SoundPool::dump()
+{
+ for (int i = 0; i < mMaxChannels; ++i) {
+ mChannelPool[i].dump();
+ }
+}
+
+
+Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length)
+{
+ init();
+ mSampleID = sampleID;
+ mFd = dup(fd);
+ mOffset = offset;
+ mLength = length;
+ ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64,
+ mSampleID, mFd, mLength, mOffset);
+}
+
+void Sample::init()
+{
+ mSize = 0;
+ mRefCount = 0;
+ mSampleID = 0;
+ mState = UNLOADED;
+ mFd = -1;
+ mOffset = 0;
+ mLength = 0;
+}
+
+Sample::~Sample()
+{
+ ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd);
+ if (mFd > 0) {
+ ALOGV("close(%d)", mFd);
+ ::close(mFd);
+ }
+}
+
+static status_t decode(int fd, int64_t offset, int64_t length,
+ uint32_t *rate, int *numChannels, audio_format_t *audioFormat,
+ sp<MemoryHeapBase> heap, size_t *memsize) {
+
+ ALOGV("fd %d, offset %" PRId64 ", size %" PRId64, fd, offset, length);
+ AMediaExtractor *ex = AMediaExtractor_new();
+ status_t err = AMediaExtractor_setDataSourceFd(ex, fd, offset, length);
+
+ if (err != AMEDIA_OK) {
+ return err;
+ }
+
+ *audioFormat = AUDIO_FORMAT_PCM_16_BIT;
+
+ size_t numTracks = AMediaExtractor_getTrackCount(ex);
+ for (size_t i = 0; i < numTracks; i++) {
+ AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
+ const char *mime;
+ if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
+ AMediaExtractor_delete(ex);
+ AMediaFormat_delete(format);
+ return UNKNOWN_ERROR;
+ }
+ if (strncmp(mime, "audio/", 6) == 0) {
+
+ AMediaCodec *codec = AMediaCodec_createDecoderByType(mime);
+ if (AMediaCodec_configure(codec, format,
+ NULL /* window */, NULL /* drm */, 0 /* flags */) != AMEDIA_OK
+ || AMediaCodec_start(codec) != AMEDIA_OK
+ || AMediaExtractor_selectTrack(ex, i) != AMEDIA_OK) {
+ AMediaExtractor_delete(ex);
+ AMediaCodec_delete(codec);
+ AMediaFormat_delete(format);
+ return UNKNOWN_ERROR;
+ }
+
+ bool sawInputEOS = false;
+ bool sawOutputEOS = false;
+ uint8_t* writePos = static_cast<uint8_t*>(heap->getBase());
+ size_t available = heap->getSize();
+ size_t written = 0;
+
+ AMediaFormat_delete(format);
+ format = AMediaCodec_getOutputFormat(codec);
+
+ while (!sawOutputEOS) {
+ if (!sawInputEOS) {
+ ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, 5000);
+ ALOGV("input buffer %zd", bufidx);
+ if (bufidx >= 0) {
+ size_t bufsize;
+ uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize);
+ int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize);
+ ALOGV("read %d", sampleSize);
+ if (sampleSize < 0) {
+ sampleSize = 0;
+ sawInputEOS = true;
+ ALOGV("EOS");
+ }
+ int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);
+
+ AMediaCodec_queueInputBuffer(codec, bufidx,
+ 0 /* offset */, sampleSize, presentationTimeUs,
+ sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
+ AMediaExtractor_advance(ex);
+ }
+ }
+
+ AMediaCodecBufferInfo info;
+ int status = AMediaCodec_dequeueOutputBuffer(codec, &info, 1);
+ ALOGV("dequeueoutput returned: %d", status);
+ if (status >= 0) {
+ if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
+ ALOGV("output EOS");
+ sawOutputEOS = true;
+ }
+ ALOGV("got decoded buffer size %d", info.size);
+
+ uint8_t *buf = AMediaCodec_getOutputBuffer(codec, status, NULL /* out_size */);
+ size_t dataSize = info.size;
+ if (dataSize > available) {
+ dataSize = available;
+ }
+ memcpy(writePos, buf + info.offset, dataSize);
+ writePos += dataSize;
+ written += dataSize;
+ available -= dataSize;
+ AMediaCodec_releaseOutputBuffer(codec, status, false /* render */);
+ if (available == 0) {
+ // there might be more data, but there's no space for it
+ sawOutputEOS = true;
+ }
+ } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
+ ALOGV("output buffers changed");
+ } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
+ AMediaFormat_delete(format);
+ format = AMediaCodec_getOutputFormat(codec);
+ ALOGV("format changed to: %s", AMediaFormat_toString(format));
+ } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
+ ALOGV("no output buffer right now");
+ } else {
+ ALOGV("unexpected info code: %d", status);
+ }
+ }
+
+ AMediaCodec_stop(codec);
+ AMediaCodec_delete(codec);
+ AMediaExtractor_delete(ex);
+ if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, (int32_t*) rate) ||
+ !AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, numChannels)) {
+ AMediaFormat_delete(format);
+ return UNKNOWN_ERROR;
+ }
+ AMediaFormat_delete(format);
+ *memsize = written;
+ return OK;
+ }
+ AMediaFormat_delete(format);
+ }
+ AMediaExtractor_delete(ex);
+ return UNKNOWN_ERROR;
+}
+
+status_t Sample::doLoad()
+{
+ uint32_t sampleRate;
+ int numChannels;
+ audio_format_t format;
+ status_t status;
+ mHeap = new MemoryHeapBase(kDefaultHeapSize);
+
+ ALOGV("Start decode");
+ status = decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format,
+ mHeap, &mSize);
+ ALOGV("close(%d)", mFd);
+ ::close(mFd);
+ mFd = -1;
+ if (status != NO_ERROR) {
+ ALOGE("Unable to load sample");
+ goto error;
+ }
+ ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d",
+ mHeap->getBase(), mSize, sampleRate, numChannels);
+
+ if (sampleRate > kMaxSampleRate) {
+ ALOGE("Sample rate (%u) out of range", sampleRate);
+ status = BAD_VALUE;
+ goto error;
+ }
+
+ if ((numChannels < 1) || (numChannels > 2)) {
+ ALOGE("Sample channel count (%d) out of range", numChannels);
+ status = BAD_VALUE;
+ goto error;
+ }
+
+ mData = new MemoryBase(mHeap, 0, mSize);
+ mSampleRate = sampleRate;
+ mNumChannels = numChannels;
+ mFormat = format;
+ mState = READY;
+ return NO_ERROR;
+
+error:
+ mHeap.clear();
+ return status;
+}
+
+
+void SoundChannel::init(SoundPool* soundPool)
+{
+ mSoundPool = soundPool;
+}
+
+// call with sound pool lock held
+void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
+ float rightVolume, int priority, int loop, float rate)
+{
+ sp<AudioTrack> oldTrack;
+ sp<AudioTrack> newTrack;
+ status_t status;
+
+ { // scope for the lock
+ Mutex::Autolock lock(&mLock);
+
+ ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f,"
+ " priority=%d, loop=%d, rate=%f",
+ this, sample->sampleID(), nextChannelID, leftVolume, rightVolume,
+ priority, loop, rate);
+
+ // if not idle, this voice is being stolen
+ if (mState != IDLE) {
+ ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
+ mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+ stop_l();
+ return;
+ }
+
+ // initialize track
+ size_t afFrameCount;
+ uint32_t afSampleRate;
+ audio_stream_type_t streamType = audio_attributes_to_stream_type(mSoundPool->attributes());
+ if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
+ afFrameCount = kDefaultFrameCount;
+ }
+ if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+ afSampleRate = kDefaultSampleRate;
+ }
+ int numChannels = sample->numChannels();
+ uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
+ size_t frameCount = 0;
+
+ if (loop) {
+ frameCount = sample->size()/numChannels/
+ ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
+ }
+
+#ifndef USE_SHARED_MEM_BUFFER
+ uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
+ // Ensure minimum audio buffer size in case of short looped sample
+ if(frameCount < totalFrames) {
+ frameCount = totalFrames;
+ }
+#endif
+
+ // mToggle toggles each time a track is started on a given channel.
+ // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
+ // as callback user data. This enables the detection of callbacks received from the old
+ // audio track while the new one is being started and avoids processing them with
+ // wrong audio audio buffer size (mAudioBufferSize)
+ unsigned long toggle = mToggle ^ 1;
+ void *userData = (void *)((unsigned long)this | toggle);
+ audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels);
+
+ // do not create a new audio track if current track is compatible with sample parameters
+#ifdef USE_SHARED_MEM_BUFFER
+ newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+ channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData);
+#else
+ uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
+ newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+ channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
+ bufferFrames);
+#endif
+ oldTrack = mAudioTrack;
+ status = newTrack->initCheck();
+ if (status != NO_ERROR) {
+ ALOGE("Error creating AudioTrack");
+ goto exit;
+ }
+ ALOGV("setVolume %p", newTrack.get());
+ newTrack->setVolume(leftVolume, rightVolume);
+ newTrack->setLoop(0, frameCount, loop);
+
+ // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
+ mToggle = toggle;
+ mAudioTrack = newTrack;
+ mPos = 0;
+ mSample = sample;
+ mChannelID = nextChannelID;
+ mPriority = priority;
+ mLoop = loop;
+ mLeftVolume = leftVolume;
+ mRightVolume = rightVolume;
+ mNumChannels = numChannels;
+ mRate = rate;
+ clearNextEvent();
+ mState = PLAYING;
+ mAudioTrack->start();
+ mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
+ }
+
+exit:
+ ALOGV("delete oldTrack %p", oldTrack.get());
+ if (status != NO_ERROR) {
+ mAudioTrack.clear();
+ }
+}
+
+void SoundChannel::nextEvent()
+{
+ sp<Sample> sample;
+ int nextChannelID;
+ float leftVolume;
+ float rightVolume;
+ int priority;
+ int loop;
+ float rate;
+
+ // check for valid event
+ {
+ Mutex::Autolock lock(&mLock);
+ nextChannelID = mNextEvent.channelID();
+ if (nextChannelID == 0) {
+ ALOGV("stolen channel has no event");
+ return;
+ }
+
+ sample = mNextEvent.sample();
+ leftVolume = mNextEvent.leftVolume();
+ rightVolume = mNextEvent.rightVolume();
+ priority = mNextEvent.priority();
+ loop = mNextEvent.loop();
+ rate = mNextEvent.rate();
+ }
+
+ ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID);
+ play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+}
+
+void SoundChannel::callback(int event, void* user, void *info)
+{
+ SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1));
+
+ channel->process(event, info, (unsigned long)user & 1);
+}
+
+void SoundChannel::process(int event, void *info, unsigned long toggle)
+{
+ //ALOGV("process(%d)", mChannelID);
+
+ Mutex::Autolock lock(&mLock);
+
+ AudioTrack::Buffer* b = NULL;
+ if (event == AudioTrack::EVENT_MORE_DATA) {
+ b = static_cast<AudioTrack::Buffer *>(info);
+ }
+
+ if (mToggle != toggle) {
+ ALOGV("process wrong toggle %p channel %d", this, mChannelID);
+ if (b != NULL) {
+ b->size = 0;
+ }
+ return;
+ }
+
+ sp<Sample> sample = mSample;
+
+// ALOGV("SoundChannel::process event %d", event);
+
+ if (event == AudioTrack::EVENT_MORE_DATA) {
+
+ // check for stop state
+ if (b->size == 0) return;
+
+ if (mState == IDLE) {
+ b->size = 0;
+ return;
+ }
+
+ if (sample != 0) {
+ // fill buffer
+ uint8_t* q = (uint8_t*) b->i8;
+ size_t count = 0;
+
+ if (mPos < (int)sample->size()) {
+ uint8_t* p = sample->data() + mPos;
+ count = sample->size() - mPos;
+ if (count > b->size) {
+ count = b->size;
+ }
+ memcpy(q, p, count);
+// ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size,
+// count);
+ } else if (mPos < mAudioBufferSize) {
+ count = mAudioBufferSize - mPos;
+ if (count > b->size) {
+ count = b->size;
+ }
+ memset(q, 0, count);
+// ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count);
+ }
+
+ mPos += count;
+ b->size = count;
+ //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]);
+ }
+ } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) {
+ ALOGV("process %p channel %d event %s",
+ this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" :
+ "BUFFER_END");
+ mSoundPool->addToStopList(this);
+ } else if (event == AudioTrack::EVENT_LOOP_END) {
+ ALOGV("End loop %p channel %d", this, mChannelID);
+ } else if (event == AudioTrack::EVENT_NEW_IAUDIOTRACK) {
+ ALOGV("process %p channel %d NEW_IAUDIOTRACK", this, mChannelID);
+ } else {
+ ALOGW("SoundChannel::process unexpected event %d", event);
+ }
+}
+
+
+// call with lock held
+bool SoundChannel::doStop_l()
+{
+ if (mState != IDLE) {
+ setVolume_l(0, 0);
+ ALOGV("stop");
+ mAudioTrack->stop();
+ mSample.clear();
+ mState = IDLE;
+ mPriority = IDLE_PRIORITY;
+ return true;
+ }
+ return false;
+}
+
+// call with lock held and sound pool lock held
+void SoundChannel::stop_l()
+{
+ if (doStop_l()) {
+ mSoundPool->done_l(this);
+ }
+}
+
+// call with sound pool lock held
+void SoundChannel::stop()
+{
+ bool stopped;
+ {
+ Mutex::Autolock lock(&mLock);
+ stopped = doStop_l();
+ }
+
+ if (stopped) {
+ mSoundPool->done_l(this);
+ }
+}
+
+//FIXME: Pause is a little broken right now
+void SoundChannel::pause()
+{
+ Mutex::Autolock lock(&mLock);
+ if (mState == PLAYING) {
+ ALOGV("pause track");
+ mState = PAUSED;
+ mAudioTrack->pause();
+ }
+}
+
+void SoundChannel::autoPause()
+{
+ Mutex::Autolock lock(&mLock);
+ if (mState == PLAYING) {
+ ALOGV("pause track");
+ mState = PAUSED;
+ mAutoPaused = true;
+ mAudioTrack->pause();
+ }
+}
+
+void SoundChannel::resume()
+{
+ Mutex::Autolock lock(&mLock);
+ if (mState == PAUSED) {
+ ALOGV("resume track");
+ mState = PLAYING;
+ mAutoPaused = false;
+ mAudioTrack->start();
+ }
+}
+
+void SoundChannel::autoResume()
+{
+ Mutex::Autolock lock(&mLock);
+ if (mAutoPaused && (mState == PAUSED)) {
+ ALOGV("resume track");
+ mState = PLAYING;
+ mAutoPaused = false;
+ mAudioTrack->start();
+ }
+}
+
+void SoundChannel::setRate(float rate)
+{
+ Mutex::Autolock lock(&mLock);
+ if (mAudioTrack != NULL && mSample != 0) {
+ uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5);
+ mAudioTrack->setSampleRate(sampleRate);
+ mRate = rate;
+ }
+}
+
+// call with lock held
+void SoundChannel::setVolume_l(float leftVolume, float rightVolume)
+{
+ mLeftVolume = leftVolume;
+ mRightVolume = rightVolume;
+ if (mAudioTrack != NULL)
+ mAudioTrack->setVolume(leftVolume, rightVolume);
+}
+
+void SoundChannel::setVolume(float leftVolume, float rightVolume)
+{
+ Mutex::Autolock lock(&mLock);
+ setVolume_l(leftVolume, rightVolume);
+}
+
+void SoundChannel::setLoop(int loop)
+{
+ Mutex::Autolock lock(&mLock);
+ if (mAudioTrack != NULL && mSample != 0) {
+ uint32_t loopEnd = mSample->size()/mNumChannels/
+ ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
+ mAudioTrack->setLoop(0, loopEnd, loop);
+ mLoop = loop;
+ }
+}
+
+SoundChannel::~SoundChannel()
+{
+ ALOGV("SoundChannel destructor %p", this);
+ {
+ Mutex::Autolock lock(&mLock);
+ clearNextEvent();
+ doStop_l();
+ }
+ // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack
+ // callback thread to exit which may need to execute process() and acquire the mLock.
+ mAudioTrack.clear();
+}
+
+void SoundChannel::dump()
+{
+ ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d",
+ mState, mChannelID, mNumChannels, mPos, mPriority, mLoop);
+}
+
+void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume,
+ float rightVolume, int priority, int loop, float rate)
+{
+ mSample = sample;
+ mChannelID = channelID;
+ mLeftVolume = leftVolume;
+ mRightVolume = rightVolume;
+ mPriority = priority;
+ mLoop = loop;
+ mRate =rate;
+}
+
+} // end namespace android
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
new file mode 100644
index 0000000..9d9cbdf
--- /dev/null
+++ b/media/jni/soundpool/SoundPool.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2007 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 SOUNDPOOL_H_
+#define SOUNDPOOL_H_
+
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <media/AudioTrack.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
+
+namespace android {
+
+static const int IDLE_PRIORITY = -1;
+
+// forward declarations
+class SoundEvent;
+class SoundPoolThread;
+class SoundPool;
+
+// for queued events
+class SoundPoolEvent {
+public:
+ SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
+ mMsg(msg), mArg1(arg1), mArg2(arg2) {}
+ int mMsg;
+ int mArg1;
+ int mArg2;
+ enum MessageType { INVALID, SAMPLE_LOADED };
+};
+
+// callback function prototype
+typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
+
+// tracks samples used by application
+class Sample : public RefBase {
+public:
+ enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
+ Sample(int sampleID, int fd, int64_t offset, int64_t length);
+ ~Sample();
+ int sampleID() { return mSampleID; }
+ int numChannels() { return mNumChannels; }
+ int sampleRate() { return mSampleRate; }
+ audio_format_t format() { return mFormat; }
+ size_t size() { return mSize; }
+ int state() { return mState; }
+ uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
+ status_t doLoad();
+ void startLoad() { mState = LOADING; }
+ sp<IMemory> getIMemory() { return mData; }
+
+private:
+ void init();
+
+ size_t mSize;
+ volatile int32_t mRefCount;
+ uint16_t mSampleID;
+ uint16_t mSampleRate;
+ uint8_t mState : 3;
+ uint8_t mNumChannels : 2;
+ audio_format_t mFormat;
+ int mFd;
+ int64_t mOffset;
+ int64_t mLength;
+ sp<IMemory> mData;
+ sp<MemoryHeapBase> mHeap;
+};
+
+// stores pending events for stolen channels
+class SoundEvent
+{
+public:
+ SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
+ mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
+ void set(const sp<Sample>& sample, int channelID, float leftVolume,
+ float rightVolume, int priority, int loop, float rate);
+ sp<Sample> sample() { return mSample; }
+ int channelID() { return mChannelID; }
+ float leftVolume() { return mLeftVolume; }
+ float rightVolume() { return mRightVolume; }
+ int priority() { return mPriority; }
+ int loop() { return mLoop; }
+ float rate() { return mRate; }
+ void clear() { mChannelID = 0; mSample.clear(); }
+
+protected:
+ sp<Sample> mSample;
+ int mChannelID;
+ float mLeftVolume;
+ float mRightVolume;
+ int mPriority;
+ int mLoop;
+ float mRate;
+};
+
+// for channels aka AudioTracks
+class SoundChannel : public SoundEvent {
+public:
+ enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
+ SoundChannel() : mState(IDLE), mNumChannels(1),
+ mPos(0), mToggle(0), mAutoPaused(false) {}
+ ~SoundChannel();
+ void init(SoundPool* soundPool);
+ void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
+ int priority, int loop, float rate);
+ void setVolume_l(float leftVolume, float rightVolume);
+ void setVolume(float leftVolume, float rightVolume);
+ void stop_l();
+ void stop();
+ void pause();
+ void autoPause();
+ void resume();
+ void autoResume();
+ void setRate(float rate);
+ int state() { return mState; }
+ void setPriority(int priority) { mPriority = priority; }
+ void setLoop(int loop);
+ int numChannels() { return mNumChannels; }
+ void clearNextEvent() { mNextEvent.clear(); }
+ void nextEvent();
+ int nextChannelID() { return mNextEvent.channelID(); }
+ void dump();
+
+private:
+ static void callback(int event, void* user, void *info);
+ void process(int event, void *info, unsigned long toggle);
+ bool doStop_l();
+
+ SoundPool* mSoundPool;
+ sp<AudioTrack> mAudioTrack;
+ SoundEvent mNextEvent;
+ Mutex mLock;
+ int mState;
+ int mNumChannels;
+ int mPos;
+ int mAudioBufferSize;
+ unsigned long mToggle;
+ bool mAutoPaused;
+};
+
+// application object for managing a pool of sounds
+class SoundPool {
+ friend class SoundPoolThread;
+ friend class SoundChannel;
+public:
+ SoundPool(int maxChannels, const audio_attributes_t* pAttributes);
+ ~SoundPool();
+ int load(int fd, int64_t offset, int64_t length, int priority);
+ bool unload(int sampleID);
+ int play(int sampleID, float leftVolume, float rightVolume, int priority,
+ int loop, float rate);
+ void pause(int channelID);
+ void autoPause();
+ void resume(int channelID);
+ void autoResume();
+ void stop(int channelID);
+ void setVolume(int channelID, float leftVolume, float rightVolume);
+ void setPriority(int channelID, int priority);
+ void setLoop(int channelID, int loop);
+ void setRate(int channelID, float rate);
+ const audio_attributes_t* attributes() { return &mAttributes; }
+
+ // called from SoundPoolThread
+ void sampleLoaded(int sampleID);
+
+ // called from AudioTrack thread
+ void done_l(SoundChannel* channel);
+
+ // callback function
+ void setCallback(SoundPoolCallback* callback, void* user);
+ void* getUserData() { return mUserData; }
+
+private:
+ SoundPool() {} // no default constructor
+ bool startThreads();
+ void doLoad(sp<Sample>& sample);
+ sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
+ SoundChannel* findChannel (int channelID);
+ SoundChannel* findNextChannel (int channelID);
+ SoundChannel* allocateChannel_l(int priority);
+ void moveToFront_l(SoundChannel* channel);
+ void notify(SoundPoolEvent event);
+ void dump();
+
+ // restart thread
+ void addToRestartList(SoundChannel* channel);
+ void addToStopList(SoundChannel* channel);
+ static int beginThread(void* arg);
+ int run();
+ void quit();
+
+ Mutex mLock;
+ Mutex mRestartLock;
+ Condition mCondition;
+ SoundPoolThread* mDecodeThread;
+ SoundChannel* mChannelPool;
+ List<SoundChannel*> mChannels;
+ List<SoundChannel*> mRestart;
+ List<SoundChannel*> mStop;
+ DefaultKeyedVector< int, sp<Sample> > mSamples;
+ int mMaxChannels;
+ audio_attributes_t mAttributes;
+ int mAllocated;
+ int mNextSampleID;
+ int mNextChannelID;
+ bool mQuit;
+
+ // callback
+ Mutex mCallbackLock;
+ SoundPoolCallback* mCallback;
+ void* mUserData;
+};
+
+} // end namespace android
+
+#endif /*SOUNDPOOL_H_*/
diff --git a/media/jni/soundpool/SoundPoolThread.cpp b/media/jni/soundpool/SoundPoolThread.cpp
new file mode 100644
index 0000000..ba3b482
--- /dev/null
+++ b/media/jni/soundpool/SoundPoolThread.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPoolThread"
+#include "utils/Log.h"
+
+#include "SoundPoolThread.h"
+
+namespace android {
+
+void SoundPoolThread::write(SoundPoolMsg msg) {
+ Mutex::Autolock lock(&mLock);
+ while (mMsgQueue.size() >= maxMessages) {
+ mCondition.wait(mLock);
+ }
+
+ // if thread is quitting, don't add to queue
+ if (mRunning) {
+ mMsgQueue.push(msg);
+ mCondition.signal();
+ }
+}
+
+const SoundPoolMsg SoundPoolThread::read() {
+ Mutex::Autolock lock(&mLock);
+ while (mMsgQueue.size() == 0) {
+ mCondition.wait(mLock);
+ }
+ SoundPoolMsg msg = mMsgQueue[0];
+ mMsgQueue.removeAt(0);
+ mCondition.signal();
+ return msg;
+}
+
+void SoundPoolThread::quit() {
+ Mutex::Autolock lock(&mLock);
+ if (mRunning) {
+ mRunning = false;
+ mMsgQueue.clear();
+ mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
+ mCondition.signal();
+ mCondition.wait(mLock);
+ }
+ ALOGV("return from quit");
+}
+
+SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
+ mSoundPool(soundPool)
+{
+ mMsgQueue.setCapacity(maxMessages);
+ if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
+ mRunning = true;
+ }
+}
+
+SoundPoolThread::~SoundPoolThread()
+{
+ quit();
+}
+
+int SoundPoolThread::beginThread(void* arg) {
+ ALOGV("beginThread");
+ SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg;
+ return soundPoolThread->run();
+}
+
+int SoundPoolThread::run() {
+ ALOGV("run");
+ for (;;) {
+ SoundPoolMsg msg = read();
+ ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
+ switch (msg.mMessageType) {
+ case SoundPoolMsg::KILL:
+ ALOGV("goodbye");
+ return NO_ERROR;
+ case SoundPoolMsg::LOAD_SAMPLE:
+ doLoadSample(msg.mData);
+ break;
+ default:
+ ALOGW("run: Unrecognized message %d\n",
+ msg.mMessageType);
+ break;
+ }
+ }
+}
+
+void SoundPoolThread::loadSample(int sampleID) {
+ write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID));
+}
+
+void SoundPoolThread::doLoadSample(int sampleID) {
+ sp <Sample> sample = mSoundPool->findSample(sampleID);
+ status_t status = -1;
+ if (sample != 0) {
+ status = sample->doLoad();
+ }
+ mSoundPool->notify(SoundPoolEvent(SoundPoolEvent::SAMPLE_LOADED, sampleID, status));
+}
+
+} // end namespace android
diff --git a/media/jni/soundpool/SoundPoolThread.h b/media/jni/soundpool/SoundPoolThread.h
new file mode 100644
index 0000000..d388388
--- /dev/null
+++ b/media/jni/soundpool/SoundPoolThread.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 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 SOUNDPOOLTHREAD_H_
+#define SOUNDPOOLTHREAD_H_
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+#include <media/AudioTrack.h>
+
+#include "SoundPool.h"
+
+namespace android {
+
+class SoundPoolMsg {
+public:
+ enum MessageType { INVALID, KILL, LOAD_SAMPLE };
+ SoundPoolMsg() : mMessageType(INVALID), mData(0) {}
+ SoundPoolMsg(MessageType MessageType, int data) :
+ mMessageType(MessageType), mData(data) {}
+ uint16_t mMessageType;
+ uint16_t mData;
+};
+
+/*
+ * This class handles background requests from the SoundPool
+ */
+class SoundPoolThread {
+public:
+ SoundPoolThread(SoundPool* SoundPool);
+ ~SoundPoolThread();
+ void loadSample(int sampleID);
+ void quit();
+ void write(SoundPoolMsg msg);
+
+private:
+ static const size_t maxMessages = 5;
+
+ static int beginThread(void* arg);
+ int run();
+ void doLoadSample(int sampleID);
+ const SoundPoolMsg read();
+
+ Mutex mLock;
+ Condition mCondition;
+ Vector<SoundPoolMsg> mMsgQueue;
+ SoundPool* mSoundPool;
+ bool mRunning;
+};
+
+} // end namespace android
+
+#endif /*SOUNDPOOLTHREAD_H_*/
diff --git a/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp b/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp
index baf61d5..b2333f8 100644
--- a/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp
+++ b/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp
@@ -23,7 +23,7 @@
#include <nativehelper/jni.h>
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
-#include <media/SoundPool.h>
+#include "SoundPool.h"
using namespace android;
@@ -45,20 +45,6 @@
static audio_attributes_fields_t javaAudioAttrFields;
// ----------------------------------------------------------------------------
-static jint
-android_media_SoundPool_SoundPoolImpl_load_URL(JNIEnv *env, jobject thiz, jstring path, jint priority)
-{
- ALOGV("android_media_SoundPool_SoundPoolImpl_load_URL");
- SoundPool *ap = MusterSoundPool(env, thiz);
- if (path == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- return 0;
- }
- const char* s = env->GetStringUTFChars(path, NULL);
- int id = ap->load(s, priority);
- env->ReleaseStringUTFChars(path, s);
- return (jint) id;
-}
static jint
android_media_SoundPool_SoundPoolImpl_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
@@ -249,10 +235,6 @@
// Dalvik VM type signatures
static JNINativeMethod gMethods[] = {
{ "_load",
- "(Ljava/lang/String;I)I",
- (void *)android_media_SoundPool_SoundPoolImpl_load_URL
- },
- { "_load",
"(Ljava/io/FileDescriptor;JJI)I",
(void *)android_media_SoundPool_SoundPoolImpl_load_FD
},
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index c2bb90c..0b7b99f 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -29,7 +29,8 @@
import android.os.ServiceManager;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
-import android.util.Log;
+import android.text.Editable;
+import android.text.TextWatcher;
import android.util.Slog;
import android.view.View;
import android.widget.Button;
@@ -180,20 +181,6 @@
mEncPassword = (TextView) findViewById(R.id.enc_password);
TextView curPwDesc = (TextView) findViewById(R.id.password_desc);
- // We vary the password prompt depending on whether one is predefined, and whether
- // the device is encrypted.
- mIsEncrypted = deviceIsEncrypted();
- if (!haveBackupPassword()) {
- curPwDesc.setVisibility(View.GONE);
- mCurPassword.setVisibility(View.GONE);
- if (layoutId == R.layout.confirm_backup) {
- TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
- encPwDesc.setText(mIsEncrypted
- ? R.string.backup_enc_password_required
- : R.string.backup_enc_password_optional);
- }
- }
-
mAllowButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -209,6 +196,7 @@
sendAcknowledgement(mToken, false, mObserver);
mAllowButton.setEnabled(false);
mDenyButton.setEnabled(false);
+ finish();
}
});
@@ -218,6 +206,39 @@
mAllowButton.setEnabled(!mDidAcknowledge);
mDenyButton.setEnabled(!mDidAcknowledge);
}
+
+ // We vary the password prompt depending on whether one is predefined, and whether
+ // the device is encrypted.
+ mIsEncrypted = deviceIsEncrypted();
+ if (!haveBackupPassword()) {
+ curPwDesc.setVisibility(View.GONE);
+ mCurPassword.setVisibility(View.GONE);
+ if (layoutId == R.layout.confirm_backup) {
+ TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
+ if (mIsEncrypted) {
+ encPwDesc.setText(R.string.backup_enc_password_required);
+ monitorEncryptionPassword();
+ } else {
+ encPwDesc.setText(R.string.backup_enc_password_optional);
+ }
+ }
+ }
+ }
+
+ private void monitorEncryptionPassword() {
+ mAllowButton.setEnabled(false);
+ mEncPassword.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) { }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ mAllowButton.setEnabled(mEncPassword.getText().length() > 0);
+ }
+ });
}
// Preserve the restore observer callback binder across activity relaunch
diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml
index c5d61ac..9f9f970 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -34,7 +34,7 @@
<string name="keyguard_low_battery" msgid="8143808018719173859">"请连接充电器。"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"按“菜单”键解锁。"</string>
<string name="keyguard_network_locked_message" msgid="9169717779058037168">"网络已锁定"</string>
- <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"无SIM卡"</string>
+ <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"无 SIM 卡"</string>
<string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"平板电脑中没有SIM卡。"</string>
<string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"手机中没有SIM卡。"</string>
<string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"请插入SIM卡。"</string>
diff --git a/packages/PrintSpooler/res/values-ca/arrays.xml b/packages/PrintSpooler/res/values-ca/arrays.xml
new file mode 100644
index 0000000..c1b149c
--- /dev/null
+++ b/packages/PrintSpooler/res/values-ca/arrays.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+
+ <string-array name="pdf_printer_media_sizes" translatable="false">
+ <item>NA_LETTER</item>
+ <item>NA_GOVT_LETTER</item>
+ <item>NA_LEGAL</item>
+ <item>NA_JUNIOR_LEGAL</item>
+ <item>NA_LEDGER</item>
+ <item>NA_TABLOID</item>
+ <item>NA_INDEX_3X5</item>
+ <item>NA_INDEX_4X6</item>
+ <item>NA_INDEX_5X8</item>
+ <item>NA_MONARCH</item>
+ <item>NA_QUARTO</item>
+ <item>NA_FOOLSCAP</item>
+ </string-array>
+
+</resources>
diff --git a/packages/SystemUI/res/layout/notification_public_default.xml b/packages/SystemUI/res/layout/notification_public_default.xml
index efabc06..044ba09 100644
--- a/packages/SystemUI/res/layout/notification_public_default.xml
+++ b/packages/SystemUI/res/layout/notification_public_default.xml
@@ -16,12 +16,9 @@
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:internal="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="64dp"
- internal:layout_minHeight="64dp"
- internal:layout_maxHeight="64dp"
>
<ImageView android:id="@+id/icon"
android:layout_width="40dp"
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index c18757d..e57c5f4 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> አስወግድ።"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ተሰናብቷል::"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ሁሉም የቅርብ ጊዜ ማመልከቻዎች ተሰናብተዋል።"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> በመጀመር ላይ።"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ማሳወቂያ ተወግዷል።"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"የማሳወቂያ ጥላ።"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ማያ ገጽ መሰካት"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ን መጀመር አልተቻለም።"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ሁሉንም ማመልከቻዎች አሰናብት"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ባትሪ ሞልቷል"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"ኃይል በመሙላት ላይ"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> እስኪሞላ ድረስ"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a011911..7fc379c 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отхвърляне на <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложението <xliff:g id="APP">%s</xliff:g> е отхвърлено."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Всички скорошни приложения са отхвърлени."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> се стартира."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известието е отхвърлено."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Падащ панел с известия."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"фиксиране на екрана"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не можа да стартира."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Отхвърляне на всички приложения"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заредена"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарежда се"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> до пълно зареждане"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 8d33282..1110310 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> খারিজ করুন।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> খারিজ করা হয়েছে৷"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"সমস্ত সাম্প্রতিক অ্যাপ্লিকেশন খারিজ করা হয়েছে।"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> তারাঙ্কিত করা হচ্ছে।"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"বিজ্ঞপ্তি খারিজ করা হয়েছে৷"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"বিজ্ঞপ্তি শেড৷"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"স্ক্রীন পিন করা"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"অনুসন্ধান"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> শুরু করা যায়নি৷"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"সমস্ত অ্যাপ্লিকেশন খারিজ করুন"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"চার্জ হয়েছে"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"চার্জ হচ্ছে"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"পূর্ণ হতে <xliff:g id="CHARGING_TIME">%s</xliff:g> সময় লাগবে"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e33c49d..ef5986b 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descarta <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"S\'ha omès <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"S\'han descartat totes les aplicacions recents."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"S\'està iniciant <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificació omesa."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Àrea de notificacions"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixació de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No s\'ha pogut iniciar <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Descarta totes les aplicacions"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"S\'està carregant"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> per completar la càrrega"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index c8907c7..6235eb1 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zavřít aplikaci <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikace <xliff:g id="APP">%s</xliff:g> byla odebrána."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všechny naposledy použité aplikace byly odstraněny."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Spouštění aplikace <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Oznámení je zavřeno."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Panel oznámení."</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"připnutí obrazovky"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikaci <xliff:g id="APP">%s</xliff:g> nelze spustit."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Odstranit všechny aplikace"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabito"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Nabíjení"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do plného nabití"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f442472..3153d3f 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Afvis <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> er annulleret."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle de seneste applikationer er lukket."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> startes."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Underretningen er annulleret."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Underretningspanel."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"bliv i app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> kunne ikke startes."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Luk alle applikationer"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opladet"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Oplader"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> indtil fuld opladet"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index f3349d2..3165a3c 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> beenden"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> entfernt"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle kürzlich verwendeten Apps wurden entfernt."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> wird gestartet."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Benachrichtigung geschlossen"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Benachrichtigungsleiste"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Bildschirmfixierung"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> konnte nicht gestartet werden."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Alle Apps entfernen"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Aufgeladen"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Wird aufgeladen"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Voll in <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 04c4fe8..e6ea177 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Παράβλεψη <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Απορρίφθηκαν <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Έγινε παράβλεψη όλων των πρόσφατων εφαρμογών."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Έναρξη <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Η ειδοποίηση έχει απορριφθεί."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Πλαίσιο σκίασης ειδοποιήσεων."</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"καρφίτσωμα οθόνης"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Δεν ήταν δυνατή η εκκίνηση της εφαρμογής <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Παράβλεψη όλων των εφαρμογών"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Φορτίστηκε"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Φόρτιση"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> για πλήρη φόρτιση"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 7cf20ba..c788677 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rechazar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartada."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se descartaron todas las aplicaciones recientes."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Pantalla de notificaciones"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Fijar pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No se pudo iniciar <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Descartar todas las aplicaciones"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completarse"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 82fe2bd..3f2fa15 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Se ha eliminado <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se han ignorado todas las aplicaciones recientes."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Pantalla de notificaciones"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fijación de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No se ha podido iniciar <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ignorar todas las aplicaciones"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completarse"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index f8ce386..9c05158 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rakendusest <xliff:g id="APP">%s</xliff:g> loobumine."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Loobusite rakendusest <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kõikidest hiljutistest rakendustest on loobutud"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Rakenduse <xliff:g id="APP">%s</xliff:g> käivitamine."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Märguandest on loobutud."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Märguande vari."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekraanikuva kinnitamine"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Rakendust <xliff:g id="APP">%s</xliff:g> ei saanud käivitada."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Loobu kõikidest rakendustest"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laetud"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Laadimine"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Täislaadimiseks kulub <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index b456bee..e2a81e9 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Baztertu <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> baztertu da."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Azken aplikazioen atala garbitu da."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> hasten."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Jakinarazpena baztertu da."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Jakinarazpenen panela."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pantaila-ainguratzea"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"bilatu"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Ezin izan da hasi <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Garbitu aplikazio guztiak"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kargatuta"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Kargatzen"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> falta zaizkio guztiz kargatzeko"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index b8b2d65..3208b1b 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hylätään <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> hylättiin."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kaikki viimeisimmät sovellukset on hylätty."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Käynnistetään <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ilmoitus hylätty."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ilmoitusalue."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"näytön kiinnitys"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Sovelluksen <xliff:g id="APP">%s</xliff:g> käynnistäminen epäonnistui."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Hylkää kaikki sovellukset"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ladattu"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Ladataan"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> kunnes täynnä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 156e4a7..e6bd1f6 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Supprimer <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toutes les applications récentes ont été supprimées."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Lancement de <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Volet des notifications"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Supprimer toutes les applications"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargée"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Charge en cours..."</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Chargée dans <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 31ef4ef..1d91c8a 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Supprimer <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toutes les applications récentes ont été supprimées."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Lancement de <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Volet des notifications"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Supprimer toutes les applications"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargé"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"En charge"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Chargé dans <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 4c40a5a..78a5fbb 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rexeitar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Rexeitouse <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Rexeitáronse todas as aplicacións recentes."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación rexeitada"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Sombra de notificación"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixación de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Non foi posible iniciar <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Rexeitar todas as aplicacións"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completar a carga"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 50ef47a..411e3c3 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> को ख़ारिज करें."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खा़रिज कर दिया गया."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"हाल ही के सभी ऐप्लिकेशन ख़ारिज कर दिए गए."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ हो रहा है."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"नोटिफिकेशन खारिज की गई."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"नोटिफिकेशन शेड."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रीन पिन करना"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ नहीं किया जा सका."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"सभी ऐप्लिकेशन ख़ारिज करें"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज हो गई है"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज हो रही है"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"पूर्ण होने में <xliff:g id="CHARGING_TIME">%s</xliff:g> शेष"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 3fb20a9..1e42832 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbacivanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> odbačena je."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Odbačene su sve nedavne aplikacije."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokretanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obavijest je odbačena."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Zaslon obavijesti."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"prikvačivanje zaslona"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacija <xliff:g id="APP">%s</xliff:g> nije pokrenuta."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Odbaci sve aplikacije"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjeno"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Punjenje"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do napunjenosti"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8787599..ed105d0 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"A(z) <xliff:g id="APP">%s</xliff:g> elvetése."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eltávolítva."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Az összes alkalmazás eltávolítva a nemrég használtak közül."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"A(z) <xliff:g id="APP">%s</xliff:g> indítása."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Értesítés elvetve."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Értesítési felület."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"képernyő rögzítése"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nem lehet elindítani a következőt: <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Összes alkalmazás elvetése"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Feltöltve"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Töltés"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> a teljes töltöttségig"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index c0f8776..6432060 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Անտեսել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>-ը անտեսված է:"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Բոլոր վերջին հավելվածները հեռացվել են ցուցակից:"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Մեկնարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ծանուցումը անտեսվեց:"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ծանուցումների վահանակ:"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"էկրանի ամրակցում"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Հնարավոր չէ գործարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Հեռացնել բոլոր հավելվածները"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Լիցքավորված է"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Լիցքավորվում է"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Լրիվ լիցքավորմանը մնաց <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 025bdbe..bd0a99f 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Menyingkirkan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> disingkirkan."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaru ditutup."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulai <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan disingkirkan."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bayangan pemberitahuan."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pin ke layar"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulai <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Tutup semua aplikasi"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Terisi"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Mengisi daya"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> sampai penuh"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 87fb619..adcda3f 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hunsa <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> vísað frá."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Öll nýleg forrit fjarlægð."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Ræsir <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Tilkynningu lokað."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Tilkynningasvæði."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skjáfesting"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"leita"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Ekki var hægt að ræsa <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Fjarlægja öll forrit"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Fullhlaðin"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Í hleðslu"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> þar til fullri hleðslu er náð"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 8144bc0..21a483f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Elimina <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eliminata."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tutte le applicazioni recenti sono state rimosse."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Avvio di <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifica eliminata."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Area notifiche."</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"blocco su schermo"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossibile avviare <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Rimuovi tutte le applicazioni"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carica"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"In carica"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> al termine della carica"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 0183e21..5b68f86 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>を削除します。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>は削除されました。"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近のアプリケーションをすべて消去しました。"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>を開始しています。"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知が削除されました。"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知シェード"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"画面固定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>を開始できません。"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"すべてのアプリケーションを消去"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"充電が完了しました"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"充電しています"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"充電完了まで<xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 42fdfe9..b6650d0 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-ის უგულებელყოფა."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ამოშლილია სიიდან."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ყველა ბოლო აპლიკაცია გაუქმდა."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> იწყება."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"შეტყობინება წაიშალა."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"შეტყობინებების ფარდა"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ეკრანზე ჩამაგრება"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-ის გამოძახება ვერ მოხერხდა."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ყველა აპლიკაციის გაუქმება"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"დატენილია"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"მიმდინარეობს დატენვა"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> სრულად დატენვამდე"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 7190aa2..15c4584 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> қолданбасынан бас тарту."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> алынып тасталған."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Барлық жақындағы қабылданбаған қолданбалар."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> іске қосылуда."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Хабар алынып тасталды."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Хабарландыру тақтасы"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экранды бекіту"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"іздеу"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> іске қосу мүмкін болмады."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Барлық қолданбаларды қабылдамау"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Зарядталды"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарядталуда"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Толғанға дейін <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index e88deb7..28d586a 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"បោះបង់ <xliff:g id="APP">%s</xliff:g> ។"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"កម្មវិធីថ្មីៗទាំងអស់ត្រូវបានបោះបង់។"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"ចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ។"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"បានបដិសេធការជូនដំណឹង"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"ពណ៌ការជូនដំណឹង"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ការភ្ជាប់អេក្រង់"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"មិនអាចចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ទេ។"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"បោះបង់កម្មវិធីទាំងអស់"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"បានបញ្ចូលថ្ម"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"កំពុងបញ្ចូលថ្ម"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> រហូតដល់ពេញ"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 5b7738b..4134c11 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸು."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ಇತ್ತೀಚಿನ ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ಅಧಿಸೂಚನೆ ವಜಾಗೊಂಡಿದೆ."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"ಅಧಿಸೂಚನೆಯ ಛಾಯೆ."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ಸ್ಕ್ರೀನ್ ಪಿನ್ನಿಂಗ್"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ಹುಡುಕಾಟ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲು ಸಾದ್ಯವಿಲ್ಲ."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ವಜಾಗೊಳಿಸಿ"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ಪೂರ್ಣಗೊಳ್ಳುವವರೆಗೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 906ba2b..549da84 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>을(를) 숨깁니다."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>이(가) 제거되었습니다."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"최근 사용한 애플리케이션을 모두 닫았습니다."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>을(를) 시작하는 중입니다."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"알림이 제거되었습니다."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"알림 세부정보"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"화면 고정"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>을(를) 시작할 수 없습니다."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"모든 애플리케이션 닫기"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"충전됨"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"충전 중"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"완충까지 <xliff:g id="CHARGING_TIME">%s</xliff:g> 남음"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 30e5c97..960541a 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -184,8 +184,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> этибарга албоо."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> жок болду."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Акыркы колдонмолордун баары көз жаздымда калтырылды."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> иштеп баштоодо."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Эскертме жок кылынды."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Эскертмелер көшөгөсү."</string>
@@ -307,8 +306,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экран кадоо"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"издөө"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> баштай алган жок."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Бардык колдонмолорду көз жаздымда калтыруу"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Кубатталды"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Кубатталууда"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> толгонго чейин"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 49f38b9..f7a8c00 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Atsisakyti <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Atsisakyta programos „<xliff:g id="APP">%s</xliff:g>“."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Atsisakyta visų naujausių programų."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Paleidžiama <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pranešimo atsisakyta."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Pranešimų gaubtas."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekrano prisegimas"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nepavyko paleisti <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Atsisakyti visų programų"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Įkrautas"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Kraunamas"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> iki visiško įkrovimo"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index a0f7b20..a9f7110 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Nerādīt lietotni <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Lietotne <xliff:g id="APP">%s</xliff:g> vairs netiek rādīta."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Visas nesen izmantotās lietojumprogrammas tika noņemtas."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Notiek lietotnes <xliff:g id="APP">%s</xliff:g> palaišana."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Paziņojums netiek rādīts."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Paziņojumu panelis"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Piespraust ekrānu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nevarēja palaist lietotni <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Noņemt visas lietojumprogrammas"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulators uzlādēts"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Notiek uzlāde"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> līdz pilnam akumulatoram"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 67314c0..4686ba5 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отфрли <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> е отфрлена."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Сите неодамнешни апликации се отфрлени."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Се стартува <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известувањето е отфрлено."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Панел за известување"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"прикачување екран"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"пребарај"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не може да се вклучи."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Отфрли ги сите апликации"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Наполнета"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Се полни"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> додека не се наполни"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 41e5ef8..41f5923 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> നിരസിക്കുക."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> നിരസിച്ചു."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"അടുത്തിടെയുള്ള എല്ലാ അപ്ലിക്കേഷനും നിരസിച്ചു."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കുന്നു."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"അറിയിപ്പ് നിരസിച്ചു."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"അറിയിപ്പ് ഷെയ്ഡ്."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"സ്ക്രീൻ പിൻ ചെയ്യൽ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"തിരയുക"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കാനായില്ല."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"എല്ലാ അപ്ലിക്കേഷനുകളും നിരസിക്കുക"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ചാർജ്ജുചെയ്തു"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"ചാർജ്ജുചെയ്യുന്നു"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index ea80976..8f81367 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-г хаах."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> байхгүй."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Хамгийн сүүлийн бүх програмыг арилгасан байна."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж байна."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Мэдэгдэл хаагдсан."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Мэдэгдлийн хураангуй самбар"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"дэлгэц тогтоох"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж чадсангүй."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Бүх програмыг арилгах"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Цэнэглэгдсэн"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Цэнэглэж байна"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"дүүргэхэд <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index e8f3a98..bf7c5a6 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> डिसमिस करा."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> डिसमिस केला."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"अलीकडील सर्व अनुप्रयोग डिसमिस झाले."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करीत आहे."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना डिसमिस केल्या."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना शेड."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रीन पिन करणे"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"शोधा"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करणे शक्य झाले नाही."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"सर्व अनुप्रयोग डिसमिस करा"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज झाली"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज होत आहे"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> पूर्ण होईपर्यंत"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 7b89c1c..5845d59 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ketepikan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ditolak."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaharu diketepikan."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulakan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan diketepikan."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bidai pemberitahuan."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"penyematan skrin"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulakan <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ketepikan semua aplikasi"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Sudah dicas"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Mengecas"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Lagi <xliff:g id="CHARGING_TIME">%s</xliff:g> untuk penuh"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 86e4729..c8f4c55 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ကို ပယ်လိုက်ရန်"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ထုတ်ထားသည်။"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"မကြာသေးမီက အပလီကေးရှင်းများအားလုံး ဖယ်ထုတ်ပြီးပါပြီ။"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ကို စတင်နေသည်။"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"အကြောင်းကြားချက်ကိုဖယ်ရှားပြီး"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"အကြောင်းကြားစာအကွက်"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"မျက်နှာပြင် ပင်ထိုးမှု"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ရှာဖွေရန်"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ကို မစနိုင်ပါ။"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"အပလီကေးရှင်းများအားလုံး ဖယ်ထုတ်မည်"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"အားသွင်းပြီး"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"အားသွင်းနေ"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ပြည်သည့် အထိ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 7ac8a69..60e27ee 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Avvis <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> avvist."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle nylig brukte apper er avvist."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starter <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Varselet ble skjult."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Varselskygge."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"én-appsmodus"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Kunne ikke starte <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Avvis alle apper"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Oppladet"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Lader"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Fulladet om <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index d1d19af..87cbb6f 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> खारेज गर्नुहोस्।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खारेज गरिएको छ।"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"सबै हालका अनुप्रयोगहरू खारेज गरियो।"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>सुरु गर्दै।"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारेज।"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना कक्ष।"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रिन पिन गर्दै"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"खोजी गर्नुहोस्"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"सुरु गर्न सकिएन <xliff:g id="APP">%s</xliff:g>।"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"सबै अनुप्रयोगहरू खारेज गर्नुहोस्"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज भयो"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज हुँदै"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> पूर्ण नभएसम्म"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 451ff9a..6786a74 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> sluiten."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwijderd."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle recente apps gesloten."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> starten."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Melding verwijderd."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Meldingenpaneel."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"scherm vastzetten"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Kan <xliff:g id="APP">%s</xliff:g> niet starten."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Alle apps sluiten"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opgeladen"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Opladen"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> tot volledig opgeladen"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 81e22ca..3f2c7fd 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Usuń stąd <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>: zamknięto."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Wszystkie ostatnie aplikacje zostały zamknięte."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Uruchamiam <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Zamknięto powiadomienie."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Obszar powiadomień."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"przypinanie ekranu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nie udało się uruchomić aplikacji <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Zamknij wszystkie aplikacje"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Naładowana"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Ładowanie"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do pełnego naładowania"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index ae7b551..b5b2650 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ignorado."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todas as aplicações recentes foram ignoradas."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"A iniciar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação ignorada."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Painel de notificações."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação no ecrã"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar o <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ignorar todas as aplicações"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"A carregar"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> até ficar completa"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 7887e06..c914a50 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todos os apps recentes foram dispensados."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Aba de notificações."</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação de tela"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Dispensar todos os apps"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Carregando"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> até concluir"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0c1b4ec..c84b96f 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Închideți <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> a fost eliminată."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toate aplicațiile recente au fost închise."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Se inițiază <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificarea a fost închisă."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Fereastră pentru notificări."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixare pe ecran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nu a putut porni."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Închideți toate aplicațiile"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"S-a încărcat"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Se încarcă"</string>
<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>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 8425cb4..cd00556 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7164937344850004466">"Графический интерфейс системы"</string>
+ <string name="app_label" msgid="7164937344850004466">"Интерфейс системы"</string>
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Очистить"</string>
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Удалить из списка"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"О приложении"</string>
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Удаление приложения <xliff:g id="APP">%s</xliff:g> из списка."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" удалено из списка."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Все недавние приложения закрыты."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запуск приложения <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Уведомление закрыто"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Панель уведомлений"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Заблокировать в приложении"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Не удалось запустить приложение \"<xliff:g id="APP">%s</xliff:g>\""</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Закрыть все приложения"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Батарея заряжена"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарядка батареи"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> до полной зарядки"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 760e49d..0a54324 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ඉවතලන්න."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> අස් කර ඇත."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"සියලු මෑත යෙඳුම් අස් කෙරිණි"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කරමින්."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"දැනුම්දීම නිෂ්ප්රභා කරඇත."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"දැනුම්දීම් ආවරණය."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"තිර ඇමිණීම"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"සෙවීම"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කළ නොහැක."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"සියලු යෙදුම් අස් කරන්න"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"අරෝපිතයි"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"ආරෝපණය වෙමින්"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> සම්පූර්ණ වන තෙක්"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index b20d8f9..9fbd73e4 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zrušiť aplikáciu <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikácia <xliff:g id="APP">%s</xliff:g> bola zrušená."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všetky nedávne aplikácie boli odmietnuté."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Spúšťa sa aplikácia <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Upozornenie bolo zrušené."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Panel upozornení."</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripnutie k obrazovke"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikáciu <xliff:g id="APP">%s</xliff:g> sa nepodarilo spustiť"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Odmietnuť všetky aplikácie"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabitá"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Nabíja sa"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Úplné nabitie o <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 1981bfd..e4a2016 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Opusti aplikacijo <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> je bila odstranjena."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Vse nedavne aplikacije so bile opuščene."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Zaganjanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obvestilo je bilo odstranjeno."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Zaslon z obvestili."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripenjanje zaslona"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacije <xliff:g id="APP">%s</xliff:g> ni bilo mogoče zagnati."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Opusti vse aplikacije"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulator napolnjen"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Polnjenje"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do napolnjenosti"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fc4dd64..f3d7da0 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Одбаците <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Апликација <xliff:g id="APP">%s</xliff:g> је одбачена."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Све недавно коришћене апликације су одбачене."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Покрећемо <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Обавештење је одбачено."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Прозор са обавештењима."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"качење екрана"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Покретање апликације <xliff:g id="APP">%s</xliff:g> није успело."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Одбаци све апликације"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Напуњена је"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Пуњење"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> док се не напуни"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 6cc5ad0..0e9879a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ta bort <xliff:g id="APP">%s</xliff:g> från listan."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> togs bort permanent."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alla appar har tagits bort från listan Senaste."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Startar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Meddelandet ignorerades."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Meddelandepanel."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fästa skärmen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Det gick inte att starta appen <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ta bort alla appar"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laddat"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Laddar"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> tills batteriet är fulladdat"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 3b539b9..05cd74a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ondoa <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> imeondolewa."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Programu za hivi majuzi zimeondolewa."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Inaanzisha <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Arifa imetupwa."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Kivuli cha arifa."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"kudumisha programu moja"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Haikuweza kuanzisha <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ondoa programu zote"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Betri imejaa"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Inachaji"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Imebakisha <xliff:g id="CHARGING_TIME">%s</xliff:g> ijae"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index bf163f6..7556c7b 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ஐ நிராகரி."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> விலக்கப்பட்டது."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"எல்லா சமீபத்திய பயன்பாடுகளும் விலக்கப்பட்டன."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ஐத் தொடங்குகிறது."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"அறிவிப்பு நிராகரிக்கப்பட்டது."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"அறிவிப்பு விவரம்."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"திரையை பின் செய்தல்"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"தேடு"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ஐத் தொடங்க முடியவில்லை."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"எல்லா பயன்பாடுகளையும் விலக்கு"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"சார்ஜ் செய்யப்பட்டது"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"சார்ஜாகிறது"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"முழுவதும் சார்ஜாக <xliff:g id="CHARGING_TIME">%s</xliff:g> ஆகும்"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 04616c9..7704e85 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ని తీసివేయండి."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> తీసివేయబడింది."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"అన్ని ఇటీవలి అనువర్తనాలు తీసివేయబడ్డాయి."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభిస్తోంది."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"నోటిఫికేషన్ తీసివేయబడింది."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"నోటిఫికేషన్ షేడ్."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"స్క్రీన్ పిన్నింగ్"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"శోధించు"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభించడం సాధ్యపడలేదు."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"అన్ని అనువర్తనాలను తీసివేయి"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ఛార్జ్ చేయబడింది"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"ఛార్జ్ అవుతోంది"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"పూర్తిగా నిండటానికి <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 5b51a87..d591d0a 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"ยกเลิก <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ถูกลบไปแล้ว"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ปิดแอปพลิเคชันล่าสุดทั้งหมดแล้ว"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"กำลังเริ่มต้น <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ปิดการแจ้งเตือนแล้ว"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"หน้าต่างแจ้งเตือน"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"การตรึงหน้าจอ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"ไม่สามารถเริ่มใช้ <xliff:g id="APP">%s</xliff:g>"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ปิดแอปพลิเคชันทั้งหมด"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ชาร์จแล้ว"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"กำลังชาร์จ"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"อีก <xliff:g id="CHARGING_TIME">%s</xliff:g> จึงจะเต็ม"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 2367762..abe7b53 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"I-dismiss ang <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Hindi pinansin ang <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Na-dismiss ang lahat ng kamakailang application."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Sinisimulan ang <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Na-dismiss ang notification."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Notification shade."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pagpi-pin sa screen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Hindi masimulan <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"I-dismiss ang lahat ng application"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nasingil na"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Nagcha-charge"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> hanggang mapuno"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 2b7f059..9bcdc27 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> uygulamasını kapat."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> kaldırıldı."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tüm son uygulamalar kapatıldı."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> başlatılıyor."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildirim kapatıldı."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bildirim gölgesi."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekran sabitleme"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> başlatılamadı."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Tüm uygulamaları kapat"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ödeme alındı"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Şarj oluyor"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Tam şarj olmasına <xliff:g id="CHARGING_TIME">%s</xliff:g> kaldı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 1f086ff..68f7daa 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Видалити додаток <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Програму <xliff:g id="APP">%s</xliff:g> закрито."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Усі останні додатки закрито."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запуск додатка <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Сповіщення відхилено."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Панель сповіщень."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"закріпити екран"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Не вдалося запустити <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Закрити всі додатки"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заряджено"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Заряджається"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"До повного зарядження <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index cb6f3f0..bc3dbc2 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> کو مسترد کریں۔"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> کو ہٹا دیا گیا۔"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"سبھی حالیہ ایپلیکیشنز کو برخاست کر دیا گیا۔"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> شروع ہو رہی ہے۔"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"اطلاع مسترد ہوگئی۔"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"اطلاعاتی شیڈ۔"</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"اسکرین کو پن کرنا"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"تلاش کریں"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> کو شروع نہیں کیا جا سکا۔"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"سبھی ایپلیکیشنز کو برخاست کریں"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"چارج ہوگئی"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"چارج ہو رہی ہے"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> مکمل ہونے تک"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 58bf477..86ad17e 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Olib tashlash: <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> olib tashlangan."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Yaqinda ishlatilgan barcha ilovalar olib tashlandi."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ishga tushirilmoqda."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Xabarnoma e‘tiborsiz qoldirildi."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Xabarnoma soyasi."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekranni qadab qo‘yish"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"qidirish"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"“<xliff:g id="APP">%s</xliff:g>” ilovasini ishga tushirib bo‘lmadi."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Barcha ilovalarni olib tashlash"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Batareya quvvati to‘ldi"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Quvvat olmoqda"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>da to‘ladi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index c34d0ed..506c60a 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -159,8 +159,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Xóa bỏ <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> đã bị loại bỏ."</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Đã loại bỏ tất cả các ứng dụng gần đây."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Bắt đầu <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Đã loại bỏ thông báo."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bóng thông báo."</string>
@@ -282,8 +281,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"khóa màn hình"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Không thể khởi động <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Loại bỏ tất cả các ứng dụng"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Đã sạc"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Đang sạc"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> cho đến khi đầy"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 49fe785..4b39f65 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -143,7 +143,7 @@
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"漫游中"</string>
<string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WLAN"</string>
- <string name="accessibility_no_sim" msgid="8274017118472455155">"无SIM卡。"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"无 SIM 卡。"</string>
<string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"蓝牙网络共享。"</string>
<string name="accessibility_airplane_mode" msgid="834748999790763092">"飞行模式。"</string>
<!-- String.format failed for translation -->
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"移除<xliff:g id="APP">%s</xliff:g>。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"已删除<xliff:g id="APP">%s</xliff:g>"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"已关闭所有最近用过的应用。"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在启动<xliff:g id="APP">%s</xliff:g>。"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"已关闭通知。"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知栏。"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"固定屏幕"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"无法启动<xliff:g id="APP">%s</xliff:g>。"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"关闭所有应用"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"充电完成"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"正在充电"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"还需<xliff:g id="CHARGING_TIME">%s</xliff:g>充满"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 22e0ed1..50d8489 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"所有最近使用的應用程式已關閉。"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知已關閉。"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知欄。"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"關閉所有應用程式"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"已完成充電"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"充電中"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>後完成充電"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 674b974..8a50cf9 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -161,8 +161,7 @@
<skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
- <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
- <skip />
+ <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近使用的使用程式已全部關閉。"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"已關閉通知。"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知欄。"</string>
@@ -284,8 +283,7 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
- <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
- <skip />
+ <string name="recents_dismiss_all_message" msgid="8495275386693095768">"關閉所有應用程式"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"已充飽"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"充電中"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>後充飽"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 071b9a3..2659009 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -250,7 +250,7 @@
<integer name="doze_pickup_vibration_threshold">2000</integer>
<!-- Doze: can we assume the pickup sensor includes a proximity check? -->
- <bool name="doze_pickup_performs_proximity_check">true</bool>
+ <bool name="doze_pickup_performs_proximity_check">false</bool>
<!-- Doze: pulse parameter - how long does it take to fade in? -->
<integer name="doze_pulse_duration_in">900</integer>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index ddb96a2..30f92b9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -97,9 +97,7 @@
state.icon = ResourceIcon.get(iconId);
state.isOverlayIconWide = cb.isDataTypeIconWide;
state.autoMirrorDrawable = !cb.noSim;
- state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) && !cb.wifiConnected
- ? cb.dataTypeIconId
- : 0;
+ state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) ? cb.dataTypeIconId : 0;
state.filter = iconId != R.drawable.ic_qs_no_sim;
state.activityIn = cb.enabled && cb.activityIn;
state.activityOut = cb.enabled && cb.activityOut;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index ac5602c..e8023bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -57,7 +57,6 @@
// Since some pieces of the phone state are interdependent we store it locally,
// this could potentially become part of MobileState for simplification/complication
// of code.
- private IccCardConstants.State mSimState = IccCardConstants.State.READY;
private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
private int mDataState = TelephonyManager.DATA_DISCONNECTED;
private ServiceState mServiceState;
@@ -146,11 +145,6 @@
return getIcons().mDataContentDescription;
}
- @VisibleForTesting
- protected IccCardConstants.State getSimState() {
- return mSimState;
- }
-
public void setAirplaneMode(boolean airplaneMode) {
mCurrentState.airplaneMode = airplaneMode;
notifyListenersIfNecessary();
@@ -239,10 +233,13 @@
String contentDescription = getStringIfExists(getContentDescription());
String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
+
+ boolean showDataIcon = mCurrentState.dataConnected && mCurrentState.inetForNetwork != 0
+ || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
+
// Only send data sim callbacks to QS.
if (mCurrentState.dataSim) {
- int qsTypeIcon = mCurrentState.dataConnected ?
- icons.mQsDataType[mCurrentState.inetForNetwork] : 0;
+ int qsTypeIcon = showDataIcon ? icons.mQsDataType[mCurrentState.inetForNetwork] : 0;
int length = mSignalsChangedCallbacks.size();
for (int i = 0; i < length; i++) {
mSignalsChangedCallbacks.get(i).onMobileDataSignalChanged(mCurrentState.enabled
@@ -257,8 +254,6 @@
icons.mIsWide && qsTypeIcon != 0);
}
}
- boolean showDataIcon = mCurrentState.dataConnected && mCurrentState.inetForNetwork != 0
- || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
int typeIcon = showDataIcon ? icons.mDataType : 0;
int signalClustersLength = mSignalClusters.size();
for (int i = 0; i < signalClustersLength; i++) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 9b95d5c..260dea0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -69,6 +69,8 @@
protected TelephonyManager mMockTm;
protected Config mConfig;
+ protected int mSubId;
+
private NetworkCapabilities mNetCapabilities;
@Override
@@ -100,13 +102,13 @@
protected void setupNetworkController() {
// For now just pretend to be the data sim, so we can test that too.
- final int subId = SubscriptionManager.getDefaultDataSubId();
+ mSubId = SubscriptionManager.getDefaultDataSubId();
SubscriptionInfo subscription = mock(SubscriptionInfo.class);
List<SubscriptionInfo> subs = new ArrayList<SubscriptionInfo>();
- when(subscription.getSubscriptionId()).thenReturn(subId);
+ when(subscription.getSubscriptionId()).thenReturn(mSubId);
subs.add(subscription);
mNetworkController.setCurrentSubscriptions(subs);
- mMobileSignalController = mNetworkController.mMobileSignalControllers.get(subId);
+ mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
mPhoneStateListener = mMobileSignalController.mPhoneStateListener;
mSignalCluster = mock(SignalCluster.class);
mNetworkSignalChangedCallback = mock(NetworkSignalChangedCallback.class);
@@ -291,10 +293,6 @@
assertEquals("Visibility in status bar", visible, (boolean) visibleArg.getValue());
}
- protected void assertSimStateEquals(IccCardConstants.State expected) {
- assertEquals("Sim state", expected, mMobileSignalController.getSimState());
- }
-
protected void assertNetworkNameEquals(String expected) {
assertEquals("Network name", expected, mNetworkController.getMobileNetworkName());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 65b0971..7fa3f68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -25,6 +25,7 @@
import android.telephony.TelephonyManager;
import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.R;
@@ -254,16 +255,6 @@
setCdmaRoaming(false);
}
- public void testOnReceive_updateSimState_noSim() {
- Intent intent = new Intent();
- intent.setAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
-
- mNetworkController.onReceive(mContext, intent);
-
- assertSimStateEquals(IccCardConstants.State.ABSENT);
- }
-
public void testOnReceive_stringsUpdatedAction_spn() {
String expectedMNetworkName = "Test";
Intent intent = createStringsUpdatedIntent(true /* showSpn */,
@@ -344,6 +335,7 @@
intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
+ intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mSubId);
return intent;
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index ed43d8e..1aa7366 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -894,7 +894,10 @@
}
void doInvalidatePanelMenu(int featureId) {
- PanelFeatureState st = getPanelState(featureId, true);
+ PanelFeatureState st = getPanelState(featureId, false);
+ if (st == null) {
+ return;
+ }
Bundle savedActionViewStates = null;
if (st.menu != null) {
savedActionViewStates = new Bundle();
@@ -933,8 +936,8 @@
// The panel key was pushed, so set the chording key
mPanelChordingKey = keyCode;
- PanelFeatureState st = getPanelState(featureId, true);
- if (!st.isOpen) {
+ PanelFeatureState st = getPanelState(featureId, false);
+ if (st != null && !st.isOpen) {
return preparePanel(st, event);
}
}
@@ -952,12 +955,14 @@
if (mPanelChordingKey != 0) {
mPanelChordingKey = 0;
- if (event.isCanceled() || (mDecor != null && mDecor.mActionMode != null)) {
+ final PanelFeatureState st = getPanelState(featureId, false);
+
+ if (event.isCanceled() || (mDecor != null && mDecor.mActionMode != null) ||
+ (st == null)) {
return;
}
boolean playSoundEffect = false;
- final PanelFeatureState st = getPanelState(featureId, true);
if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null &&
mDecorContentParent.canShowOverflowMenu() &&
!ViewConfiguration.get(getContext()).hasPermanentMenuKey()) {
@@ -1056,7 +1061,7 @@
@Override
public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
- return performPanelShortcut(getPanelState(featureId, true), keyCode, event, flags);
+ return performPanelShortcut(getPanelState(featureId, false), keyCode, event, flags);
}
private boolean performPanelShortcut(PanelFeatureState st, int keyCode, KeyEvent event,
@@ -1149,11 +1154,11 @@
mInvalidatePanelMenuRunnable.run();
}
- final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
+ final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
// If we don't have a menu or we're waiting for a full content refresh,
// forget it. This is a lingering event that no longer matters.
- if (st.menu != null && !st.refreshMenuContent &&
+ if (st != null && st.menu != null && !st.refreshMenuContent &&
cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu);
mDecorContentParent.showOverflowMenu();
@@ -1161,15 +1166,19 @@
}
} else {
mDecorContentParent.hideOverflowMenu();
- if (cb != null && !isDestroyed()) {
- final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
+ final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+ if (st != null && cb != null && !isDestroyed()) {
cb.onPanelClosed(FEATURE_ACTION_BAR, st.menu);
}
}
return;
}
- PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
+ PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+
+ if (st == null) {
+ return;
+ }
// Save the future expanded mode state since closePanel will reset it
boolean newExpandedMode = toggleMenuMode ? !st.isInExpandedMode : st.isInExpandedMode;
@@ -2302,8 +2311,8 @@
// combination such as Control+C. Temporarily prepare the panel then mark it
// unprepared again when finished to ensure that the panel will again be prepared
// the next time it is shown for real.
- if (mPreparedPanel == null) {
- PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
+ PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+ if (st != null && mPreparedPanel == null) {
preparePanel(st, ev);
handled = performPanelShortcut(st, ev.getKeyCode(), ev,
Menu.FLAG_PERFORM_NO_CLOSE);
@@ -3156,7 +3165,7 @@
// If the user is chording a menu shortcut, release the chord since
// this window lost focus
- if (!hasWindowFocus && mPanelChordingKey != 0) {
+ if (hasFeature(FEATURE_OPTIONS_PANEL) && !hasWindowFocus && mPanelChordingKey != 0) {
closePanel(FEATURE_OPTIONS_PANEL);
}
@@ -3906,8 +3915,8 @@
@Override
public boolean isShortcutKey(int keyCode, KeyEvent event) {
- PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
- return st.menu != null && st.menu.isShortcutKey(keyCode, event);
+ PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+ return st != null && st.menu != null && st.menu.isShortcutKey(keyCode, event);
}
private void updateDrawable(int featureId, DrawableFeatureState st, boolean fromResume) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 7124e5b..d4032cc 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1723,7 +1723,6 @@
case TYPE_STATUS_BAR_PANEL:
case TYPE_STATUS_BAR_SUB_PANEL:
case TYPE_SYSTEM_DIALOG:
- case TYPE_UNIVERSE_BACKGROUND:
case TYPE_VOLUME_OVERLAY:
case TYPE_PRIVATE_PRESENTATION:
break;
@@ -1822,8 +1821,6 @@
return 2;
}
switch (type) {
- case TYPE_UNIVERSE_BACKGROUND:
- return 1;
case TYPE_PRIVATE_PRESENTATION:
return 2;
case TYPE_WALLPAPER:
@@ -1935,11 +1932,6 @@
}
@Override
- public int getAboveUniverseLayer() {
- return windowTypeToLayerLw(TYPE_SYSTEM_ERROR);
- }
-
- @Override
public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
if (mHasNavigationBar) {
// For a basic navigation bar, when we are in landscape mode we place
@@ -1997,7 +1989,6 @@
case TYPE_NAVIGATION_BAR:
case TYPE_WALLPAPER:
case TYPE_DREAM:
- case TYPE_UNIVERSE_BACKGROUND:
case TYPE_KEYGUARD_SCRIM:
return false;
default:
@@ -3769,8 +3760,7 @@
+ mOverscanScreenWidth;
pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
+ mOverscanScreenHeight;
- } else if (attrs.type == TYPE_BOOT_PROGRESS
- || attrs.type == TYPE_UNIVERSE_BACKGROUND) {
+ } else if (attrs.type == TYPE_BOOT_PROGRESS) {
// Boot progress screen always covers entire display.
pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index dced99a..06f4def 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1382,6 +1382,14 @@
sc.zStart = limit_ptr[4];
sc.zEnd = limit_ptr[5];
sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
+ sc.arrayStart = 0;
+ sc.arrayEnd = 0;
+ sc.array2Start = 0;
+ sc.array2End = 0;
+ sc.array3Start = 0;
+ sc.array3End = 0;
+ sc.array4Start = 0;
+ sc.array4End = 0;
sca = ≻
}
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index fddb54e..d6abce9 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -55,7 +55,7 @@
private static final int EVENT_AUTO_TIME_CHANGED = 1;
private static final int EVENT_POLL_NETWORK_TIME = 2;
- private static final int EVENT_NETWORK_CONNECTED = 3;
+ private static final int EVENT_NETWORK_CHANGED = 3;
private static final String ACTION_POLL =
"com.android.server.NetworkTimeUpdateService.action.POLL";
@@ -248,18 +248,8 @@
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
- // There is connectivity
- final ConnectivityManager connManager = (ConnectivityManager) context
- .getSystemService(Context.CONNECTIVITY_SERVICE);
- final NetworkInfo netInfo = connManager.getActiveNetworkInfo();
- if (netInfo != null) {
- // Verify that it's a WIFI connection
- if (netInfo.getState() == NetworkInfo.State.CONNECTED &&
- (netInfo.getType() == ConnectivityManager.TYPE_WIFI ||
- netInfo.getType() == ConnectivityManager.TYPE_ETHERNET) ) {
- mHandler.obtainMessage(EVENT_NETWORK_CONNECTED).sendToTarget();
- }
- }
+ // Don't bother checking if we have connectivity, NtpTrustedTime does that for us.
+ mHandler.obtainMessage(EVENT_NETWORK_CHANGED).sendToTarget();
}
}
};
@@ -276,7 +266,7 @@
switch (msg.what) {
case EVENT_AUTO_TIME_CHANGED:
case EVENT_POLL_NETWORK_TIME:
- case EVENT_NETWORK_CONNECTED:
+ case EVENT_NETWORK_CHANGED:
onPollNetworkTime(msg.what);
break;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 9f8d665..059dde1 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -72,7 +72,7 @@
static final boolean DEBUG_DELAYED_SERVICE = ActivityManagerService.DEBUG_SERVICE;
static final boolean DEBUG_DELAYED_STARTS = DEBUG_DELAYED_SERVICE;
static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
- static final boolean LOG_SERVICE_START_STOP = true;
+ static final boolean LOG_SERVICE_START_STOP = false;
static final String TAG = ActivityManagerService.TAG;
static final String TAG_MU = ActivityManagerService.TAG_MU;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2935bc0..b5d2720 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2363,7 +2363,7 @@
return mAppBindArgs;
}
- final void setFocusedActivityLocked(ActivityRecord r) {
+ final void setFocusedActivityLocked(ActivityRecord r, String reason) {
if (mFocusedActivity != r) {
if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedActivityLocked: r=" + r);
mFocusedActivity = r;
@@ -2372,7 +2372,7 @@
} else {
finishRunningVoiceLocked();
}
- mStackSupervisor.setFocusedStack(r);
+ mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity");
if (r != null) {
mWindowManager.setFocusedApp(r.appToken, true);
}
@@ -2396,7 +2396,7 @@
if (stack != null) {
ActivityRecord r = stack.topRunningActivityLocked(null);
if (r != null) {
- setFocusedActivityLocked(r);
+ setFocusedActivityLocked(r, "setFocusedStack");
}
}
}
@@ -2440,7 +2440,7 @@
mHandler.sendMessage(msg);
}
- private final int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
+ private int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
String what, Object obj, ProcessRecord srcApp) {
app.lastActivityTime = now;
@@ -3114,7 +3114,7 @@
return intent;
}
- boolean startHomeActivityLocked(int userId) {
+ boolean startHomeActivityLocked(int userId, String reason) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
@@ -3136,7 +3136,7 @@
aInfo.applicationInfo.uid, true);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
- mStackSupervisor.startHomeActivity(intent, aInfo);
+ mStackSupervisor.startHomeActivity(intent, aInfo, reason);
}
}
@@ -5697,7 +5697,7 @@
startProcessLocked(procs.get(ip), "on-hold", null);
}
}
-
+
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
// Start looking for apps that are abusing wake locks.
Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
@@ -5837,7 +5837,7 @@
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
- stack.activityDestroyedLocked(token);
+ stack.activityDestroyedLocked(token, "activityDestroyed");
}
}
}
@@ -5948,7 +5948,7 @@
throw new IllegalArgumentException("File descriptors passed in options");
}
}
-
+
synchronized(this) {
int callingUid = Binder.getCallingUid();
int origUserId = userId;
@@ -5978,7 +5978,7 @@
return getIntentSenderLocked(type, packageName, callingUid, userId,
token, resultWho, requestCode, intents, resolvedTypes, flags, options);
-
+
} catch (RemoteException e) {
throw new SecurityException(e);
}
@@ -8019,7 +8019,7 @@
if (prev != null && prev.isRecentsActivity()) {
task.setTaskToReturnTo(ActivityRecord.RECENTS_ACTIVITY_TYPE);
}
- mStackSupervisor.findTaskToMoveToFrontLocked(task, flags, options);
+ mStackSupervisor.findTaskToMoveToFrontLocked(task, flags, options, "moveTaskToFront");
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -8048,7 +8048,7 @@
mStackSupervisor.showLockTaskToast();
return false;
}
- return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId, null);
+ return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -8154,7 +8154,7 @@
try {
if (DEBUG_STACK) Slog.d(TAG, "moveTaskToStack: moving task=" + taskId + " to stackId="
+ stackId + " toTop=" + toTop);
- mStackSupervisor.moveTaskToStack(taskId, stackId, toTop);
+ mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -8162,12 +8162,14 @@
}
@Override
- public void resizeStack(int stackBoxId, Rect bounds) {
+ public void resizeStack(int stackId, Rect bounds) {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"resizeStackBox()");
long ident = Binder.clearCallingIdentity();
try {
- mWindowManager.resizeStack(stackBoxId, bounds);
+ synchronized (this) {
+ mStackSupervisor.resizeStackLocked(stackId, bounds);
+ }
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -8260,7 +8262,8 @@
|| (task != mStackSupervisor.getFocusedStack().topTask()))) {
throw new IllegalArgumentException("Invalid task, not in foreground");
}
- mStackSupervisor.setLockTaskModeLocked(task, !isSystemInitiated);
+ mStackSupervisor.setLockTaskModeLocked(task, !isSystemInitiated,
+ "startLockTask");
}
}
} finally {
@@ -8345,7 +8348,7 @@
Log.d(TAG, "stopLockTaskMode");
// Stop lock task
synchronized (this) {
- mStackSupervisor.setLockTaskModeLocked(null, false);
+ mStackSupervisor.setLockTaskModeLocked(null, false, "stopLockTask");
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -10811,7 +10814,7 @@
// Start up initial activity.
mBooting = true;
- startHomeActivityLocked(mCurrentUserId);
+ startHomeActivityLocked(mCurrentUserId, "systemReady");
try {
if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
@@ -18366,7 +18369,7 @@
return true;
}
- mStackSupervisor.setLockTaskModeLocked(null, false);
+ mStackSupervisor.setLockTaskModeLocked(null, false, "startUser");
final UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
if (userInfo == null) {
@@ -18623,7 +18626,7 @@
void moveUserToForeground(UserStartedState uss, int oldUserId, int newUserId) {
boolean homeInFront = mStackSupervisor.switchUserLocked(newUserId, uss);
if (homeInFront) {
- startHomeActivityLocked(newUserId);
+ startHomeActivityLocked(newUserId, "moveUserToFroreground");
} else {
mStackSupervisor.resumeTopActivitiesLocked();
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index af6a314..a3676f9 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -127,6 +127,10 @@
long pauseTime; // last time we started pausing the activity
long launchTickTime; // base time for launch tick messages
Configuration configuration; // configuration activity was last running in
+ // Overridden configuration by the activity stack
+ // WARNING: Reference points to {@link ActivityStack#mOverrideConfig}, so its internal state
+ // should never be altered directly.
+ Configuration stackConfigOverride;
CompatibilityInfo compat;// last used compatibility mode
ActivityRecord resultTo; // who started this entry, so will get our reply
final String resultWho; // additional identifier for use by resultTo.
@@ -204,6 +208,7 @@
pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
pw.print(prefix); pw.print("config="); pw.println(configuration);
+ pw.print(prefix); pw.print("stackConfigOverride="); pw.println(stackConfigOverride);
if (resultTo != null || resultWho != null) {
pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
pw.print(" resultWho="); pw.print(resultWho);
@@ -394,6 +399,8 @@
resolvedType = _resolvedType;
componentSpecified = _componentSpecified;
configuration = _configuration;
+ stackConfigOverride = (container != null)
+ ? container.mStack.mOverrideConfig : Configuration.EMPTY;
resultTo = _resultTo;
resultWho = _resultWho;
requestCode = _reqCode;
@@ -515,7 +522,7 @@
void setTask(TaskRecord newTask, TaskRecord taskToAffiliateWith) {
if (task != null && task.removeActivity(this)) {
if (task != newTask) {
- task.stack.removeTask(task);
+ task.stack.removeTask(task, "setTask");
} else {
Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" +
(newTask == null ? null : newTask.stack));
@@ -1066,10 +1073,7 @@
static ActivityRecord isInStackLocked(IBinder token) {
final ActivityRecord r = ActivityRecord.forToken(token);
- if (r != null) {
- return r.task.stack.isInStackLocked(token);
- }
- return null;
+ return (r != null) ? r.task.stack.isInStackLocked(r) : null;
}
static ActivityStack getStackLocked(IBinder token) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 5d21de7..dbd787b 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -235,6 +235,8 @@
/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;
+ Configuration mOverrideConfig;
+
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;
@@ -292,7 +294,7 @@
// so we need to be conservative and assume it isn't.
Slog.w(TAG, "Activity destroy timeout for " + r);
synchronized (mService) {
- activityDestroyedLocked(r != null ? r.appToken : null);
+ activityDestroyedLocked(r != null ? r.appToken : null, "destroyTimeout");
}
} break;
case STOP_TIMEOUT_MSG: {
@@ -348,6 +350,7 @@
mStackId = activityContainer.mStackId;
mCurrentUser = mService.mCurrentUserId;
mRecentTasks = recentTasks;
+ mOverrideConfig = Configuration.EMPTY;
}
/**
@@ -450,13 +453,18 @@
ActivityRecord isInStackLocked(IBinder token) {
final ActivityRecord r = ActivityRecord.forToken(token);
- if (r != null) {
- final TaskRecord task = r.task;
- if (task != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
- if (task.stack != this) Slog.w(TAG,
+ return isInStackLocked(r);
+ }
+
+ ActivityRecord isInStackLocked(ActivityRecord r) {
+ if (r == null) {
+ return null;
+ }
+ final TaskRecord task = r.task;
+ if (task != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
+ if (task.stack != this) Slog.w(TAG,
"Illegal state! task does not point to stack it is in.");
- return r;
- }
+ return r;
}
return null;
}
@@ -476,10 +484,10 @@
mActivityContainer.mActivityDisplay.mDisplayId == Display.DEFAULT_DISPLAY;
}
- final void moveToFront() {
+ final void moveToFront(String reason) {
if (isAttached()) {
if (isOnHomeDisplay()) {
- mStackSupervisor.moveHomeStack(isHomeStack());
+ mStackSupervisor.moveHomeStack(isHomeStack(), reason);
}
mStacks.remove(this);
mStacks.add(this);
@@ -1497,7 +1505,7 @@
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
- mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
+ mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "noMoreActivities");
}
next.delayedResume = false;
@@ -1533,7 +1541,7 @@
"resumeTopActivityLocked: Launching home next");
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
- return mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
+ return mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
}
}
@@ -1819,11 +1827,8 @@
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
}
- EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
- next.userId, System.identityHashCode(next),
- next.task.taskId, next.shortComponentName + " top="
- + mStacks.get(mStacks.size() - 1).mStackId + " Callers="
- + Debug.getCallers(6));
+ EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
+ System.identityHashCode(next), next.task.taskId, next.shortComponentName);
next.sleeping = false;
mService.showAskCompatModeDialogLocked(next);
@@ -2198,7 +2203,7 @@
}
final int targetTaskId = targetTask.taskId;
- mWindowManager.setAppGroupId(target.appToken, targetTaskId);
+ mWindowManager.setAppTask(target.appToken, targetTaskId);
boolean noOptions = canMoveOptions;
final int start = replyChainEnd < 0 ? i : replyChainEnd;
@@ -2223,7 +2228,7 @@
p.setTask(targetTask, null);
targetTask.addActivityAtBottom(p);
- mWindowManager.setAppGroupId(p.appToken, targetTaskId);
+ mWindowManager.setAppTask(p.appToken, targetTaskId);
}
mWindowManager.moveTaskToBottom(targetTaskId);
@@ -2363,7 +2368,7 @@
new RuntimeException("here").fillInStackTrace());
if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p + " from " + srcPos
+ " in to resetting task " + task);
- mWindowManager.setAppGroupId(p.appToken, taskId);
+ mWindowManager.setAppTask(p.appToken, taskId);
}
mWindowManager.moveTaskToTop(taskId);
if (VALIDATE_TOKENS) {
@@ -2472,18 +2477,19 @@
r.addResultLocked(null, resultWho, requestCode, resultCode, data);
}
- private void adjustFocusedActivityLocked(ActivityRecord r) {
+ private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
ActivityRecord next = topRunningActivityLocked(null);
if (next != r) {
final TaskRecord task = r.task;
if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
- mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
+ mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(),
+ reason + " adjustFocus");
}
}
ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
if (top != null) {
- mService.setFocusedActivityLocked(top);
+ mService.setFocusedActivityLocked(top, reason + " adjustTopFocus");
}
}
}
@@ -2507,7 +2513,7 @@
}
if (r.app != null && r.app.thread != null) {
- adjustFocusedActivityLocked(r);
+ adjustFocusedActivityLocked(r, "stopActivity");
r.resumeKeyDispatchingLocked();
try {
r.stopped = false;
@@ -2711,7 +2717,7 @@
r.pauseKeyDispatchingLocked();
- adjustFocusedActivityLocked(r);
+ adjustFocusedActivityLocked(r, "finishActivity");
finishActivityResultsLocked(r, resultCode, resultData);
@@ -3014,7 +3020,7 @@
r.finishLaunchTickingLocked();
}
- private void removeActivityFromHistoryLocked(ActivityRecord r) {
+ private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
mStackSupervisor.removeChildActivityContainers(r);
finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
r.makeFinishing();
@@ -3039,9 +3045,9 @@
"removeActivityFromHistoryLocked: last activity removed from " + this);
if (mStackSupervisor.isFrontStack(this) && task == topTask() &&
task.isOverHomeStack()) {
- mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
+ mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason);
}
- removeTask(task);
+ removeTask(task, reason);
}
cleanUpActivityServicesLocked(r);
r.removeUriPermissionsLocked();
@@ -3206,7 +3212,7 @@
// up.
//Slog.w(TAG, "Exception thrown during finish", e);
if (r.finishing) {
- removeActivityFromHistoryLocked(r);
+ removeActivityFromHistoryLocked(r, reason + " exceptionInScheduleDestroy");
removedFromHistory = true;
skipDestroy = true;
}
@@ -3236,7 +3242,7 @@
} else {
// remove this record from the history.
if (r.finishing) {
- removeActivityFromHistoryLocked(r);
+ removeActivityFromHistoryLocked(r, reason + " hadNoApp");
removedFromHistory = true;
} else {
if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (no app)");
@@ -3255,7 +3261,7 @@
return removedFromHistory;
}
- final void activityDestroyedLocked(IBinder token) {
+ final void activityDestroyedLocked(IBinder token, String reason) {
final long origId = Binder.clearCallingIdentity();
try {
ActivityRecord r = ActivityRecord.forToken(token);
@@ -3264,10 +3270,10 @@
}
if (DEBUG_CONTAINERS) Slog.d(TAG, "activityDestroyedLocked: r=" + r);
- if (isInStackLocked(token) != null) {
+ if (isInStackLocked(r) != null) {
if (r.state == ActivityState.DESTROYING) {
cleanUpActivityLocked(r, true, false);
- removeActivityFromHistoryLocked(r);
+ removeActivityFromHistoryLocked(r, reason);
}
}
mStackSupervisor.resumeTopActivitiesLocked();
@@ -3403,7 +3409,7 @@
mService.updateUsageStats(r, false);
}
}
- removeActivityFromHistoryLocked(r);
+ removeActivityFromHistoryLocked(r, "appDied");
} else {
// We have the current state for this activity, so
@@ -3472,15 +3478,15 @@
}
}
- final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
+ final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, Bundle options,
+ String reason) {
if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
final int numTasks = mTaskHistory.size();
final int index = mTaskHistory.indexOf(tr);
if (numTasks == 0 || index < 0) {
// nothing to do!
- if (reason != null &&
- (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
+ if (noAnimation) {
ActivityOptions.abort(options);
} else {
updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
@@ -3491,11 +3497,10 @@
// Shift all activities with this task up to the top
// of the stack, keeping them in the same internal order.
insertTaskAtTop(tr);
- moveToFront();
+ moveToFront(reason);
if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
- if (reason != null &&
- (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
+ if (noAnimation) {
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
ActivityRecord r = topRunningActivityLocked(null);
if (r != null) {
@@ -3525,7 +3530,7 @@
* @param taskId The taskId to collect and move to the bottom.
* @return Returns true if the move completed, false if not.
*/
- final boolean moveTaskToBackLocked(int taskId, ActivityRecord reason) {
+ final boolean moveTaskToBackLocked(int taskId) {
final TaskRecord tr = taskForIdLocked(taskId);
if (tr == null) {
Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId);
@@ -3580,16 +3585,7 @@
}
}
- if (reason != null &&
- (reason.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
- mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
- ActivityRecord r = topRunningActivityLocked(null);
- if (r != null) {
- mNoAnimActivities.add(r);
- }
- } else {
- mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false);
- }
+ mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false);
mWindowManager.moveTaskToBottom(taskId);
if (VALIDATE_TOKENS) {
@@ -3604,7 +3600,7 @@
}
final int taskToReturnTo = tr.getTaskToReturnTo();
tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
- return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null);
+ return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null, "moveTaskToBack");
}
mStackSupervisor.resumeTopActivitiesLocked();
@@ -3643,7 +3639,9 @@
// Short circuit: if the two configurations are the exact same
// object (the common case), then there is nothing to do.
Configuration newConfig = mService.mConfiguration;
- if (r.configuration == newConfig && !r.forceNewConfig) {
+ if (r.configuration == newConfig
+ && r.stackConfigOverride == mOverrideConfig
+ && !r.forceNewConfig) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
"Configuration unchanged in " + r);
return true;
@@ -3659,14 +3657,22 @@
// Okay we now are going to make this activity have the new config.
// But then we need to figure out how it needs to deal with that.
- Configuration oldConfig = r.configuration;
+ final Configuration oldConfig = r.configuration;
+ final Configuration oldStackOverride = r.stackConfigOverride;
r.configuration = newConfig;
+ r.stackConfigOverride = mOverrideConfig;
// Determine what has changed. May be nothing, if this is a config
// that has come back from the app after going idle. In that case
// we just want to leave the official config object now in the
// activity and do nothing else.
- final int changes = oldConfig.diff(newConfig);
+ int stackChanges = oldStackOverride.diff(mOverrideConfig);
+ if (stackChanges == 0 && !oldStackOverride.equals(mOverrideConfig)) {
+ // Assume size change if diff didn't report any changes,
+ // but configurations are not equal.
+ stackChanges = ActivityInfo.CONFIG_SCREEN_SIZE;
+ }
+ final int changes = oldConfig.diff(newConfig) | stackChanges;
if (changes == 0 && !r.forceNewConfig) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
"Configuration no differences in " + r);
@@ -3770,8 +3776,9 @@
(andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
+ r);
r.forceNewConfig = false;
- r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
- changes, !andResume, new Configuration(mService.mConfiguration));
+ r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes,
+ !andResume, new Configuration(mService.mConfiguration),
+ new Configuration(mOverrideConfig));
// Note: don't need to call pauseIfSleepingLocked() here, because
// the caller will only pass in 'andResume' if this activity is
// currently resumed, which implies we aren't sleeping.
@@ -4046,7 +4053,7 @@
return starting;
}
- void removeTask(TaskRecord task) {
+ void removeTask(TaskRecord task, String reason) {
mStackSupervisor.endLockTaskModeIfTaskEnding(task);
mWindowManager.removeTask(task.taskId);
final ActivityRecord r = mResumedActivity;
@@ -4084,7 +4091,7 @@
if (mTaskHistory.isEmpty()) {
if (DEBUG_STACK) Slog.i(TAG, "removeTask: moving to back stack=" + this);
if (isOnHomeDisplay()) {
- mStackSupervisor.moveHomeStack(!isHomeStack());
+ mStackSupervisor.moveHomeStack(!isHomeStack(), reason + " leftTaskHistoryEmpty");
}
if (mStacks != null) {
mStacks.remove(this);
@@ -4132,4 +4139,10 @@
return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
+ " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}";
}
+
+ boolean updateOverrideConfiguration(Configuration newConfig) {
+ Configuration oldConfig = mOverrideConfig;
+ mOverrideConfig = (newConfig == null) ? Configuration.EMPTY : newConfig;
+ return !mOverrideConfig.equals(oldConfig);
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4cf8f00..4674cc2 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -63,6 +63,7 @@
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.graphics.Point;
+import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.hardware.display.DisplayManagerGlobal;
@@ -399,7 +400,7 @@
return false;
}
- void moveHomeStack(boolean toFront) {
+ void moveHomeStack(boolean toFront, String reason) {
ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
final int topNdx = stacks.size() - 1;
if (topNdx <= 0) {
@@ -417,7 +418,7 @@
}
EventLog.writeEvent(EventLogTags.AM_HOME_STACK_MOVED,
mCurrentUser, toFront ? 1 : 0, stacks.get(topNdx).getStackId(),
- mFocusedStack == null ? -1 : mFocusedStack.getStackId());
+ mFocusedStack == null ? -1 : mFocusedStack.getStackId(), reason);
if (mService.mBooting || !mService.mBooted) {
final ActivityRecord r = topRunningActivityLocked();
@@ -427,16 +428,16 @@
}
}
- void moveHomeStackTaskToTop(int homeStackTaskType) {
+ void moveHomeStackTaskToTop(int homeStackTaskType, String reason) {
if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
mWindowManager.showRecentApps();
return;
}
- moveHomeStack(true);
+ moveHomeStack(true, reason);
mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
}
- boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev) {
+ boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev, String reason) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
@@ -446,7 +447,7 @@
mWindowManager.showRecentApps();
return false;
}
- moveHomeStackTaskToTop(homeStackTaskType);
+ moveHomeStackTaskToTop(homeStackTaskType, reason);
if (prev != null) {
prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
@@ -454,10 +455,10 @@
ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
// if (r != null && (r.isHomeActivity() || r.isRecentsActivity())) {
if (r != null && r.isHomeActivity()) {
- mService.setFocusedActivityLocked(r);
+ mService.setFocusedActivityLocked(r, reason);
return resumeTopActivitiesLocked(mHomeStack, prev, null);
}
- return mService.startHomeActivityLocked(mCurrentUser);
+ return mService.startHomeActivityLocked(mCurrentUser, reason);
}
TaskRecord anyTaskForIdLocked(int id) {
@@ -829,8 +830,8 @@
return aInfo;
}
- void startHomeActivity(Intent intent, ActivityInfo aInfo) {
- moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE);
+ void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
+ moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null,
0, 0, 0, null, false, null, null, null);
}
@@ -874,8 +875,7 @@
} else {
stack = container.mStack;
}
- stack.mConfigWillChange = config != null
- && mService.mConfiguration.diff(config) != 0;
+ stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG,
"Starting activity when config will change = " + stack.mConfigWillChange);
@@ -1181,9 +1181,9 @@
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
- r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
- r.icicle, r.persistentState, results, newIntents, !andResume,
- mService.isNextTransitionForward(), profilerInfo);
+ new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
+ r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
+ newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
// This may be a heavy-weight process! Note that the package
@@ -1581,7 +1581,7 @@
return mHomeStack;
}
- void setFocusedStack(ActivityRecord r) {
+ void setFocusedStack(ActivityRecord r, String reason) {
if (r != null) {
final TaskRecord task = r.task;
boolean isHomeActivity = !r.isApplicationActivity();
@@ -1592,11 +1592,11 @@
final ActivityRecord parent = task.stack.mActivityContainer.mParentActivity;
isHomeActivity = parent != null && parent.isHomeActivity();
}
- moveHomeStack(isHomeActivity);
+ moveHomeStack(isHomeActivity, reason);
}
}
- final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,
+ final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, Bundle options, TaskRecord inTask) {
final Intent intent = r.intent;
@@ -1807,6 +1807,7 @@
ActivityStack targetStack;
intent.setFlags(launchFlags);
+ final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0;
// We may want to try to place the new activity in to an existing task. We always
// do this if the target activity is singleTask or singleInstance; we will also do
@@ -1840,7 +1841,7 @@
targetStack.mLastPausedActivity = null;
if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack
+ " from " + intentActivity);
- targetStack.moveToFront();
+ targetStack.moveToFront("intentActivityFound");
if (intentActivity.task.intent == null) {
// This task was started because of movement of
// the activity based on affinity... now that we
@@ -1869,7 +1870,8 @@
intentActivity.setTaskToAffiliateWith(sourceRecord.task);
}
movedHome = true;
- targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
+ targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation,
+ options, "bringingFoundTaskToFront");
if ((launchFlags &
(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
@@ -2067,7 +2069,7 @@
newTask = true;
targetStack = adjustStackFocus(r, newTask);
if (!launchTaskBehind) {
- targetStack.moveToFront();
+ targetStack.moveToFront("startingNewTask");
}
if (reuseTask == null) {
r.setTask(targetStack.createTaskRecord(getNextTaskId(),
@@ -2096,10 +2098,11 @@
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
targetStack = sourceTask.stack;
- targetStack.moveToFront();
+ targetStack.moveToFront("sourceStackToFront");
final TaskRecord topTask = targetStack.topTask();
if (topTask != sourceTask) {
- targetStack.moveTaskToFrontLocked(sourceTask, r, options);
+ targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options,
+ "sourceTaskToFront");
}
if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
// In this case, we are adding the activity to an existing
@@ -2153,7 +2156,7 @@
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
targetStack = inTask.stack;
- targetStack.moveTaskToFrontLocked(inTask, r, options);
+ targetStack.moveTaskToFrontLocked(inTask, noAnimation, options, "inTaskToFront");
// Check whether we should actually launch the new activity in to the task,
// or just reuse the current activity on top.
@@ -2189,7 +2192,7 @@
// of a new task... just put it in the top task, though these days
// this case should never happen.
targetStack = adjustStackFocus(r, newTask);
- targetStack.moveToFront();
+ targetStack.moveToFront("addingToTopTask");
ActivityRecord prev = targetStack.topActivity();
r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(),
r.info, intent, null, null, true), null);
@@ -2212,7 +2215,7 @@
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
if (!launchTaskBehind) {
// Don't set focus on an activity that's going to the back.
- mService.setFocusedActivityLocked(r);
+ mService.setFocusedActivityLocked(r, "startedActivity");
}
return ActivityManager.START_SUCCESS;
}
@@ -2509,7 +2512,7 @@
}
}
- void findTaskToMoveToFrontLocked(TaskRecord task, int flags, Bundle options) {
+ void findTaskToMoveToFrontLocked(TaskRecord task, int flags, Bundle options, String reason) {
if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
mUserLeaving = true;
}
@@ -2518,7 +2521,7 @@
// we'll just indicate that this task returns to the home task.
task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
}
- task.stack.moveTaskToFrontLocked(task, null, options);
+ task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options, reason);
if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
+ task.stack);
}
@@ -2595,6 +2598,27 @@
}
}
+ void resizeStackLocked(int stackId, Rect bounds) {
+ final ActivityStack stack = getStack(stackId);
+ if (stack == null) {
+ Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
+ return;
+ }
+ final Configuration overrideConfig = mWindowManager.resizeStack(stackId, bounds);
+ if (stack.updateOverrideConfiguration(overrideConfig)) {
+ final ActivityRecord r = stack.topRunningActivityLocked(null);
+ if (r != null) {
+ final boolean updated = stack.ensureActivityConfigurationLocked(r, 0);
+ // And we need to make sure at this point that all other activities
+ // are made visible with the correct configuration.
+ ensureActivitiesVisibleLocked(r, 0);
+ if (!updated) {
+ resumeTopActivitiesLocked(stack, null, null);
+ }
+ }
+ }
+ }
+
ActivityStack createStackOnDisplay(int stackId, int displayId) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
@@ -2643,7 +2667,7 @@
// display.
stack = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
// Restore home stack to top.
- moveHomeStack(true);
+ moveHomeStack(true, "restoreRecentTask");
if (DEBUG_RECENTS)
Slog.v(TAG, "Created stack=" + stack + " for recents restoration.");
}
@@ -2670,7 +2694,7 @@
return true;
}
- void moveTaskToStack(int taskId, int stackId, boolean toTop) {
+ void moveTaskToStackLocked(int taskId, int stackId, boolean toTop) {
final TaskRecord task = anyTaskForIdLocked(taskId);
if (task == null) {
return;
@@ -2680,7 +2704,7 @@
Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
return;
}
- task.stack.removeTask(task);
+ task.stack.removeTask(task, "moveTaskToStack");
stack.addTask(task, toTop, true);
mWindowManager.addTask(taskId, stackId, toTop);
resumeTopActivitiesLocked();
@@ -3046,14 +3070,14 @@
}
final boolean homeInFront = stack.isHomeStack();
if (stack.isOnHomeDisplay()) {
- moveHomeStack(homeInFront);
+ moveHomeStack(homeInFront, "switchUserOnHomeDisplay");
TaskRecord task = stack.topTask();
if (task != null) {
mWindowManager.moveTaskToTop(task.taskId);
}
} else {
// Stack was moved to another display while user was swapped out.
- resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
+ resumeHomeStackTask(HOME_ACTIVITY_TYPE, null, "switchUserOnOtherDisplay");
}
return homeInFront;
}
@@ -3448,7 +3472,7 @@
mLockTaskNotify.showToast(mLockTaskIsLocked);
}
- void setLockTaskModeLocked(TaskRecord task, boolean isLocked) {
+ void setLockTaskModeLocked(TaskRecord task, boolean isLocked, String reason) {
if (task == null) {
// Take out of lock task mode if necessary
if (mLockTaskModeTask != null) {
@@ -3465,7 +3489,7 @@
return;
}
mLockTaskModeTask = task;
- findTaskToMoveToFrontLocked(task, 0, null);
+ findTaskToMoveToFrontLocked(task, 0, null, reason);
resumeTopActivitiesLocked();
final Message lockTaskMsg = Message.obtain();
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 41499be..c376744 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -94,4 +94,4 @@
30043 am_focused_activity (User|1|5),(Component Name|3)
# Home Stack brought to front or rear
-30044 am_home_stack_moved (User|1|5),(To Front|1|5),(Top Stack Id|1|5),(Focused Stack Id|1|5)
+30044 am_home_stack_moved (User|1|5),(To Front|1|5),(Top Stack Id|1|5),(Focused Stack Id|1|5),(Reason|3)
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index af5ed83..f900d0d 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -163,6 +163,7 @@
/**
* Force evaluation even if it has succeeded in the past.
* arg1 = UID responsible for requesting this reeval. Will be billed for data.
+ * arg2 = Number of evaluation attempts to make. (If 0, make INITIAL_ATTEMPTS attempts.)
*/
public static final int CMD_FORCE_REEVALUATION = BASE + 8;
@@ -212,11 +213,14 @@
// Negative values disable reevaluation.
private static final String REEVALUATE_DELAY_PROPERTY = "persist.netmon.reeval_delay";
- // Default to 5s reevaluation delay.
+ // When connecting, attempt to validate 3 times, pausing 5s between them.
private static final int DEFAULT_REEVALUATE_DELAY_MS = 5000;
- private static final int MAX_RETRIES = 10;
- // Between groups of MAX_RETRIES evaluation attempts, pause 10 mins in hopes ISP outage passes.
+ private static final int INITIAL_ATTEMPTS = 3;
+ // If a network is not validated, make one attempt every 10 mins to see if it starts working.
private static final int REEVALUATE_PAUSE_MS = 10*60*1000;
+ private static final int PERIODIC_ATTEMPTS = 1;
+ // When an application calls reportBadNetwork, only make one attempt.
+ private static final int REEVALUATE_ATTEMPTS = 1;
private final int mReevaluateDelayMs;
private int mReevaluateToken = 0;
private static final int INVALID_UID = -1;
@@ -236,6 +240,14 @@
// Set if the user explicitly selected "Do not use this network" in captive portal sign-in app.
private boolean mUserDoesNotWant = false;
+ // How many times we should attempt validation. Only checked in EvaluatingState; must be set
+ // before entering EvaluatingState. Note that whatever code causes us to transition to
+ // EvaluatingState last decides how many attempts will be made, so if one codepath were to
+ // enter EvaluatingState with a specific number of attempts, and then another were to enter it
+ // with a different number of attempts, the second number would be used. This is not currently
+ // a problem because EvaluatingState is not reentrant.
+ private int mMaxAttempts;
+
public boolean systemReady = false;
private final State mDefaultState = new DefaultState();
@@ -305,6 +317,7 @@
return HANDLED;
case CMD_NETWORK_CONNECTED:
if (DBG) log("Connected");
+ mMaxAttempts = INITIAL_ATTEMPTS;
transitionTo(mEvaluatingState);
return HANDLED;
case CMD_NETWORK_DISCONNECTED:
@@ -318,6 +331,7 @@
case CMD_FORCE_REEVALUATION:
if (DBG) log("Forcing reevaluation");
mUidResponsibleForReeval = message.arg1;
+ mMaxAttempts = message.arg2 != 0 ? message.arg2 : REEVALUATE_ATTEMPTS;
transitionTo(mEvaluatingState);
return HANDLED;
case CMD_CAPTIVE_PORTAL_APP_FINISHED:
@@ -347,7 +361,10 @@
public void enter() {
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
NETWORK_TEST_RESULT_INVALID, 0, mNetworkAgentInfo));
- if (!mUserDoesNotWant) sendMessageDelayed(CMD_FORCE_REEVALUATION, REEVALUATE_PAUSE_MS);
+ if (!mUserDoesNotWant) {
+ sendMessageDelayed(CMD_FORCE_REEVALUATION, 0 /* no UID */,
+ PERIODIC_ATTEMPTS, REEVALUATE_PAUSE_MS);
+ }
}
@Override
@@ -413,11 +430,11 @@
// Being in the EvaluatingState State indicates the Network is being evaluated for internet
// connectivity.
private class EvaluatingState extends State {
- private int mRetries;
+ private int mAttempt;
@Override
public void enter() {
- mRetries = 0;
+ mAttempt = 1;
sendMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
if (mUidResponsibleForReeval != INVALID_UID) {
TrafficStats.setThreadStatsUid(mUidResponsibleForReeval);
@@ -454,18 +471,18 @@
transitionTo(mValidatedState);
return HANDLED;
}
- // Note: This call to isCaptivePortal() could take minutes. Resolving the
- // server's IP addresses could hit the DNS timeout and attempting connections
- // to each of the server's several (e.g. 11) IP addresses could each take
- // SOCKET_TIMEOUT_MS. During this time this StateMachine will be unresponsive.
- // isCaptivePortal() could be executed on another Thread if this is found to
- // cause problems.
+ // Note: This call to isCaptivePortal() could take up to a minute. Resolving the
+ // server's IP addresses could hit the DNS timeout, and attempting connections
+ // to each of the server's several IP addresses (currently one IPv4 and one
+ // IPv6) could each take SOCKET_TIMEOUT_MS. During this time this StateMachine
+ // will be unresponsive. isCaptivePortal() could be executed on another Thread
+ // if this is found to cause problems.
int httpResponseCode = isCaptivePortal();
if (httpResponseCode == 204) {
transitionTo(mValidatedState);
} else if (httpResponseCode >= 200 && httpResponseCode <= 399) {
transitionTo(mCaptivePortalState);
- } else if (++mRetries > MAX_RETRIES) {
+ } else if (++mAttempt > mMaxAttempts) {
transitionTo(mOfflineState);
} else if (mReevaluateDelayMs >= 0) {
Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
diff --git a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
index 59d5605..7f48768 100644
--- a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
+++ b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
@@ -62,11 +62,6 @@
void process(ActiveSource newActive, int deviceType) {
// Seq #17
HdmiCecLocalDeviceTv tv = mSource;
- ActiveSource activeSource = tv.getActiveSource();
- if (activeSource.equals(newActive)) {
- invokeCallback(HdmiControlManager.RESULT_SUCCESS);
- return;
- }
HdmiDeviceInfo device = mService.getDeviceInfo(newActive.logicalAddress);
if (device == null) {
tv.startNewDeviceAction(newActive, deviceType);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 43ef457..664f541 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -34,6 +34,7 @@
import android.content.Context;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.HdmiRecordSources;
import android.hardware.hdmi.HdmiTimerRecordSources;
import android.hardware.hdmi.IHdmiControlCallback;
@@ -878,6 +879,17 @@
return oldStatus;
}
+ @ServiceThreadOnly
+ private void updateArcFeatureStatus(int portId, boolean isConnected) {
+ assertRunOnServiceThread();
+ // HEAC 2.4, HEACT 5-15
+ // Should not activate ARC if +5V status is false.
+ HdmiPortInfo portInfo = mService.getPortInfo(portId);
+ if (portInfo.isArcSupported()) {
+ changeArcFeatureEnabled(isConnected);
+ }
+ }
+
private void notifyArcStatusToAudioService(boolean enabled) {
// Note that we don't set any name to ARC.
mService.getAudioManager().setWiredDeviceConnectionState(
@@ -1456,6 +1468,25 @@
}
/**
+ * Returns the {@link HdmiDeviceInfo} instance whose physical address matches
+ * the given routing path. This is the version accessible safely from threads
+ * other than service thread.
+ *
+ * @param path routing path or physical address
+ * @return {@link HdmiDeviceInfo} if the matched info is found; otherwise null
+ */
+ HdmiDeviceInfo getSafeDeviceInfoByPath(int path) {
+ synchronized (mLock) {
+ for (HdmiDeviceInfo info : mSafeAllDeviceInfos) {
+ if (info.getPhysicalAddress() == path) {
+ return info;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
* Whether a device of the specified physical address and logical address exists
* in a device info list. However, both are minimal condition and it could
* be different device from the original one.
@@ -1490,6 +1521,7 @@
// It covers seq #40, #43.
hotplugActions.get(0).pollAllDevicesNow();
}
+ updateArcFeatureStatus(portId, connected);
}
private void removeCecSwitches(int portId) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 9f78c61..49a96d8 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1196,7 +1196,7 @@
}
int activePath = tv.getActivePath();
if (activePath != HdmiDeviceInfo.PATH_INVALID) {
- HdmiDeviceInfo info = tv.getDeviceInfoByPath(activePath);
+ HdmiDeviceInfo info = tv.getSafeDeviceInfoByPath(activePath);
return (info != null) ? info : new HdmiDeviceInfo(activePath, tv.getActivePortId());
}
return null;
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index 722be71..1bbd038 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -38,6 +38,7 @@
private static final int POLLING_INTERVAL_MS = 5000;
private static final int TIMEOUT_COUNT = 3;
+ private static final int AVR_COUNT_MAX = 3;
// State in which waits for next polling
private static final int STATE_WAIT_FOR_NEXT_POLLING = 1;
@@ -48,6 +49,12 @@
private int mTimeoutCount = 0;
+ // Counter used to ensure the connection to AVR is stable. Occasional failure to get
+ // polling response from AVR despite its presence leads to unstable status flipping.
+ // This is a workaround to deal with it, by removing the device only if the removal
+ // is detected {@code AVR_COUNT_MAX} times in a row.
+ private int mAvrStatusCount = 0;
+
/**
* Constructor
*
@@ -148,10 +155,22 @@
BitSet removed = complement(currentInfos, polledResult);
int index = -1;
while ((index = removed.nextSetBit(index + 1)) != -1) {
+ if (index == Constants.ADDR_AUDIO_SYSTEM) {
+ ++mAvrStatusCount;
+ Slog.w(TAG, "Ack not returned from AVR. count: " + mAvrStatusCount);
+ if (mAvrStatusCount < AVR_COUNT_MAX) {
+ continue;
+ }
+ }
Slog.v(TAG, "Remove device by hot-plug detection:" + index);
removeDevice(index);
}
+ // Reset the counter if the ack is returned from AVR.
+ if (!removed.get(Constants.ADDR_AUDIO_SYSTEM)) {
+ mAvrStatusCount = 0;
+ }
+
// Next, check added devices.
BitSet added = complement(polledResult, currentInfos);
index = -1;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 77a1fa9..667d02a 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -117,7 +117,6 @@
public void onStart() {
publishBinderService(Context.MEDIA_SESSION_SERVICE, mSessionManagerImpl);
Watchdog.getInstance().addMonitor(this);
- updateUser();
mKeyguardManager =
(KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
mAudioService = getAudioService();
@@ -125,6 +124,8 @@
mContentResolver = getContext().getContentResolver();
mSettingsObserver = new SettingsObserver();
mSettingsObserver.observe();
+
+ updateUser();
}
private IAudioService getAudioService() {
@@ -501,6 +502,12 @@
UserRecord user = mUserRecords.get(record.getUserId());
if (receiver != null && user != null) {
user.mLastMediaButtonReceiver = receiver;
+ ComponentName component = receiver.getIntent().getComponent();
+ if (component != null && record.getPackageName().equals(component.getPackageName())) {
+ Settings.Secure.putStringForUser(mContentResolver,
+ Settings.System.MEDIA_BUTTON_RECEIVER, component.flattenToString(),
+ record.getUserId());
+ }
}
}
@@ -511,14 +518,17 @@
final class UserRecord {
private final int mUserId;
private final ArrayList<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>();
+ private final Context mContext;
private PendingIntent mLastMediaButtonReceiver;
+ private ComponentName mRestoredMediaButtonReceiver;
public UserRecord(Context context, int userId) {
+ mContext = context;
mUserId = userId;
+ restoreMediaButtonReceiver();
}
public void startLocked() {
- // nothing for now
}
public void stopLocked() {
@@ -548,6 +558,7 @@
pw.println(prefix + "Record for user " + mUserId);
String indent = prefix + " ";
pw.println(indent + "MediaButtonReceiver:" + mLastMediaButtonReceiver);
+ pw.println(indent + "Restored ButtonReceiver:" + mRestoredMediaButtonReceiver);
int size = mSessions.size();
pw.println(indent + size + " Sessions:");
for (int i = 0; i < size; i++) {
@@ -556,6 +567,19 @@
pw.println(indent + mSessions.get(i).toString());
}
}
+
+ private void restoreMediaButtonReceiver() {
+ String receiverName = Settings.Secure.getStringForUser(mContentResolver,
+ Settings.System.MEDIA_BUTTON_RECEIVER, UserHandle.USER_CURRENT);
+ if (!TextUtils.isEmpty(receiverName)) {
+ ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
+ if (eventReceiver == null) {
+ // an invalid name was persisted
+ return;
+ }
+ mRestoredMediaButtonReceiver = eventReceiver;
+ }
+ }
}
final class SessionsListenerRecord implements IBinder.DeathRecipient {
@@ -723,8 +747,9 @@
synchronized (mLock) {
// If we don't have a media button receiver to fall back on
// include non-playing sessions for dispatching
- boolean useNotPlayingSessions = mUserRecords.get(
- ActivityManager.getCurrentUser()).mLastMediaButtonReceiver == null;
+ UserRecord ur = mUserRecords.get(ActivityManager.getCurrentUser());
+ boolean useNotPlayingSessions = ur.mLastMediaButtonReceiver == null
+ && ur.mRestoredMediaButtonReceiver == null;
MediaSessionRecord session = mPriorityStack
.getDefaultMediaButtonSession(mCurrentUserId, useNotPlayingSessions);
if (isVoiceKey(keyEvent.getKeyCode())) {
@@ -929,9 +954,12 @@
// Launch the last PendingIntent we had with priority
int userId = ActivityManager.getCurrentUser();
UserRecord user = mUserRecords.get(userId);
- if (user.mLastMediaButtonReceiver != null) {
+ if (user.mLastMediaButtonReceiver != null
+ || user.mRestoredMediaButtonReceiver != null) {
if (DEBUG) {
- Log.d(TAG, "Sending media key to last known PendingIntent");
+ Log.d(TAG, "Sending media key to last known PendingIntent "
+ + user.mLastMediaButtonReceiver + " or restored Intent "
+ + user.mRestoredMediaButtonReceiver);
}
if (needWakeLock) {
mKeyEventReceiver.aquireWakeLockLocked();
@@ -939,9 +967,15 @@
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
try {
- user.mLastMediaButtonReceiver.send(getContext(),
- needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
- mediaButtonIntent, mKeyEventReceiver, null);
+ if (user.mLastMediaButtonReceiver != null) {
+ user.mLastMediaButtonReceiver.send(getContext(),
+ needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
+ mediaButtonIntent, mKeyEventReceiver, null);
+ } else {
+ mediaButtonIntent.setComponent(user.mRestoredMediaButtonReceiver);
+ getContext().sendBroadcastAsUser(mediaButtonIntent,
+ new UserHandle(userId));
+ }
} catch (CanceledException e) {
Log.i(TAG, "Error sending key event to media button receiver "
+ user.mLastMediaButtonReceiver, e);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 13b2b0f..359359e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3281,7 +3281,7 @@
// If the result set is different from when this
// was created, we need to clear it and re-ask the
// user their preference, if we're looking for an "always" type entry.
- if (always && !pa.mPref.sameSet(query, priority)) {
+ if (always && !pa.mPref.sameSet(query)) {
Slog.i(TAG, "Result set changed, dropping preferred activity for "
+ intent + " type " + resolvedType);
if (DEBUG_PREFERRED) {
@@ -3381,7 +3381,7 @@
if (resolveInfo != null) {
List<ResolveInfo> result = new ArrayList<ResolveInfo>(1);
result.add(resolveInfo);
- return result;
+ return filterIfNotPrimaryUser(result, userId);
}
// Check for cross profile results.
resolveInfo = queryCrossProfileIntents(
@@ -3394,17 +3394,38 @@
result.add(resolveInfo);
Collections.sort(result, mResolvePrioritySorter);
}
- return result;
+ return filterIfNotPrimaryUser(result, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- return mActivities.queryIntentForPackage(intent, resolvedType, flags,
- pkg.activities, userId);
+ return filterIfNotPrimaryUser(
+ mActivities.queryIntentForPackage(
+ intent, resolvedType, flags, pkg.activities, userId),
+ userId);
}
return new ArrayList<ResolveInfo>();
}
}
+ /**
+ * Filter out activities with primaryUserOnly flag set, when current user is not the owner.
+ *
+ * @return filtered list
+ */
+ private List<ResolveInfo> filterIfNotPrimaryUser(List<ResolveInfo> resolveInfos, int userId) {
+ if (userId == UserHandle.USER_OWNER) {
+ 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) {
+ resolveInfos.remove(i);
+ }
+ }
+ return resolveInfos;
+ }
+
+
private ResolveInfo querySkipCurrentProfileIntents(
List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
int flags, int sourceUserId) {
diff --git a/services/core/java/com/android/server/pm/PreferredComponent.java b/services/core/java/com/android/server/pm/PreferredComponent.java
index 69c1909..8e2e0cd 100644
--- a/services/core/java/com/android/server/pm/PreferredComponent.java
+++ b/services/core/java/com/android/server/pm/PreferredComponent.java
@@ -192,7 +192,7 @@
}
}
- public boolean sameSet(List<ResolveInfo> query, int priority) {
+ public boolean sameSet(List<ResolveInfo> query) {
if (mSetPackages == null) {
return query == null;
}
@@ -201,10 +201,10 @@
}
final int NQ = query.size();
final int NS = mSetPackages.length;
+
int numMatch = 0;
for (int i=0; i<NQ; i++) {
ResolveInfo ri = query.get(i);
- if (ri.priority != priority) continue;
ActivityInfo ai = ri.activityInfo;
boolean good = false;
for (int j=0; j<NS; j++) {
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 2af56fe..50b2262 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -677,7 +677,9 @@
private AudioDevicePort mAudioSource;
private List<AudioDevicePort> mAudioSink = new ArrayList<>();
private AudioPatch mAudioPatch = null;
- private float mCommittedVolume = 0.0f;
+ // Set to an invalid value for a volume, so that current volume can be applied at the
+ // first call to updateAudioConfigLocked().
+ private float mCommittedVolume = -1f;
private float mSourceVolume = 0.0f;
private TvStreamConfig mActiveConfig = null;
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 08754f9..f8b40d1 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -606,9 +606,8 @@
final int windowCount = windowList.size();
for (int i = 0; i < windowCount; i++) {
WindowState windowState = windowList.get(i);
- if ((windowState.isOnScreen() || windowState.mAttrs.type == WindowManager
- .LayoutParams.TYPE_UNIVERSE_BACKGROUND)
- && !windowState.mWinAnimator.mEnterAnimationPending) {
+ if (windowState.isOnScreen() &&
+ !windowState.mWinAnimator.mEnterAnimationPending) {
outWindows.put(windowState.mLayer, windowState);
}
}
@@ -1237,7 +1236,6 @@
&& windowType != WindowManager.LayoutParams.TYPE_DRAG
&& windowType != WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER
&& windowType != WindowManager.LayoutParams.TYPE_POINTER
- && windowType != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
&& windowType != WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY
&& windowType != WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
&& windowType != WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 3b27cd2..a04f6cb 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -52,7 +52,7 @@
final boolean voiceInteraction;
- int groupId = -1;
+ Task mTask;
boolean appFullscreen;
int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean layoutConfigChanges;
@@ -256,7 +256,8 @@
mIsExiting = false;
removeAllWindows();
- final Task task = service.mTaskIdToTask.get(groupId);
+ // Use local variable because removeAppToken will null out mTask.
+ final Task task = mTask;
if (task != null) {
if (!task.removeAppToken(this)) {
Slog.e(WindowManagerService.TAG, "removeAppFromTaskLocked: token=" + this
@@ -295,8 +296,8 @@
if (allAppWindows.size() > 0) {
pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
}
- pw.print(prefix); pw.print("groupId="); pw.print(groupId);
- pw.print(" appFullscreen="); pw.print(appFullscreen);
+ pw.print(prefix); pw.print("task="); pw.println(mTask);
+ pw.print(prefix); pw.print(" appFullscreen="); pw.print(appFullscreen);
pw.print(" requestedOrientation="); pw.println(requestedOrientation);
pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
pw.print(" clientHidden="); pw.print(clientHidden);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e3b53b0..8bbc5a9 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -379,7 +379,7 @@
ArrayList<Task> tasks = stack.getTasks();
for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
final Task task = tasks.get(taskNdx);
- pw.print(" mTaskId="); pw.println(task.taskId);
+ pw.print(" mTaskId="); pw.println(task.mTaskId);
AppTokenList tokens = task.mAppTokens;
for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx, ++ndx) {
final AppWindowToken wtoken = tokens.get(tokenNdx);
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 27ac32a..55dd911 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -239,9 +239,6 @@
// As an optimization, we could try to prune the list of windows but this turns
// out to be difficult because only the native code knows for sure which window
// currently has touch focus.
- final WindowStateAnimator universeBackground = mService.mAnimator.mUniverseBackground;
- final int aboveUniverseLayer = mService.mAnimator.mAboveUniverseLayer;
- boolean addedUniverse = false;
boolean disableWallpaperTouchEvents = false;
// If there's a drag in flight, provide a pseudowindow to catch drag input
@@ -299,20 +296,8 @@
mService.mDragState.sendDragStartedIfNeededLw(child);
}
- if (universeBackground != null && !addedUniverse
- && child.mBaseLayer < aboveUniverseLayer && onDefaultDisplay) {
- final WindowState u = universeBackground.mWin;
- if (u.mInputChannel != null && u.mInputWindowHandle != null) {
- addInputWindowHandleLw(u.mInputWindowHandle, u, u.mAttrs.flags,
- u.mAttrs.type, true, u == mInputFocus, false);
- }
- addedUniverse = true;
- }
-
- if (child.mWinAnimator != universeBackground) {
- addInputWindowHandleLw(inputWindowHandle, child, flags, type, isVisible,
- hasFocus, hasWallpaper);
- }
+ addInputWindowHandleLw(inputWindowHandle, child, flags, type, isVisible, hasFocus,
+ hasWallpaper);
}
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index a4dfd8a4..d68c056 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -446,20 +446,6 @@
mService.wallpaperCommandComplete(window, result);
}
- public void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
- float dsdx, float dtdx, float dsdy, float dtdy) {
- synchronized(mService.mWindowMap) {
- long ident = Binder.clearCallingIdentity();
- try {
- mService.setUniverseTransformLocked(
- mService.windowForClientLocked(this, window, true),
- alpha, offx, offy, dsdx, dtdx, dsdy, dtdy);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
synchronized(mService.mWindowMap) {
final long identity = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 80d727d..a9b26e2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -26,14 +26,13 @@
class Task {
TaskStack mStack;
final AppTokenList mAppTokens = new AppTokenList();
- final int taskId;
+ final int mTaskId;
final int mUserId;
boolean mDeferRemoval = false;
final WindowManagerService mService;
- Task(AppWindowToken wtoken, TaskStack stack, int userId, WindowManagerService service) {
- taskId = wtoken.groupId;
- mAppTokens.add(wtoken);
+ Task(int taskId, TaskStack stack, int userId, WindowManagerService service) {
+ mTaskId = taskId;
mStack = stack;
mUserId = userId;
mService = service;
@@ -45,38 +44,47 @@
void addAppToken(int addPos, AppWindowToken wtoken) {
final int lastPos = mAppTokens.size();
- for (int pos = 0; pos < lastPos && pos < addPos; ++pos) {
- if (mAppTokens.get(pos).removed) {
- // addPos assumes removed tokens are actually gone.
- ++addPos;
+ if (addPos >= lastPos) {
+ addPos = lastPos;
+ } else {
+ for (int pos = 0; pos < lastPos && pos < addPos; ++pos) {
+ if (mAppTokens.get(pos).removed) {
+ // addPos assumes removed tokens are actually gone.
+ ++addPos;
+ }
}
}
mAppTokens.add(addPos, wtoken);
+ wtoken.mTask = this;
mDeferRemoval = false;
}
void removeLocked() {
if (!mAppTokens.isEmpty() && mStack.isAnimating()) {
- if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId);
+ if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId);
mDeferRemoval = true;
return;
}
- if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId);
- EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
+ if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
+ EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
mDeferRemoval = false;
mStack.removeTask(this);
- mService.mTaskIdToTask.delete(taskId);
+ mService.mTaskIdToTask.delete(mTaskId);
}
boolean removeAppToken(AppWindowToken wtoken) {
boolean removed = mAppTokens.remove(wtoken);
if (mAppTokens.size() == 0) {
- EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, taskId,
+ EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, mTaskId,
"removeAppToken: last token");
if (mDeferRemoval) {
removeLocked();
}
}
+ wtoken.mTask = null;
+ /* Leave mTaskId for now, it might be useful for debug
+ wtoken.mTaskId = -1;
+ */
return removed;
}
@@ -88,6 +96,6 @@
@Override
public String toString() {
- return "{taskId=" + taskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
+ return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
}
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index d6741b3..5d73149 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -19,8 +19,10 @@
import static com.android.server.wm.WindowManagerService.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerService.TAG;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Debug;
+import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Slog;
import android.util.TypedValue;
@@ -78,9 +80,14 @@
/** Detach this stack from its display when animation completes. */
boolean mDeferDetach;
+ // Contains configurations settings that are different from the global configuration due to
+ // stack specific operations. E.g. {@link #setBounds}.
+ Configuration mOverrideConfig;
+
TaskStack(WindowManagerService service, int stackId) {
mService = service;
mStackId = stackId;
+ mOverrideConfig = Configuration.EMPTY;
// TODO: remove bounds from log, they are always 0.
EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, mBounds.left, mBounds.top,
mBounds.right, mBounds.bottom);
@@ -129,7 +136,7 @@
mDimLayer.setBounds(bounds);
mAnimationBackgroundSurface.setBounds(bounds);
mBounds.set(bounds);
-
+ updateOverrideConfiguration();
return true;
}
@@ -137,6 +144,27 @@
out.set(mBounds);
}
+ void updateOverrideConfiguration() {
+ final Configuration serviceConfig = mService.mCurConfiguration;
+ if (mFullscreen) {
+ mOverrideConfig = Configuration.EMPTY;
+ return;
+ }
+
+ if (mOverrideConfig == Configuration.EMPTY) {
+ mOverrideConfig = new Configuration();
+ }
+
+ // TODO(multidisplay): Update Dp to that of display stack is on.
+ final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ mOverrideConfig.screenWidthDp =
+ Math.min((int)(mBounds.width() / density), serviceConfig.screenWidthDp);
+ mOverrideConfig.screenHeightDp =
+ Math.min((int)(mBounds.height() / density), serviceConfig.screenHeightDp);
+ mOverrideConfig.smallestScreenWidthDp =
+ Math.min(mOverrideConfig.screenWidthDp, mOverrideConfig.screenHeightDp);
+ }
+
void updateDisplayInfo() {
if (mFullscreen && mDisplayContent != null) {
mDisplayContent.getLogicalDisplayRect(mTmpRect);
@@ -194,7 +222,7 @@
if (toTop) {
mDisplayContent.moveStack(this, true);
}
- EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, stackNdx);
+ EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.mTaskId, toTop ? 1 : 0, stackNdx);
}
void moveTaskToTop(Task task) {
@@ -224,10 +252,9 @@
}
mDisplayContent.layoutNeeded = true;
}
- final int taskId = task.taskId;
for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
- if (wtoken.groupId == taskId) {
+ if (wtoken.mTask == task) {
wtoken.mIsExiting = false;
mExitingAppTokens.remove(appNdx);
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 7e1f061..3987132 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -79,9 +79,6 @@
* seen. If multiple windows satisfy this, use the lowest window. */
WindowState mWindowDetachedWallpaper = null;
- WindowStateAnimator mUniverseBackground = null;
- int mAboveUniverseLayer = 0;
-
int mBulkUpdateParams = 0;
Object mLastWindowFreezeSource;
@@ -814,10 +811,6 @@
pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
pw.println(mWindowDetachedWallpaper);
}
- if (mUniverseBackground != null) {
- pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
- pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
- }
}
int getPendingLayoutChanges(final int displayId) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2c05e93..66bef41 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -769,7 +769,7 @@
* Whether the UI is currently running in touch mode (not showing
* navigational focus because the user is directly pressing the screen).
*/
- boolean mInTouchMode = true;
+ boolean mInTouchMode;
private ViewServer mViewServer;
private final ArrayList<WindowChangeListener> mWindowChangeListeners =
@@ -813,9 +813,6 @@
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
- mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
- * TYPE_LAYER_MULTIPLIER
- + TYPE_LAYER_OFFSET;
}
}, 0);
}
@@ -830,6 +827,8 @@
com.android.internal.R.bool.config_sf_limitedAlpha);
mHasPermanentDpad = context.getResources().getBoolean(
com.android.internal.R.bool.config_hasPermanentDpad);
+ mInTouchMode = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_defaultInTouchMode);
mInputManager = inputManager; // Must be before createDisplayContentLocked.
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mDisplaySettings = new DisplaySettings();
@@ -2945,37 +2944,6 @@
return null;
}
- public void setUniverseTransformLocked(WindowState window, float alpha,
- float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
- Transformation transform = window.mWinAnimator.mUniverseTransform;
- transform.setAlpha(alpha);
- Matrix matrix = transform.getMatrix();
- matrix.getValues(mTmpFloats);
- mTmpFloats[Matrix.MTRANS_X] = offx;
- mTmpFloats[Matrix.MTRANS_Y] = offy;
- mTmpFloats[Matrix.MSCALE_X] = dsdx;
- mTmpFloats[Matrix.MSKEW_Y] = dtdx;
- mTmpFloats[Matrix.MSKEW_X] = dsdy;
- mTmpFloats[Matrix.MSCALE_Y] = dtdy;
- matrix.setValues(mTmpFloats);
- final DisplayContent displayContent = window.getDisplayContent();
- if (displayContent == null) {
- return;
- }
-
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final RectF dispRect = new RectF(0, 0,
- displayInfo.logicalWidth, displayInfo.logicalHeight);
- matrix.mapRect(dispRect);
- window.mGivenTouchableRegion.set(0, 0,
- displayInfo.logicalWidth, displayInfo.logicalHeight);
- window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
- (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
- window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
- displayContent.layoutNeeded = true;
- performLayoutAndPlaceSurfacesLocked();
- }
-
public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
synchronized (mWindowMap) {
if (mAccessibilityController != null) {
@@ -3612,15 +3580,15 @@
Binder.restoreCallingIdentity(origId);
}
- private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) {
- if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId
+ private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken) {
+ if (DEBUG_STACK) Slog.i(TAG, "createTaskLocked: taskId=" + taskId + " stackId=" + stackId
+ " atoken=" + atoken);
final TaskStack stack = mStackIdToStack.get(stackId);
if (stack == null) {
throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
}
EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
- Task task = new Task(atoken, stack, userId, this);
+ Task task = new Task(taskId, stack, userId, this);
mTaskIdToTask.put(taskId, task);
stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */);
return task;
@@ -3657,7 +3625,6 @@
}
atoken = new AppWindowToken(this, token, voiceInteraction);
atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
- atoken.groupId = taskId;
atoken.appFullscreen = fullscreen;
atoken.showWhenLocked = showWhenLocked;
atoken.requestedOrientation = requestedOrientation;
@@ -3669,10 +3636,9 @@
Task task = mTaskIdToTask.get(taskId);
if (task == null) {
- createTask(taskId, stackId, userId, atoken);
- } else {
- task.addAppToken(addPos, atoken);
+ task = createTaskLocked(taskId, stackId, userId, atoken);
}
+ task.addAppToken(addPos, atoken);
mTokenMap.put(token.asBinder(), atoken);
@@ -3685,28 +3651,27 @@
}
@Override
- public void setAppGroupId(IBinder token, int groupId) {
+ public void setAppTask(IBinder token, int taskId) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
- "setAppGroupId()")) {
+ "setAppTask()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
synchronized(mWindowMap) {
final AppWindowToken atoken = findAppWindowToken(token);
if (atoken == null) {
- Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
+ Slog.w(TAG, "Attempted to set task id of non-existing app token: " + token);
return;
}
- final Task oldTask = mTaskIdToTask.get(atoken.groupId);
+ final Task oldTask = atoken.mTask;
oldTask.removeAppToken(atoken);
- atoken.groupId = groupId;
- Task newTask = mTaskIdToTask.get(groupId);
+ Task newTask = mTaskIdToTask.get(taskId);
if (newTask == null) {
- newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
- } else {
- newTask.mAppTokens.add(atoken);
+ newTask =
+ createTaskLocked(taskId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
}
+ newTask.addAppToken(Integer.MAX_VALUE /* at top */, atoken);
}
}
@@ -3990,7 +3955,7 @@
void setFocusedStackFrame() {
final TaskStack stack;
if (mFocusedApp != null) {
- Task task = mTaskIdToTask.get(mFocusedApp.groupId);
+ final Task task = mFocusedApp.mTask;
stack = task.mStack;
final DisplayContent displayContent = task.getDisplayContent();
if (displayContent != null) {
@@ -4812,7 +4777,7 @@
+ " animating=" + wtoken.mAppAnimator.animating);
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: "
+ wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
- final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
+ final TaskStack stack = wtoken.mTask.mStack;
if (delayed && !wtoken.allAppWindows.isEmpty()) {
// set the token aside because it has an active animation to be finished
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
@@ -4877,7 +4842,7 @@
final int numTasks = tasks.size();
for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
final Task task = tasks.get(taskNdx);
- Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:");
+ Slog.v(TAG, " Task #" + task.mTaskId + " activities from bottom to top:");
AppTokenList tokens = task.mAppTokens;
final int numTokens = tokens.size();
for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
@@ -5128,7 +5093,12 @@
}
}
- public void resizeStack(int stackId, Rect bounds) {
+ /**
+ * Re-sizes the specified stack and its containing windows.
+ * Returns a {@link Configuration} object that contains configurations settings
+ * that should be overridden due to the operation.
+ */
+ public Configuration resizeStack(int stackId, Rect bounds) {
synchronized (mWindowMap) {
final TaskStack stack = mStackIdToStack.get(stackId);
if (stack == null) {
@@ -5140,6 +5110,7 @@
stack.getDisplayContent().layoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
}
+ return new Configuration(stack.mOverrideConfig);
}
}
@@ -7068,7 +7039,7 @@
return sw;
}
- boolean computeScreenConfigurationLocked(Configuration config) {
+ private boolean computeScreenConfigurationLocked(Configuration config) {
if (!mDisplayReady) {
return false;
}
@@ -7951,16 +7922,16 @@
break;
case TAP_OUTSIDE_STACK: {
- int stackId;
- synchronized (mWindowMap) {
- stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
- }
- if (stackId >= 0) {
- try {
- mActivityManager.setFocusedStack(stackId);
- } catch (RemoteException e) {
- }
- }
+// int stackId;
+// synchronized (mWindowMap) {
+// stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
+// }
+// if (stackId >= 0) {
+// try {
+// mActivityManager.setFocusedStack(stackId);
+// } catch (RemoteException e) {
+// }
+// }
}
break;
case NOTIFY_ACTIVITY_DRAWN:
@@ -8476,7 +8447,7 @@
numRemoved++;
continue;
} else if (lastBelow == i-1) {
- if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
+ if (w.mAttrs.type == TYPE_WALLPAPER) {
lastBelow = i;
}
}
@@ -8731,8 +8702,6 @@
+ displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
}
- WindowStateAnimator universeBackground = null;
-
mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
if (isDefaultDisplay) {
// Not needed on non-default displays.
@@ -8790,8 +8759,7 @@
|| ((win.isConfigChanged() || win.setInsetsChanged()) &&
((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
(win.mHasSurface && win.mAppToken != null &&
- win.mAppToken.layoutConfigChanges)))
- || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
+ win.mAppToken.layoutConfigChanges)))) {
if (!win.mLayoutAttached) {
if (initial) {
//Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
@@ -8815,16 +8783,6 @@
if (topAttached < 0) topAttached = i;
}
}
- if (win.mViewVisibility == View.VISIBLE
- && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
- && universeBackground == null) {
- universeBackground = win.mWinAnimator;
- }
- }
-
- if (mAnimator.mUniverseBackground != universeBackground) {
- mFocusMayChange = true;
- mAnimator.mUniverseBackground = universeBackground;
}
boolean attachedBehindDream = false;
@@ -10367,11 +10325,6 @@
}
private WindowState computeFocusedWindowLocked() {
- if (mAnimator.mUniverseBackground != null
- && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
- return mAnimator.mUniverseBackground.mWin;
- }
-
final int displayCount = mDisplayContents.size();
for (int i = 0; i < displayCount; i++) {
final DisplayContent displayContent = mDisplayContents.valueAt(i);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 978f5c3..98f00de 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -130,7 +130,8 @@
int mLayoutSeq = -1;
- Configuration mConfiguration = null;
+ private Configuration mConfiguration = Configuration.EMPTY;
+ private Configuration mOverrideConfig = Configuration.EMPTY;
// Sticky answer to isConfigChanged(), remains true until new Configuration is assigned.
// Used only on {@link #TYPE_KEYGUARD}.
private boolean mConfigHasChanged;
@@ -792,14 +793,14 @@
TaskStack getStack() {
AppWindowToken wtoken = mAppToken == null ? mService.mFocusedApp : mAppToken;
if (wtoken != null) {
- Task task = mService.mTaskIdToTask.get(wtoken.groupId);
+ Task task = wtoken.mTask;
if (task != null) {
if (task.mStack != null) {
return task.mStack;
}
Slog.e(TAG, "getStack: mStack null for task=" + task);
} else {
- Slog.e(TAG, "getStack: " + this + " couldn't find taskId=" + wtoken.groupId
+ Slog.e(TAG, "getStack: " + this + " couldn't find task for " + wtoken
+ " Callers=" + Debug.getCallers(4));
}
}
@@ -1076,9 +1077,13 @@
}
boolean isConfigChanged() {
- boolean configChanged = mConfiguration != mService.mCurConfiguration
- && (mConfiguration == null
- || (mConfiguration.diff(mService.mCurConfiguration) != 0));
+ final TaskStack stack = getStack();
+ final Configuration overrideConfig =
+ (stack != null) ? stack.mOverrideConfig : Configuration.EMPTY;
+ final Configuration serviceConfig = mService.mCurConfiguration;
+ boolean configChanged =
+ (mConfiguration != serviceConfig && mConfiguration.diff(serviceConfig) != 0)
+ || (mOverrideConfig != overrideConfig && !mOverrideConfig.equals(overrideConfig));
if ((mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
// Retain configuration changed status until resetConfiguration called.
@@ -1107,8 +1112,10 @@
}
}
- void setConfiguration(final Configuration newConfig) {
+ private void setConfiguration(
+ final Configuration newConfig, final Configuration newOverrideConfig) {
mConfiguration = newConfig;
+ mOverrideConfig = newOverrideConfig;
mConfigHasChanged = false;
}
@@ -1384,12 +1391,15 @@
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
+ ": " + mCompatFrame);
boolean configChanged = isConfigChanged();
+ final TaskStack stack = getStack();
+ final Configuration overrideConfig =
+ (stack != null) ? stack.mOverrideConfig : Configuration.EMPTY;
if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) {
Slog.i(TAG, "Sending new config to window " + this + ": "
- + mWinAnimator.mSurfaceW + "x" + mWinAnimator.mSurfaceH
- + " / " + mService.mCurConfiguration);
+ + mWinAnimator.mSurfaceW + "x" + mWinAnimator.mSurfaceH + " / config="
+ + mService.mCurConfiguration + " overrideConfig=" + overrideConfig);
}
- setConfiguration(mService.mCurConfiguration);
+ setConfiguration(mService.mCurConfiguration, overrideConfig);
if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING)
Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index c2d8004..8202880 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -85,10 +85,6 @@
final Context mContext;
final boolean mIsWallpaper;
- // If this is a universe background window, this is the transformation
- // it is applying to the rest of the universe.
- final Transformation mUniverseTransform = new Transformation();
-
// Currently running animation.
boolean mAnimating;
boolean mLocalAnimating;
@@ -1096,9 +1092,6 @@
if (appTransformation != null) {
tmpMatrix.postConcat(appTransformation.getMatrix());
}
- if (mAnimator.mUniverseBackground != null) {
- tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
- }
if (screenAnimation) {
tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
}
@@ -1164,9 +1157,6 @@
mHasClipRect = true;
}
}
- if (mAnimator.mUniverseBackground != null) {
- mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
- }
if (screenAnimation) {
mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
}
@@ -1192,15 +1182,12 @@
TAG, "computeShownFrameLocked: " + this +
" not attached, mAlpha=" + mAlpha);
- final boolean applyUniverseTransformation = (mAnimator.mUniverseBackground != null
- && mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
- && mWin.mBaseLayer < mAnimator.mAboveUniverseLayer);
MagnificationSpec spec = null;
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) {
spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
}
- if (applyUniverseTransformation || spec != null) {
+ if (spec != null) {
final Rect frame = mWin.mFrame;
final float tmpFloats[] = mService.mTmpFloats;
final Matrix tmpMatrix = mWin.mTmpMatrix;
@@ -1208,10 +1195,6 @@
tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
- if (applyUniverseTransformation) {
- tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
- }
-
if (spec != null && !spec.isNop()) {
tmpMatrix.postScale(spec.scale, spec.scale);
tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
@@ -1231,9 +1214,6 @@
mWin.mShownFrame.set(x, y, x + w, y + h);
mShownAlpha = mAlpha;
- if (applyUniverseTransformation) {
- mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
- }
} else {
mWin.mShownFrame.set(mWin.mFrame);
if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
@@ -1301,17 +1281,9 @@
displayInfo.logicalHeight - w.mCompatFrame.top);
} else if (w.mLayer >= mService.mSystemDecorLayer) {
// Above the decor layer is easy, just use the entire window.
- // Unless we have a universe background... in which case all the
- // windows need to be cropped by the screen, so they don't cover
- // the universe background.
- if (mAnimator.mUniverseBackground == null) {
- w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
- } else {
- applyDecorRect(mService.mScreenRect);
- }
- } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
- || w.mDecorFrame.isEmpty()) {
- // The universe background isn't cropped, nor windows without policy decor.
+ w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
+ } else if (w.mDecorFrame.isEmpty()) {
+ // Windows without policy decor aren't cropped.
w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
} else if (w.mAttrs.type == LayoutParams.TYPE_WALLPAPER && mAnimator.mAnimating) {
// If we're animating, the wallpaper crop should only be updated at the end of the
@@ -1932,11 +1904,6 @@
pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
}
- if (mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) {
- pw.print(prefix); pw.print("mUniverseTransform=");
- mUniverseTransform.printShortString(pw);
- pw.println();
- }
if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
pw.print(" mAlpha="); pw.print(mAlpha);
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 7f0ab6b..b508c89 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -20,12 +20,15 @@
import android.alsa.AlsaDevicesParser;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.media.AudioSystem;
import android.media.IAudioService;
+import android.midi.MidiDeviceInfo;
import android.os.FileObserver;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -73,6 +76,9 @@
private UsbAudioDevice mSelectedAudioDevice = null;
+ // UsbMidiDevice for USB peripheral mode (gadget) device
+ private UsbMidiDevice mPeripheralMidiDevice = null;
+
private final class AlsaDevice {
public static final int TYPE_UNKNOWN = 0;
public static final int TYPE_PLAYBACK = 1;
@@ -391,7 +397,17 @@
int device = mDevicesParser.getDefaultDeviceNum(addedCard);
AlsaDevice alsaDevice = waitForAlsaDevice(addedCard, device, AlsaDevice.TYPE_MIDI);
if (alsaDevice != null) {
- UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, usbDevice,
+ Bundle properties = new Bundle();
+ properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER,
+ usbDevice.getManufacturerName());
+ properties.putString(MidiDeviceInfo.PROPERTY_MODEL, usbDevice.getProductName());
+ properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER,
+ usbDevice.getSerialNumber());
+ properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, alsaDevice.mCard);
+ properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, alsaDevice.mDevice);
+ properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice);
+
+ UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, properties,
alsaDevice.mCard, alsaDevice.mDevice);
if (usbMidiDevice != null) {
mMidiDevices.put(usbDevice, usbMidiDevice);
@@ -436,6 +452,23 @@
}
}
+ /* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
+ if (enabled) {
+ Bundle properties = new Bundle();
+ Resources r = mContext.getResources();
+ properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, r.getString(
+ com.android.internal.R.string.usb_midi_peripheral_manufacturer_name));
+ properties.putString(MidiDeviceInfo.PROPERTY_MODEL, r.getString(
+ com.android.internal.R.string.usb_midi_peripheral_model_name));
+ properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, card);
+ properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, device);
+ mPeripheralMidiDevice = UsbMidiDevice.create(mContext, properties, card, device);
+ } else if (mPeripheralMidiDevice != null) {
+ IoUtils.closeQuietly(mPeripheralMidiDevice);
+ mPeripheralMidiDevice = null;
+ }
+ }
+
//
// Devices List
//
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 1426551..2fb6dbf 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -31,6 +31,7 @@
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.media.AudioManager;
+import android.midi.MidiDeviceInfo;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
@@ -85,6 +86,8 @@
"/sys/class/android_usb/android0/f_rndis/ethaddr";
private static final String AUDIO_SOURCE_PCM_PATH =
"/sys/class/android_usb/android0/f_audio_source/pcm";
+ private static final String MIDI_ALSA_PATH =
+ "/sys/class/android_usb/android0/f_midi/alsa";
private static final int MSG_UPDATE_STATE = 0;
private static final int MSG_ENABLE_ADB = 1;
@@ -124,6 +127,7 @@
private boolean mUseUsbNotification;
private boolean mAdbEnabled;
private boolean mAudioSourceEnabled;
+ private boolean mMidiEnabled;
private Map<String, List<Pair<String, String>>> mOemModeMap;
private String[] mAccessoryStrings;
private UsbDebuggingManager mDebuggingManager;
@@ -618,6 +622,31 @@
}
}
+ private void updateMidiFunction() {
+ boolean enabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MIDI);
+ if (enabled != mMidiEnabled) {
+ int card = -1;
+ int device = -1;
+
+ if (enabled) {
+ Scanner scanner = null;
+ try {
+ scanner = new Scanner(new File(MIDI_ALSA_PATH));
+ card = scanner.nextInt();
+ device = scanner.nextInt();
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "could not open MIDI PCM file", e);
+ } finally {
+ if (scanner != null) {
+ scanner.close();
+ }
+ }
+ }
+ mUsbAlsaManager.setPeripheralMidiState(enabled, card, device);
+ mMidiEnabled = enabled;
+ }
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -636,6 +665,7 @@
if (mBootCompleted) {
updateUsbState();
updateAudioSourceFunction();
+ updateMidiFunction();
}
break;
case MSG_ENABLE_ADB:
@@ -651,6 +681,7 @@
updateAdbNotification();
updateUsbState();
updateAudioSourceFunction();
+ updateMidiFunction();
break;
case MSG_BOOT_COMPLETED:
mBootCompleted = true;
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index 01b2df9..8d44905 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -17,13 +17,12 @@
package com.android.server.usb;
import android.content.Context;
-import android.hardware.usb.UsbDevice;
import android.midi.MidiDeviceInfo;
import android.midi.MidiDeviceServer;
import android.midi.MidiManager;
+import android.midi.MidiPort;
import android.midi.MidiReceiver;
import android.midi.MidiSender;
-import android.midi.MidiUtils;
import android.os.Bundle;
import android.system.ErrnoException;
import android.system.Os;
@@ -45,10 +44,12 @@
// for polling multiple FileDescriptors for MIDI events
private final StructPollfd[] mPollFDs;
+ // streams for reading from ALSA driver
private final FileInputStream[] mInputStreams;
+ // streams for writing to ALSA driver
private final FileOutputStream[] mOutputStreams;
- public static UsbMidiDevice create(Context context, UsbDevice usbDevice, int card, int device) {
+ public static UsbMidiDevice create(Context context, Bundle properties, int card, int device) {
MidiManager midiManager = (MidiManager)context.getSystemService(Context.MIDI_SERVICE);
if (midiManager == null) {
Log.e(TAG, "No MidiManager in UsbMidiDevice.create()");
@@ -69,13 +70,6 @@
return null;
}
- Bundle properties = new Bundle();
- properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, usbDevice.getManufacturerName());
- properties.putString(MidiDeviceInfo.PROPERTY_MODEL, usbDevice.getProductName());
- properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER, usbDevice.getSerialNumber());
- properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, card);
- properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, device);
- properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice);
MidiDeviceServer server = midiManager.createDeviceServer(subDevices, subDevices, properties,
false, MidiDeviceInfo.TYPE_USB);
if (server == null) {
@@ -131,7 +125,7 @@
new Thread() {
@Override
public void run() {
- byte[] buffer = new byte[3];
+ byte[] buffer = new byte[MidiPort.MAX_PACKET_DATA_SIZE];
try {
boolean done = false;
while (!done) {
@@ -141,7 +135,8 @@
if ((pfd.revents & OsConstants.POLLIN) != 0) {
// clear readable flag
pfd.revents = 0;
- int count = readMessage(buffer, index);
+
+ int count = mInputStreams[index].read(buffer);
mOutputPortReceivers[index].onPost(buffer, 0, count,
System.nanoTime());
} else if ((pfd.revents & (OsConstants.POLLERR
@@ -150,7 +145,7 @@
}
}
- // poll if none are readable
+ // wait until we have a readable port
Os.poll(mPollFDs, -1 /* infinite timeout */);
}
} catch (IOException e) {
@@ -174,26 +169,6 @@
}
}
- private int readMessage(byte[] buffer, int index) throws IOException {
- FileInputStream inputStream = mInputStreams[index];
-
- if (inputStream.read(buffer, 0, 1) != 1) {
- Log.e(TAG, "could not read command byte");
- return -1;
- }
- int dataSize = MidiUtils.getMessageDataSize(buffer[0]);
- if (dataSize < 0) {
- return -1;
- }
- if (dataSize > 0) {
- if (inputStream.read(buffer, 1, dataSize) != dataSize) {
- Log.e(TAG, "could not read command data");
- return -1;
- }
- }
- return dataSize + 1;
- }
-
private static native int nativeGetSubdeviceCount(int card, int device);
private static native FileDescriptor[] nativeOpen(int card, int device, int subdeviceCount);
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 6621726..1a6b292 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -691,7 +691,7 @@
getTelecomService().clearAccounts(packageName);
}
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecomService#clearAccountsForPackage()", e);
+ Log.e(TAG, "Error calling ITelecomService#clearAccountsForPackage", e);
}
}
@@ -726,7 +726,7 @@
return getTelecomService().isVoiceMailNumber(accountHandle, number);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException calling isInCall().", e);
+ Log.e(TAG, "RemoteException calling ITelecomService#isVoiceMailNumber.", e);
}
return false;
}
@@ -746,12 +746,32 @@
return getTelecomService().hasVoiceMailNumber(accountHandle);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException calling isInCall().", e);
+ Log.e(TAG, "RemoteException calling ITelecomService#hasVoiceMailNumber.", e);
}
return false;
}
/**
+ * Return the line 1 phone number for given phone account.
+ *
+ * @param accountHandle The handle for the account retrieve a number for.
+ * @return A string representation of the line 1 phone number.
+ *
+ * @hide
+ */
+ @SystemApi
+ public String getLine1Number(PhoneAccountHandle accountHandle) {
+ try {
+ if (isServiceConnected()) {
+ return getTelecomService().getLine1Number(accountHandle);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException calling ITelecomService#getLine1Number.", e);
+ }
+ return null;
+ }
+
+ /**
* Returns whether there is an ongoing phone call (can be in dialing, ringing, active or holding
* states).
* <p>
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index f8d7539..d2030f2 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -126,6 +126,11 @@
boolean hasVoiceMailNumber(in PhoneAccountHandle accountHandle);
/**
+ * @see TelecomServiceImpl#getLine1Number
+ */
+ String getLine1Number(in PhoneAccountHandle accountHandle);
+
+ /**
* @see TelecomServiceImpl#getDefaultPhoneApp
*/
ComponentName getDefaultPhoneApp();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ace945d..339fc6d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -640,13 +640,9 @@
*/
/** {@hide} */
public String getDeviceId(int slotId) {
- // FIXME methods taking slot id should not use subscription, instead us Uicc directly
- int[] subId = SubscriptionManager.getSubId(slotId);
- if (subId == null || subId.length == 0) {
- return null;
- }
+ // FIXME this assumes phoneId == slotId
try {
- return getSubscriberInfo().getDeviceIdForSubscriber(subId[0]);
+ return getSubscriberInfo().getDeviceIdForPhone(slotId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -703,7 +699,11 @@
public String getNai(int slotId) {
int[] subId = SubscriptionManager.getSubId(slotId);
try {
- return getSubscriberInfo().getNaiForSubscriber(subId[0]);
+ String nai = getSubscriberInfo().getNaiForSubscriber(subId[0]);
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Rlog.v(TAG, "Nai = " + nai);
+ }
+ return nai;
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index eec5333..c91a59c 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -33,10 +33,10 @@
String getNaiForSubscriber(int subId);
/**
- * Retrieves the unique device ID of a subId for the device, e.g., IMEI
+ * Retrieves the unique device ID of a phone for the device, e.g., IMEI
* for GSM phones.
*/
- String getDeviceIdForSubscriber(int subId);
+ String getDeviceIdForPhone(int phoneId);
/**
* Retrieves the IMEI.
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 62c92a1..e44969d 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -103,7 +103,7 @@
}
try {
- mWm.setAppGroupId(null, 0);
+ mWm.setAppTask(null, 0);
fail("IWindowManager.setAppGroupId did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 5176419..d90271b 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -293,7 +293,7 @@
}
@Override
- public void setAppGroupId(IBinder arg0, int arg1) throws RemoteException {
+ public void setAppTask(IBinder arg0, int arg1) throws RemoteException {
// TODO Auto-generated method stub
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 0f51d00..62a03e1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -191,12 +191,6 @@
}
@Override
- public void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
- float dsdx, float dtdx, float dsdy, float dtdy) {
- // pass for now.
- }
-
- @Override
public IBinder asBinder() {
// pass for now.
return null;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 5202cc3..52f2372 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -733,6 +733,31 @@
/**
* @hide
+ * Last time the system tried to roam and failed because of authentication failure or DHCP
+ * RENEW failure.
+ */
+ public long lastRoamingFailure;
+
+ /** @hide */
+ public static int ROAMING_FAILURE_IP_CONFIG = 1;
+ /** @hide */
+ public static int ROAMING_FAILURE_AUTH_FAILURE = 2;
+
+ /**
+ * @hide
+ * Initial amount of time this Wifi configuration gets blacklisted for network switching
+ * because of roaming failure
+ */
+ public long roamingFailureBlackListTimeMilli = 1000;
+
+ /**
+ * @hide
+ * Last roaming failure reason code
+ */
+ public int lastRoamingFailureReason;
+
+ /**
+ * @hide
* Last time the system was disconnected to this configuration.
*/
public long lastDisconnected;
@@ -1209,6 +1234,18 @@
sbuf.append( "sec");
}
}
+ if (this.lastRoamingFailure != 0) {
+ sbuf.append('\n');
+ long diff = now_ms - this.lastRoamingFailure;
+ if (diff <= 0) {
+ sbuf.append("lastRoamingFailure since <incorrect>");
+ } else {
+ sbuf.append("lastRoamingFailure: ").append(Long.toString(diff/1000));
+ sbuf.append( "sec");
+ }
+ }
+ sbuf.append("roamingFailureBlackListTimeMilli: ").
+ append(Long.toString(this.roamingFailureBlackListTimeMilli));
sbuf.append('\n');
if (this.linkedConfigurations != null) {
for(String key : this.linkedConfigurations.keySet()) {
@@ -1595,6 +1632,9 @@
lastConnected = source.lastConnected;
lastDisconnected = source.lastDisconnected;
lastConnectionFailure = source.lastConnectionFailure;
+ lastRoamingFailure = source.lastRoamingFailure;
+ lastRoamingFailureReason = source.lastRoamingFailureReason;
+ roamingFailureBlackListTimeMilli = source.roamingFailureBlackListTimeMilli;
numConnectionFailures = source.numConnectionFailures;
numIpConfigFailures = source.numIpConfigFailures;
numAuthFailures = source.numAuthFailures;
@@ -1667,6 +1707,9 @@
dest.writeString(lastUpdateName);
dest.writeLong(blackListTimestamp);
dest.writeLong(lastConnectionFailure);
+ dest.writeLong(lastRoamingFailure);
+ dest.writeInt(lastRoamingFailureReason);
+ dest.writeLong(roamingFailureBlackListTimeMilli);
dest.writeInt(numConnectionFailures);
dest.writeInt(numIpConfigFailures);
dest.writeInt(numAuthFailures);
@@ -1732,6 +1775,9 @@
config.lastUpdateName = in.readString();
config.blackListTimestamp = in.readLong();
config.lastConnectionFailure = in.readLong();
+ config.lastRoamingFailure = in.readLong();
+ config.lastRoamingFailureReason = in.readInt();
+ config.roamingFailureBlackListTimeMilli = in.readLong();
config.numConnectionFailures = in.readInt();
config.numIpConfigFailures = in.readInt();
config.numAuthFailures = in.readInt();