summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt8
-rw-r--r--api/system-current.txt9
-rw-r--r--core/java/android/app/Activity.java16
-rw-r--r--core/java/android/app/Dialog.java14
-rw-r--r--core/java/android/provider/ContactsContract.java8
-rw-r--r--core/java/android/util/NtpTrustedTime.java20
-rw-r--r--core/java/android/view/IWindowManager.aidl2
-rw-r--r--core/java/android/view/View.java1
-rw-r--r--core/java/android/widget/ListPopupWindow.java25
-rw-r--r--core/java/android/widget/RadialTimePickerView.java20
-rw-r--r--core/java/com/android/internal/widget/FaceUnlockView.java67
-rw-r--r--core/java/com/android/internal/widget/SizeAdaptiveLayout.java442
-rw-r--r--core/java/com/android/internal/widget/WaveView.java663
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/Ease.java132
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/GlowPadView.java1383
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/PointCloud.java225
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java229
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/Tweener.java177
-rw-r--r--core/res/res/layout/notification_template_material_base.xml3
-rw-r--r--core/res/res/layout/notification_template_material_big_base.xml3
-rw-r--r--core/res/res/layout/notification_template_material_big_picture.xml3
-rw-r--r--core/res/res/layout/notification_template_material_big_text.xml3
-rw-r--r--core/res/res/layout/notification_template_material_inbox.xml3
-rw-r--r--core/res/res/layout/notification_template_material_media.xml3
-rw-r--r--core/res/res/values-television/config.xml26
-rw-r--r--core/res/res/values/attrs.xml93
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/tests/coretests/res/layout/size_adaptive.xml40
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_color.xml41
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_color_statelist.xml41
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_four_u.xml68
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_four_u_text.xml59
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_gappy.xml40
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_large_only.xml31
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_lies.xml40
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_one_u.xml66
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_one_u_text.xml54
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_overlapping.xml40
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_singleton.xml31
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_text.xml40
-rw-r--r--core/tests/coretests/res/layout/size_adaptive_three_way.xml48
-rw-r--r--core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java479
-rw-r--r--docs/html/training/location/display-address.jd680
-rw-r--r--docs/html/training/wearables/data-layer/data-items.jd128
-rw-r--r--docs/html/training/wearables/data-layer/events.jd3
-rwxr-xr-xmedia/java/android/mtp/MtpDatabase.java68
-rw-r--r--media/java/android/mtp/MtpPropertyGroup.java22
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp5
-rw-r--r--packages/SystemUI/res/layout/notification_public_default.xml3
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java39
-rw-r--r--services/core/java/com/android/server/NetworkTimeUpdateService.java18
-rwxr-xr-xservices/core/java/com/android/server/am/ActiveServices.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java37
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityRecord.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java80
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java63
-rw-r--r--services/core/java/com/android/server/am/EventLogTags.logtags2
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java52
-rw-r--r--services/core/java/com/android/server/tv/TvInputHardwareManager.java4
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java9
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java2
-rw-r--r--services/core/java/com/android/server/wm/Task.java36
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java35
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java4
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java26
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl5
-rw-r--r--tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java2
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java2
69 files changed, 967 insertions, 5065 deletions
diff --git a/api/current.txt b/api/current.txt
index e6d088d..120025d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -482,7 +482,7 @@ package android {
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 @@ package android {
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
@@ -24813,6 +24813,8 @@ package android.provider {
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 +26141,8 @@ package android.provider {
}
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;
diff --git a/api/system-current.txt b/api/system-current.txt
index e6ddb4f..0d51f5a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -554,7 +554,7 @@ package android {
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 @@ package android {
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
@@ -26402,6 +26402,8 @@ package android.provider {
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 +27730,8 @@ package android.provider {
}
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;
@@ -30677,6 +30681,7 @@ package android.telecom {
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);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a597d5e..74c468d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2373,8 +2373,10 @@ public class Activity extends ContextThemeWrapper
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 @@ public class Activity extends ContextThemeWrapper
* 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 @@ public class Activity extends ContextThemeWrapper
* 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 @@ public class Activity extends ContextThemeWrapper
* 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);
+ }
}
/**
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 @@ public class Dialog implements DialogInterface, Window.Callback,
* @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/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 @@ public final class ContactsContract {
* 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 @@ public final class ContactsContract {
* 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 @@ package android.util;
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 @@ public class NtpTrustedTime implements TrustedTime {
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 @@ public class NtpTrustedTime implements TrustedTime {
final String server = secureServer != null ? secureServer : defaultServer;
sSingleton = new NtpTrustedTime(server, timeout);
+ sContext = context;
}
return sSingleton;
@@ -79,6 +85,20 @@ public class NtpTrustedTime implements TrustedTime {
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 @@ interface IWindowManager
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/View.java b/core/java/android/view/View.java
index 1e6f6c9..f55892d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16642,6 +16642,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (changed) {
requestLayout();
+ invalidateOutline();
}
}
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 @@ public class ListPopupWindow {
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 @@ public class RadialTimePickerView extends View {
@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 @@ public class RadialTimePickerView extends View {
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/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/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>&lt;FragmentBreadCrumbs&gt;</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/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/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/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>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>
-<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>
<pre>
-&lt;ProgressBar
-android:id="&#64;+id/address_progress"
-android:layout_width="wrap_content"
-android:layout_height="wrap_content"
-android:layout_centerHorizontal="true"
-android:indeterminate="true"
-android:visibility="gone" /&gt;
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.gms.location.sample.locationupdates" &gt;
+
+ &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/&gt;
+&lt;/manifest&gt;
</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 {
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.gms.location.sample.locationaddress" &gt;
+ &lt;application
+ ...
+ &lt;service
+ android:name=".FetchAddressIntentService"
+ android:exported="false"/&gt;
+ &lt;/application&gt;
...
- private TextView mAddress;
- private ProgressBar mActivityIndicator;
+&lt;/manifest&gt;
+</pre>
+
+<p class="note"><strong>Note:</strong> The {@code &lt;service&gt;} 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>
+&#64;Override
+protected void onHandleIntent(Intent intent) {
+ Geocoder geocoder = new Geocoder(this, Locale.getDefault());
...
- &#64;Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+}
+</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>
+&#64;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);
+
...
- mAddress = (TextView) findViewById(R.id.address);
- mActivityIndicator =
- (ProgressBar) findViewById(R.id.address_progress);
+
+ List&lt;Address&gt; 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);
}
- ...
- /**
- * 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&lt;Location, Void, String&gt; {
- Context mContext;
- public GetAddressTask(Context context) {
- super();
- mContext = context;
+
+ // 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);
}
- ...
- /**
- * Get a Geocoder instance, get the latitude and longitude
- * look up the address, and return it
- *
- * &#64;params params One or more Location objects
- * &#64;return A string containing the address of the current
- * location, or an empty string if no address can be found,
- * or an error message
- */
- &#64;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&lt;Address&gt; 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;
- }
- // If the reverse geocode returned an address
- if (addresses != null &amp;&amp; addresses.size() &gt; 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(
- "&#037;s, &#037;s, &#037;s",
- // If there's a street address, add it
- address.getMaxAddressLineIndex() &gt; 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";
- }
+ deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
+ } else {
+ Address address = addresses.get(0);
+ ArrayList&lt;String&gt; addressFragments = new ArrayList&lt;String&gt;();
+
+ // 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>
-<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:
+
+<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>
- private class GetAddressTask extends
- AsyncTask&lt;Location, Void, String&gt; {
- ...
- /**
- * 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.
- */
- &#64;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);
- }
- ...
+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>
-<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>
+
+<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 FragmentActivity {
+public class MainActivity extends ActionBarActivity implements
+ ConnectionCallbacks, OnConnectionFailedListener {
+
+ protected Location mLastLocation;
+ private AddressResultReceiver mResultReceiver;
...
- /**
- * The "Get Address" button in the UI is defined with
- * android:onClick="getAddress". The method is invoked whenever the
- * user clicks the button.
- *
- * &#64;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 &gt;=
- Build.VERSION_CODES.GINGERBREAD
- &amp;&amp;
- 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);
+
+ 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 {
+ ...
+ &#64;Override
+ 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 (mAddressRequested) {
+ startIntentService();
+ }
}
- ...
}
+}
+</pre>
+
+<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>
+public class MainActivity extends ActionBarActivity implements
+ ConnectionCallbacks, OnConnectionFailedListener {
...
+ class AddressResultReceiver extends ResultReceiver {
+ public AddressResultReceiver(Handler handler) {
+ super(handler);
+ }
+
+ &#64;Override
+ 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 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/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 @@ directly. Instead, you:
</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 @@ app, you should create a path scheme that matches the structure of the data.
</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&lt;DataApi.DataItemResult&gt; pendingResult = Wearable.DataApi
- .putDataItem(mGoogleApiClient, request);
+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;
+
+ ...
+
+ // 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&lt;DataApi.DataItemResult> pendingResult =
+ Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
+ }
+
+ ...
+}
</pre>
+<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>
-If one side of the data layer connection changes a data item, you probably want
+
+<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.
+You can do this by implementing a listener for data item events.</p>
-<p>For example, here's what a typical callback looks like to carry out certain actions
-when data changes:</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>
-&#64;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());
+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;
+
+ &#64;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();
+ }
+
+ &#64;Override
+ protected void onResume() {
+ super.onStart();
+ mGoogleApiClient.connect();
+ }
+
+ &#64;Override
+ public void onConnected(Bundle bundle) {
+ <strong>Wearable.DataApi.addListener</strong>(mGoogleApiClient, this);
+ }
+
+ &#64;Override
+ protected void onPause() {
+ super.onPause();
+ <strong>Wearable.DataApi.removeListener</strong>(mGoogleApiClient, this);
+ mGoogleApiClient.disconnect();
+ }
+
+ &#64;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 is just a snippet that requires more implementation details. Learn about
-how to implement a full listener service or activity in
+
+<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 @@ or <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.html#rem
public class MainActivity extends Activity implements
DataApi.DataListener, ConnectionCallbacks, OnConnectionFailedListener {
+ private GoogleApiClient mGoogleApiClient;
+
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -314,4 +316,5 @@ public class MainActivity extends Activity implements
}
}
}
+}
</pre>
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 @@ public class MtpDatabase {
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 @@ public class MtpDatabase {
MtpConstants.PROPERTY_PARENT_OBJECT,
MtpConstants.PROPERTY_PERSISTENT_UID,
MtpConstants.PROPERTY_NAME,
+ MtpConstants.PROPERTY_DISPLAY_NAME,
MtpConstants.PROPERTY_DATE_ADDED,
};
@@ -669,43 +674,6 @@ public class MtpDatabase {
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 @@ public class MtpDatabase {
case MtpConstants.FORMAT_PNG:
case MtpConstants.FORMAT_BMP:
return IMAGE_PROPERTIES;
- case 0:
- return ALL_PROPERTIES;
default:
return FILE_PROPERTIES;
}
@@ -749,6 +715,10 @@ public class MtpDatabase {
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 @@ public class MtpDatabase {
}
}
+ 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 @@ class MtpPropertyGroup {
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 @@ class MtpPropertyGroup {
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/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 @@ static const PropertyTableEntry kObjectPropertyTable[] = {
{ 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/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/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index ed43d8e..153b67b 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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// 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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
@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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
} 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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// 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);
@@ -3906,8 +3915,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
@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/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 @@ public class NetworkTimeUpdateService {
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 class NetworkTimeUpdateService {
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 @@ public class NetworkTimeUpdateService {
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 @@ public final class ActiveServices {
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 2b65c18..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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
} else {
finishRunningVoiceLocked();
}
- mStackSupervisor.setFocusedStack(r);
+ mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity");
if (r != null) {
mWindowManager.setFocusedApp(r.appToken, true);
}
@@ -2396,7 +2396,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (stack != null) {
ActivityRecord r = stack.topRunningActivityLocked(null);
if (r != null) {
- setFocusedActivityLocked(r);
+ setFocusedActivityLocked(r, "setFocusedStack");
}
}
}
@@ -2440,7 +2440,7 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
- stack.activityDestroyedLocked(token);
+ stack.activityDestroyedLocked(token, "activityDestroyed");
}
}
}
@@ -5948,7 +5948,7 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new IllegalArgumentException("File descriptors passed in options");
}
}
-
+
synchronized(this) {
int callingUid = Binder.getCallingUid();
int origUserId = userId;
@@ -5978,7 +5978,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return getIntentSenderLocked(type, packageName, callingUid, userId,
token, resultWho, requestCode, intents, resolvedTypes, flags, options);
-
+
} catch (RemoteException e) {
throw new SecurityException(e);
}
@@ -8019,7 +8019,7 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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);
}
@@ -8262,7 +8262,8 @@ public final class ActivityManagerService extends ActivityManagerNative
|| (task != mStackSupervisor.getFocusedStack().topTask()))) {
throw new IllegalArgumentException("Invalid task, not in foreground");
}
- mStackSupervisor.setLockTaskModeLocked(task, !isSystemInitiated);
+ mStackSupervisor.setLockTaskModeLocked(task, !isSystemInitiated,
+ "startLockTask");
}
}
} finally {
@@ -8347,7 +8348,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Log.d(TAG, "stopLockTaskMode");
// Stop lock task
synchronized (this) {
- mStackSupervisor.setLockTaskModeLocked(null, false);
+ mStackSupervisor.setLockTaskModeLocked(null, false, "stopLockTask");
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -10813,7 +10814,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Start up initial activity.
mBooting = true;
- startHomeActivityLocked(mCurrentUserId);
+ startHomeActivityLocked(mCurrentUserId, "systemReady");
try {
if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
@@ -18368,7 +18369,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return true;
}
- mStackSupervisor.setLockTaskModeLocked(null, false);
+ mStackSupervisor.setLockTaskModeLocked(null, false, "startUser");
final UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
if (userInfo == null) {
@@ -18625,7 +18626,7 @@ public final class ActivityManagerService extends ActivityManagerNative
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 8569ea4..a3676f9 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -522,7 +522,7 @@ final class ActivityRecord {
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));
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 7c1d54c..dbd787b 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -294,7 +294,7 @@ final class ActivityStack {
// 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: {
@@ -484,10 +484,10 @@ final class ActivityStack {
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);
@@ -1505,7 +1505,7 @@ final class ActivityStack {
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;
@@ -1541,7 +1541,7 @@ final class ActivityStack {
"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");
}
}
@@ -1827,11 +1827,8 @@ final class ActivityStack {
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);
@@ -2206,7 +2203,7 @@ final class ActivityStack {
}
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;
@@ -2231,7 +2228,7 @@ final class ActivityStack {
p.setTask(targetTask, null);
targetTask.addActivityAtBottom(p);
- mWindowManager.setAppGroupId(p.appToken, targetTaskId);
+ mWindowManager.setAppTask(p.appToken, targetTaskId);
}
mWindowManager.moveTaskToBottom(targetTaskId);
@@ -2371,7 +2368,7 @@ final class ActivityStack {
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) {
@@ -2480,18 +2477,19 @@ final class ActivityStack {
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");
}
}
}
@@ -2515,7 +2513,7 @@ final class ActivityStack {
}
if (r.app != null && r.app.thread != null) {
- adjustFocusedActivityLocked(r);
+ adjustFocusedActivityLocked(r, "stopActivity");
r.resumeKeyDispatchingLocked();
try {
r.stopped = false;
@@ -2719,7 +2717,7 @@ final class ActivityStack {
r.pauseKeyDispatchingLocked();
- adjustFocusedActivityLocked(r);
+ adjustFocusedActivityLocked(r, "finishActivity");
finishActivityResultsLocked(r, resultCode, resultData);
@@ -3022,7 +3020,7 @@ final class ActivityStack {
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();
@@ -3047,9 +3045,9 @@ final class ActivityStack {
"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();
@@ -3214,7 +3212,7 @@ final class ActivityStack {
// up.
//Slog.w(TAG, "Exception thrown during finish", e);
if (r.finishing) {
- removeActivityFromHistoryLocked(r);
+ removeActivityFromHistoryLocked(r, reason + " exceptionInScheduleDestroy");
removedFromHistory = true;
skipDestroy = true;
}
@@ -3244,7 +3242,7 @@ final class ActivityStack {
} 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)");
@@ -3263,7 +3261,7 @@ final class ActivityStack {
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);
@@ -3275,7 +3273,7 @@ final class ActivityStack {
if (isInStackLocked(r) != null) {
if (r.state == ActivityState.DESTROYING) {
cleanUpActivityLocked(r, true, false);
- removeActivityFromHistoryLocked(r);
+ removeActivityFromHistoryLocked(r, reason);
}
}
mStackSupervisor.resumeTopActivitiesLocked();
@@ -3411,7 +3409,7 @@ final class ActivityStack {
mService.updateUsageStats(r, false);
}
}
- removeActivityFromHistoryLocked(r);
+ removeActivityFromHistoryLocked(r, "appDied");
} else {
// We have the current state for this activity, so
@@ -3480,15 +3478,15 @@ final class ActivityStack {
}
}
- 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);
@@ -3499,11 +3497,10 @@ final class ActivityStack {
// 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) {
@@ -3533,7 +3530,7 @@ final class ActivityStack {
* @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);
@@ -3588,16 +3585,7 @@ final class ActivityStack {
}
}
- 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) {
@@ -3612,7 +3600,7 @@ final class ActivityStack {
}
final int taskToReturnTo = tr.getTaskToReturnTo();
tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
- return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null);
+ return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null, "moveTaskToBack");
}
mStackSupervisor.resumeTopActivitiesLocked();
@@ -4065,7 +4053,7 @@ final class ActivityStack {
return starting;
}
- void removeTask(TaskRecord task) {
+ void removeTask(TaskRecord task, String reason) {
mStackSupervisor.endLockTaskModeIfTaskEnding(task);
mWindowManager.removeTask(task.taskId);
final ActivityRecord r = mResumedActivity;
@@ -4103,7 +4091,7 @@ final class ActivityStack {
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);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index b1bb02a..4674cc2 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -400,7 +400,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
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) {
@@ -418,7 +418,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
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();
@@ -428,16 +428,16 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
}
- 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;
@@ -447,7 +447,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
mWindowManager.showRecentApps();
return false;
}
- moveHomeStackTaskToTop(homeStackTaskType);
+ moveHomeStackTaskToTop(homeStackTaskType, reason);
if (prev != null) {
prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
@@ -455,10 +455,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
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) {
@@ -830,8 +830,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
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);
}
@@ -1581,7 +1581,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
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 @@ public final class ActivityStackSupervisor implements DisplayListener {
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 @@ public final class ActivityStackSupervisor implements DisplayListener {
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 @@ public final class ActivityStackSupervisor implements DisplayListener {
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 @@ public final class ActivityStackSupervisor implements DisplayListener {
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 @@ public final class ActivityStackSupervisor implements DisplayListener {
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 @@ public final class ActivityStackSupervisor implements DisplayListener {
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 @@ public final class ActivityStackSupervisor implements DisplayListener {
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 @@ public final class ActivityStackSupervisor implements DisplayListener {
// 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 @@ public final class ActivityStackSupervisor implements DisplayListener {
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 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
}
- 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 @@ public final class ActivityStackSupervisor implements DisplayListener {
// 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);
}
@@ -2664,7 +2667,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
// 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.");
}
@@ -2691,7 +2694,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
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;
@@ -2701,7 +2704,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
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();
@@ -3067,14 +3070,14 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
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;
}
@@ -3469,7 +3472,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
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) {
@@ -3486,7 +3489,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
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 @@ option java_package com.android.server.am
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/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 class MediaSessionService extends SystemService implements Monitor {
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 @@ public class MediaSessionService extends SystemService implements Monitor {
mContentResolver = getContext().getContentResolver();
mSettingsObserver = new SettingsObserver();
mSettingsObserver.observe();
+
+ updateUser();
}
private IAudioService getAudioService() {
@@ -501,6 +502,12 @@ public class MediaSessionService extends SystemService implements Monitor {
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 @@ public class MediaSessionService extends SystemService implements Monitor {
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 @@ public class MediaSessionService extends SystemService implements Monitor {
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 @@ public class MediaSessionService extends SystemService implements Monitor {
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 @@ public class MediaSessionService extends SystemService implements Monitor {
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 @@ public class MediaSessionService extends SystemService implements Monitor {
// 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 @@ public class MediaSessionService extends SystemService implements Monitor {
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/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 @@ class TvInputHardwareManager implements TvInputHal.Callback {
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/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 @@ class AppWindowToken extends WindowToken {
final boolean voiceInteraction;
- int groupId = -1;
+ Task mTask;
boolean appFullscreen;
int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean layoutConfigChanges;
@@ -256,7 +256,8 @@ class AppWindowToken extends WindowToken {
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 @@ class AppWindowToken extends WindowToken {
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 @@ class DisplayContent {
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/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 @@ import com.android.server.EventLogTags;
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 @@ class Task {
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 @@ class Task {
@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 d6927e1..5d73149 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -222,7 +222,7 @@ public class TaskStack {
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) {
@@ -252,10 +252,9 @@ public class TaskStack {
}
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/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 46db132..a30dc91 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3612,15 +3612,15 @@ public class WindowManagerService extends IWindowManager.Stub
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 +3657,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
atoken = new AppWindowToken(this, token, voiceInteraction);
atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
- atoken.groupId = taskId;
atoken.appFullscreen = fullscreen;
atoken.showWhenLocked = showWhenLocked;
atoken.requestedOrientation = requestedOrientation;
@@ -3669,10 +3668,9 @@ public class WindowManagerService extends IWindowManager.Stub
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 +3683,27 @@ public class WindowManagerService extends IWindowManager.Stub
}
@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 +3987,7 @@ public class WindowManagerService extends IWindowManager.Stub
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 +4809,7 @@ public class WindowManagerService extends IWindowManager.Stub
+ " 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 +4874,7 @@ public class WindowManagerService extends IWindowManager.Stub
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) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a22ba33..98f00de 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -793,14 +793,14 @@ final class WindowState implements WindowManagerPolicy.WindowState {
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));
}
}
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 @@ public class TelecomManager {
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 @@ public class TelecomManager {
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 @@ public class TelecomManager {
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 @@ interface ITelecomService {
boolean hasVoiceMailNumber(in PhoneAccountHandle accountHandle);
/**
+ * @see TelecomServiceImpl#getLine1Number
+ */
+ String getLine1Number(in PhoneAccountHandle accountHandle);
+
+ /**
* @see TelecomServiceImpl#getDefaultPhoneApp
*/
ComponentName getDefaultPhoneApp();
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 @@ public class WindowManagerPermissionTests extends TestCase {
}
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 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
- public void setAppGroupId(IBinder arg0, int arg1) throws RemoteException {
+ public void setAppTask(IBinder arg0, int arg1) throws RemoteException {
// TODO Auto-generated method stub
}