summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/app/Activity.java39
-rw-r--r--core/java/android/app/ActivityManager.java8
-rw-r--r--core/java/android/app/ActivityThread.java2
-rw-r--r--core/java/android/app/ActivityTransitionCoordinator.java42
-rw-r--r--core/java/android/app/ActivityTransitionState.java1
-rw-r--r--core/java/android/app/AlarmManager.java2
-rw-r--r--core/java/android/app/AppOpsManager.java5
-rw-r--r--core/java/android/app/ApplicationPackageManager.java5
-rw-r--r--core/java/android/app/BackStackRecord.java763
-rw-r--r--core/java/android/app/EnterTransitionCoordinator.java26
-rw-r--r--core/java/android/app/ExitTransitionCoordinator.java14
-rw-r--r--core/java/android/app/Fragment.java583
-rw-r--r--core/java/android/app/FragmentManager.java13
-rw-r--r--core/java/android/app/FragmentTransaction.java17
-rw-r--r--core/java/android/app/INotificationManager.aidl4
-rw-r--r--core/java/android/app/Notification.java66
-rw-r--r--core/java/android/app/SharedElementCallback.java (renamed from core/java/android/app/SharedElementListener.java)92
-rw-r--r--core/java/android/app/admin/DeviceAdminReceiver.java4
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java95
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl1
-rw-r--r--core/java/android/app/job/JobScheduler.java14
-rw-r--r--core/java/android/app/usage/ConfigurationStats.java161
-rw-r--r--core/java/android/app/usage/IUsageStatsManager.aidl2
-rw-r--r--core/java/android/app/usage/UsageEvents.java121
-rw-r--r--core/java/android/app/usage/UsageStatsManager.java29
-rw-r--r--core/java/android/app/usage/UsageStatsManagerInternal.java16
-rw-r--r--core/java/android/appwidget/AppWidgetManager.java2
-rw-r--r--core/java/android/appwidget/AppWidgetProviderInfo.java4
-rw-r--r--core/java/android/bluetooth/BluetoothSocket.java8
-rw-r--r--core/java/android/content/Intent.java2
-rw-r--r--core/java/android/content/res/Configuration.java235
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java29
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java10
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlManager.java19
-rw-r--r--core/java/android/net/ConnectivityManager.java25
-rw-r--r--core/java/android/net/IConnectivityManager.aidl1
-rw-r--r--core/java/android/net/LinkAddress.java3
-rw-r--r--core/java/android/net/Network.java31
-rw-r--r--core/java/android/net/NetworkInfo.java8
-rw-r--r--core/java/android/net/NetworkRequest.java3
-rw-r--r--core/java/android/net/ProxyInfo.java4
-rw-r--r--core/java/android/os/Build.java2
-rw-r--r--core/java/android/os/INetworkManagementService.aidl5
-rw-r--r--core/java/android/os/UserHandle.java7
-rw-r--r--core/java/android/os/UserManager.java15
-rw-r--r--core/java/android/preference/CheckBoxPreference.java1
-rw-r--r--core/java/android/preference/SwitchPreference.java2
-rw-r--r--core/java/android/preference/TwoStatePreference.java29
-rw-r--r--core/java/android/provider/CallLog.java4
-rw-r--r--core/java/android/provider/ContactsContract.java13
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java47
-rw-r--r--core/java/android/service/notification/NotificationRankingUpdate.java11
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java41
-rw-r--r--core/java/android/text/Layout.java7
-rw-r--r--core/java/android/text/Selection.java13
-rw-r--r--core/java/android/transition/ChangeTransform.java36
-rw-r--r--core/java/android/transition/TransitionManager.java10
-rw-r--r--core/java/android/transition/TransitionUtils.java27
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java58
-rw-r--r--core/java/android/view/KeyEvent.java92
-rw-r--r--core/java/android/view/PointerIcon.java12
-rw-r--r--core/java/android/view/ThreadedRenderer.java4
-rw-r--r--core/java/android/view/View.java54
-rw-r--r--core/java/android/view/ViewAnimationUtils.java10
-rw-r--r--core/java/android/view/ViewGroup.java3
-rw-r--r--core/java/android/view/ViewRootImpl.java65
-rw-r--r--core/java/android/view/Window.java61
-rw-r--r--core/java/android/view/WindowManagerPolicy.java18
-rw-r--r--core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl19
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java10
-rw-r--r--core/java/android/view/inputmethod/CursorAnchorInfo.java90
-rw-r--r--core/java/android/view/inputmethod/InputConnection.java30
-rw-r--r--core/java/android/view/inputmethod/InputConnectionWrapper.java13
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java10
-rw-r--r--core/java/android/webkit/WebResourceRequest.java7
-rw-r--r--core/java/android/webkit/WebView.java21
-rw-r--r--core/java/android/webkit/WebViewFactoryProvider.java6
-rw-r--r--core/java/android/widget/AbsListView.java10
-rw-r--r--core/java/android/widget/ActionMenuView.java18
-rw-r--r--core/java/android/widget/AdapterView.java2
-rw-r--r--core/java/android/widget/DatePicker.java4
-rw-r--r--core/java/android/widget/DatePickerCalendarDelegate.java12
-rw-r--r--core/java/android/widget/EdgeEffect.java36
-rw-r--r--core/java/android/widget/Editor.java29
-rw-r--r--core/java/android/widget/RadialTimePickerView.java7
-rw-r--r--core/java/android/widget/RemoteViews.java33
-rw-r--r--core/java/android/widget/SearchView.java4
-rw-r--r--core/java/android/widget/TextView.java8
-rw-r--r--core/java/android/widget/TimePickerSpinnerDelegate.java71
-rw-r--r--core/java/android/widget/Toolbar.java24
-rw-r--r--core/java/com/android/internal/app/AlertController.java153
-rw-r--r--core/java/com/android/internal/app/ToolbarActionBar.java79
-rw-r--r--core/java/com/android/internal/os/Zygote.java21
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java26
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java2
-rw-r--r--core/java/com/android/internal/util/ImageUtils.java42
-rw-r--r--core/java/com/android/internal/util/NotificationColorUtil.java47
-rw-r--r--core/java/com/android/internal/view/IInputConnectionWrapper.java2
-rw-r--r--core/java/com/android/internal/view/InputConnectionWrapper.java9
-rw-r--r--core/java/com/android/internal/widget/ActionBarContextView.java11
-rw-r--r--core/java/com/android/internal/widget/EditableInputConnection.java8
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java9
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp3
-rw-r--r--core/jni/android/graphics/Graphics.cpp1
-rw-r--r--core/jni/android_view_RenderNode.cpp2
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp26
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp25
-rw-r--r--core/res/res/drawable-hdpi/pointer_arrow_icon.xml5
-rw-r--r--core/res/res/drawable-hdpi/pointer_spot_anchor.pngbin6817 -> 7374 bytes
-rw-r--r--core/res/res/drawable-hdpi/pointer_spot_anchor_icon.xml5
-rw-r--r--core/res/res/drawable-hdpi/pointer_spot_hover.pngbin9669 -> 8005 bytes
-rw-r--r--core/res/res/drawable-hdpi/pointer_spot_hover_icon.xml5
-rw-r--r--core/res/res/drawable-hdpi/pointer_spot_touch.pngbin2880 -> 3410 bytes
-rw-r--r--core/res/res/drawable-mdpi/pointer_arrow_icon.xml5
-rw-r--r--core/res/res/drawable-mdpi/pointer_spot_anchor.pngbin6817 -> 3682 bytes
-rw-r--r--core/res/res/drawable-mdpi/pointer_spot_hover.pngbin9669 -> 4044 bytes
-rw-r--r--core/res/res/drawable-mdpi/pointer_spot_touch.pngbin2880 -> 1797 bytes
-rw-r--r--core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml5
-rw-r--r--core/res/res/drawable-xhdpi/pointer_spot_anchor.pngbin11988 -> 11807 bytes
-rw-r--r--core/res/res/drawable-xhdpi/pointer_spot_hover.pngbin14878 -> 12994 bytes
-rw-r--r--core/res/res/drawable-xhdpi/pointer_spot_touch.pngbin5060 -> 5307 bytes
-rw-r--r--core/res/res/drawable/pointer_arrow_icon.xml (renamed from core/res/res/drawable-xhdpi/pointer_arrow_icon.xml)4
-rw-r--r--core/res/res/drawable/pointer_spot_anchor_icon.xml (renamed from core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml)4
-rw-r--r--core/res/res/drawable/pointer_spot_hover_icon.xml (renamed from core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml)4
-rw-r--r--core/res/res/drawable/pointer_spot_touch_icon.xml (renamed from core/res/res/drawable-hdpi/pointer_spot_touch_icon.xml)4
-rw-r--r--core/res/res/drawable/stat_sys_tether_wifi.xml9
-rw-r--r--core/res/res/drawable/time_picker_header_material.xml (renamed from core/res/res/drawable/ic_cab_done_material.xml)9
-rw-r--r--core/res/res/layout-land/time_picker_holo.xml5
-rw-r--r--core/res/res/layout/action_mode_close_item_material.xml26
-rw-r--r--core/res/res/layout/preference_material.xml3
-rw-r--r--core/res/res/layout/screen_toolbar.xml1
-rw-r--r--core/res/res/layout/time_picker_holo.xml25
-rw-r--r--core/res/res/values-cs/strings.xml4
-rw-r--r--core/res/res/values-fr-rCA/strings.xml2
-rw-r--r--core/res/res/values-in/strings.xml4
-rw-r--r--core/res/res/values-iw/strings.xml2
-rw-r--r--core/res/res/values-mcc310-mnc004/config.xml7
-rw-r--r--core/res/res/values-mcc310-mnc120/config.xml6
-rw-r--r--core/res/res/values-mcc310-mnc150/config.xml6
-rw-r--r--core/res/res/values-mcc310-mnc260/config.xml5
-rw-r--r--core/res/res/values-mcc310-mnc410/config.xml11
-rw-r--r--core/res/res/values-mcc311-mnc190/config.xml7
-rw-r--r--core/res/res/values-mcc311-mnc480/config.xml7
-rw-r--r--core/res/res/values-pt/strings.xml2
-rw-r--r--core/res/res/values-sw/strings.xml2
-rw-r--r--core/res/res/values-ta-rIN/strings.xml110
-rw-r--r--core/res/res/values-zh-rHK/strings.xml4
-rw-r--r--core/res/res/values-zh-rTW/strings.xml2
-rw-r--r--core/res/res/values/attrs.xml123
-rw-r--r--core/res/res/values/config.xml9
-rw-r--r--core/res/res/values/public.xml14
-rw-r--r--core/res/res/values/styles.xml1
-rw-r--r--core/res/res/values/styles_holo.xml12
-rw-r--r--core/res/res/values/styles_material.xml29
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/res/res/values/themes_material.xml4
-rw-r--r--core/tests/ConnectivityManagerTest/assets/accesspoints.xml40
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java373
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java128
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java364
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java19
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java66
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java122
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java21
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java55
165 files changed, 3973 insertions, 1795 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8ab344e..89a9692 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -788,8 +788,8 @@ public class Activity extends ContextThemeWrapper
final Handler mHandler = new Handler();
ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
- SharedElementListener mEnterTransitionListener = SharedElementListener.NULL_LISTENER;
- SharedElementListener mExitTransitionListener = SharedElementListener.NULL_LISTENER;
+ SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
+ SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK;
/** Return the intent that started this activity. */
public Intent getIntent() {
@@ -955,7 +955,7 @@ public class Activity extends ContextThemeWrapper
* @see #onRestoreInstanceState
* @see #onPostCreate
*/
- protected void onCreate(@Nullable Bundle savedInstanceState,
+ public void onCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
onCreate(savedInstanceState);
}
@@ -1040,7 +1040,7 @@ public class Activity extends ContextThemeWrapper
* @see #onResume
* @see #onSaveInstanceState
*/
- protected void onRestoreInstanceState(Bundle savedInstanceState,
+ public void onRestoreInstanceState(Bundle savedInstanceState,
PersistableBundle persistentState) {
if (savedInstanceState != null) {
onRestoreInstanceState(savedInstanceState);
@@ -1130,7 +1130,7 @@ public class Activity extends ContextThemeWrapper
*
* @see #onCreate
*/
- protected void onPostCreate(@Nullable Bundle savedInstanceState,
+ public void onPostCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
onPostCreate(savedInstanceState);
}
@@ -1380,7 +1380,7 @@ public class Activity extends ContextThemeWrapper
* @see #onRestoreInstanceState(Bundle, PersistableBundle)
* @see #onPause
*/
- protected void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
+ public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
onSaveInstanceState(outState);
}
@@ -4769,7 +4769,7 @@ public class Activity extends ContextThemeWrapper
* @param data An Intent, which can return result data to the caller
* (various data can be attached to Intent "extras").
*/
- protected void onActivityReenter(int resultCode, Intent data) {
+ public void onActivityReenter(int resultCode, Intent data) {
}
/**
@@ -5410,6 +5410,7 @@ public class Activity extends ContextThemeWrapper
mTranslucentCallback = callback;
mChangeCanvasToTranslucent =
ActivityManagerNative.getDefault().convertToTranslucent(mToken, options);
+ WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, false);
drawComplete = true;
} catch (RemoteException e) {
// Make callback return as though it timed out.
@@ -5778,33 +5779,33 @@ public class Activity extends ContextThemeWrapper
/**
* When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
- * android.view.View, String)} was used to start an Activity, <var>listener</var>
+ * android.view.View, String)} was used to start an Activity, <var>callback</var>
* will be called to handle shared elements on the <i>launched</i> Activity. This requires
* {@link Window#FEATURE_CONTENT_TRANSITIONS}.
*
- * @param listener Used to manipulate shared element transitions on the launched Activity.
+ * @param callback Used to manipulate shared element transitions on the launched Activity.
*/
- public void setEnterSharedElementListener(SharedElementListener listener) {
- if (listener == null) {
- listener = SharedElementListener.NULL_LISTENER;
+ public void setEnterSharedElementCallback(SharedElementCallback callback) {
+ if (callback == null) {
+ callback = SharedElementCallback.NULL_CALLBACK;
}
- mEnterTransitionListener = listener;
+ mEnterTransitionListener = callback;
}
/**
* When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
- * android.view.View, String)} was used to start an Activity, <var>listener</var>
+ * android.view.View, String)} was used to start an Activity, <var>callback</var>
* will be called to handle shared elements on the <i>launching</i> Activity. Most
* calls will only come when returning from the started Activity.
* This requires {@link Window#FEATURE_CONTENT_TRANSITIONS}.
*
- * @param listener Used to manipulate shared element transitions on the launching Activity.
+ * @param callback Used to manipulate shared element transitions on the launching Activity.
*/
- public void setExitSharedElementListener(SharedElementListener listener) {
- if (listener == null) {
- listener = SharedElementListener.NULL_LISTENER;
+ public void setExitSharedElementCallback(SharedElementCallback callback) {
+ if (callback == null) {
+ callback = SharedElementCallback.NULL_CALLBACK;
}
- mExitTransitionListener = listener;
+ mExitTransitionListener = callback;
}
/**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index bc54055..3e03893 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -18,12 +18,14 @@ package android.app;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
import android.os.BatteryStats;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+
import com.android.internal.app.ProcessStats;
import com.android.internal.os.TransferPipe;
import com.android.internal.util.FastPrintWriter;
@@ -2464,7 +2466,11 @@ public class ActivityManager {
}
}
- /** @hide */
+ /**
+ * Gets the userId of the current foreground user. Requires system permissions.
+ * @hide
+ */
+ @SystemApi
public static int getCurrentUser() {
UserInfo ui;
try {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 38999a8..4f2a3bc 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1938,7 +1938,7 @@ public final class ActivityThread {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
"Shared", "Private", "Swapped", "Heap", "Heap", "Heap");
- printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
+ printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "",
"Clean", "Clean", "Dirty", "Size", "Alloc", "Free");
printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
"------", "------", "------", "------", "------", "------");
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index a09a2e7..9e80a4b 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -197,7 +197,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
final protected ArrayList<View> mSharedElements = new ArrayList<View>();
final protected ArrayList<String> mSharedElementNames = new ArrayList<String>();
final protected ArrayList<View> mTransitioningViews = new ArrayList<View>();
- protected SharedElementListener mListener;
+ protected SharedElementCallback mListener;
protected ResultReceiver mResultReceiver;
final private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback();
final protected boolean mIsReturning;
@@ -208,7 +208,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
public ActivityTransitionCoordinator(Window window,
ArrayList<String> allSharedElementNames,
- SharedElementListener listener, boolean isReturning) {
+ SharedElementCallback listener, boolean isReturning) {
super(new Handler());
mWindow = window;
mListener = listener;
@@ -218,7 +218,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
protected void viewsReady(ArrayMap<String, View> sharedElements) {
sharedElements.retainAll(mAllSharedElementNames);
- mListener.remapSharedElements(mAllSharedElementNames, sharedElements);
+ mListener.onMapSharedElements(mAllSharedElementNames, sharedElements);
mSharedElementNames.addAll(sharedElements.keySet());
mSharedElements.addAll(sharedElements.values());
if (getViewsTransition() != null) {
@@ -251,9 +251,11 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
*/
protected void setEpicenter() {
View epicenter = null;
- if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty() &&
- mAllSharedElementNames.get(0).equals(mSharedElementNames.get(0))) {
- epicenter = mSharedElements.get(0);
+ if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty()) {
+ int index = mSharedElementNames.indexOf(mAllSharedElementNames.get(0));
+ if (index >= 0) {
+ epicenter = mSharedElements.get(index);
+ }
}
setEpicenter(epicenter);
}
@@ -458,20 +460,21 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
tempMatrix, tempRect, null);
}
}
- mListener.setSharedElementStart(mSharedElementNames, mSharedElements, snapshots);
+ mListener.onSharedElementStart(mSharedElementNames, mSharedElements, snapshots);
return originalImageState;
}
protected void notifySharedElementEnd(ArrayList<View> snapshots) {
- mListener.setSharedElementEnd(mSharedElementNames, mSharedElements, snapshots);
+ mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, snapshots);
}
protected void scheduleSetSharedElementEnd(final ArrayList<View> snapshots) {
- getDecor().getViewTreeObserver().addOnPreDrawListener(
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
notifySharedElementEnd(snapshots);
return true;
}
@@ -526,7 +529,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
Parcelable parcelable = sharedElementBundle.getParcelable(KEY_SNAPSHOT);
View snapshot = null;
if (parcelable != null) {
- snapshot = mListener.createSnapshotView(context, parcelable);
+ snapshot = mListener.onCreateSnapshotView(context, parcelable);
}
if (snapshot != null) {
setSharedElementState(snapshot, name, state, null, null, decorLoc);
@@ -618,7 +621,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ());
sharedElementBundle.putFloat(KEY_ELEVATION, view.getElevation());
- Parcelable bitmap = mListener.captureSharedElementSnapshot(view, tempMatrix, tempBounds);
+ Parcelable bitmap = mListener.onCaptureSharedElementSnapshot(view, tempMatrix, tempBounds);
if (bitmap != null) {
sharedElementBundle.putParcelable(KEY_SNAPSHOT, bitmap);
}
@@ -664,8 +667,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
GhostView.addGhost(view, decor);
ViewGroup parent = (ViewGroup) view.getParent();
if (moveWithParent && !isInTransitionGroup(parent, decor)) {
- GhostViewListeners listener =
- new GhostViewListeners(view, decor);
+ GhostViewListeners listener = new GhostViewListeners(view, parent, decor);
parent.getViewTreeObserver().addOnPreDrawListener(listener);
mGhostViewListeners.add(listener);
}
@@ -723,11 +725,12 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
}
protected void scheduleGhostVisibilityChange(final int visibility) {
- getDecor().getViewTreeObserver()
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
setGhostVisibility(visibility);
return true;
}
@@ -769,10 +772,12 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener {
private View mView;
private ViewGroup mDecor;
+ private View mParent;
private Matrix mMatrix = new Matrix();
- public GhostViewListeners(View view, ViewGroup decor) {
+ public GhostViewListeners(View view, View parent, ViewGroup decor) {
mView = view;
+ mParent = parent;
mDecor = decor;
}
@@ -782,10 +787,9 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
@Override
public boolean onPreDraw() {
- ViewGroup parent = ((ViewGroup) mView.getParent());
GhostView ghostView = GhostView.getGhost(mView);
if (ghostView == null) {
- parent.getViewTreeObserver().removeOnPreDrawListener(this);
+ mParent.getViewTreeObserver().removeOnPreDrawListener(this);
} else {
GhostView.calculateMatrix(mView, mDecor, mMatrix);
ghostView.setMatrix(mMatrix);
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 613e248..ad4a22b 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -151,6 +151,7 @@ class ActivityTransitionState {
mEnterActivityOptions = options;
mIsEnterTriggered = false;
if (mEnterActivityOptions.isReturning()) {
+ restoreExitedViews();
int result = mEnterActivityOptions.getResultCode();
if (result != 0) {
activity.onActivityReenter(result, mEnterActivityOptions.getResultData());
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index a64e0ed..2c596e5 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -17,6 +17,7 @@
package android.app;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
@@ -385,6 +386,7 @@ public class AlarmManager
}
/** @hide */
+ @SystemApi
public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis,
PendingIntent operation, WorkSource workSource) {
setImpl(type, triggerAtMillis, windowMillis, intervalMillis, operation, workSource, null);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 66928ca..ba9c9d6 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -220,6 +220,9 @@ public class AppOpsManager {
/** Continually monitoring location data with a relatively high power request. */
public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION
= "android:monitor_location_high_power";
+ /** Access to {@link android.app.usage.UsageStatsManager}. */
+ public static final String OPSTR_GET_USAGE_STATS
+ = "android:get_usage_stats";
/** Activate a VPN connection without user intervention. @hide */
@SystemApi
public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn";
@@ -331,7 +334,7 @@ public class AppOpsManager {
null,
OPSTR_MONITOR_LOCATION,
OPSTR_MONITOR_HIGH_POWER_LOCATION,
- null,
+ OPSTR_GET_USAGE_STATS,
null,
null,
null,
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 6843827..e2def31 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1640,7 +1640,10 @@ final class ApplicationPackageManager extends PackageManager {
if (itemInfo.showUserIcon != UserHandle.USER_NULL) {
return new BitmapDrawable(getUserManager().getUserIcon(itemInfo.showUserIcon));
}
- Drawable dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo);
+ Drawable dr = null;
+ if (itemInfo.packageName != null) {
+ dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo);
+ }
if (dr == null) {
dr = itemInfo.loadDefaultIcon(this);
}
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 67863a5..8227915 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -23,15 +23,17 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.transition.Transition;
-import android.transition.TransitionInflater;
import android.transition.TransitionManager;
import android.transition.TransitionSet;
+import android.transition.TransitionUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.LogWriter;
import android.util.Pair;
+import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -42,8 +44,6 @@ final class BackStackState implements Parcelable {
final int[] mOps;
final int mTransition;
final int mTransitionStyle;
- final int mCustomTransition;
- final int mSceneRoot;
final String mName;
final int mIndex;
final int mBreadCrumbTitleRes;
@@ -96,8 +96,6 @@ final class BackStackState implements Parcelable {
mBreadCrumbTitleText = bse.mBreadCrumbTitleText;
mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes;
mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText;
- mCustomTransition = bse.mCustomTransition;
- mSceneRoot = bse.mSceneRoot;
mSharedElementSourceNames = bse.mSharedElementSourceNames;
mSharedElementTargetNames = bse.mSharedElementTargetNames;
}
@@ -112,8 +110,6 @@ final class BackStackState implements Parcelable {
mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mBreadCrumbShortTitleRes = in.readInt();
mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- mCustomTransition = in.readInt();
- mSceneRoot = in.readInt();
mSharedElementSourceNames = in.createStringArrayList();
mSharedElementTargetNames = in.createStringArrayList();
}
@@ -164,8 +160,6 @@ final class BackStackState implements Parcelable {
bse.mBreadCrumbTitleText = mBreadCrumbTitleText;
bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes;
bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText;
- bse.mCustomTransition = mCustomTransition;
- bse.mSceneRoot = mSceneRoot;
bse.mSharedElementSourceNames = mSharedElementSourceNames;
bse.mSharedElementTargetNames = mSharedElementTargetNames;
bse.bumpBackStackNesting(1);
@@ -186,8 +180,6 @@ final class BackStackState implements Parcelable {
TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0);
dest.writeInt(mBreadCrumbShortTitleRes);
TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0);
- dest.writeInt(mCustomTransition);
- dest.writeInt(mSceneRoot);
dest.writeStringList(mSharedElementSourceNames);
dest.writeStringList(mSharedElementTargetNames);
}
@@ -254,8 +246,6 @@ final class BackStackRecord extends FragmentTransaction implements
int mBreadCrumbShortTitleRes;
CharSequence mBreadCrumbShortTitleText;
- int mCustomTransition;
- int mSceneRoot;
ArrayList<String> mSharedElementSourceNames;
ArrayList<String> mSharedElementTargetNames;
@@ -573,13 +563,6 @@ final class BackStackRecord extends FragmentTransaction implements
}
@Override
- public FragmentTransaction setCustomTransition(int sceneRootId, int transitionId) {
- mSceneRoot = sceneRootId;
- mCustomTransition = transitionId;
- return this;
- }
-
- @Override
public FragmentTransaction addSharedElement(View sharedElement, String name) {
String transitionName = sharedElement.getTransitionName();
if (transitionName == null) {
@@ -760,8 +743,15 @@ final class BackStackRecord extends FragmentTransaction implements
bumpBackStackNesting(1);
- TransitionState state = beginTransition(mSharedElementSourceNames,
- mSharedElementTargetNames);
+ SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
+ SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
+
+ calculateFragments(firstOutFragments, lastInFragments);
+
+ TransitionState state = null;
+ if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
+ state = beginTransition(firstOutFragments, lastInFragments, false);
+ }
Op op = mHead;
while (op != null) {
@@ -854,144 +844,608 @@ final class BackStackRecord extends FragmentTransaction implements
}
if (state != null) {
- updateTransitionEndState(state, mSharedElementTargetNames);
+ updateTransitionEndState(state, firstOutFragments, lastInFragments, false);
}
}
- private TransitionState beginTransition(ArrayList<String> sourceNames,
- ArrayList<String> targetNames) {
- if (mCustomTransition <= 0 || mSceneRoot <= 0) {
- return null;
+ private static void setFirstOut(SparseArray<Fragment> fragments, Fragment fragment) {
+ if (fragment != null) {
+ int containerId = fragment.mContainerId;
+ if (containerId != 0 && !fragment.isHidden() && fragment.isAdded() &&
+ fragment.getView() != null && fragments.get(containerId) == null) {
+ fragments.put(containerId, fragment);
+ }
+ }
+ }
+
+ private void setLastIn(SparseArray<Fragment> fragments, Fragment fragment) {
+ if (fragment != null) {
+ int containerId = fragment.mContainerId;
+ if (containerId != 0) {
+ fragments.put(containerId, fragment);
+ }
+ }
+ }
+
+ /**
+ * Finds the first removed fragment and last added fragments when going forward.
+ * If none of the fragments have transitions, then both lists will be empty.
+ *
+ * @param firstOutFragments The list of first fragments to be removed, keyed on the
+ * container ID. This list will be modified by the method.
+ * @param lastInFragments The list of last fragments to be added, keyed on the
+ * container ID. This list will be modified by the method.
+ */
+ private void calculateFragments(SparseArray<Fragment> firstOutFragments,
+ SparseArray<Fragment> lastInFragments) {
+ Op op = mHead;
+ while (op != null) {
+ switch (op.cmd) {
+ case OP_ADD:
+ setLastIn(lastInFragments, op.fragment);
+ break;
+ case OP_REPLACE: {
+ Fragment f = op.fragment;
+ if (mManager.mAdded != null) {
+ for (int i = 0; i < mManager.mAdded.size(); i++) {
+ Fragment old = mManager.mAdded.get(i);
+ if (f == null || old.mContainerId == f.mContainerId) {
+ if (old == f) {
+ f = null;
+ } else {
+ setFirstOut(firstOutFragments, old);
+ }
+ }
+ }
+ }
+ setLastIn(lastInFragments, f);
+ break;
+ }
+ case OP_REMOVE:
+ setFirstOut(firstOutFragments, op.fragment);
+ break;
+ case OP_HIDE:
+ setFirstOut(firstOutFragments, op.fragment);
+ break;
+ case OP_SHOW:
+ setLastIn(lastInFragments, op.fragment);
+ break;
+ case OP_DETACH:
+ setFirstOut(firstOutFragments, op.fragment);
+ break;
+ case OP_ATTACH:
+ setLastIn(lastInFragments, op.fragment);
+ break;
+ }
+
+ op = op.next;
+ }
+
+ if (!haveTransitions(firstOutFragments, lastInFragments, false)) {
+ firstOutFragments.clear();
+ lastInFragments.clear();
+ }
+ }
+
+ /**
+ * @return true if custom transitions exist on any fragment in firstOutFragments or
+ * lastInFragments or false otherwise.
+ */
+ private static boolean haveTransitions(SparseArray<Fragment> firstOutFragments,
+ SparseArray<Fragment> lastInFragments, boolean isBack) {
+ for (int i = firstOutFragments.size() - 1; i >= 0; i--) {
+ Fragment f = firstOutFragments.valueAt(i);
+ if (isBack) {
+ if (f.getReturnTransition() != null ||
+ f.getSharedElementReturnTransition() != null) {
+ return true;
+ }
+ } else if (f.getExitTransition() != null) {
+ return true;
+ }
+ }
+
+ for (int i = lastInFragments.size() - 1; i >= 0; i--) {
+ Fragment f = lastInFragments.valueAt(i);
+ if (isBack) {
+ if (f.getReenterTransition() != null) {
+ return true;
+ }
+ } else if (f.getEnterTransition() != null ||
+ f.getSharedElementEnterTransition() != null) {
+ return true;
+ }
}
- View rootView = mManager.mContainer.findViewById(mSceneRoot);
- if (!(rootView instanceof ViewGroup)) {
- throw new IllegalArgumentException("SceneRoot is not a ViewGroup");
+ return false;
+ }
+
+ /**
+ * Finds the first removed fragment and last added fragments when popping the back stack.
+ * If none of the fragments have transitions, then both lists will be empty.
+ *
+ * @param firstOutFragments The list of first fragments to be removed, keyed on the
+ * container ID. This list will be modified by the method.
+ * @param lastInFragments The list of last fragments to be added, keyed on the
+ * container ID. This list will be modified by the method.
+ */
+ public void calculateBackFragments(SparseArray<Fragment> firstOutFragments,
+ SparseArray<Fragment> lastInFragments) {
+ Op op = mHead;
+ while (op != null) {
+ switch (op.cmd) {
+ case OP_ADD:
+ setFirstOut(firstOutFragments, op.fragment);
+ break;
+ case OP_REPLACE:
+ if (op.removed != null) {
+ for (int i = op.removed.size() - 1; i >= 0; i--) {
+ setLastIn(lastInFragments, op.removed.get(i));
+ }
+ }
+ setFirstOut(firstOutFragments, op.fragment);
+ break;
+ case OP_REMOVE:
+ setLastIn(lastInFragments, op.fragment);
+ break;
+ case OP_HIDE:
+ setLastIn(lastInFragments, op.fragment);
+ break;
+ case OP_SHOW:
+ setFirstOut(firstOutFragments, op.fragment);
+ break;
+ case OP_DETACH:
+ setLastIn(lastInFragments, op.fragment);
+ break;
+ case OP_ATTACH:
+ setFirstOut(firstOutFragments, op.fragment);
+ break;
+ }
+
+ op = op.next;
}
+
+ if (!haveTransitions(firstOutFragments, lastInFragments, true)) {
+ firstOutFragments.clear();
+ lastInFragments.clear();
+ }
+ }
+
+ /**
+ * When custom fragment transitions are used, this sets up the state for each transition
+ * and begins the transition. A different transition is started for each fragment container
+ * and consists of up to 3 different transitions: the exit transition, a shared element
+ * transition and an enter transition.
+ *
+ * <p>The exit transition operates against the leaf nodes of the first fragment
+ * with a view that was removed. If no such fragment was removed, then no exit
+ * transition is executed. The exit transition comes from the outgoing fragment.</p>
+ *
+ * <p>The enter transition operates against the last fragment that was added. If
+ * that fragment does not have a view or no fragment was added, then no enter
+ * transition is executed. The enter transition comes from the incoming fragment.</p>
+ *
+ * <p>The shared element transition operates against all views and comes either
+ * from the outgoing fragment or the incoming fragment, depending on whether this
+ * is going forward or popping the back stack. When going forward, the incoming
+ * fragment's enter shared element transition is used, but when going back, the
+ * outgoing fragment's return shared element transition is used. Shared element
+ * transitions only operate if there is both an incoming and outgoing fragment.</p>
+ *
+ * @param firstOutFragments The list of first fragments to be removed, keyed on the
+ * container ID.
+ * @param lastInFragments The list of last fragments to be added, keyed on the
+ * container ID.
+ * @param isBack true if this is popping the back stack or false if this is a
+ * forward operation.
+ * @return The TransitionState used to complete the operation of the transition
+ * in {@link #updateTransitionEndState(android.app.BackStackRecord.TransitionState,
+ * android.util.SparseArray, android.util.SparseArray, boolean)}.
+ */
+ private TransitionState beginTransition(SparseArray<Fragment> firstOutFragments,
+ SparseArray<Fragment> lastInFragments, boolean isBack) {
TransitionState state = new TransitionState();
- // get Transition scene root and create Transitions
- state.sceneRoot = (ViewGroup) rootView;
- state.sceneRoot.captureTransitioningViews(state.transitioningViews);
-
- state.exitTransition = TransitionInflater.from(mManager.mActivity)
- .inflateTransition(mCustomTransition);
- state.sharedElementTransition = TransitionInflater.from(mManager.mActivity)
- .inflateTransition(mCustomTransition);
- state.enterTransition = TransitionInflater.from(mManager.mActivity)
- .inflateTransition(mCustomTransition);
+
// Adding a non-existent target view makes sure that the transitions don't target
// any views by default. They'll only target the views we tell add. If we don't
// add any, then no views will be targeted.
- View nonExistentView = new View(mManager.mActivity);
- state.enterTransition.addTarget(nonExistentView);
- state.exitTransition.addTarget(nonExistentView);
- state.sharedElementTransition.addTarget(nonExistentView);
-
- setSharedElementEpicenter(state.enterTransition, state);
-
- state.excludingTransition = new TransitionSet()
- .addTransition(state.exitTransition)
- .addTransition(state.enterTransition);
+ state.nonExistentView = new View(mManager.mActivity);
+
+ ArrayMap<String, View> tempViews1 = new ArrayMap<String, View>();
+ ArrayMap<String, View> tempViews2 = new ArrayMap<String, View>();
+ ArrayList<String> tempNames = new ArrayList<String>();
+ ArrayList<View> tempViewList = new ArrayList<View>();
+
+ // Go over all leaving fragments.
+ for (int i = 0; i < firstOutFragments.size(); i++) {
+ int containerId = firstOutFragments.keyAt(i);
+ configureTransitions(containerId, state, isBack, firstOutFragments,
+ lastInFragments, tempViews1, tempViews2, tempNames, tempViewList);
+ }
- if (sourceNames != null) {
- // Map shared elements.
- state.sceneRoot.findNamedViews(state.namedViews);
- state.namedViews.retainAll(sourceNames);
- View epicenterView = state.namedViews.get(sourceNames.get(0));
- if (epicenterView != null) {
- // The epicenter is only the first shared element.
- setEpicenter(state.exitTransition, epicenterView);
- setEpicenter(state.sharedElementTransition, epicenterView);
+ // Now go over all entering fragments that didn't have a leaving fragment.
+ for (int i = 0; i < lastInFragments.size(); i++) {
+ int containerId = lastInFragments.keyAt(i);
+ if (firstOutFragments.get(containerId) == null) {
+ configureTransitions(containerId, state, isBack, firstOutFragments,
+ lastInFragments, tempViews1, tempViews2, tempNames, tempViewList);
}
- state.transitioningViews.removeAll(state.namedViews.values());
- state.excludingTransition.addTransition(state.sharedElementTransition);
- addTransitioningViews(state.sharedElementTransition, state.namedViews.values());
}
- // Adds the (maybe) exiting views, not including the shared element.
- // If some stay, that's ok.
- addTransitioningViews(state.exitTransition, state.transitioningViews);
+ if (state.overallTransitions.size() == 0) {
+ state = null;
+ }
+ return state;
+ }
- // Prepare for shared element name mapping. This could be chained in the case
- // of popping several back stack states.
- state.excludingTransition.setNameOverrides(new ArrayMap<String, String>());
- setNameOverrides(state, sourceNames, targetNames);
+ private static Transition getEnterTransition(Fragment inFragment, boolean isBack) {
+ if (inFragment == null) {
+ return null;
+ }
+ return isBack ? inFragment.getReenterTransition() : inFragment.getEnterTransition();
+ }
- // Don't include any subtree in the views that are hidden when capturing the
- // view hierarchy transitions. They should be as if not there.
- excludeHiddenFragments(state, true);
+ private static Transition getExitTransition(Fragment outFragment, boolean isBack) {
+ if (outFragment == null) {
+ return null;
+ }
+ return isBack ? outFragment.getReturnTransition() : outFragment.getExitTransition();
+ }
- TransitionManager.beginDelayedTransition(state.sceneRoot, state.excludingTransition);
- return state;
+ private static Transition getSharedElementTransition(Fragment inFragment, Fragment outFragment,
+ boolean isBack) {
+ if (inFragment == null || outFragment == null) {
+ return null;
+ }
+ return isBack ? outFragment.getSharedElementReturnTransition() :
+ inFragment.getSharedElementEnterTransition();
}
- private void updateTransitionEndState(TransitionState state, ArrayList<String> names) {
- // Find all views that are entering.
- ArrayList<View> enteringViews = new ArrayList<View>();
- state.sceneRoot.captureTransitioningViews(enteringViews);
- enteringViews.removeAll(state.transitioningViews);
-
- if (names != null) {
- // find all shared elements.
- state.namedViews.clear();
- state.sceneRoot.findNamedViews(state.namedViews);
- state.namedViews.retainAll(names);
- if (!state.namedViews.isEmpty()) {
- enteringViews.removeAll(state.namedViews.values());
- addTransitioningViews(state.sharedElementTransition, state.namedViews.values());
- // now we know the epicenter of the entering transition.
- state.mEnteringEpicenterView = state.namedViews.get(names.get(0));
+ private static Transition captureExitingViews(Transition exitTransition, Fragment outFragment,
+ ArrayList<View> viewList) {
+ if (exitTransition != null) {
+ View root = outFragment.getView();
+ viewList.clear();
+ root.captureTransitioningViews(viewList);
+ if (viewList.isEmpty()) {
+ exitTransition = null;
+ } else {
+ addTransitioningViews(exitTransition, viewList);
+ }
+ }
+ return exitTransition;
+ }
+
+ private ArrayMap<String, View> remapSharedElements(TransitionState state, Fragment outFragment,
+ ArrayMap<String, View> namedViews, ArrayMap<String, View> tempViews2, boolean isBack) {
+ if (mSharedElementSourceNames != null) {
+ outFragment.getView().findNamedViews(namedViews);
+ if (isBack) {
+ namedViews.retainAll(mSharedElementTargetNames);
+ } else {
+ namedViews = remapNames(mSharedElementSourceNames, mSharedElementTargetNames,
+ namedViews, tempViews2);
}
}
- // Add all entering views to the enter transition.
- addTransitioningViews(state.enterTransition, enteringViews);
+ if (isBack) {
+ outFragment.mEnterTransitionCallback.onMapSharedElements(
+ mSharedElementTargetNames, namedViews);
+ setBackNameOverrides(state, namedViews, false);
+ } else {
+ outFragment.mExitTransitionCallback.onMapSharedElements(
+ mSharedElementTargetNames, namedViews);
+ setNameOverrides(state, namedViews, false);
+ }
- // Don't allow capturing state for the newly-hidden fragments.
- excludeHiddenFragments(state, false);
+ return namedViews;
+ }
- // Allow capturing state for the newly-shown fragments
- includeVisibleFragments(state.excludingTransition);
+ /**
+ * Prepares the enter transition by adding a non-existent view to the transition's target list
+ * and setting it epicenter callback. By adding a non-existent view to the target list,
+ * we can prevent any view from being targeted at the beginning of the transition.
+ * We will add to the views before the end state of the transition is captured so that the
+ * views will appear. At the start of the transition, we clear the list of targets so that
+ * we can restore the state of the transition and use it again.
+ */
+ private void prepareEnterTransition(TransitionState state, final Transition enterTransition,
+ final View container, final Fragment inFragment) {
+ if (enterTransition != null) {
+ final ArrayList<View> enteringViews = new ArrayList<View>();
+ final View nonExistentView = state.nonExistentView;
+ enterTransition.addTarget(state.nonExistentView);
+ enterTransition.addListener(new Transition.TransitionListenerAdapter() {
+ @Override
+ public void onTransitionStart(Transition transition) {
+ transition.removeListener(this);
+ transition.removeTarget(nonExistentView);
+ int numViews = enteringViews.size();
+ for (int i = 0; i < numViews; i++) {
+ transition.removeTarget(enteringViews.get(i));
+ }
+ }
+ });
+ container.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ container.getViewTreeObserver().removeOnPreDrawListener(this);
+ View view = inFragment.getView();
+ if (view != null) {
+ view.captureTransitioningViews(enteringViews);
+ addTransitioningViews(enterTransition, enteringViews);
+ }
+ return true;
+ }
+ });
+ setSharedElementEpicenter(enterTransition, state);
+ }
}
- private void addTransitioningViews(Transition transition, Collection<View> views) {
- if (views.isEmpty()) {
- // Add a view so that we can modify the valid views at the end of the
- // fragment transaction.
- transition.addTarget(new View(mManager.mActivity));
+ private static Transition mergeTransitions(Transition enterTransition,
+ Transition exitTransition, Transition sharedElementTransition, Fragment inFragment,
+ boolean isBack) {
+ boolean overlap = true;
+ if (enterTransition != null && exitTransition != null) {
+ overlap = isBack ? inFragment.getAllowReturnTransitionOverlap() :
+ inFragment.getAllowEnterTransitionOverlap();
+ }
+
+ Transition transition;
+ if (overlap) {
+ transition = TransitionUtils.mergeTransitions(enterTransition, exitTransition,
+ sharedElementTransition);
} else {
- for (View view : views) {
- transition.addTarget(view);
+ TransitionSet staggered = new TransitionSet()
+ .addTransition(exitTransition)
+ .addTransition(enterTransition)
+ .setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
+ transition = TransitionUtils.mergeTransitions(staggered, sharedElementTransition);
+ }
+ return transition;
+ }
+
+ /**
+ * Configures custom transitions for a specific fragment container.
+ *
+ * @param containerId The container ID of the fragments to configure the transition for.
+ * @param state The Transition State to be shared with {@link #updateTransitionEndState(
+ * android.app.BackStackRecord.TransitionState, android.util.SparseArray,
+ * android.util.SparseArray, boolean)} later.
+ * @param firstOutFragments The list of first fragments to be removed, keyed on the
+ * container ID.
+ * @param lastInFragments The list of last fragments to be added, keyed on the
+ * container ID.
+ * @param isBack true if this is popping the back stack or false if this is a
+ * forward operation.
+ * @param tempViews1 A temporary mapping of names to Views, used to avoid allocation
+ * inside a loop.
+ * @param tempViews2 A temporary mapping of names to Views, used to avoid allocation
+ * inside a loop.
+ * @param tempNames A temporary list of Strings, used to avoid allocation inside a loop.
+ * @param tempViewList A temporary list of Views, used to avoid allocation inside a loop.
+ */
+ private void configureTransitions(int containerId, TransitionState state, boolean isBack,
+ SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments,
+ ArrayMap<String, View> tempViews1, ArrayMap<String, View> tempViews2,
+ ArrayList<String> tempNames, ArrayList<View> tempViewList) {
+ ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.findViewById(containerId);
+ if (sceneRoot != null) {
+ Fragment inFragment = lastInFragments.get(containerId);
+ Fragment outFragment = firstOutFragments.get(containerId);
+
+ Transition enterTransition = getEnterTransition(inFragment, isBack);
+ Transition sharedElementTransition = getSharedElementTransition(inFragment, outFragment,
+ isBack);
+ Transition exitTransition = getExitTransition(outFragment, isBack);
+ exitTransition = captureExitingViews(exitTransition, outFragment, tempViewList);
+
+ ArrayMap<String, View> namedViews = tempViews1;
+ namedViews.clear();
+ if (sharedElementTransition != null) {
+ namedViews = remapSharedElements(state,
+ outFragment, namedViews, tempViews2, isBack);
+ }
+
+ // Notify the start of the transition.
+ SharedElementCallback callback = isBack ?
+ outFragment.mEnterTransitionCallback :
+ inFragment.mEnterTransitionCallback;
+ tempNames.clear();
+ tempNames.addAll(namedViews.keySet());
+ tempViewList.clear();
+ tempViewList.addAll(namedViews.values());
+ callback.onSharedElementStart(tempNames, tempViewList, null);
+
+ // Set the epicenter of the exit transition
+ if (mSharedElementTargetNames != null && exitTransition != null) {
+ View epicenterView = namedViews.get(mSharedElementTargetNames.get(0));
+ if (epicenterView != null) {
+ setEpicenter(exitTransition, epicenterView);
+ }
+ }
+
+ prepareEnterTransition(state, enterTransition, sceneRoot, inFragment);
+
+ Transition transition = mergeTransitions(enterTransition, exitTransition,
+ sharedElementTransition, inFragment, isBack);
+
+ if (transition != null) {
+ state.overallTransitions.put(containerId, transition);
+ transition.setNameOverrides(state.nameOverrides);
+ // We want to exclude hidden views later, so we need a non-null list in the
+ // transition now.
+ transition.excludeTarget(state.nonExistentView, true);
+ // Now exclude all currently hidden fragments.
+ excludeHiddenFragments(state, containerId, transition);
+ cleanupHiddenFragments(transition, state);
+ TransitionManager.beginDelayedTransition(sceneRoot, transition);
}
}
}
- private void excludeHiddenFragments(TransitionState state, boolean forceExclude) {
- if (mManager.mAdded != null) {
- for (int i = 0; i < mManager.mAdded.size(); i++) {
- Fragment fragment = mManager.mAdded.get(i);
- if (fragment.mView != null && fragment.mHidden
- && (forceExclude || !state.hiddenViews.contains(fragment.mView))) {
- state.excludingTransition.excludeTarget(fragment.mView, true);
- state.hiddenViews.add(fragment.mView);
+ /**
+ * Remaps a name-to-View map, substituting different names for keys.
+ *
+ * @param inMap A list of keys found in the map, in the order in toGoInMap
+ * @param toGoInMap A list of keys to use for the new map, in the order of inMap
+ * @param namedViews The current mapping
+ * @param tempMap A temporary mapping that will be filled with the new values.
+ * @return tempMap after it has been mapped with the new names as keys.
+ */
+ private static ArrayMap<String, View> remapNames(ArrayList<String> inMap,
+ ArrayList<String> toGoInMap, ArrayMap<String, View> namedViews,
+ ArrayMap<String, View> tempMap) {
+ tempMap.clear();
+ if (!namedViews.isEmpty()) {
+ int numKeys = inMap.size();
+ for (int i = 0; i < numKeys; i++) {
+ View view = namedViews.get(inMap.get(i));
+ if (view != null) {
+ tempMap.put(toGoInMap.get(i), view);
}
}
}
- if (forceExclude && state.hiddenViews.isEmpty()) {
- state.excludingTransition.excludeTarget(new View(mManager.mActivity), true);
+ return tempMap;
+ }
+
+ /**
+ * After making all fragment changes, this updates the custom transitions to take into
+ * account the entering views and any remapping.
+ *
+ * @param state The transition State as returned from {@link #beginTransition(
+ * android.util.SparseArray, android.util.SparseArray, boolean)}.
+ * @param outFragments The list of first fragments to be removed, keyed on the
+ * container ID.
+ * @param inFragments The list of last fragments to be added, keyed on the
+ * container ID.
+ * @param isBack true if this is popping the back stack or false if this is a
+ * forward operation.
+ */
+ private void updateTransitionEndState(TransitionState state, SparseArray<Fragment> outFragments,
+ SparseArray<Fragment> inFragments, boolean isBack) {
+ ArrayMap<String, View> tempViews1 = new ArrayMap<String, View>();
+ ArrayMap<String, View> tempViews2 = new ArrayMap<String, View>();
+ ArrayList<String> tempNames = new ArrayList<String>();
+ ArrayList<View> tempViews = new ArrayList<View>();
+
+ int numInFragments = inFragments.size();
+ for (int i = 0; i < numInFragments; i++) {
+ Fragment inFragment = inFragments.valueAt(i);
+ tempViews1.clear();
+ ArrayMap<String, View> namedViews = mapEnteringSharedElements(inFragment, tempViews1,
+ tempViews2, isBack);
+ // remap shared elements and set the name mapping used in the shared element transition.
+ if (isBack) {
+ inFragment.mExitTransitionCallback.onMapSharedElements(
+ mSharedElementTargetNames, namedViews);
+ setBackNameOverrides(state, namedViews, true);
+ } else {
+ inFragment.mEnterTransitionCallback.onMapSharedElements(
+ mSharedElementTargetNames, namedViews);
+ setNameOverrides(state, namedViews, true);
+ }
+
+ if (mSharedElementTargetNames != null && !namedViews.isEmpty()) {
+ // now we know the epicenter of the entering transition.
+ View epicenter = namedViews.get(mSharedElementTargetNames.get(0));
+ if (epicenter != null) {
+ state.enteringEpicenterView = epicenter;
+ }
+ }
+
+ int containerId = inFragments.keyAt(i);
+ SharedElementCallback sharedElementCallback = isBack ?
+ outFragments.get(containerId).mEnterTransitionCallback :
+ inFragment.mEnterTransitionCallback;
+ tempNames.clear();
+ tempNames.addAll(namedViews.keySet());
+ tempViews.clear();
+ tempViews.addAll(namedViews.values());
+ sharedElementCallback.onSharedElementEnd(tempNames, tempViews, null);
}
+
+ // Don't include any newly-hidden fragments in the transition.
+ excludeHiddenFragments(state);
}
- private void includeVisibleFragments(Transition transition) {
+ private ArrayMap<String, View> mapEnteringSharedElements(Fragment inFragment,
+ ArrayMap<String, View> namedViews, ArrayMap<String, View> tempViews2, boolean isBack) {
+ View root = inFragment.getView();
+ if (root != null) {
+ if (mSharedElementSourceNames != null) {
+ root.findNamedViews(namedViews);
+ if (isBack) {
+ namedViews = remapNames(mSharedElementSourceNames,
+ mSharedElementTargetNames, namedViews, tempViews2);
+ } else {
+ namedViews.retainAll(mSharedElementTargetNames);
+ }
+ }
+ }
+ return namedViews;
+ }
+
+ private static void cleanupHiddenFragments(Transition transition, TransitionState state) {
+ final ArrayList<View> hiddenViews = state.hiddenFragmentViews;
+ transition.addListener(new Transition.TransitionListenerAdapter() {
+ @Override
+ public void onTransitionStart(Transition transition) {
+ transition.removeListener(this);
+ int numViews = hiddenViews.size();
+ for (int i = 0; i < numViews; i++) {
+ transition.excludeTarget(hiddenViews.get(i), false);
+ }
+ }
+ });
+ }
+
+ private void excludeHiddenFragments(TransitionState state, int containerId,
+ Transition transition) {
if (mManager.mAdded != null) {
for (int i = 0; i < mManager.mAdded.size(); i++) {
Fragment fragment = mManager.mAdded.get(i);
- if (fragment.mView != null && !fragment.mHidden) {
- transition.excludeTarget(fragment.mView, false);
+ if (fragment.mView != null && fragment.mContainer != null &&
+ fragment.mContainerId == containerId) {
+ if (fragment.mHidden) {
+ if (!state.hiddenFragmentViews.contains(fragment.mView)) {
+ transition.excludeTarget(fragment.mView, true);
+ state.hiddenFragmentViews.add(fragment.mView);
+ }
+ } else {
+ transition.excludeTarget(fragment.mView, false);
+ state.hiddenFragmentViews.remove(fragment.mView);
+ }
}
}
}
}
+ private void excludeHiddenFragments(TransitionState state) {
+ int numTransitions = state.overallTransitions.size();
+ for (int i = 0; i < numTransitions; i++) {
+ Transition transition = state.overallTransitions.valueAt(i);
+ int containerId = state.overallTransitions.keyAt(i);
+ excludeHiddenFragments(state, containerId, transition);
+ }
+ }
+
+ private static void addTransitioningViews(Transition transition, final Collection<View> views) {
+ for (View view : views) {
+ transition.addTarget(view);
+ }
+
+ transition.addListener(new Transition.TransitionListenerAdapter() {
+ @Override
+ public void onTransitionStart(Transition transition) {
+ transition.removeListener(this);
+ for (View view : views) {
+ transition.removeTarget(view);
+ }
+ }
+ });
+ }
+
private static void setEpicenter(Transition transition, View view) {
final Rect epicenter = new Rect();
view.getBoundsOnScreen(epicenter);
@@ -1010,16 +1464,17 @@ final class BackStackRecord extends FragmentTransaction implements
@Override
public Rect onGetEpicenter(Transition transition) {
- if (mEpicenter == null && state.mEnteringEpicenterView != null) {
+ if (mEpicenter == null && state.enteringEpicenterView != null) {
mEpicenter = new Rect();
- state.mEnteringEpicenterView.getBoundsOnScreen(mEpicenter);
+ state.enteringEpicenterView.getBoundsOnScreen(mEpicenter);
}
return mEpicenter;
}
});
}
- public TransitionState popFromBackStack(boolean doStateMove, TransitionState state) {
+ public TransitionState popFromBackStack(boolean doStateMove, TransitionState state,
+ SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) {
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "popFromBackStack: " + this);
LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
@@ -1029,8 +1484,10 @@ final class BackStackRecord extends FragmentTransaction implements
}
if (state == null) {
- state = beginTransition(mSharedElementTargetNames, mSharedElementSourceNames);
- } else {
+ if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
+ state = beginTransition(firstOutFragments, lastInFragments, true);
+ }
+ } else if (!doStateMove) {
setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames);
}
@@ -1110,7 +1567,7 @@ final class BackStackRecord extends FragmentTransaction implements
mManager.moveToState(mManager.mCurState,
FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true);
if (state != null) {
- updateTransitionEndState(state, mSharedElementSourceNames);
+ updateTransitionEndState(state, firstOutFragments, lastInFragments, true);
state = null;
}
}
@@ -1122,15 +1579,17 @@ final class BackStackRecord extends FragmentTransaction implements
return state;
}
- private static void setNameOverride(Transition transition, String source, String target) {
- ArrayMap<String, String> overrides = transition.getNameOverrides();
- for (int index = 0; index < overrides.size(); index++) {
- if (source.equals(overrides.valueAt(index))) {
- overrides.setValueAt(index, target);
- return;
+ private static void setNameOverride(ArrayMap<String, String> overrides,
+ String source, String target) {
+ if (source != null && target != null && !source.equals(target)) {
+ for (int index = 0; index < overrides.size(); index++) {
+ if (source.equals(overrides.valueAt(index))) {
+ overrides.setValueAt(index, target);
+ return;
+ }
}
+ overrides.put(source, target);
}
- overrides.put(source, target);
}
private static void setNameOverrides(TransitionState state, ArrayList<String> sourceNames,
@@ -1139,7 +1598,36 @@ final class BackStackRecord extends FragmentTransaction implements
for (int i = 0; i < sourceNames.size(); i++) {
String source = sourceNames.get(i);
String target = targetNames.get(i);
- setNameOverride(state.excludingTransition, source, target);
+ setNameOverride(state.nameOverrides, source, target);
+ }
+ }
+ }
+
+ private void setBackNameOverrides(TransitionState state, ArrayMap<String, View> namedViews,
+ boolean isEnd) {
+ int count = mSharedElementTargetNames.size();
+ for (int i = 0; i < count; i++) {
+ String source = mSharedElementSourceNames.get(i);
+ String originalTarget = mSharedElementTargetNames.get(i);
+ String target = namedViews.get(originalTarget).getTransitionName();
+ if (isEnd) {
+ setNameOverride(state.nameOverrides, source, target);
+ } else {
+ setNameOverride(state.nameOverrides, target, source);
+ }
+ }
+ }
+
+ private void setNameOverrides(TransitionState state, ArrayMap<String, View> namedViews,
+ boolean isEnd) {
+ int count = namedViews.size();
+ for (int i = 0; i < count; i++) {
+ String source = namedViews.keyAt(i);
+ String target = namedViews.valueAt(i).getTransitionName();
+ if (isEnd) {
+ setNameOverride(state.nameOverrides, source, target);
+ } else {
+ setNameOverride(state.nameOverrides, target, source);
}
}
}
@@ -1161,14 +1649,11 @@ final class BackStackRecord extends FragmentTransaction implements
}
public class TransitionState {
- public ArrayList<View> hiddenViews = new ArrayList<View>();
- public ArrayList<View> transitioningViews = new ArrayList<View>();
- public ArrayMap<String, View> namedViews = new ArrayMap<String, View>();
- public Transition exitTransition;
- public Transition sharedElementTransition;
- public Transition enterTransition;
- public TransitionSet excludingTransition;
- public ViewGroup sceneRoot;
- public View mEnteringEpicenterView;
+ public SparseArray<Transition> overallTransitions = new SparseArray<Transition>();
+ public ArrayMap<String, String> nameOverrides = new ArrayMap<String, String>();
+ public ArrayList<View> hiddenFragmentViews = new ArrayList<View>();
+
+ public View enteringEpicenterView;
+ public View nonExistentView;
}
}
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 47d3fd6..f432c49 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -21,8 +21,6 @@ import android.animation.ObjectAnimator;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
import android.os.ResultReceiver;
import android.text.TextUtils;
import android.transition.Transition;
@@ -71,12 +69,13 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
Bundle resultReceiverBundle = new Bundle();
resultReceiverBundle.putParcelable(KEY_REMOTE_RECEIVER, this);
mResultReceiver.send(MSG_SET_REMOTE_RECEIVER, resultReceiverBundle);
- getDecor().getViewTreeObserver().addOnPreDrawListener(
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (mIsReadyForTransition) {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
}
return mIsReadyForTransition;
}
@@ -170,7 +169,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
private void sendSharedElementDestination() {
boolean allReady;
- if (allowOverlappingTransitions()) {
+ if (allowOverlappingTransitions() && getEnterViewsTransition() != null) {
allReady = false;
} else {
allReady = !getDecor().isLayoutRequested();
@@ -189,11 +188,12 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
moveSharedElementsToOverlay();
mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state);
} else {
- getDecor().getViewTreeObserver()
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
if (mResultReceiver != null) {
Bundle state = captureSharedElementState();
setSharedElementMatrices();
@@ -209,7 +209,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
}
}
- private static SharedElementListener getListener(Activity activity, boolean isReturning) {
+ private static SharedElementCallback getListener(Activity activity, boolean isReturning) {
return isReturning ? activity.mExitTransitionListener : activity.mEnterTransitionListener;
}
@@ -294,7 +294,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
ArrayList<String> rejectedNames = new ArrayList<String>(mAllSharedElementNames);
rejectedNames.removeAll(mSharedElementNames);
ArrayList<View> rejectedSnapshots = createSnapshots(sharedElementState, rejectedNames);
- mListener.handleRejectedSharedElements(rejectedSnapshots);
+ mListener.onRejectSharedElements(rejectedSnapshots);
startRejectedAnimations(rejectedSnapshots);
// Now start shared element transition
@@ -344,11 +344,12 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
}
final Bundle sharedElementState = mSharedElementsBundle;
mSharedElementsBundle = null;
- getDecor().getViewTreeObserver()
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
startTransition(new Runnable() {
@Override
public void run() {
@@ -358,7 +359,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
return false;
}
});
- getDecor().invalidate();
+ decorView.invalidate();
}
private void requestLayoutForSharedElements() {
@@ -466,6 +467,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
Drawable background = getDecor().getBackground();
if (background != null) {
background = background.mutate();
+ getWindow().setBackgroundDrawable(background);
mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 255);
mBackgroundAnimator.setDuration(getFadeDuration());
mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 3760b96..a59a927 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -79,7 +79,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
mActivity = activity;
}
- private static SharedElementListener getListener(Activity activity, boolean isReturning) {
+ private static SharedElementCallback getListener(Activity activity, boolean isReturning) {
return isReturning ? activity.mEnterTransitionListener : activity.mExitTransitionListener;
}
@@ -140,7 +140,8 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
if (getDecor() != null) {
getDecor().suppressLayout(true);
}
- if (!mSharedElements.isEmpty() && getSharedElementTransition() != null) {
+ if (mExitSharedElementBundle != null && !mExitSharedElementBundle.isEmpty() &&
+ !mSharedElements.isEmpty() && getSharedElementTransition() != null) {
startTransition(new Runnable() {
public void run() {
startSharedElementExit();
@@ -164,18 +165,19 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
});
final ArrayList<View> sharedElementSnapshots = createSnapshots(mExitSharedElementBundle,
mSharedElementNames);
- getDecor().getViewTreeObserver()
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
setSharedElementState(mExitSharedElementBundle, sharedElementSnapshots);
return true;
}
});
setGhostVisibility(View.INVISIBLE);
scheduleGhostVisibilityChange(View.INVISIBLE);
- mListener.setSharedElementEnd(mSharedElementNames, mSharedElements, sharedElementSnapshots);
+ mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, sharedElementSnapshots);
TransitionManager.beginDelayedTransition(getDecor(), transition);
scheduleGhostVisibilityChange(View.VISIBLE);
setGhostVisibility(View.VISIBLE);
@@ -259,6 +261,8 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
ViewGroup decor = getDecor();
Drawable background;
if (decor != null && (background = decor.getBackground()) != null) {
+ background = background.mutate();
+ getWindow().setBackgroundDrawable(background);
mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 0);
mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
@Override
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 2ff3d57..672ef7b 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -23,10 +23,14 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.transition.Transition;
+import android.transition.TransitionInflater;
+import android.transition.TransitionSet;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.AttributeSet;
@@ -58,11 +62,11 @@ final class FragmentState implements Parcelable {
final boolean mRetainInstance;
final boolean mDetached;
final Bundle mArguments;
-
+
Bundle mSavedFragmentState;
-
+
Fragment mInstance;
-
+
public FragmentState(Fragment frag) {
mClassName = frag.getClass().getName();
mIndex = frag.mIndex;
@@ -74,7 +78,7 @@ final class FragmentState implements Parcelable {
mDetached = frag.mDetached;
mArguments = frag.mArguments;
}
-
+
public FragmentState(Parcel in) {
mClassName = in.readString();
mIndex = in.readInt();
@@ -87,18 +91,18 @@ final class FragmentState implements Parcelable {
mArguments = in.readBundle();
mSavedFragmentState = in.readBundle();
}
-
+
public Fragment instantiate(Activity activity, Fragment parent) {
if (mInstance != null) {
return mInstance;
}
-
+
if (mArguments != null) {
mArguments.setClassLoader(activity.getClassLoader());
}
-
+
mInstance = Fragment.instantiate(activity, mClassName, mArguments);
-
+
if (mSavedFragmentState != null) {
mSavedFragmentState.setClassLoader(activity.getClassLoader());
mInstance.mSavedFragmentState = mSavedFragmentState;
@@ -117,7 +121,7 @@ final class FragmentState implements Parcelable {
return mInstance;
}
-
+
public int describeContents() {
return 0;
}
@@ -134,13 +138,13 @@ final class FragmentState implements Parcelable {
dest.writeBundle(mArguments);
dest.writeBundle(mSavedFragmentState);
}
-
+
public static final Parcelable.Creator<FragmentState> CREATOR
= new Parcelable.Creator<FragmentState>() {
public FragmentState createFromParcel(Parcel in) {
return new FragmentState(in);
}
-
+
public FragmentState[] newArray(int size) {
return new FragmentState[size];
}
@@ -299,17 +303,17 @@ final class FragmentState implements Parcelable {
* how you can determine if a fragment placed in a container is no longer
* running in a layout with that container and avoid creating its view hierarchy
* in that case.)
- *
+ *
* <p>The attributes of the &lt;fragment&gt; tag are used to control the
* LayoutParams provided when attaching the fragment's view to the parent
* container. They can also be parsed by the fragment in {@link #onInflate}
* as parameters.
- *
+ *
* <p>The fragment being instantiated must have some kind of unique identifier
* so that it can be re-associated with a previous instance if the parent
* activity needs to be destroyed and recreated. This can be provided these
* ways:
- *
+ *
* <ul>
* <li>If nothing is explicitly supplied, the view ID of the container will
* be used.
@@ -318,7 +322,7 @@ final class FragmentState implements Parcelable {
* <li><code>android:id</code> can be used in &lt;fragment&gt; to provide
* a specific identifier for the fragment.
* </ul>
- *
+ *
* <a name="BackStack"></a>
* <h3>Back Stack</h3>
*
@@ -347,7 +351,7 @@ final class FragmentState implements Parcelable {
public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener {
private static final ArrayMap<String, Class<?>> sClassMap =
new ArrayMap<String, Class<?>>();
-
+
static final int INVALID_STATE = -1; // Invalid state used as a null value.
static final int INITIALIZING = 0; // Not yet created.
static final int CREATED = 1; // Created.
@@ -355,9 +359,11 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
static final int STOPPED = 3; // Fully created, not started.
static final int STARTED = 4; // Created and started, not resumed.
static final int RESUMED = 5; // Created started and resumed.
-
+
+ private static final Transition USE_DEFAULT_TRANSITION = new TransitionSet();
+
int mState = INITIALIZING;
-
+
// Non-null if the fragment's view hierarchy is currently animating away,
// meaning we need to wait a bit on completely destroying it. This is the
// animation that is running.
@@ -370,13 +376,13 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
// When instantiated from saved state, this is the saved state.
Bundle mSavedFragmentState;
SparseArray<Parcelable> mSavedViewState;
-
+
// Index into active fragment array.
int mIndex = -1;
-
+
// Internal unique name for this fragment;
String mWho;
-
+
// Construction arguments;
Bundle mArguments;
@@ -391,25 +397,25 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
// True if the fragment is in the list of added fragments.
boolean mAdded;
-
+
// If set this fragment is being removed from its activity.
boolean mRemoving;
// True if the fragment is in the resumed state.
boolean mResumed;
-
+
// Set to true if this fragment was instantiated from a layout file.
boolean mFromLayout;
-
+
// Set to true when the view has actually been inflated in its layout.
boolean mInLayout;
// True if this fragment has been restored from previously saved state.
boolean mRestored;
-
+
// Number of active back stack entries this fragment is in.
int mBackStackNesting;
-
+
// The fragment manager we are associated with. Set as soon as the
// fragment is used in a transaction; cleared after it has been removed
// from all transactions.
@@ -428,29 +434,29 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
// was dynamically added to the view hierarchy, or the ID supplied in
// layout.
int mFragmentId;
-
+
// When a fragment is being dynamically added to the view hierarchy, this
// is the identifier of the parent container it is being added to.
int mContainerId;
-
+
// The optional named tag for this fragment -- usually used to find
// fragments that are not part of the layout.
String mTag;
-
+
// Set to true when the app has requested that this fragment be hidden
// from the user.
boolean mHidden;
-
+
// Set to true when the app has requested that this fragment be detached.
boolean mDetached;
// If set this fragment would like its instance retained across
// configuration changes.
boolean mRetainInstance;
-
+
// If set this fragment is being retained across the current config change.
boolean mRetaining;
-
+
// If set this fragment has menu items to contribute.
boolean mHasMenu;
@@ -459,16 +465,16 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
// Used to verify that subclasses call through to super class.
boolean mCalled;
-
+
// If app has requested a specific animation, this is the one to use.
int mNextAnim;
-
+
// The parent container of the fragment after dynamically added to UI.
ViewGroup mContainer;
-
+
// The View generated for this fragment.
View mView;
-
+
// Whether this fragment should defer starting until after other fragments
// have been started and their loaders are finished.
boolean mDeferStart;
@@ -479,7 +485,19 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
LoaderManagerImpl mLoaderManager;
boolean mLoadersStarted;
boolean mCheckedForLoaderManager;
-
+
+ private Transition mEnterTransition = null;
+ private Transition mReturnTransition = USE_DEFAULT_TRANSITION;
+ private Transition mExitTransition = null;
+ private Transition mReenterTransition = USE_DEFAULT_TRANSITION;
+ private Transition mSharedElementEnterTransition = null;
+ private Transition mSharedElementReturnTransition = USE_DEFAULT_TRANSITION;
+ private Boolean mAllowReturnTransitionOverlap;
+ private Boolean mAllowEnterTransitionOverlap;
+
+ SharedElementCallback mEnterTransitionCallback = SharedElementCallback.NULL_CALLBACK;
+ SharedElementCallback mExitTransitionCallback = SharedElementCallback.NULL_CALLBACK;
+
/**
* State information that has been retrieved from a fragment instance
* through {@link FragmentManager#saveFragmentInstanceState(Fragment)
@@ -543,7 +561,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* will not be called when the fragment is re-instantiated; instead,
* arguments can be supplied by the caller with {@link #setArguments}
* and later retrieved by the Fragment with {@link #getArguments}.
- *
+ *
* <p>Applications should generally not implement a constructor. The
* first place application code an run where the fragment is ready to
* be used is in {@link #onAttach(Activity)}, the point where the fragment
@@ -609,7 +627,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
+ " empty constructor that is public", e);
}
}
-
+
final void restoreViewState(Bundle savedInstanceState) {
if (mSavedViewState != null) {
mView.restoreHierarchyState(mSavedViewState);
@@ -649,7 +667,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
@Override final public int hashCode() {
return super.hashCode();
}
-
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder(128);
@@ -669,7 +687,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
sb.append('}');
return sb.toString();
}
-
+
/**
* Return the identifier this fragment is known by. This is either
* the android:id value supplied in a layout or the container view ID
@@ -678,14 +696,14 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
final public int getId() {
return mFragmentId;
}
-
+
/**
* Get the tag name of the fragment, if specified.
*/
final public String getTag() {
return mTag;
}
-
+
/**
* Supply the construction arguments for this fragment. This can only
* be called before the fragment has been attached to its activity; that
@@ -760,7 +778,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
final public Activity getActivity() {
return mActivity;
}
-
+
/**
* Return <code>getActivity().getResources()</code>.
*/
@@ -770,7 +788,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
return mActivity.getResources();
}
-
+
/**
* Return a localized, styled CharSequence from the application's package's
* default string table.
@@ -870,7 +888,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
final public boolean isRemoving() {
return mRemoving;
}
-
+
/**
* Return true if the layout is included as part of an activity view
* hierarchy via the &lt;fragment&gt; tag. This will always be true when
@@ -889,7 +907,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
final public boolean isResumed() {
return mResumed;
}
-
+
/**
* Return true if the fragment is currently visible to the user. This means
* it: (1) has been added, (2) has its view attached to the window, and
@@ -899,7 +917,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
return isAdded() && !isHidden() && mView != null
&& mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE;
}
-
+
/**
* Return true if the fragment has been hidden. By default fragments
* are shown. You can find out about changes to this state with
@@ -910,7 +928,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
final public boolean isHidden() {
return mHidden;
}
-
+
/**
* Called when the hidden state (as returned by {@link #isHidden()} of
* the fragment has changed. Fragments start out not hidden; this will
@@ -920,7 +938,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
*/
public void onHiddenChanged(boolean hidden) {
}
-
+
/**
* Control whether a fragment instance is retained across Activity
* re-creation (such as from a configuration change). This can only
@@ -942,16 +960,16 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
mRetainInstance = retain;
}
-
+
final public boolean getRetainInstance() {
return mRetainInstance;
}
-
+
/**
* Report that this fragment would like to participate in populating
* the options menu by receiving a call to {@link #onCreateOptionsMenu}
* and related methods.
- *
+ *
* @param hasMenu If true, the fragment has menu items to contribute.
*/
public void setHasOptionsMenu(boolean hasMenu) {
@@ -1034,7 +1052,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
public void startActivity(Intent intent) {
startActivity(intent, null);
}
-
+
/**
* Call {@link Activity#startActivity(Intent, Bundle)} from the fragment's
* containing Activity.
@@ -1081,13 +1099,13 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
mActivity.startActivityFromFragment(this, intent, requestCode, options);
}
}
-
+
/**
* Receive the result from a previous call to
* {@link #startActivityForResult(Intent, int)}. This follows the
* related Activity API as described there in
* {@link Activity#onActivityResult(int, int, Intent)}.
- *
+ *
* @param requestCode The integer request code originally supplied to
* startActivityForResult(), allowing you to identify who this
* result came from.
@@ -1098,7 +1116,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
*/
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
-
+
/**
* @hide Hack so that DialogFragment can make its Dialog before creating
* its views, and the view construction can use the dialog's context for
@@ -1115,7 +1133,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
return mActivity.getLayoutInflater();
}
}
-
+
/**
* @deprecated Use {@link #onInflate(Activity, AttributeSet, Bundle)} instead.
*/
@@ -1131,7 +1149,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* tag in a layout file. Note this is <em>before</em> the fragment's
* {@link #onAttach(Activity)} has been called; all you should do here is
* parse the attributes and save them away.
- *
+ *
* <p>This is called every time the fragment is inflated, even if it is
* being inflated into a new instance with saved state. It typically makes
* sense to re-parse the parameters each time, to allow them to change with
@@ -1169,8 +1187,33 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
onInflate(attrs, savedInstanceState);
mCalled = true;
+
+ TypedArray a = activity.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.Fragment);
+ mEnterTransition = loadTransition(activity, a, mEnterTransition, null,
+ com.android.internal.R.styleable.Fragment_fragmentEnterTransition);
+ mReturnTransition = loadTransition(activity, a, mReturnTransition, USE_DEFAULT_TRANSITION,
+ com.android.internal.R.styleable.Fragment_fragmentReturnTransition);
+ mExitTransition = loadTransition(activity, a, mExitTransition, null,
+ com.android.internal.R.styleable.Fragment_fragmentExitTransition);
+ mReenterTransition = loadTransition(activity, a, mReenterTransition, USE_DEFAULT_TRANSITION,
+ com.android.internal.R.styleable.Fragment_fragmentReenterTransition);
+ mSharedElementEnterTransition = loadTransition(activity, a, mSharedElementEnterTransition,
+ null, com.android.internal.R.styleable.Fragment_fragmentSharedElementEnterTransition);
+ mSharedElementReturnTransition = loadTransition(activity, a, mSharedElementReturnTransition,
+ USE_DEFAULT_TRANSITION,
+ com.android.internal.R.styleable.Fragment_fragmentSharedElementReturnTransition);
+ if (mAllowEnterTransitionOverlap == null) {
+ mAllowEnterTransitionOverlap = a.getBoolean(
+ com.android.internal.R.styleable.Fragment_fragmentAllowEnterTransitionOverlap, true);
+ }
+ if (mAllowReturnTransitionOverlap == null) {
+ mAllowReturnTransitionOverlap = a.getBoolean(
+ com.android.internal.R.styleable.Fragment_fragmentAllowReturnTransitionOverlap, true);
+ }
+ a.recycle();
}
-
+
/**
* Called when a fragment is first attached to its activity.
* {@link #onCreate(Bundle)} will be called after this.
@@ -1178,25 +1221,25 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
public void onAttach(Activity activity) {
mCalled = true;
}
-
+
/**
* Called when a fragment loads an animation.
*/
public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
return null;
}
-
+
/**
* Called to do initial creation of a fragment. This is called after
* {@link #onAttach(Activity)} and before
* {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
- *
+ *
* <p>Note that this can be called while the fragment's activity is
* still in the process of being created. As such, you can not rely
* on things like the activity's content view hierarchy being initialized
* at this point. If you want to do work once the activity itself is
* created, see {@link #onActivityCreated(Bundle)}.
- *
+ *
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
@@ -1209,10 +1252,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* This is optional, and non-graphical fragments can return null (which
* is the default implementation). This will be called between
* {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}.
- *
+ *
* <p>If you return a View from here, you will later be called in
* {@link #onDestroyView} when the view is being released.
- *
+ *
* @param inflater The LayoutInflater object that can be used to inflate
* any views in the fragment,
* @param container If non-null, this is the parent view that the fragment's
@@ -1220,7 +1263,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* but this can be used to generate the LayoutParams of the view.
* @param savedInstanceState If non-null, this fragment is being re-constructed
* from a previous saved state as given here.
- *
+ *
* @return Return the View for the fragment's UI, or null.
*/
@Nullable
@@ -1241,18 +1284,18 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
*/
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
}
-
+
/**
* Get the root view for the fragment's layout (the one returned by {@link #onCreateView}),
* if provided.
- *
+ *
* @return The fragment's root view, or null if it has no layout.
*/
@Nullable
public View getView() {
return mView;
}
-
+
/**
* Called when the fragment's activity has been created and this
* fragment's view hierarchy instantiated. It can be used to do final
@@ -1292,7 +1335,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
*/
public void onStart() {
mCalled = true;
-
+
if (!mLoadersStarted) {
mLoadersStarted = true;
if (!mCheckedForLoaderManager) {
@@ -1304,7 +1347,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
}
}
-
+
/**
* Called when the fragment is visible to the user and actively running.
* This is generally
@@ -1314,7 +1357,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
public void onResume() {
mCalled = true;
}
-
+
/**
* Called to ask the fragment to save its current dynamic state, so it
* can later be reconstructed in a new instance of its process is
@@ -1336,11 +1379,11 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
*/
public void onSaveInstanceState(Bundle outState) {
}
-
+
public void onConfigurationChanged(Configuration newConfig) {
mCalled = true;
}
-
+
/**
* Called when the Fragment is no longer resumed. This is generally
* tied to {@link Activity#onPause() Activity.onPause} of the containing
@@ -1349,7 +1392,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
public void onPause() {
mCalled = true;
}
-
+
/**
* Called when the Fragment is no longer started. This is generally
* tied to {@link Activity#onStop() Activity.onStop} of the containing
@@ -1358,11 +1401,11 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
public void onStop() {
mCalled = true;
}
-
+
public void onLowMemory() {
mCalled = true;
}
-
+
public void onTrimMemory(int level) {
mCalled = true;
}
@@ -1379,7 +1422,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
public void onDestroyView() {
mCalled = true;
}
-
+
/**
* Called when the fragment is no longer in use. This is called
* after {@link #onStop()} and before {@link #onDetach()}.
@@ -1434,16 +1477,16 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
public void onDetach() {
mCalled = true;
}
-
+
/**
* Initialize the contents of the Activity's standard options menu. You
* should place your menu items in to <var>menu</var>. For this method
* to be called, you must have first called {@link #setHasOptionsMenu}. See
* {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu}
* for more information.
- *
+ *
* @param menu The options menu in which you place your items.
- *
+ *
* @see #setHasOptionsMenu
* @see #onPrepareOptionsMenu
* @see #onOptionsItemSelected
@@ -1458,10 +1501,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* dynamically modify the contents. See
* {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu}
* for more information.
- *
+ *
* @param menu The options menu as last shown or first initialized by
* onCreateOptionsMenu().
- *
+ *
* @see #setHasOptionsMenu
* @see #onCreateOptionsMenu
*/
@@ -1477,7 +1520,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
*/
public void onDestroyOptionsMenu() {
}
-
+
/**
* This hook is called whenever an item in your options menu is selected.
* The default implementation simply returns false to have the normal
@@ -1485,15 +1528,15 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* its Handler as appropriate). You can use this method for any items
* for which you would like to do processing without those other
* facilities.
- *
+ *
* <p>Derived classes should call through to the base class for it to
* perform the default menu handling.
- *
+ *
* @param item The menu item that was selected.
- *
+ *
* @return boolean Return false to allow normal menu processing to
* proceed, true to consume it here.
- *
+ *
* @see #onCreateOptionsMenu
*/
public boolean onOptionsItemSelected(MenuItem item) {
@@ -1503,13 +1546,13 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
/**
* This hook is called whenever the options menu is being closed (either by the user canceling
* the menu with the back/menu button, or when an item is selected).
- *
+ *
* @param menu The options menu as last shown or first initialized by
* onCreateOptionsMenu().
*/
public void onOptionsMenuClosed(Menu menu) {
}
-
+
/**
* Called when a context menu for the {@code view} is about to be shown.
* Unlike {@link #onCreateOptionsMenu}, this will be called every
@@ -1537,25 +1580,25 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* {@link OnCreateContextMenuListener} on the view to this fragment, so
* {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be
* called when it is time to show the context menu.
- *
+ *
* @see #unregisterForContextMenu(View)
* @param view The view that should show a context menu.
*/
public void registerForContextMenu(View view) {
view.setOnCreateContextMenuListener(this);
}
-
+
/**
* Prevents a context menu to be shown for the given view. This method will
* remove the {@link OnCreateContextMenuListener} on the view.
- *
+ *
* @see #registerForContextMenu(View)
* @param view The view that should stop showing a context menu.
*/
public void unregisterForContextMenu(View view) {
view.setOnCreateContextMenuListener(null);
}
-
+
/**
* This hook is called whenever an item in a context menu is selected. The
* default implementation simply returns false to have the normal processing
@@ -1568,7 +1611,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* <p>
* Derived classes should call through to the base class for it to perform
* the default menu handling.
- *
+ *
* @param item The context menu item that was selected.
* @return boolean Return false to allow normal context menu processing to
* proceed, true to consume it here.
@@ -1576,7 +1619,284 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
public boolean onContextItemSelected(MenuItem item) {
return false;
}
-
+
+ /**
+ * When custom transitions are used with Fragments, the enter transition callback
+ * is called when this Fragment is attached or detached when not popping the back stack.
+ *
+ * @param callback Used to manipulate the shared element transitions on this Fragment
+ * when added not as a pop from the back stack.
+ */
+ public void setEnterSharedElementTransitionCallback(SharedElementCallback callback) {
+ if (callback == null) {
+ callback = SharedElementCallback.NULL_CALLBACK;
+ }
+ mEnterTransitionCallback = callback;
+ }
+
+ /**
+ * When custom transitions are used with Fragments, the exit transition callback
+ * is called when this Fragment is attached or detached when popping the back stack.
+ *
+ * @param callback Used to manipulate the shared element transitions on this Fragment
+ * when added as a pop from the back stack.
+ */
+ public void setExitSharedElementTransitionCallback(SharedElementCallback callback) {
+ if (callback == null) {
+ callback = SharedElementCallback.NULL_CALLBACK;
+ }
+ mExitTransitionCallback = callback;
+ }
+
+ /**
+ * Sets the Transition that will be used to move Views into the initial scene. The entering
+ * Views will be those that are regular Views or ViewGroups that have
+ * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+ * {@link android.transition.Visibility} as entering is governed by changing visibility from
+ * {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null,
+ * entering Views will remain unaffected.
+ *
+ * @param transition The Transition to use to move Views into the initial Scene.
+ * @attr ref android.R.styleable#Fragment_fragmentEnterTransition
+ */
+ public void setEnterTransition(Transition transition) {
+ mEnterTransition = transition;
+ }
+
+ /**
+ * Returns the Transition that will be used to move Views into the initial scene. The entering
+ * Views will be those that are regular Views or ViewGroups that have
+ * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+ * {@link android.transition.Visibility} as entering is governed by changing visibility from
+ * {@link View#INVISIBLE} to {@link View#VISIBLE}.
+ *
+ * @return the Transition to use to move Views into the initial Scene.
+ * @attr ref android.R.styleable#Fragment_fragmentEnterTransition
+ */
+ public Transition getEnterTransition() {
+ return mEnterTransition;
+ }
+
+ /**
+ * Sets the Transition that will be used to move Views out of the scene when the Fragment is
+ * preparing to be removed, hidden, or detached because of popping the back stack. The exiting
+ * Views will be those that are regular Views or ViewGroups that have
+ * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+ * {@link android.transition.Visibility} as entering is governed by changing visibility from
+ * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null,
+ * entering Views will remain unaffected. If nothing is set, the default will be to
+ * use the same value as set in {@link #setEnterTransition(android.transition.Transition)}.
+ *
+ * @param transition The Transition to use to move Views out of the Scene when the Fragment
+ * is preparing to close.
+ * @attr ref android.R.styleable#Fragment_fragmentExitTransition
+ */
+ public void setReturnTransition(Transition transition) {
+ mReturnTransition = transition;
+ }
+
+ /**
+ * Returns the Transition that will be used to move Views out of the scene when the Fragment is
+ * preparing to be removed, hidden, or detached because of popping the back stack. The exiting
+ * Views will be those that are regular Views or ViewGroups that have
+ * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+ * {@link android.transition.Visibility} as entering is governed by changing visibility from
+ * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null,
+ * entering Views will remain unaffected.
+ *
+ * @return the Transition to use to move Views out of the Scene when the Fragment
+ * is preparing to close.
+ * @attr ref android.R.styleable#Fragment_fragmentExitTransition
+ */
+ public Transition getReturnTransition() {
+ return mReturnTransition == USE_DEFAULT_TRANSITION ? getEnterTransition()
+ : mReturnTransition;
+ }
+
+ /**
+ * Sets the Transition that will be used to move Views out of the scene when the
+ * fragment is removed, hidden, or detached when not popping the back stack.
+ * The exiting Views will be those that are regular Views or ViewGroups that
+ * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+ * {@link android.transition.Visibility} as exiting is governed by changing visibility
+ * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
+ * remain unaffected.
+ *
+ * @param transition The Transition to use to move Views out of the Scene when the Fragment
+ * is being closed not due to popping the back stack.
+ * @attr ref android.R.styleable#Fragment_fragmentExitTransition
+ */
+ public void setExitTransition(Transition transition) {
+ mExitTransition = transition;
+ }
+
+ /**
+ * Returns the Transition that will be used to move Views out of the scene when the
+ * fragment is removed, hidden, or detached when not popping the back stack.
+ * The exiting Views will be those that are regular Views or ViewGroups that
+ * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+ * {@link android.transition.Visibility} as exiting is governed by changing visibility
+ * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
+ * remain unaffected.
+ *
+ * @return the Transition to use to move Views out of the Scene when the Fragment
+ * is being closed not due to popping the back stack.
+ * @attr ref android.R.styleable#Fragment_fragmentExitTransition
+ */
+ public Transition getExitTransition() {
+ return mExitTransition;
+ }
+
+ /**
+ * Sets the Transition that will be used to move Views in to the scene when returning due
+ * to popping a back stack. The entering Views will be those that are regular Views
+ * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions
+ * will extend {@link android.transition.Visibility} as exiting is governed by changing
+ * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null,
+ * the views will remain unaffected. If nothing is set, the default will be to use the same
+ * transition as {@link #setExitTransition(android.transition.Transition)}.
+ *
+ * @param transition The Transition to use to move Views into the scene when reentering from a
+ * previously-started Activity.
+ * @attr ref android.R.styleable#Fragment_fragmentReenterTransition
+ */
+ public void setReenterTransition(Transition transition) {
+ mReenterTransition = transition;
+ }
+
+ /**
+ * Returns the Transition that will be used to move Views in to the scene when returning due
+ * to popping a back stack. The entering Views will be those that are regular Views
+ * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions
+ * will extend {@link android.transition.Visibility} as exiting is governed by changing
+ * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null,
+ * the views will remain unaffected. If nothing is set, the default will be to use the same
+ * transition as {@link #setExitTransition(android.transition.Transition)}.
+ *
+ * @return the Transition to use to move Views into the scene when reentering from a
+ * previously-started Activity.
+ * @attr ref android.R.styleable#Fragment_fragmentReenterTransition
+ */
+ public Transition getReenterTransition() {
+ return mReenterTransition == USE_DEFAULT_TRANSITION ? getExitTransition()
+ : mReenterTransition;
+ }
+
+ /**
+ * Sets the Transition that will be used for shared elements transferred into the content
+ * Scene. Typical Transitions will affect size and location, such as
+ * {@link android.transition.ChangeBounds}. A null
+ * value will cause transferred shared elements to blink to the final position.
+ *
+ * @param transition The Transition to use for shared elements transferred into the content
+ * Scene.
+ * @attr ref android.R.styleable#Fragment_fragmentSharedElementEnterTransition
+ */
+ public void setSharedElementEnterTransition(Transition transition) {
+ mSharedElementEnterTransition = transition;
+ }
+
+ /**
+ * Returns the Transition that will be used for shared elements transferred into the content
+ * Scene. Typical Transitions will affect size and location, such as
+ * {@link android.transition.ChangeBounds}. A null
+ * value will cause transferred shared elements to blink to the final position.
+ *
+ * @return The Transition to use for shared elements transferred into the content
+ * Scene.
+ * @attr ref android.R.styleable#Fragment_fragmentSharedElementEnterTransition
+ */
+ public Transition getSharedElementEnterTransition() {
+ return mSharedElementEnterTransition;
+ }
+
+ /**
+ * Sets the Transition that will be used for shared elements transferred back during a
+ * pop of the back stack. This Transition acts in the leaving Fragment.
+ * Typical Transitions will affect size and location, such as
+ * {@link android.transition.ChangeBounds}. A null
+ * value will cause transferred shared elements to blink to the final position.
+ * If no value is set, the default will be to use the same value as
+ * {@link #setSharedElementEnterTransition(android.transition.Transition)}.
+ *
+ * @param transition The Transition to use for shared elements transferred out of the content
+ * Scene.
+ * @attr ref android.R.styleable#Fragment_fragmentSharedElementReturnTransition
+ */
+ public void setSharedElementReturnTransition(Transition transition) {
+ mSharedElementReturnTransition = transition;
+ }
+
+ /**
+ * Return the Transition that will be used for shared elements transferred back during a
+ * pop of the back stack. This Transition acts in the leaving Fragment.
+ * Typical Transitions will affect size and location, such as
+ * {@link android.transition.ChangeBounds}. A null
+ * value will cause transferred shared elements to blink to the final position.
+ * If no value is set, the default will be to use the same value as
+ * {@link #setSharedElementEnterTransition(android.transition.Transition)}.
+ *
+ * @return The Transition to use for shared elements transferred out of the content
+ * Scene.
+ * @attr ref android.R.styleable#Fragment_fragmentSharedElementReturnTransition
+ */
+ public Transition getSharedElementReturnTransition() {
+ return mSharedElementReturnTransition == USE_DEFAULT_TRANSITION ?
+ getSharedElementEnterTransition() : mSharedElementReturnTransition;
+ }
+
+ /**
+ * Sets whether the the exit transition and enter transition overlap or not.
+ * When true, the enter transition will start as soon as possible. When false, the
+ * enter transition will wait until the exit transition completes before starting.
+ *
+ * @param allow true to start the enter transition when possible or false to
+ * wait until the exiting transition completes.
+ * @attr ref android.R.styleable#Fragment_fragmentAllowEnterTransitionOverlap
+ */
+ public void setAllowEnterTransitionOverlap(boolean allow) {
+ mAllowEnterTransitionOverlap = allow;
+ }
+
+ /**
+ * Returns whether the the exit transition and enter transition overlap or not.
+ * When true, the enter transition will start as soon as possible. When false, the
+ * enter transition will wait until the exit transition completes before starting.
+ *
+ * @return true when the enter transition should start as soon as possible or false to
+ * when it should wait until the exiting transition completes.
+ * @attr ref android.R.styleable#Fragment_fragmentAllowEnterTransitionOverlap
+ */
+ public boolean getAllowEnterTransitionOverlap() {
+ return (mAllowEnterTransitionOverlap == null) ? true : mAllowEnterTransitionOverlap;
+ }
+
+ /**
+ * Sets whether the the return transition and reenter transition overlap or not.
+ * When true, the reenter transition will start as soon as possible. When false, the
+ * reenter transition will wait until the return transition completes before starting.
+ *
+ * @param allow true to start the reenter transition when possible or false to wait until the
+ * return transition completes.
+ * @attr ref android.R.styleable#Fragment_fragmentAllowReturnTransitionOverlap
+ */
+ public void setAllowReturnTransitionOverlap(boolean allow) {
+ mAllowReturnTransitionOverlap = allow;
+ }
+
+ /**
+ * Returns whether the the return transition and reenter transition overlap or not.
+ * When true, the reenter transition will start as soon as possible. When false, the
+ * reenter transition will wait until the return transition completes before starting.
+ *
+ * @return true to start the reenter transition when possible or false to wait until the
+ * return transition completes.
+ * @attr ref android.R.styleable#Fragment_fragmentAllowReturnTransitionOverlap
+ */
+ public boolean getAllowReturnTransitionOverlap() {
+ return (mAllowReturnTransitionOverlap == null) ? true : mAllowReturnTransitionOverlap;
+ }
+
/**
* Print the Fragments's state into the given stream.
*
@@ -1588,53 +1908,53 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
*/
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
writer.print(prefix); writer.print("mFragmentId=#");
- writer.print(Integer.toHexString(mFragmentId));
- writer.print(" mContainerId=#");
- writer.print(Integer.toHexString(mContainerId));
- writer.print(" mTag="); writer.println(mTag);
+ writer.print(Integer.toHexString(mFragmentId));
+ writer.print(" mContainerId=#");
+ writer.print(Integer.toHexString(mContainerId));
+ writer.print(" mTag="); writer.println(mTag);
writer.print(prefix); writer.print("mState="); writer.print(mState);
- writer.print(" mIndex="); writer.print(mIndex);
- writer.print(" mWho="); writer.print(mWho);
- writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
+ writer.print(" mIndex="); writer.print(mIndex);
+ writer.print(" mWho="); writer.print(mWho);
+ writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
writer.print(prefix); writer.print("mAdded="); writer.print(mAdded);
- writer.print(" mRemoving="); writer.print(mRemoving);
- writer.print(" mResumed="); writer.print(mResumed);
- writer.print(" mFromLayout="); writer.print(mFromLayout);
- writer.print(" mInLayout="); writer.println(mInLayout);
+ writer.print(" mRemoving="); writer.print(mRemoving);
+ writer.print(" mResumed="); writer.print(mResumed);
+ writer.print(" mFromLayout="); writer.print(mFromLayout);
+ writer.print(" mInLayout="); writer.println(mInLayout);
writer.print(prefix); writer.print("mHidden="); writer.print(mHidden);
- writer.print(" mDetached="); writer.print(mDetached);
- writer.print(" mMenuVisible="); writer.print(mMenuVisible);
- writer.print(" mHasMenu="); writer.println(mHasMenu);
+ writer.print(" mDetached="); writer.print(mDetached);
+ writer.print(" mMenuVisible="); writer.print(mMenuVisible);
+ writer.print(" mHasMenu="); writer.println(mHasMenu);
writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance);
- writer.print(" mRetaining="); writer.print(mRetaining);
- writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint);
+ writer.print(" mRetaining="); writer.print(mRetaining);
+ writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint);
if (mFragmentManager != null) {
writer.print(prefix); writer.print("mFragmentManager=");
- writer.println(mFragmentManager);
+ writer.println(mFragmentManager);
}
if (mActivity != null) {
writer.print(prefix); writer.print("mActivity=");
- writer.println(mActivity);
+ writer.println(mActivity);
}
if (mParentFragment != null) {
writer.print(prefix); writer.print("mParentFragment=");
- writer.println(mParentFragment);
+ writer.println(mParentFragment);
}
if (mArguments != null) {
writer.print(prefix); writer.print("mArguments="); writer.println(mArguments);
}
if (mSavedFragmentState != null) {
writer.print(prefix); writer.print("mSavedFragmentState=");
- writer.println(mSavedFragmentState);
+ writer.println(mSavedFragmentState);
}
if (mSavedViewState != null) {
writer.print(prefix); writer.print("mSavedViewState=");
- writer.println(mSavedViewState);
+ writer.println(mSavedViewState);
}
if (mTarget != null) {
writer.print(prefix); writer.print("mTarget="); writer.print(mTarget);
- writer.print(" mTargetRequestCode=");
- writer.println(mTargetRequestCode);
+ writer.print(" mTargetRequestCode=");
+ writer.println(mTargetRequestCode);
}
if (mNextAnim != 0) {
writer.print(prefix); writer.print("mNextAnim="); writer.println(mNextAnim);
@@ -1648,7 +1968,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
if (mAnimatingAway != null) {
writer.print(prefix); writer.print("mAnimatingAway="); writer.println(mAnimatingAway);
writer.print(prefix); writer.print("mStateAfterAnimating=");
- writer.println(mStateAfterAnimating);
+ writer.println(mStateAfterAnimating);
}
if (mLoaderManager != null) {
writer.print(prefix); writer.println("Loader Manager:");
@@ -1886,7 +2206,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onStop()");
}
-
+
if (mLoadersStarted) {
mLoadersStarted = false;
if (!mCheckedForLoaderManager) {
@@ -1929,4 +2249,23 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
+ " did not call through to super.onDestroy()");
}
}
+
+ private static Transition loadTransition(Context context, TypedArray typedArray,
+ Transition currentValue, Transition defaultValue, int id) {
+ if (currentValue != defaultValue) {
+ return currentValue;
+ }
+ int transitionId = typedArray.getResourceId(id, 0);
+ Transition transition = defaultValue;
+ if (transitionId != 0 && transitionId != com.android.internal.R.transition.no_transition) {
+ TransitionInflater inflater = TransitionInflater.from(context);
+ transition = inflater.inflateTransition(transitionId);
+ if (transition instanceof TransitionSet &&
+ ((TransitionSet)transition).getTransitionCount() == 0) {
+ transition = null;
+ }
+ }
+ return transition;
+ }
+
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 1df1d42..ef69fdd 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1497,7 +1497,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
return false;
}
final BackStackRecord bss = mBackStack.remove(last);
- bss.popFromBackStack(true, null);
+ SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
+ SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
+ bss.calculateBackFragments(firstOutFragments, lastInFragments);
+ bss.popFromBackStack(true, null, firstOutFragments, lastInFragments);
reportBackStackChanged();
} else {
int index = -1;
@@ -1541,10 +1544,16 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
states.add(mBackStack.remove(i));
}
final int LAST = states.size()-1;
+ SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
+ SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
+ for (int i=0; i<=LAST; i++) {
+ states.get(i).calculateBackFragments(firstOutFragments, lastInFragments);
+ }
BackStackRecord.TransitionState state = null;
for (int i=0; i<=LAST; i++) {
if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
- state = states.get(i).popFromBackStack(i == LAST, state);
+ state = states.get(i).popFromBackStack(i == LAST, state,
+ firstOutFragments, lastInFragments);
}
reportBackStackChanged();
}
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 1077bac..25cd3cc 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -172,19 +172,16 @@ public abstract class FragmentTransaction {
public abstract FragmentTransaction setTransition(int transit);
/**
- * Set a {@link android.transition.Transition} resource id to use with this transaction.
- * <var>transitionId</var> will be played for fragments when going forward and when popping
- * the back stack.
- * @param sceneRootId The ID of the element acting as the scene root for the transition.
- * This should be a ViewGroup containing all Fragments in the transaction.
- * @param transitionId The resource ID for the Transition used during the Fragment transaction.
+ * TODO: remove from API
+ * @hide
*/
- public abstract FragmentTransaction setCustomTransition(int sceneRootId, int transitionId);
+ public FragmentTransaction setCustomTransition(int sceneRootId, int transitionId) {
+ return this;
+ }
/**
- * Used with {@link #setCustomTransition(int, int)} to map a View from a removed or hidden
- * Fragment to a View from a shown or added Fragment.
- * <var>sharedElement</var> must have a unique transitionName in the View hierarchy.
+ * Used with to map a View from a removed or hidden Fragment to a View from a shown
+ * or added Fragment.
* @param sharedElement A View in a disappearing Fragment to match with a View in an
* appearing Fragment.
* @param name The transitionName for a View in an appearing Fragment to match to the shared
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index dbd180f..7d4512b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -48,6 +48,9 @@ interface INotificationManager
void setPackagePriority(String pkg, int uid, int priority);
int getPackagePriority(String pkg, int uid);
+ void setPackageVisibilityOverride(String pkg, int uid, int visibility);
+ int getPackageVisibilityOverride(String pkg, int uid);
+
// TODO: Remove this when callers have been migrated to the equivalent
// INotificationListener method.
StatusBarNotification[] getActiveNotifications(String callingPkg);
@@ -68,6 +71,7 @@ interface INotificationManager
ComponentName getEffectsSuppressor();
boolean matchesCallFilter(in Bundle extras);
+ boolean matchesCallFilterAsUser(in Bundle extras, int userId);
ZenModeConfig getZenModeConfig();
boolean setZenModeConfig(in ZenModeConfig config);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 800734a..f8dfdd9 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -21,6 +21,7 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -129,6 +130,14 @@ public class Notification implements Parcelable
public static final int DEFAULT_LIGHTS = 4;
/**
+ * Maximum length of CharSequences accepted by Builder and friends.
+ *
+ * <p>
+ * Avoids spamming the system with overly large strings such as full e-mails.
+ */
+ private static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024;
+
+ /**
* A timestamp related to this notification, in milliseconds since the epoch.
*
* Default value: {@link System#currentTimeMillis() Now}.
@@ -816,13 +825,6 @@ public class Notification implements Parcelable
public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
/**
- * {@link #extras} key: the user that built the notification.
- *
- * @hide
- */
- public static final String EXTRA_ORIGINATING_USERID = "android.originatingUserId";
-
- /**
* Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be
* displayed in the heads up space.
*
@@ -1423,6 +1425,7 @@ public class Notification implements Parcelable
extras.remove(Notification.EXTRA_LARGE_ICON);
extras.remove(Notification.EXTRA_LARGE_ICON_BIG);
extras.remove(Notification.EXTRA_PICTURE);
+ extras.remove(Notification.EXTRA_BIG_TEXT);
// Prevent light notifications from being rebuilt.
extras.remove(Builder.EXTRA_NEEDS_REBUILD);
}
@@ -1434,6 +1437,10 @@ public class Notification implements Parcelable
* @hide
*/
public static CharSequence safeCharSequence(CharSequence cs) {
+ if (cs == null) return cs;
+ if (cs.length() > MAX_CHARSEQUENCE_LENGTH) {
+ cs = cs.subSequence(0, MAX_CHARSEQUENCE_LENGTH);
+ }
if (cs instanceof Parcelable) {
Log.e(TAG, "warning: " + cs.getClass().getCanonicalName()
+ " instance is a custom Parcelable and not allowed in Notification");
@@ -1800,10 +1807,12 @@ public class Notification implements Parcelable
= "android.rebuild.hudViewActionCount";
/**
- * The package name of the context used to create the notification via a Builder.
+ * The ApplicationInfo of the package that created the notification, used to create
+ * a context to rebuild the notification via a Builder.
+ * @hide
*/
- private static final String EXTRA_REBUILD_CONTEXT_PACKAGE =
- "android.rebuild.contextPackage";
+ private static final String EXTRA_REBUILD_CONTEXT_APPLICATION_INFO =
+ "android.rebuild.applicationInfo";
// Whether to enable stripping (at post time) & rebuilding (at listener receive time) of
// memory intensive resources.
@@ -1854,11 +1863,6 @@ public class Notification implements Parcelable
private int mColor = COLOR_DEFAULT;
/**
- * The user that built the notification originally.
- */
- private int mOriginatingUserId;
-
- /**
* Contains extras related to rebuilding during the build phase.
*/
private Bundle mRebuildBundle = new Bundle();
@@ -1916,7 +1920,7 @@ public class Notification implements Parcelable
mPeople = new ArrayList<String>();
mColorUtil = context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.L ?
- NotificationColorUtil.getInstance() : null;
+ NotificationColorUtil.getInstance(mContext) : null;
}
/**
@@ -2578,7 +2582,7 @@ public class Notification implements Parcelable
// Note: This assumes that the current user can read the profile badge of the
// originating user.
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- return userManager.getBadgeForUser(new UserHandle(mOriginatingUserId), 0);
+ return userManager.getBadgeForUser(new UserHandle(mContext.getUserId()), 0);
}
private Bitmap getProfileBadge() {
@@ -2657,8 +2661,7 @@ public class Notification implements Parcelable
* @param hasProgress whether the progress bar should be shown and set
*/
private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
- RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(),
- mOriginatingUserId, resId);
+ RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
resetStandardTemplate(contentView);
@@ -2889,7 +2892,7 @@ public class Notification implements Parcelable
}
private void processLegacyAction(Action action, RemoteViews button) {
- if (!isLegacy() || mColorUtil.isGrayscale(mContext, action.icon)) {
+ if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, action.icon)) {
button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0,
mContext.getResources().getColor(R.color.notification_action_color_filter),
PorterDuff.Mode.MULTIPLY);
@@ -2908,7 +2911,7 @@ public class Notification implements Parcelable
* Apply any necessary background to smallIcons being used in the largeIcon spot.
*/
private void processSmallIconAsLarge(int largeIconId, RemoteViews contentView) {
- if (!isLegacy() || mColorUtil.isGrayscale(mContext, largeIconId)) {
+ if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, largeIconId)) {
applyLargeIconBackground(contentView);
}
}
@@ -2919,7 +2922,7 @@ public class Notification implements Parcelable
*/
// TODO: also check bounds, transparency, that sort of thing.
private void processLargeLegacyIcon(Bitmap largeIcon, RemoteViews contentView) {
- if (isLegacy() && mColorUtil.isGrayscale(largeIcon)) {
+ if (isLegacy() && mColorUtil.isGrayscaleIcon(largeIcon)) {
applyLargeIconBackground(contentView);
} else {
removeLargeIconBackground(contentView);
@@ -2955,7 +2958,7 @@ public class Notification implements Parcelable
*/
private void processSmallRightIcon(int smallIconDrawableId,
RemoteViews contentView) {
- if (!isLegacy() || mColorUtil.isGrayscale(mContext, smallIconDrawableId)) {
+ if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, smallIconDrawableId)) {
contentView.setDrawableParameters(R.id.right_icon, false, -1,
0xFFFFFFFF,
PorterDuff.Mode.SRC_ATOP, -1);
@@ -3050,8 +3053,8 @@ public class Notification implements Parcelable
*/
public void populateExtras(Bundle extras) {
// Store original information used in the construction of this object
- extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId);
- extras.putString(EXTRA_REBUILD_CONTEXT_PACKAGE, mContext.getPackageName());
+ extras.putParcelable(EXTRA_REBUILD_CONTEXT_APPLICATION_INFO,
+ mContext.getApplicationInfo());
extras.putCharSequence(EXTRA_TITLE, mContentTitle);
extras.putCharSequence(EXTRA_TEXT, mContentText);
extras.putCharSequence(EXTRA_SUB_TEXT, mSubText);
@@ -3139,13 +3142,14 @@ public class Notification implements Parcelable
extras.remove(EXTRA_NEEDS_REBUILD);
// Re-create notification context so we can access app resources.
- String packageName = extras.getString(EXTRA_REBUILD_CONTEXT_PACKAGE);
+ ApplicationInfo applicationInfo = extras.getParcelable(
+ EXTRA_REBUILD_CONTEXT_APPLICATION_INFO);
Context builderContext;
try {
- builderContext = context.createPackageContext(packageName,
+ builderContext = context.createApplicationContext(applicationInfo,
Context.CONTEXT_RESTRICTED);
} catch (NameNotFoundException e) {
- Log.e(TAG, "Package name " + packageName + " not found");
+ Log.e(TAG, "ApplicationInfo " + applicationInfo + " not found");
builderContext = context; // try with our context
}
@@ -3280,7 +3284,6 @@ public class Notification implements Parcelable
// Extras.
Bundle extras = n.extras;
- mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID);
mContentTitle = extras.getCharSequence(EXTRA_TITLE);
mContentText = extras.getCharSequence(EXTRA_TEXT);
mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
@@ -3313,7 +3316,6 @@ public class Notification implements Parcelable
* object.
*/
public Notification build() {
- mOriginatingUserId = mContext.getUserId();
mHasThreeLines = hasThreeLines();
Notification n = buildUnstyled();
@@ -4813,8 +4815,8 @@ public class Notification implements Parcelable
super(parcel);
}
- public BuilderRemoteViews(String packageName, int userId, int layoutId) {
- super(packageName, userId, layoutId);
+ public BuilderRemoteViews(ApplicationInfo appInfo, int layoutId) {
+ super(appInfo, layoutId);
}
@Override
diff --git a/core/java/android/app/SharedElementListener.java b/core/java/android/app/SharedElementCallback.java
index f36d05f..82d8e5b 100644
--- a/core/java/android/app/SharedElementListener.java
+++ b/core/java/android/app/SharedElementCallback.java
@@ -22,7 +22,6 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
import android.os.Parcelable;
import android.view.View;
@@ -31,28 +30,23 @@ import java.util.Map;
/**
* Listener provided in
- * {@link Activity#setEnterSharedElementListener(SharedElementListener)} and
- * {@link Activity#setExitSharedElementListener(SharedElementListener)}
- * to monitor the Activity transitions. The events can be used to customize Activity
- * Transition behavior.
+ * {@link Activity#setEnterSharedElementCallback(SharedElementCallback)} and
+ * {@link Activity#setExitSharedElementCallback(SharedElementCallback)} as well as
+ * {@link Fragment#setEnterSharedElementTransitionCallback(SharedElementCallback)} and
+ * {@link Fragment#setExitSharedElementTransitionCallback(SharedElementCallback)}
+ * to monitor the Shared element transitions. The events can be used to customize Activity
+ * and Fragment Transition behavior.
*/
-public abstract class SharedElementListener {
+public abstract class SharedElementCallback {
private Matrix mTempMatrix;
- static final SharedElementListener NULL_LISTENER = new SharedElementListener() {
+ static final SharedElementCallback NULL_CALLBACK = new SharedElementCallback() {
};
/**
- * Called to allow the listener to customize the start state of the shared element when
- * transferring in shared element state.
- * <p>
- * The shared element will start at the size and position of the shared element
- * in the launching Activity or Fragment. It will also transfer ImageView scaleType
- * and imageMatrix if the shared elements in the calling and called Activities are
- * ImageViews. Some applications may want to make additional changes, such as
- * changing the clip bounds, scaling, or rotation if the shared element end state
- * does not map well to the start state.
- * </p>
+ * Called immediately after the start state is set for the shared element.
+ * The shared element will start at the size and position of the shared element
+ * in the launching Activity or Fragment.
*
* @param sharedElementNames The names of the shared elements that were accepted into
* the View hierarchy.
@@ -60,20 +54,21 @@ public abstract class SharedElementListener {
* @param sharedElementSnapshots The Views containing snap shots of the shared element
* from the launching Window. These elements will not
* be part of the scene, but will be positioned relative
- * to the Window decor View.
+ * to the Window decor View. This list is null for Fragment
+ * Transitions.
*/
- public void setSharedElementStart(List<String> sharedElementNames,
+ public void onSharedElementStart(List<String> sharedElementNames,
List<View> sharedElements, List<View> sharedElementSnapshots) {}
/**
- * Called to allow the listener to customize the end state of the shared element when
- * transferring in shared element state.
+ * Called after the end state is set for the shared element, but before the end state
+ * is captured by the shared element transition.
* <p>
* Any customization done in
- * {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)}
+ * {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)}
* may need to be modified to the final state of the shared element if it is not
* automatically corrected by layout. For example, rotation or scale will not
- * be affected by layout and if changed in {@link #setSharedElementStart(java.util.List,
+ * be affected by layout and if changed in {@link #onSharedElementStart(java.util.List,
* java.util.List, java.util.List)}, it will also have to be set here again to correct
* the end state.
* </p>
@@ -84,24 +79,27 @@ public abstract class SharedElementListener {
* @param sharedElementSnapshots The Views containing snap shots of the shared element
* from the launching Window. These elements will not
* be part of the scene, but will be positioned relative
- * to the Window decor View.
+ * to the Window decor View. This list will be null for
+ * Fragment Transitions.
*/
- public void setSharedElementEnd(List<String> sharedElementNames,
+ public void onSharedElementEnd(List<String> sharedElementNames,
List<View> sharedElements, List<View> sharedElementSnapshots) {}
/**
- * Called after {@link #remapSharedElements(java.util.List, java.util.Map)} when
+ * Called after {@link #onMapSharedElements(java.util.List, java.util.Map)} when
* transferring shared elements in. Any shared elements that have no mapping will be in
* <var>rejectedSharedElements</var>. The elements remaining in
* <var>rejectedSharedElements</var> will be transitioned out of the Scene. If a
* View is removed from <var>rejectedSharedElements</var>, it must be handled by the
- * <code>SharedElementListener</code>.
+ * <code>SharedElementCallback</code>.
* <p>
* Views in rejectedSharedElements will have their position and size set to the
* position of the calling shared element, relative to the Window decor View and contain
* snapshots of the View from the calling Activity or Fragment. This
* view may be safely added to the decor View's overlay to remain in position.
* </p>
+ * <p>This method is not called for Fragment Transitions. All rejected shared elements
+ * will be handled by the exit transition.</p>
*
* @param rejectedSharedElements Views containing visual information of shared elements
* that are not part of the entering scene. These Views
@@ -109,25 +107,27 @@ public abstract class SharedElementListener {
* View removed from this list will not be transitioned
* automatically.
*/
- public void handleRejectedSharedElements(List<View> rejectedSharedElements) {}
+ public void onRejectSharedElements(List<View> rejectedSharedElements) {}
/**
- * Lets the ActivityTransitionListener adjust the mapping of shared element names to
+ * Lets the SharedElementCallback adjust the mapping of shared element names to
* Views.
*
* @param names The names of all shared elements transferred from the calling Activity
- * to the started Activity.
+ * or Fragment in the order they were provided.
* @param sharedElements The mapping of shared element names to Views. The best guess
* will be filled into sharedElements based on the transitionNames.
*/
- public void remapSharedElements(List<String> names, Map<String, View> sharedElements) {}
+ public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {}
/**
* Creates a snapshot of a shared element to be used by the remote Activity and reconstituted
- * with {@link #createSnapshotView(android.content.Context, android.os.Parcelable)}. A
+ * with {@link #onCreateSnapshotView(android.content.Context, android.os.Parcelable)}. A
* null return value will mean that the remote Activity will have a null snapshot View in
- * {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)} and
- * {@link #setSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
+ * {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} and
+ * {@link #onSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
+ *
+ * <p>This is not called for Fragment Transitions.</p>
*
* @param sharedElement The shared element View to create a snapshot for.
* @param viewToGlobalMatrix A matrix containing a transform from the view to the screen
@@ -135,11 +135,11 @@ public abstract class SharedElementListener {
* @param screenBounds The bounds of shared element in screen coordinate space. This is
* the bounds of the view with the viewToGlobalMatrix applied.
* @return A snapshot to send to the remote Activity to be reconstituted with
- * {@link #createSnapshotView(android.content.Context, android.os.Parcelable)} and passed
- * into {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)} and
- * {@link #setSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
+ * {@link #onCreateSnapshotView(android.content.Context, android.os.Parcelable)} and passed
+ * into {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} and
+ * {@link #onSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
*/
- public Parcelable captureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,
+ public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,
RectF screenBounds) {
int bitmapWidth = Math.round(screenBounds.width());
int bitmapHeight = Math.round(screenBounds.height());
@@ -160,20 +160,22 @@ public abstract class SharedElementListener {
/**
* Reconstitutes a snapshot View from a Parcelable returned in
- * {@link #captureSharedElementSnapshot(android.view.View, android.graphics.Matrix,
- * android.graphics.RectF)} to be used in {@link #setSharedElementStart(java.util.List,
- * java.util.List, java.util.List)} and {@link #setSharedElementEnd(java.util.List,
+ * {@link #onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix,
+ * android.graphics.RectF)} to be used in {@link #onSharedElementStart(java.util.List,
+ * java.util.List, java.util.List)} and {@link #onSharedElementEnd(java.util.List,
* java.util.List, java.util.List)}. The returned View will be sized and positioned after
* this call so that it is ready to be added to the decor View's overlay.
*
+ * <p>This is not called for Fragment Transitions.</p>
+ *
* @param context The Context used to create the snapshot View.
- * @param snapshot The Parcelable returned by {@link #captureSharedElementSnapshot(
+ * @param snapshot The Parcelable returned by {@link #onCaptureSharedElementSnapshot(
* android.view.View, android.graphics.Matrix, android.graphics.RectF)}.
- * @return A View to be sent in {@link #setSharedElementStart(java.util.List, java.util.List,
- * java.util.List)} and {@link #setSharedElementEnd(java.util.List, java.util.List,
+ * @return A View to be sent in {@link #onSharedElementStart(java.util.List, java.util.List,
+ * java.util.List)} and {@link #onSharedElementEnd(java.util.List, java.util.List,
* java.util.List)}. A null value will produce a null snapshot value for those two methods.
*/
- public View createSnapshotView(Context context, Parcelable snapshot) {
+ public View onCreateSnapshotView(Context context, Parcelable snapshot) {
View view = null;
if (snapshot instanceof Bitmap) {
Bitmap bitmap = (Bitmap) snapshot;
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 15def09..e2f175c 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -177,7 +177,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_LOCK_TASK_ENTERING
- = "android.app.action.ACTION_LOCK_TASK_ENTERING";
+ = "android.app.action.LOCK_TASK_ENTERING";
/**
* Action sent to a device administrator to notify that the device is exiting
@@ -190,7 +190,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_LOCK_TASK_EXITING
- = "android.app.action.ACTION_LOCK_TASK_EXITING";
+ = "android.app.action.LOCK_TASK_EXITING";
/**
* A boolean describing whether the device is currently entering or exiting
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 69b1139..112fc82 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -115,6 +115,19 @@ public class DevicePolicyManager {
= "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
/**
+ * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
+ * a mobile device management application that starts managed profile provisioning to pass data
+ * to itself on the managed profile when provisioning completes. The mobile device management
+ * application sends this extra in an intent with the action
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE} and receives it in
+ * {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with the action
+ * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is not changed
+ * during the managed profile provisioning.
+ */
+ public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE =
+ "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
+
+ /**
* A String extra holding the package name of the mobile device management application that
* will be set as the profile owner or device owner.
*
@@ -135,21 +148,15 @@ public class DevicePolicyManager {
* <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
*/
public static final String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME
- = "android.app.extra.DEFAULT_MANAGED_PROFILE_NAME";
+ = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
/**
- * A String extra that, holds the email address of the account which a managed profile is
- * created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
- * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}.
- *
- * <p> If the {@link #ACTION_PROVISION_MANAGED_PROFILE} intent that starts managed provisioning
- * contains this extra, it is forwarded in the
- * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} intent to the mobile
- * device management application that was set as the profile owner during provisioning.
- * It is usually used to avoid that the user has to enter their email address twice.
+ * A bundle key, used in the bundle extra {@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}. The
+ * corresponding value holds the email address of the account which the managed profile is
+ * created for.
*/
- public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS
- = "android.app.extra.ManagedProfileEmailAddress";
+ public static final String KEY_PROVISIONING_EMAIL_ADDRESS
+ = "android.app.key.PROVISIONING_EMAIL_ADDRESS";
/**
* A String extra holding the time zone {@link android.app.AlarmManager} that the device
@@ -159,7 +166,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_TIME_ZONE
- = "android.app.extra.TIME_ZONE";
+ = "android.app.extra.PROVISIONING_TIME_ZONE";
/**
* A Long extra holding the wall clock time (in milliseconds) to be set on the device's
@@ -169,7 +176,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_LOCAL_TIME
- = "android.app.extra.LOCAL_TIME";
+ = "android.app.extra.PROVISIONING_LOCAL_TIME";
/**
* A String extra holding the {@link java.util.Locale} that the device will be set to.
@@ -179,7 +186,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_LOCALE
- = "android.app.extra.LOCALE";
+ = "android.app.extra.PROVISIONING_LOCALE";
/**
* A String extra holding the ssid of the wifi network that should be used during nfc device
@@ -189,7 +196,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_SSID
- = "android.app.extra.WIFI_SSID";
+ = "android.app.extra.PROVISIONING_WIFI_SSID";
/**
* A boolean extra indicating whether the wifi network in {@link #EXTRA_PROVISIONING_WIFI_SSID}
@@ -199,7 +206,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_HIDDEN
- = "android.app.extra.WIFI_HIDDEN";
+ = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
/**
* A String extra indicating the security type of the wifi network in
@@ -209,7 +216,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE
- = "android.app.extra.WIFI_SECURITY_TYPE";
+ = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
/**
* A String extra holding the password of the wifi network in
@@ -219,7 +226,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PASSWORD
- = "android.app.extra.WIFI_PASSWORD";
+ = "android.app.extra.PROVISIONING_WIFI_PASSWORD";
/**
* A String extra holding the proxy host for the wifi network in
@@ -229,7 +236,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_HOST
- = "android.app.extra.WIFI_PROXY_HOST";
+ = "android.app.extra.PROVISIONING_WIFI_PROXY_HOST";
/**
* An int extra holding the proxy port for the wifi network in
@@ -239,7 +246,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_PORT
- = "android.app.extra.WIFI_PROXY_PORT";
+ = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
/**
* A String extra holding the proxy bypass for the wifi network in
@@ -249,7 +256,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS
- = "android.app.extra.WIFI_PROXY_BYPASS_HOSTS";
+ = "android.app.extra.PROVISIONING_WIFI_PROXY_BYPASS";
/**
* A String extra holding the proxy auto-config (PAC) URL for the wifi network in
@@ -259,7 +266,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PAC_URL
- = "android.app.extra.WIFI_PAC_URL";
+ = "android.app.extra.PROVISIONING_WIFI_PAC_URL";
/**
* A String extra holding a url that specifies the download location of the device admin
@@ -269,7 +276,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION
- = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
+ = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
/**
* A String extra holding a http cookie header which should be used in the http request to the
@@ -279,7 +286,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER
- = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
+ = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
/**
* A String extra holding the SHA-1 checksum of the file at download location specified in
@@ -291,7 +298,7 @@ public class DevicePolicyManager {
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
- = "android.app.extra.DEVICE_ADMIN_PACKAGE_CHECKSUM";
+ = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
/**
* This MIME type is used for starting the Device Owner provisioning.
@@ -1773,16 +1780,24 @@ public class DevicePolicyManager {
* If a user has installed any certificates by other means than device policy these will be
* included too.
*
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @return a List of byte[] arrays, each encoding one user CA certificate.
*/
- public List<byte[]> getInstalledCaCerts() {
- final TrustedCertificateStore certStore = new TrustedCertificateStore();
+ public List<byte[]> getInstalledCaCerts(ComponentName admin) {
List<byte[]> certs = new ArrayList<byte[]>();
- for (String alias : certStore.userAliases()) {
+ if (mService != null) {
try {
- certs.add(certStore.getCertificate(alias).getEncoded());
- } catch (CertificateException ce) {
- Log.w(TAG, "Could not encode certificate: " + alias, ce);
+ mService.enforceCanManageCaCerts(admin);
+ final TrustedCertificateStore certStore = new TrustedCertificateStore();
+ for (String alias : certStore.userAliases()) {
+ try {
+ certs.add(certStore.getCertificate(alias).getEncoded());
+ } catch (CertificateException ce) {
+ Log.w(TAG, "Could not encode certificate: " + alias, ce);
+ }
+ }
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed talking with device policy service", re);
}
}
return certs;
@@ -1809,13 +1824,19 @@ public class DevicePolicyManager {
/**
* Returns whether this certificate is installed as a trusted CA.
*
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param certBuffer encoded form of the certificate to look up.
*/
- public boolean hasCaCertInstalled(byte[] certBuffer) {
- try {
- return getCaCertAlias(certBuffer) != null;
- } catch (CertificateException ce) {
- Log.w(TAG, "Could not parse certificate", ce);
+ public boolean hasCaCertInstalled(ComponentName admin, byte[] certBuffer) {
+ if (mService != null) {
+ try {
+ mService.enforceCanManageCaCerts(admin);
+ return getCaCertAlias(certBuffer) != null;
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed talking with device policy service", re);
+ } catch (CertificateException ce) {
+ Log.w(TAG, "Could not parse certificate", ce);
+ }
}
return false;
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c984cf9..57d8b95 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -124,6 +124,7 @@ interface IDevicePolicyManager {
boolean installCaCert(in ComponentName admin, in byte[] certBuffer);
void uninstallCaCert(in ComponentName admin, in String alias);
+ void enforceCanManageCaCerts(in ComponentName admin);
void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index ca7022d..89efeb2 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -21,14 +21,24 @@ import java.util.List;
import android.content.Context;
/**
- * Class for scheduling various types of jobs with the scheduling framework on the device.
+ * This is an API for scheduling various types of jobs against the framework that will be executed
+ * in your application's own process.
+ * <p>
* See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run
- * and how to construct them.
+ * and how to construct them. You will construct these JobInfo objects and pass them to the
+ * JobScheduler with {@link #schedule(JobInfo)}. When the criteria declared are met, the
+ * system will execute this job on your application's {@link android.app.job.JobService}.
+ * You identify which JobService is meant to execute the logic for your job when you create the
+ * JobInfo with
+ * {@link android.app.job.JobInfo.Builder#JobInfo.Builder(int,android.content.ComponentName)}.
+ * </p>
+ * <p>
* The framework will be intelligent about when you receive your callbacks, and attempt to batch
* and defer them as much as possible. Typically if you don't specify a deadline on your job, it
* can be run at any moment depending on the current state of the JobScheduler's internal queue,
* however it might be deferred as long as until the next time the device is connected to a power
* source.
+ * </p>
* <p>You do not
* instantiate this class directly; instead, retrieve it through
* {@link android.content.Context#getSystemService
diff --git a/core/java/android/app/usage/ConfigurationStats.java b/core/java/android/app/usage/ConfigurationStats.java
new file mode 100644
index 0000000..080216c
--- /dev/null
+++ b/core/java/android/app/usage/ConfigurationStats.java
@@ -0,0 +1,161 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package android.app.usage;
+
+import android.content.res.Configuration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents the usage statistics of a device {@link android.content.res.Configuration} for a
+ * specific time range.
+ */
+public final class ConfigurationStats implements Parcelable {
+
+ /**
+ * {@hide}
+ */
+ public Configuration mConfiguration;
+
+ /**
+ * {@hide}
+ */
+ public long mBeginTimeStamp;
+
+ /**
+ * {@hide}
+ */
+ public long mEndTimeStamp;
+
+ /**
+ * {@hide}
+ */
+ public long mLastTimeActive;
+
+ /**
+ * {@hide}
+ */
+ public long mTotalTimeActive;
+
+ /**
+ * {@hide}
+ */
+ public int mActivationCount;
+
+ /**
+ * {@hide}
+ */
+ public ConfigurationStats() {
+ }
+
+ public ConfigurationStats(ConfigurationStats stats) {
+ mConfiguration = stats.mConfiguration;
+ mBeginTimeStamp = stats.mBeginTimeStamp;
+ mEndTimeStamp = stats.mEndTimeStamp;
+ mLastTimeActive = stats.mLastTimeActive;
+ mTotalTimeActive = stats.mTotalTimeActive;
+ mActivationCount = stats.mActivationCount;
+ }
+
+ public Configuration getConfiguration() {
+ return mConfiguration;
+ }
+
+ /**
+ * Get the beginning of the time range this {@link ConfigurationStats} represents,
+ * measured in milliseconds since the epoch.
+ * <p/>
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getFirstTimeStamp() {
+ return mBeginTimeStamp;
+ }
+
+ /**
+ * Get the end of the time range this {@link ConfigurationStats} represents,
+ * measured in milliseconds since the epoch.
+ * <p/>
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getLastTimeStamp() {
+ return mEndTimeStamp;
+ }
+
+ /**
+ * Get the last time this configuration was active, measured in milliseconds since the epoch.
+ * <p/>
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getLastTimeActive() {
+ return mLastTimeActive;
+ }
+
+ /**
+ * Get the total time this configuration was active, measured in milliseconds.
+ */
+ public long getTotalTimeActive() {
+ return mTotalTimeActive;
+ }
+
+ /**
+ * Get the number of times this configuration was active.
+ */
+ public int getActivationCount() {
+ return mActivationCount;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mConfiguration != null) {
+ dest.writeInt(1);
+ mConfiguration.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
+
+ dest.writeLong(mBeginTimeStamp);
+ dest.writeLong(mEndTimeStamp);
+ dest.writeLong(mLastTimeActive);
+ dest.writeLong(mTotalTimeActive);
+ dest.writeInt(mActivationCount);
+ }
+
+ public static final Creator<ConfigurationStats> CREATOR = new Creator<ConfigurationStats>() {
+ @Override
+ public ConfigurationStats createFromParcel(Parcel source) {
+ ConfigurationStats stats = new ConfigurationStats();
+ if (source.readInt() != 0) {
+ stats.mConfiguration = Configuration.CREATOR.createFromParcel(source);
+ }
+ stats.mBeginTimeStamp = source.readLong();
+ stats.mEndTimeStamp = source.readLong();
+ stats.mLastTimeActive = source.readLong();
+ stats.mTotalTimeActive = source.readLong();
+ stats.mActivationCount = source.readInt();
+ return stats;
+ }
+
+ @Override
+ public ConfigurationStats[] newArray(int size) {
+ return new ConfigurationStats[size];
+ }
+ };
+}
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 3b09888..4ed1489 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -27,5 +27,7 @@ import android.content.pm.ParceledListSlice;
interface IUsageStatsManager {
ParceledListSlice queryUsageStats(int bucketType, long beginTime, long endTime,
String callingPackage);
+ ParceledListSlice queryConfigurationStats(int bucketType, long beginTime, long endTime,
+ String callingPackage);
UsageEvents queryEvents(long beginTime, long endTime, String callingPackage);
}
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index fb80de2..1a947ec 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -16,6 +16,7 @@
package android.app.usage;
import android.content.ComponentName;
+import android.content.res.Configuration;
import android.os.Parcel;
import android.os.Parcelable;
@@ -63,6 +64,11 @@ public final class UsageEvents implements Parcelable {
public static final int CONTINUE_PREVIOUS_DAY = 4;
/**
+ * An event type denoting that the device configuration has changed.
+ */
+ public static final int CONFIGURATION_CHANGE = 5;
+
+ /**
* {@hide}
*/
public String mPackage;
@@ -83,6 +89,12 @@ public final class UsageEvents implements Parcelable {
public int mEventType;
/**
+ * Only present for {@link #CONFIGURATION_CHANGE} event types.
+ * {@hide}
+ */
+ public Configuration mConfiguration;
+
+ /**
* TODO(adamlesinski): Removed before release.
* {@hide}
*/
@@ -123,6 +135,14 @@ public final class UsageEvents implements Parcelable {
public int getEventType() {
return mEventType;
}
+
+ /**
+ * Returns a {@link Configuration} for this event if the event is of type
+ * {@link #CONFIGURATION_CHANGE}, otherwise it returns null.
+ */
+ public Configuration getConfiguration() {
+ return mConfiguration;
+ }
}
// Only used when creating the resulting events. Not used for reading/unparceling.
@@ -201,23 +221,9 @@ public final class UsageEvents implements Parcelable {
return false;
}
- final int packageIndex = mParcel.readInt();
- if (packageIndex >= 0) {
- eventOut.mPackage = mStringPool[packageIndex];
- } else {
- eventOut.mPackage = null;
- }
+ readEventFromParcel(mParcel, eventOut);
- final int classIndex = mParcel.readInt();
- if (classIndex >= 0) {
- eventOut.mClass = mStringPool[classIndex];
- } else {
- eventOut.mClass = null;
- }
- eventOut.mEventType = mParcel.readInt();
- eventOut.mTimeStamp = mParcel.readLong();
mIndex++;
-
if (mIndex >= mEventCount) {
mParcel.recycle();
mParcel = null;
@@ -235,11 +241,6 @@ public final class UsageEvents implements Parcelable {
}
}
- @Override
- public int describeContents() {
- return 0;
- }
-
private int findStringIndex(String str) {
final int index = Arrays.binarySearch(mStringPool, str);
if (index < 0) {
@@ -248,6 +249,66 @@ public final class UsageEvents implements Parcelable {
return index;
}
+ /**
+ * Writes a single event to the parcel. Modify this when updating {@link Event}.
+ */
+ private void writeEventToParcel(Event event, Parcel p, int flags) {
+ final int packageIndex;
+ if (event.mPackage != null) {
+ packageIndex = findStringIndex(event.mPackage);
+ } else {
+ packageIndex = -1;
+ }
+
+ final int classIndex;
+ if (event.mClass != null) {
+ classIndex = findStringIndex(event.mClass);
+ } else {
+ classIndex = -1;
+ }
+ p.writeInt(packageIndex);
+ p.writeInt(classIndex);
+ p.writeInt(event.mEventType);
+ p.writeLong(event.mTimeStamp);
+
+ if (event.mEventType == Event.CONFIGURATION_CHANGE) {
+ event.mConfiguration.writeToParcel(p, flags);
+ }
+ }
+
+ /**
+ * Reads a single event from the parcel. Modify this when updating {@link Event}.
+ */
+ private void readEventFromParcel(Parcel p, Event eventOut) {
+ final int packageIndex = p.readInt();
+ if (packageIndex >= 0) {
+ eventOut.mPackage = mStringPool[packageIndex];
+ } else {
+ eventOut.mPackage = null;
+ }
+
+ final int classIndex = p.readInt();
+ if (classIndex >= 0) {
+ eventOut.mClass = mStringPool[classIndex];
+ } else {
+ eventOut.mClass = null;
+ }
+ eventOut.mEventType = p.readInt();
+ eventOut.mTimeStamp = p.readLong();
+
+ // Extract the configuration for configuration change events.
+ if (eventOut.mEventType == Event.CONFIGURATION_CHANGE) {
+ eventOut.mConfiguration = Configuration.CREATOR.createFromParcel(p);
+ } else {
+ eventOut.mConfiguration = null;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mEventCount);
@@ -262,25 +323,9 @@ public final class UsageEvents implements Parcelable {
p.setDataPosition(0);
for (int i = 0; i < mEventCount; i++) {
final Event event = mEventsToWrite.get(i);
-
- final int packageIndex;
- if (event.mPackage != null) {
- packageIndex = findStringIndex(event.mPackage);
- } else {
- packageIndex = -1;
- }
-
- final int classIndex;
- if (event.mClass != null) {
- classIndex = findStringIndex(event.mClass);
- } else {
- classIndex = -1;
- }
- p.writeInt(packageIndex);
- p.writeInt(classIndex);
- p.writeInt(event.getEventType());
- p.writeLong(event.getTimeStamp());
+ writeEventToParcel(event, p, flags);
}
+
final int listByteLength = p.dataPosition();
// Write the total length of the data.
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 5830fcf..bc6099a 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -125,9 +125,9 @@ public final class UsageStatsManager {
* @see #INTERVAL_YEARLY
* @see #INTERVAL_BEST
*/
- @SuppressWarnings("unchecked")
public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime) {
try {
+ @SuppressWarnings("unchecked")
ParceledListSlice<UsageStats> slice = mService.queryUsageStats(intervalType, beginTime,
endTime, mContext.getOpPackageName());
if (slice != null) {
@@ -136,7 +136,32 @@ public final class UsageStatsManager {
} catch (RemoteException e) {
// fallthrough and return null.
}
- return Collections.EMPTY_LIST;
+ return Collections.emptyList();
+ }
+
+ /**
+ * Gets the hardware configurations the device was in for the given time range, aggregated by
+ * the specified interval. The results are ordered as in
+ * {@link #queryUsageStats(int, long, long)}.
+ *
+ * @param intervalType The time interval by which the stats are aggregated.
+ * @param beginTime The inclusive beginning of the range of stats to include in the results.
+ * @param endTime The exclusive end of the range of stats to include in the results.
+ * @return A list of {@link ConfigurationStats} or null if none are available.
+ */
+ public List<ConfigurationStats> queryConfigurations(int intervalType, long beginTime,
+ long endTime) {
+ try {
+ @SuppressWarnings("unchecked")
+ ParceledListSlice<ConfigurationStats> slice = mService.queryConfigurationStats(
+ intervalType, beginTime, endTime, mContext.getOpPackageName());
+ if (slice != null) {
+ return slice.getList();
+ }
+ } catch (RemoteException e) {
+ // fallthrough and return the empty list.
+ }
+ return Collections.emptyList();
}
/**
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 119d705..083a48a 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -17,6 +17,7 @@
package android.app.usage;
import android.content.ComponentName;
+import android.content.res.Configuration;
/**
* UsageStatsManager local system service interface.
@@ -28,14 +29,19 @@ public abstract class UsageStatsManagerInternal {
/**
* Reports an event to the UsageStatsManager.
*
- * @param component The component for which this event ocurred.
+ * @param component The component for which this event occurred.
* @param userId The user id to which the component belongs to.
- * @param timeStamp The time at which this event ocurred.
- * @param eventType The event that occured. Valid values can be found at
+ * @param eventType The event that occurred. Valid values can be found at
* {@link UsageEvents}
*/
- public abstract void reportEvent(ComponentName component, int userId,
- long timeStamp, int eventType);
+ public abstract void reportEvent(ComponentName component, int userId, int eventType);
+
+ /**
+ * Reports a configuration change to the UsageStatsManager.
+ *
+ * @param config The new device configuration.
+ */
+ public abstract void reportConfigurationChange(Configuration config, int userId);
/**
* Prepares the UsageStatsService for shutdown.
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index bd45c7e..00248cc 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -188,7 +188,7 @@ public class AppWidgetManager {
* this widget. Can have the value {@link
* AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
* AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD} or {@link
- * AppWidgetProviderInfo#WIDGET_CATEGORY_RECENTS}.
+ * AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX}.
*/
public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 02f70c8..b4d79b4 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -61,9 +61,9 @@ public class AppWidgetProviderInfo implements Parcelable {
public static final int WIDGET_CATEGORY_KEYGUARD = 2;
/**
- * Indicates that the widget can be displayed within recents.
+ * Indicates that the widget can be displayed within a space reserved for the search box.
*/
- public static final int WIDGET_CATEGORY_RECENTS = 4;
+ public static final int WIDGET_CATEGORY_SEARCHBOX = 4;
/**
* Identity of this AppWidget component. This component should be a {@link
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index b98e5ae..36997e5 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -375,6 +375,14 @@ public final class BluetoothSocket implements Closeable {
} // else ASSERT(mPort == channel)
ret = 0;
} catch (IOException e) {
+ if (mPfd != null) {
+ try {
+ mPfd.close();
+ } catch (IOException e1) {
+ Log.e(TAG, "bindListen, close mPfd: " + e1);
+ }
+ mPfd = null;
+ }
Log.e(TAG, "bindListen, fail to get port number, exception: " + e);
return -1;
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b825c94..51a58d1 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3363,7 +3363,7 @@ public class Intent implements Parcelable, Cloneable {
* profiles - {@link #ACTION_MANAGED_PROFILE_ADDED} and {@link #ACTION_MANAGED_PROFILE_REMOVED}.
*/
public static final String EXTRA_USER =
- "android.intent.extra.user";
+ "android.intent.extra.USER";
/**
* Extra used in the response from a BroadcastReceiver that handles
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index e63fd07..27bbb24 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -16,6 +16,12 @@
package android.content.res;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Parcel;
@@ -23,7 +29,7 @@ import android.os.Parcelable;
import android.text.TextUtils;
import android.view.View;
-import java.text.Format;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Locale;
@@ -1353,8 +1359,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* Returns a string representation of the configuration that can be parsed
* by build tools (like AAPT).
*
- *
- *
* @hide
*/
public static String resourceQualifierString(Configuration config) {
@@ -1568,4 +1572,229 @@ public final class Configuration implements Parcelable, Comparable<Configuration
parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
return TextUtils.join("-", parts);
}
+
+ /**
+ * Generate a delta Configuration between <code>base</code> and <code>change</code>. The
+ * resulting delta can be used with {@link #updateFrom(Configuration)}.
+ * <p />
+ * Caveat: If the any of the Configuration's members becomes undefined, then
+ * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member.
+ *
+ * This is fine for device configurations as no member is ever undefined.
+ * {@hide}
+ */
+ public static Configuration generateDelta(Configuration base, Configuration change) {
+ final Configuration delta = new Configuration();
+ if (base.fontScale != change.fontScale) {
+ delta.fontScale = change.fontScale;
+ }
+
+ if (base.mcc != change.mcc) {
+ delta.mcc = change.mcc;
+ }
+
+ if (base.mnc != change.mnc) {
+ delta.mnc = change.mnc;
+ }
+
+ if ((base.locale == null && change.locale != null) ||
+ (base.locale != null && !base.locale.equals(change.locale))) {
+ delta.locale = change.locale;
+ }
+
+ if (base.touchscreen != change.touchscreen) {
+ delta.touchscreen = change.touchscreen;
+ }
+
+ if (base.keyboard != change.keyboard) {
+ delta.keyboard = change.keyboard;
+ }
+
+ if (base.keyboardHidden != change.keyboardHidden) {
+ delta.keyboardHidden = change.keyboardHidden;
+ }
+
+ if (base.navigation != change.navigation) {
+ delta.navigation = change.navigation;
+ }
+
+ if (base.navigationHidden != change.navigationHidden) {
+ delta.navigationHidden = change.navigationHidden;
+ }
+
+ if (base.orientation != change.orientation) {
+ delta.orientation = change.orientation;
+ }
+
+ if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
+ (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
+ delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
+ }
+
+ if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) !=
+ (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
+ delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
+ }
+
+ if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) !=
+ (change.screenLayout & SCREENLAYOUT_LONG_MASK)) {
+ delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK;
+ }
+
+ if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
+ delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
+ }
+
+ if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) {
+ delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK;
+ }
+
+ if (base.screenWidthDp != change.screenWidthDp) {
+ delta.screenWidthDp = change.screenWidthDp;
+ }
+
+ if (base.screenHeightDp != change.screenHeightDp) {
+ delta.screenHeightDp = change.screenHeightDp;
+ }
+
+ if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) {
+ delta.smallestScreenWidthDp = change.smallestScreenWidthDp;
+ }
+
+ if (base.densityDpi != change.densityDpi) {
+ delta.densityDpi = change.densityDpi;
+ }
+ return delta;
+ }
+
+ private static final String XML_ATTR_FONT_SCALE = "fs";
+ private static final String XML_ATTR_MCC = "mcc";
+ private static final String XML_ATTR_MNC = "mnc";
+ private static final String XML_ATTR_LOCALE = "locale";
+ private static final String XML_ATTR_TOUCHSCREEN = "touch";
+ private static final String XML_ATTR_KEYBOARD = "key";
+ private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid";
+ private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid";
+ private static final String XML_ATTR_NAVIGATION = "nav";
+ private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
+ private static final String XML_ATTR_ORIENTATION = "ori";
+ private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
+ private static final String XML_ATTR_UI_MODE = "ui";
+ private static final String XML_ATTR_SCREEN_WIDTH = "width";
+ private static final String XML_ATTR_SCREEN_HEIGHT = "height";
+ private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
+ private static final String XML_ATTR_DENSITY = "density";
+
+ /**
+ * Reads the attributes corresponding to Configuration member fields from the Xml parser.
+ * The parser is expected to be on a tag which has Configuration attributes.
+ *
+ * @param parser The Xml parser from which to read attributes.
+ * @param configOut The Configuration to populate from the Xml attributes.
+ * {@hide}
+ */
+ public static void readXmlAttrs(XmlPullParser parser, Configuration configOut)
+ throws XmlPullParserException, IOException {
+ configOut.fontScale = Float.intBitsToFloat(
+ XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0));
+ configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0);
+ configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0);
+
+ final String localeStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALE);
+ if (localeStr != null) {
+ configOut.locale = Locale.forLanguageTag(localeStr);
+ }
+
+ configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN,
+ TOUCHSCREEN_UNDEFINED);
+ configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD,
+ KEYBOARD_UNDEFINED);
+ configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN,
+ KEYBOARDHIDDEN_UNDEFINED);
+ configOut.hardKeyboardHidden =
+ XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN,
+ HARDKEYBOARDHIDDEN_UNDEFINED);
+ configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION,
+ NAVIGATION_UNDEFINED);
+ configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN,
+ NAVIGATIONHIDDEN_UNDEFINED);
+ configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION,
+ ORIENTATION_UNDEFINED);
+ configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
+ SCREENLAYOUT_UNDEFINED);
+ configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
+ configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
+ SCREEN_WIDTH_DP_UNDEFINED);
+ configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT,
+ SCREEN_HEIGHT_DP_UNDEFINED);
+ configOut.smallestScreenWidthDp =
+ XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH,
+ SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
+ configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
+ DENSITY_DPI_UNDEFINED);
+ }
+
+
+ /**
+ * Writes the Configuration's member fields as attributes into the XmlSerializer.
+ * The serializer is expected to have already started a tag so that attributes can be
+ * immediately written.
+ *
+ * @param xml The serializer to which to write the attributes.
+ * @param config The Configuration whose member fields to write.
+ * {@hide}
+ */
+ public static void writeXmlAttrs(XmlSerializer xml, Configuration config) throws IOException {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_FONT_SCALE,
+ Float.floatToIntBits(config.fontScale));
+ if (config.mcc != 0) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_MCC, config.mcc);
+ }
+ if (config.mnc != 0) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc);
+ }
+ if (config.locale != null) {
+ XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALE, config.locale.toLanguageTag());
+ }
+ if (config.touchscreen != TOUCHSCREEN_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen);
+ }
+ if (config.keyboard != KEYBOARD_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD, config.keyboard);
+ }
+ if (config.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD_HIDDEN, config.keyboardHidden);
+ }
+ if (config.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_HARD_KEYBOARD_HIDDEN,
+ config.hardKeyboardHidden);
+ }
+ if (config.navigation != NAVIGATION_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION, config.navigation);
+ }
+ if (config.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION_HIDDEN, config.navigationHidden);
+ }
+ if (config.orientation != ORIENTATION_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_ORIENTATION, config.orientation);
+ }
+ if (config.screenLayout != SCREENLAYOUT_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout);
+ }
+ if (config.uiMode != 0) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode);
+ }
+ if (config.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_WIDTH, config.screenWidthDp);
+ }
+ if (config.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_HEIGHT, config.screenHeightDp);
+ }
+ if (config.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_SMALLEST_WIDTH, config.smallestScreenWidthDp);
+ }
+ if (config.densityDpi != DENSITY_DPI_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
+ }
+ }
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java b/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java
index d0a3a3f..d5ec71a 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java
@@ -114,21 +114,24 @@ public class LegacyFocusStateMapper {
currentAfRun = mAfRun;
}
- mCamera.setAutoFocusMoveCallback(new Camera.AutoFocusMoveCallback() {
+ Camera.AutoFocusMoveCallback afMoveCallback = new Camera.AutoFocusMoveCallback() {
@Override
public void onAutoFocusMoving(boolean start, Camera camera) {
synchronized (mLock) {
int latestAfRun = mAfRun;
if (VERBOSE) {
- Log.v(TAG, "onAutoFocusMoving - start " + start + " latest AF run " +
- latestAfRun + ", last AF run " + currentAfRun);
+ Log.v(TAG,
+ "onAutoFocusMoving - start " + start + " latest AF run " +
+ latestAfRun + ", last AF run " + currentAfRun
+ );
}
if (currentAfRun != latestAfRun) {
Log.d(TAG,
"onAutoFocusMoving - ignoring move callbacks from old af run"
- + currentAfRun);
+ + currentAfRun
+ );
return;
}
@@ -151,9 +154,19 @@ public class LegacyFocusStateMapper {
mAfState = newAfState;
}
}
- });
+ };
+
+ // Only set move callback if we can call autofocus.
+ switch (afMode) {
+ case Parameters.FOCUS_MODE_AUTO:
+ case Parameters.FOCUS_MODE_MACRO:
+ case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
+ case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
+ mCamera.setAutoFocusMoveCallback(afMoveCallback);
+ }
}
+
// AF Locking
switch (afTrigger) {
case CONTROL_AF_TRIGGER_START:
@@ -167,6 +180,7 @@ public class LegacyFocusStateMapper {
case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
afStateAfterStart = CONTROL_AF_STATE_PASSIVE_SCAN;
+ break;
default:
// EDOF, INFINITY
afStateAfterStart = CONTROL_AF_STATE_INACTIVE;
@@ -183,6 +197,11 @@ public class LegacyFocusStateMapper {
"new AF run is " + currentAfRun);
}
+ // Avoid calling autofocus unless we are in a state that supports calling this.
+ if (afStateAfterStart == CONTROL_AF_STATE_INACTIVE) {
+ break;
+ }
+
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
index 4c4ad0d..42ee4fa 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
@@ -122,7 +122,10 @@ public class LegacyRequestMapper {
activeArray, zoomData, aeRegions, maxNumMeteringAreas,
/*regionName*/"AE");
- params.setMeteringAreas(meteringAreaList);
+ // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
+ if (maxNumMeteringAreas > 0) {
+ params.setMeteringAreas(meteringAreaList);
+ }
}
// afRegions
@@ -133,7 +136,10 @@ public class LegacyRequestMapper {
activeArray, zoomData, afRegions, maxNumFocusAreas,
/*regionName*/"AF");
- params.setFocusAreas(focusAreaList);
+ // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
+ if (maxNumFocusAreas > 0) {
+ params.setFocusAreas(focusAreaList);
+ }
}
}
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 4b5ced9..30f3576 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -55,10 +55,29 @@ public final class HdmiControlManager {
public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1;
/**
+ * Message used by TV to receive volume status from Audio Receiver. It should check volume value
+ * that is retrieved from extra value with the key {@link #EXTRA_MESSAGE_EXTRAM_PARAM1}. If the
+ * value is in range of [0,100], it is current volume of Audio Receiver. And there is another
+ * value, {@link #AVR_VOLUME_MUTED}, which is used to inform volume mute.
+ */
+ public static final int OSD_MESSAGE_AVR_VOLUME_CHANGED = 2;
+
+ /**
* Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the ID of
* the message to display on screen.
*/
public static final String EXTRA_MESSAGE_ID = "android.hardware.hdmi.extra.MESSAGE_ID";
+ /**
+ * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the extra value
+ * of the message.
+ */
+ public static final String EXTRA_MESSAGE_EXTRAM_PARAM1 =
+ "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1";
+
+ /**
+ * Volume value for mute state.
+ */
+ public static final int AVR_VOLUME_MUTED = 101;
public static final int POWER_STATUS_UNKNOWN = -1;
public static final int POWER_STATUS_ON = 0;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 4bfef41..70b402d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -685,6 +685,23 @@ public class ConnectivityManager {
}
/**
+ * Returns the {@link Network} object currently serving a given type, or
+ * null if the given type is not connected.
+ *
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ *
+ * @hide
+ */
+ public Network getNetworkForType(int networkType) {
+ try {
+ return mService.getNetworkForType(networkType);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
* Returns an array of all {@link Network} currently tracked by the
* framework.
*
@@ -1281,7 +1298,7 @@ public class ConnectivityManager {
}
/**
- * Callback for use with {@link ConnectivityManager#registerDefaultNetworkActiveListener}
+ * Callback for use with {@link ConnectivityManager#addDefaultNetworkActiveListener}
* to find out when the system default network has gone in to a high power state.
*/
public interface OnNetworkActiveListener {
@@ -1323,7 +1340,7 @@ public class ConnectivityManager {
*
* @param l The listener to be told when the network is active.
*/
- public void registerDefaultNetworkActiveListener(final OnNetworkActiveListener l) {
+ public void addDefaultNetworkActiveListener(final OnNetworkActiveListener l) {
INetworkActivityListener rl = new INetworkActivityListener.Stub() {
@Override
public void onNetworkActive() throws RemoteException {
@@ -1340,11 +1357,11 @@ public class ConnectivityManager {
/**
* Remove network active listener previously registered with
- * {@link #registerDefaultNetworkActiveListener}.
+ * {@link #addDefaultNetworkActiveListener}.
*
* @param l Previously registered listener.
*/
- public void unregisterDefaultNetworkActiveListener(OnNetworkActiveListener l) {
+ public void removeDefaultNetworkActiveListener(OnNetworkActiveListener l) {
INetworkActivityListener rl = mNetworkActivityListeners.get(l);
if (rl == null) {
throw new IllegalArgumentException("Listener not registered: " + l);
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index b2fc3be..974c4cd 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -48,6 +48,7 @@ interface IConnectivityManager
NetworkInfo getNetworkInfo(int networkType);
NetworkInfo getNetworkInfoForNetwork(in Network network);
NetworkInfo[] getAllNetworkInfo();
+ Network getNetworkForType(int networkType);
Network[] getAllNetworks();
NetworkInfo getProvisioningOrActiveNetworkInfo();
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index f9a25f9..c387055 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -274,7 +274,6 @@ public class LinkAddress implements Parcelable {
/**
* Implement the Parcelable interface.
- * @hide
*/
public int describeContents() {
return 0;
@@ -282,7 +281,6 @@ public class LinkAddress implements Parcelable {
/**
* Implement the Parcelable interface.
- * @hide
*/
public void writeToParcel(Parcel dest, int flags) {
dest.writeByteArray(address.getAddress());
@@ -293,7 +291,6 @@ public class LinkAddress implements Parcelable {
/**
* Implement the Parcelable interface.
- * @hide
*/
public static final Creator<LinkAddress> CREATOR =
new Creator<LinkAddress>() {
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index d2a4728..e686be7 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -35,6 +35,7 @@ import java.net.URLStreamHandler;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.SocketFactory;
+import com.android.okhttp.ConnectionPool;
import com.android.okhttp.HostResolver;
import com.android.okhttp.OkHttpClient;
@@ -60,6 +61,17 @@ public class Network implements Parcelable {
private volatile OkHttpClient mOkHttpClient = null;
private Object mLock = new Object();
+ // Default connection pool values. These are evaluated at startup, just
+ // like the OkHttp code. Also like the OkHttp code, we will throw parse
+ // exceptions at class loading time if the properties are set but are not
+ // valid integers.
+ private static final boolean httpKeepAlive =
+ Boolean.parseBoolean(System.getProperty("http.keepAlive", "true"));
+ private static final int httpMaxConnections =
+ httpKeepAlive ? Integer.parseInt(System.getProperty("http.maxConnections", "5")) : 0;
+ private static final long httpKeepAliveDurationMs =
+ Long.parseLong(System.getProperty("http.keepAliveDuration", "300000")); // 5 minutes.
+
/**
* @hide
*/
@@ -183,6 +195,20 @@ public class Network implements Parcelable {
return mNetworkBoundSocketFactory;
}
+ // TODO: This creates an OkHttpClient with its own connection pool for
+ // every Network object, instead of one for every NetId. This is
+ // suboptimal, because an app could potentially have more than one
+ // Network object for the same NetId, causing increased memory footprint
+ // and performance penalties due to lack of connection reuse (connection
+ // setup time, congestion window growth time, etc.).
+ //
+ // Instead, investigate only having one OkHttpClient for every NetId,
+ // perhaps by using a static HashMap of NetIds to OkHttpClient objects. The
+ // tricky part is deciding when to remove an OkHttpClient; a WeakHashMap
+ // shouldn't be used because whether a Network is referenced doesn't
+ // correlate with whether a new Network will be instantiated in the near
+ // future with the same NetID. A good solution would involve purging empty
+ // (or when all connections are timed out) ConnectionPools.
private void maybeInitHttpClient() {
if (mOkHttpClient == null) {
synchronized (mLock) {
@@ -193,9 +219,12 @@ public class Network implements Parcelable {
return Network.this.getAllByName(host);
}
};
+ ConnectionPool pool = new ConnectionPool(httpMaxConnections,
+ httpKeepAliveDurationMs);
mOkHttpClient = new OkHttpClient()
.setSocketFactory(getSocketFactory())
- .setHostResolver(hostResolver);
+ .setHostResolver(hostResolver)
+ .setConnectionPool(pool);
}
}
}
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index d279412..7664c95 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -128,14 +128,6 @@ public class NetworkInfo implements Parcelable {
private boolean mIsAvailable;
/**
- * @param type network type
- * @deprecated
- * @hide because this constructor was only meant for internal use (and
- * has now been superseded by the package-private constructor below).
- */
- public NetworkInfo(int type) {}
-
- /**
* @hide
*/
public NetworkInfo(int type, int subtype, String typeName, String subtypeName) {
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 83bdfaa..5a09b46 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -52,6 +52,9 @@ public class NetworkRequest implements Parcelable {
* @hide
*/
public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId) {
+ if (nc == null) {
+ throw new NullPointerException();
+ }
requestId = rId;
networkCapabilities = nc;
this.legacyType = legacyType;
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index 7ea6bae..1534e2c 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -334,10 +334,6 @@ public class ProxyInfo implements Parcelable {
dest.writeStringArray(mParsedExclusionList);
}
- /**
- * Implement the Parcelable interface.
- * @hide
- */
public static final Creator<ProxyInfo> CREATOR =
new Creator<ProxyInfo>() {
public ProxyInfo createFromParcel(Parcel in) {
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index b0e0b49..1e0dc53 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -541,7 +541,7 @@ public class Build {
* Intent.</li>
* </ul>
*/
- public static final int L = CUR_DEVELOPMENT;
+ public static final int L = 21;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 6d4a302..b3e28ea 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -19,6 +19,7 @@ package android.os;
import android.net.InterfaceConfiguration;
import android.net.INetworkManagementEventObserver;
+import android.net.Network;
import android.net.NetworkStats;
import android.net.RouteInfo;
import android.net.UidRange;
@@ -164,10 +165,10 @@ interface INetworkManagementService
/**
* Sets the list of DNS forwarders (in order of priority)
*/
- void setDnsForwarders(in String[] dns);
+ void setDnsForwarders(in Network network, in String[] dns);
/**
- * Returns the list of DNS fowarders (in order of priority)
+ * Returns the list of DNS forwarders (in order of priority)
*/
String[] getDnsForwarders();
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 5ce9d5c..0ff5f6a 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -234,6 +234,7 @@ public final class UserHandle implements Parcelable {
* @return user id of the current process
* @hide
*/
+ @SystemApi
public static final int myUserId() {
return getUserId(Process.myUid());
}
@@ -253,7 +254,11 @@ public final class UserHandle implements Parcelable {
mHandle = h;
}
- /** @hide */
+ /**
+ * Returns the userId stored in this UserHandle.
+ * @hide
+ */
+ @SystemApi
public int getIdentifier() {
return mHandle;
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index f793667..3749892 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -15,6 +15,7 @@
*/
package android.os;
+import android.annotation.SystemApi;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.content.Context;
@@ -424,6 +425,19 @@ public class UserManager {
}
/**
+ * Checks if the calling app is running in a managed profile.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * @return whether the caller is in a managed profile.
+ * @hide
+ */
+ @SystemApi
+ public boolean isManagedProfile() {
+ UserInfo user = getUserInfo(UserHandle.myUserId());
+ return user != null ? user.isManagedProfile() : false;
+ }
+
+ /**
* Return whether the given user is actively running. This means that
* the user is in the "started" state, not "stopped" -- it is currently
* allowed to run code through scheduled alarms, receiving broadcasts,
@@ -646,6 +660,7 @@ public class UserManager {
try {
Bundle guestRestrictions = mService.getDefaultGuestRestrictions();
guestRestrictions.putBoolean(DISALLOW_SMS, true);
+ guestRestrictions.putBoolean(DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
mService.setUserRestrictions(guestRestrictions, guest.id);
} catch (RemoteException re) {
Log.w(TAG, "Could not update guest restrictions");
diff --git a/core/java/android/preference/CheckBoxPreference.java b/core/java/android/preference/CheckBoxPreference.java
index 1ce98b8..fee3f0f 100644
--- a/core/java/android/preference/CheckBoxPreference.java
+++ b/core/java/android/preference/CheckBoxPreference.java
@@ -66,7 +66,6 @@ public class CheckBoxPreference extends TwoStatePreference {
View checkboxView = view.findViewById(com.android.internal.R.id.checkbox);
if (checkboxView != null && checkboxView instanceof Checkable) {
((Checkable) checkboxView).setChecked(mChecked);
- sendAccessibilityEvent(checkboxView);
}
syncSummaryView(view);
diff --git a/core/java/android/preference/SwitchPreference.java b/core/java/android/preference/SwitchPreference.java
index 46be928..53b5aad 100644
--- a/core/java/android/preference/SwitchPreference.java
+++ b/core/java/android/preference/SwitchPreference.java
@@ -130,8 +130,6 @@ public class SwitchPreference extends TwoStatePreference {
((Checkable) checkableView).setChecked(mChecked);
- sendAccessibilityEvent(checkableView);
-
if (checkableView instanceof Switch) {
final Switch switchView = (Switch) checkableView;
switchView.setTextOn(mSwitchOn);
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index 6f8be1f..3823b27 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -24,8 +24,6 @@ import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;
/**
@@ -39,7 +37,6 @@ public abstract class TwoStatePreference extends Preference {
private CharSequence mSummaryOff;
boolean mChecked;
private boolean mCheckedSet;
- private boolean mSendClickAccessibilityEvent;
private boolean mDisableDependentsState;
public TwoStatePreference(
@@ -63,15 +60,10 @@ public abstract class TwoStatePreference extends Preference {
protected void onClick() {
super.onClick();
- boolean newValue = !isChecked();
-
- mSendClickAccessibilityEvent = true;
-
- if (!callChangeListener(newValue)) {
- return;
+ final boolean newValue = !isChecked();
+ if (callChangeListener(newValue)) {
+ setChecked(newValue);
}
-
- setChecked(newValue);
}
/**
@@ -196,21 +188,6 @@ public abstract class TwoStatePreference extends Preference {
: (Boolean) defaultValue);
}
- void sendAccessibilityEvent(View view) {
- // Since the view is still not attached we create, populate,
- // and send the event directly since we do not know when it
- // will be attached and posting commands is not as clean.
- AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(getContext());
- if (mSendClickAccessibilityEvent && accessibilityManager.isEnabled()) {
- AccessibilityEvent event = AccessibilityEvent.obtain();
- event.setEventType(AccessibilityEvent.TYPE_VIEW_CLICKED);
- view.onInitializeAccessibilityEvent(event);
- view.dispatchPopulateAccessibilityEvent(event);
- accessibilityManager.sendAccessibilityEvent(event);
- }
- mSendClickAccessibilityEvent = false;
- }
-
/**
* Sync a summary view contained within view's subhierarchy with the correct summary text.
* @param view View where a summary should be located
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 0202f91..5fa1cc9 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -116,8 +116,8 @@ public class CallLog {
* </pre>
* </p>
*/
- public static final String EXTRA_CALL_TYPE_FILTER
- = "android.provider.extra.call_type_filter";
+ public static final String EXTRA_CALL_TYPE_FILTER =
+ "android.provider.extra.CALL_TYPE_FILTER";
/**
* Content uri used to access call log entries, including voicemail records. You must have
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 27473e3..18a9eb1 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1125,7 +1125,7 @@ public final class ContactsContract {
* import android.provider.ContactsContract.Contacts;
*
* Uri uri = Contacts.CONTENT_URI.buildUpon()
- * .appendQueryParameter(Contacts.ADDRESS_BOOK_INDEX_EXTRAS, "true")
+ * .appendQueryParameter(Contacts.EXTRA_ADDRESS_BOOK_INDEX, "true")
* .build();
* Cursor cursor = getContentResolver().query(uri,
* new String[] {Contacts.DISPLAY_NAME},
@@ -1140,21 +1140,24 @@ public final class ContactsContract {
* </pre>
* </p>
*/
- public static final String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
+ public static final String EXTRA_ADDRESS_BOOK_INDEX =
+ "android.provider.extra.ADDRESS_BOOK_INDEX";
/**
* The array of address book index titles, which are returned in the
* same order as the data in the cursor.
* <p>TYPE: String[]</p>
*/
- public static final String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ public static final String EXTRA_ADDRESS_BOOK_INDEX_TITLES =
+ "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
/**
* The array of group counts for the corresponding group. Contains the same number
* of elements as the EXTRA_ADDRESS_BOOK_INDEX_TITLES array.
* <p>TYPE: int[]</p>
*/
- public static final String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
+ public static final String EXTRA_ADDRESS_BOOK_INDEX_COUNTS =
+ "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
}
/**
@@ -8111,7 +8114,7 @@ public final class ContactsContract {
* for the provided {@link Contacts} entry.
*/
public static final String ACTION_QUICK_CONTACT =
- "com.android.contacts.action.QUICK_CONTACT";
+ "android.provider.action.QUICK_CONTACT";
/**
* Extra used to specify pivot dialog location in screen coordinates.
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index cb0bcf2..2ca8098 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -26,6 +26,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -101,6 +102,7 @@ public abstract class NotificationListenerService extends Service {
* <li>{@link Notification#EXTRA_LARGE_ICON extras[EXTRA_LARGE_ICON]}</li>
* <li>{@link Notification#EXTRA_LARGE_ICON_BIG extras[EXTRA_LARGE_ICON_BIG]}</li>
* <li>{@link Notification#EXTRA_PICTURE extras[EXTRA_PICTURE]}</li>
+ * <li>{@link Notification#EXTRA_BIG_TEXT extras[EXTRA_BIG_TEXT]}</li>
* </ol>
*
* @hide
@@ -692,10 +694,15 @@ public abstract class NotificationListenerService extends Service {
* current {@link RankingMap}.
*/
public static class Ranking {
+ /** Value signifying that the user has not expressed a per-app visibility override value.
+ * @hide */
+ public static final int VISIBILITY_NO_OVERRIDE = -1000;
+
private String mKey;
private int mRank = -1;
private boolean mIsAmbient;
private boolean mMatchesInterruptionFilter;
+ private int mVisibilityOverride;
public Ranking() {}
@@ -725,6 +732,17 @@ public abstract class NotificationListenerService extends Service {
}
/**
+ * Returns the user specificed visibility for the package that posted
+ * this notification, or
+ * {@link NotificationListenerService.Ranking#VISIBILITY_NO_OVERRIDE} if
+ * no such preference has been expressed.
+ * @hide
+ */
+ public int getVisibilityOverride() {
+ return mVisibilityOverride;
+ }
+
+ /**
* Returns whether the notification meets the user's interruption
* filter.
*
@@ -743,11 +761,12 @@ public abstract class NotificationListenerService extends Service {
}
private void populate(String key, int rank, boolean isAmbient,
- boolean matchesInterruptionFilter) {
+ boolean matchesInterruptionFilter, int visibilityOverride) {
mKey = key;
mRank = rank;
mIsAmbient = isAmbient;
mMatchesInterruptionFilter = matchesInterruptionFilter;
+ mVisibilityOverride = visibilityOverride;
}
}
@@ -763,6 +782,7 @@ public abstract class NotificationListenerService extends Service {
private final NotificationRankingUpdate mRankingUpdate;
private ArrayMap<String,Integer> mRanks;
private ArraySet<Object> mIntercepted;
+ private ArrayMap<String, Integer> mVisibilityOverrides;
private RankingMap(NotificationRankingUpdate rankingUpdate) {
mRankingUpdate = rankingUpdate;
@@ -787,7 +807,8 @@ public abstract class NotificationListenerService extends Service {
*/
public boolean getRanking(String key, Ranking outRanking) {
int rank = getRank(key);
- outRanking.populate(key, rank, isAmbient(key), !isIntercepted(key));
+ outRanking.populate(key, rank, isAmbient(key), !isIntercepted(key),
+ getVisibilityOverride(key));
return rank >= 0;
}
@@ -819,6 +840,19 @@ public abstract class NotificationListenerService extends Service {
return mIntercepted.contains(key);
}
+ private int getVisibilityOverride(String key) {
+ synchronized (this) {
+ if (mVisibilityOverrides == null) {
+ buildVisibilityOverridesLocked();
+ }
+ }
+ Integer overide = mVisibilityOverrides.get(key);
+ if (overide == null) {
+ return Ranking.VISIBILITY_NO_OVERRIDE;
+ }
+ return overide.intValue();
+ }
+
// Locked by 'this'
private void buildRanksLocked() {
String[] orderedKeys = mRankingUpdate.getOrderedKeys();
@@ -836,6 +870,15 @@ public abstract class NotificationListenerService extends Service {
Collections.addAll(mIntercepted, dndInterceptedKeys);
}
+ // Locked by 'this'
+ private void buildVisibilityOverridesLocked() {
+ Bundle visibilityBundle = mRankingUpdate.getVisibilityOverrides();
+ mVisibilityOverrides = new ArrayMap<>(visibilityBundle.size());
+ for (String key: visibilityBundle.keySet()) {
+ mVisibilityOverrides.put(key, visibilityBundle.getInt(key));
+ }
+ }
+
// ----------- Parcelable
@Override
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index 26af38b..6fba900 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -15,6 +15,7 @@
*/
package android.service.notification;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -26,18 +27,21 @@ public class NotificationRankingUpdate implements Parcelable {
private final String[] mKeys;
private final String[] mInterceptedKeys;
private final int mFirstAmbientIndex;
+ private final Bundle mVisibilityOverrides;
public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
- int firstAmbientIndex) {
+ Bundle visibilityOverrides, int firstAmbientIndex) {
mKeys = keys;
mFirstAmbientIndex = firstAmbientIndex;
mInterceptedKeys = interceptedKeys;
+ mVisibilityOverrides = visibilityOverrides;
}
public NotificationRankingUpdate(Parcel in) {
mKeys = in.readStringArray();
mFirstAmbientIndex = in.readInt();
mInterceptedKeys = in.readStringArray();
+ mVisibilityOverrides = in.readBundle();
}
@Override
@@ -50,6 +54,7 @@ public class NotificationRankingUpdate implements Parcelable {
out.writeStringArray(mKeys);
out.writeInt(mFirstAmbientIndex);
out.writeStringArray(mInterceptedKeys);
+ out.writeBundle(mVisibilityOverrides);
}
public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -74,4 +79,8 @@ public class NotificationRankingUpdate implements Parcelable {
public String[] getInterceptedKeys() {
return mInterceptedKeys;
}
+
+ public Bundle getVisibilityOverrides() {
+ return mVisibilityOverrides;
+ }
}
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 519bc28..4de5f41 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -450,7 +450,7 @@ public class AlwaysOnHotwordDetector {
* This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
* Starting re-enrollment is only valid if the keyphrase is un-enrolled,
* i.e. {@link #STATE_KEYPHRASE_UNENROLLED},
- * otherwise {@link #createIntentToReEnroll()} should be preferred.
+ * otherwise {@link #createReEnrollIntent()} should be preferred.
*
* @return An {@link Intent} to start enrollment for the given keyphrase.
* @throws UnsupportedOperationException if managing they keyphrase isn't supported.
@@ -460,6 +460,19 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
+ public Intent createEnrollIntent() {
+ if (DBG) Slog.d(TAG, "createEnrollIntent");
+ synchronized (mLock) {
+ return getManageIntentLocked(MANAGE_ACTION_ENROLL);
+ }
+ }
+
+ /**
+ * FIXME: Remove once the prebuilts are updated.
+ *
+ * @hide
+ */
+ @Deprecated
public Intent createIntentToEnroll() {
if (DBG) Slog.d(TAG, "createIntentToEnroll");
synchronized (mLock) {
@@ -481,6 +494,19 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
+ public Intent createUnEnrollIntent() {
+ if (DBG) Slog.d(TAG, "createUnEnrollIntent");
+ synchronized (mLock) {
+ return getManageIntentLocked(MANAGE_ACTION_UN_ENROLL);
+ }
+ }
+
+ /**
+ * FIXME: Remove once the prebuilts are updated.
+ *
+ * @hide
+ */
+ @Deprecated
public Intent createIntentToUnEnroll() {
if (DBG) Slog.d(TAG, "createIntentToUnEnroll");
synchronized (mLock) {
@@ -502,6 +528,19 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
+ public Intent createReEnrollIntent() {
+ if (DBG) Slog.d(TAG, "createReEnrollIntent");
+ synchronized (mLock) {
+ return getManageIntentLocked(MANAGE_ACTION_RE_ENROLL);
+ }
+ }
+
+ /**
+ * FIXME: Remove once the prebuilts are updated.
+ *
+ * @hide
+ */
+ @Deprecated
public Intent createIntentToReEnroll() {
if (DBG) Slog.d(TAG, "createIntentToReEnroll");
synchronized (mLock) {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 7dce348..2b53c48 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -727,10 +727,9 @@ public abstract class Layout {
int[] runs = dirs.mDirections;
int lineStart = getLineStart(line);
for (int i = 0; i < runs.length; i += 2) {
- int start = lineStart + (runs[i] & RUN_LENGTH_MASK);
- // No need to test the end as an offset after the last run should return the value
- // corresponding of the last run
- if (offset >= start) {
+ int start = lineStart + runs[i];
+ int limit = start + (runs[i+1] & RUN_LENGTH_MASK);
+ if (offset >= start && offset < limit) {
int level = (runs[i+1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK;
return ((level & 1) != 0);
}
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 679e2cc..3222dbf 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -116,7 +116,8 @@ public class Selection {
/**
* Move the cursor to the buffer offset physically above the current
- * offset, or return false if the cursor is already on the top line.
+ * offset, to the beginning if it is on the top line but not at the
+ * start, or return false if the cursor is already on the top line.
*/
public static boolean moveUp(Spannable text, Layout layout) {
int start = getSelectionStart(text);
@@ -149,6 +150,9 @@ public class Selection {
setSelection(text, move);
return true;
+ } else if (end != 0) {
+ setSelection(text, 0);
+ return true;
}
}
@@ -157,7 +161,9 @@ public class Selection {
/**
* Move the cursor to the buffer offset physically below the current
- * offset, or return false if the cursor is already on the bottom line.
+ * offset, to the end of the buffer if it is on the bottom line but
+ * not at the end, or return false if the cursor is already at the
+ * end of the buffer.
*/
public static boolean moveDown(Spannable text, Layout layout) {
int start = getSelectionStart(text);
@@ -190,6 +196,9 @@ public class Selection {
setSelection(text, move);
return true;
+ } else if (end != text.length()) {
+ setSelection(text, text.length());
+ return true;
}
}
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index d579f54..cb0a875 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -45,6 +45,10 @@ public class ChangeTransform extends Transition {
private static final String PROPNAME_TRANSFORMS = "android:changeTransform:transforms";
private static final String PROPNAME_PARENT = "android:changeTransform:parent";
private static final String PROPNAME_PARENT_MATRIX = "android:changeTransform:parentMatrix";
+ private static final String PROPNAME_INTERMEDIATE_PARENT_MATRIX =
+ "android:changeTransform:intermediateParentMatrix";
+ private static final String PROPNAME_INTERMEDIATE_MATRIX =
+ "android:changeTransform:intermediateMatrix";
private static final String[] sTransitionProperties = {
PROPNAME_MATRIX,
@@ -172,6 +176,10 @@ public class ChangeTransform extends Transition {
parent.transformMatrixToGlobal(parentMatrix);
parentMatrix.preTranslate(-parent.getScrollX(), -parent.getScrollY());
transitionValues.values.put(PROPNAME_PARENT_MATRIX, parentMatrix);
+ transitionValues.values.put(PROPNAME_INTERMEDIATE_MATRIX,
+ view.getTag(R.id.transitionTransform));
+ transitionValues.values.put(PROPNAME_INTERMEDIATE_PARENT_MATRIX,
+ view.getTag(R.id.parentMatrix));
}
return;
}
@@ -199,12 +207,13 @@ public class ChangeTransform extends Transition {
ViewGroup endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
boolean handleParentChange = mReparent && !parentsMatch(startParent, endParent);
- Matrix startMatrix = (Matrix) startValues.view.getTag(R.id.transitionTransform);
+ Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_INTERMEDIATE_MATRIX);
if (startMatrix != null) {
startValues.values.put(PROPNAME_MATRIX, startMatrix);
}
- Matrix startParentMatrix = (Matrix) startValues.view.getTag(R.id.parentMatrix);
+ Matrix startParentMatrix = (Matrix)
+ startValues.values.get(PROPNAME_INTERMEDIATE_PARENT_MATRIX);
if (startParentMatrix != null) {
startValues.values.put(PROPNAME_PARENT_MATRIX, startParentMatrix);
}
@@ -250,9 +259,11 @@ public class ChangeTransform extends Transition {
ObjectAnimator animator = ObjectAnimator.ofObject(view, ANIMATION_MATRIX_PROPERTY,
new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix);
+ final Matrix finalEndMatrix = endMatrix;
+
AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
private boolean mIsCanceled;
- private Matrix mTempMatrix;
+ private Matrix mTempMatrix = new Matrix();
@Override
public void onAnimationCancel(Animator animation) {
@@ -262,8 +273,7 @@ public class ChangeTransform extends Transition {
@Override
public void onAnimationEnd(Animator animation) {
if (!mIsCanceled) {
- view.setTagInternal(R.id.transitionTransform, null);
- view.setTagInternal(R.id.parentMatrix, null);
+ setCurrentMatrix(finalEndMatrix);
}
ANIMATION_MATRIX_PROPERTY.set(view, null);
transforms.restore(view);
@@ -273,19 +283,19 @@ public class ChangeTransform extends Transition {
public void onAnimationPause(Animator animation) {
ValueAnimator animator = (ValueAnimator) animation;
Matrix currentMatrix = (Matrix) animator.getAnimatedValue();
- if (mTempMatrix == null) {
- mTempMatrix = new Matrix(currentMatrix);
- } else {
- mTempMatrix.set(currentMatrix);
- }
- view.setTagInternal(R.id.transitionTransform, mTempMatrix);
- transforms.restore(view);
+ setCurrentMatrix(currentMatrix);
}
@Override
public void onAnimationResume(Animator animation) {
setIdentityTransforms(view);
}
+
+ private void setCurrentMatrix(Matrix currentMatrix) {
+ mTempMatrix.set(currentMatrix);
+ view.setTagInternal(R.id.transitionTransform, mTempMatrix);
+ transforms.restore(view);
+ }
};
animator.addListener(listener);
@@ -423,6 +433,8 @@ public class ChangeTransform extends Transition {
public void onTransitionEnd(Transition transition) {
transition.removeListener(this);
GhostView.removeGhost(mView);
+ mView.setTagInternal(R.id.transitionTransform, null);
+ mView.setTagInternal(R.id.parentMatrix, null);
}
@Override
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index ce3cc2f..7bd6287 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -182,11 +182,15 @@ public class TransitionManager {
final ViewGroup sceneRoot = scene.getSceneRoot();
- Transition transitionClone = transition.clone();
- transitionClone.setSceneRoot(sceneRoot);
+ Transition transitionClone = null;
+ if (transition != null) {
+ transitionClone = transition.clone();
+ transitionClone.setSceneRoot(sceneRoot);
+ }
Scene oldScene = Scene.getCurrentScene(sceneRoot);
- if (oldScene != null && oldScene.isCreatedFromLayoutResource()) {
+ if (oldScene != null && transitionClone != null &&
+ oldScene.isCreatedFromLayoutResource()) {
transitionClone.setCanRemoveViews(true);
}
diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java
index b0c9e9a..a84ecd1 100644
--- a/core/java/android/transition/TransitionUtils.java
+++ b/core/java/android/transition/TransitionUtils.java
@@ -40,6 +40,33 @@ public class TransitionUtils {
}
}
+ public static Transition mergeTransitions(Transition... transitions) {
+ int count = 0;
+ int nonNullIndex = -1;
+ for (int i = 0; i < transitions.length; i++) {
+ if (transitions[i] != null) {
+ count++;
+ nonNullIndex = i;
+ }
+ }
+
+ if (count == 0) {
+ return null;
+ }
+
+ if (count == 1) {
+ return transitions[nonNullIndex];
+ }
+
+ TransitionSet transitionSet = new TransitionSet();
+ for (int i = 0; i < transitions.length; i++) {
+ if (transitions[i] != null) {
+ transitionSet.addTransition(transitions[i]);
+ }
+ }
+ return transitionSet;
+ }
+
public static class MatrixEvaluator implements TypeEvaluator<Matrix> {
float[] mTempStartValues = new float[9];
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 477c994..a10dda3 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -18,6 +18,7 @@ package android.view;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.Region;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -96,7 +97,7 @@ final class AccessibilityInteractionController {
}
public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
- long accessibilityNodeId, int interactionId,
+ long accessibilityNodeId, Region interactiveRegion, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
@@ -109,6 +110,7 @@ final class AccessibilityInteractionController {
args.argi3 = interactionId;
args.arg1 = callback;
args.arg2 = spec;
+ args.arg3 = interactiveRegion;
message.obj = args;
// If the interrogation is performed by the same thread as the main UI
@@ -133,6 +135,7 @@ final class AccessibilityInteractionController {
final IAccessibilityInteractionConnectionCallback callback =
(IAccessibilityInteractionConnectionCallback) args.arg1;
final MagnificationSpec spec = (MagnificationSpec) args.arg2;
+ final Region interactiveRegion = (Region) args.arg3;
args.recycle();
@@ -159,6 +162,7 @@ final class AccessibilityInteractionController {
if (spec != null) {
spec.recycle();
}
+ adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
infos.clear();
} catch (RemoteException re) {
@@ -168,8 +172,9 @@ final class AccessibilityInteractionController {
}
public void findAccessibilityNodeInfosByViewIdClientThread(long accessibilityNodeId,
- String viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback,
- int flags, int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+ String viewId, Region interactiveRegion, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+ long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID;
message.arg1 = flags;
@@ -180,6 +185,7 @@ final class AccessibilityInteractionController {
args.arg1 = callback;
args.arg2 = spec;
args.arg3 = viewId;
+ args.arg4 = interactiveRegion;
message.obj = args;
@@ -205,6 +211,7 @@ final class AccessibilityInteractionController {
(IAccessibilityInteractionConnectionCallback) args.arg1;
final MagnificationSpec spec = (MagnificationSpec) args.arg2;
final String viewId = (String) args.arg3;
+ final Region interactiveRegion = (Region) args.arg4;
args.recycle();
@@ -241,6 +248,7 @@ final class AccessibilityInteractionController {
if (spec != null) {
spec.recycle();
}
+ adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
} catch (RemoteException re) {
/* ignore - the other side will time out */
@@ -249,8 +257,9 @@ final class AccessibilityInteractionController {
}
public void findAccessibilityNodeInfosByTextClientThread(long accessibilityNodeId,
- String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
- int flags, int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+ String text, Region interactiveRegion, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+ long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
message.arg1 = flags;
@@ -262,6 +271,7 @@ final class AccessibilityInteractionController {
args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
args.argi3 = interactionId;
+ args.arg4 = interactiveRegion;
message.obj = args;
// If the interrogation is performed by the same thread as the main UI
@@ -287,6 +297,7 @@ final class AccessibilityInteractionController {
final int accessibilityViewId = args.argi1;
final int virtualDescendantId = args.argi2;
final int interactionId = args.argi3;
+ final Region interactiveRegion = (Region) args.arg4;
args.recycle();
List<AccessibilityNodeInfo> infos = null;
@@ -347,6 +358,7 @@ final class AccessibilityInteractionController {
if (spec != null) {
spec.recycle();
}
+ adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
} catch (RemoteException re) {
/* ignore - the other side will time out */
@@ -354,7 +366,8 @@ final class AccessibilityInteractionController {
}
}
- public void findFocusClientThread(long accessibilityNodeId, int focusType, int interactionId,
+ public void findFocusClientThread(long accessibilityNodeId, int focusType,
+ Region interactiveRegion, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
@@ -368,6 +381,7 @@ final class AccessibilityInteractionController {
args.argi3 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
args.arg1 = callback;
args.arg2 = spec;
+ args.arg3 = interactiveRegion;
message.obj = args;
@@ -394,6 +408,7 @@ final class AccessibilityInteractionController {
final IAccessibilityInteractionConnectionCallback callback =
(IAccessibilityInteractionConnectionCallback) args.arg1;
final MagnificationSpec spec = (MagnificationSpec) args.arg2;
+ final Region interactiveRegion = (Region) args.arg3;
args.recycle();
AccessibilityNodeInfo focused = null;
@@ -457,6 +472,7 @@ final class AccessibilityInteractionController {
if (spec != null) {
spec.recycle();
}
+ adjustIsVisibleToUserIfNeeded(focused, interactiveRegion);
callback.setFindAccessibilityNodeInfoResult(focused, interactionId);
} catch (RemoteException re) {
/* ignore - the other side will time out */
@@ -464,7 +480,8 @@ final class AccessibilityInteractionController {
}
}
- public void focusSearchClientThread(long accessibilityNodeId, int direction, int interactionId,
+ public void focusSearchClientThread(long accessibilityNodeId, int direction,
+ Region interactiveRegion, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
@@ -477,6 +494,7 @@ final class AccessibilityInteractionController {
args.argi3 = interactionId;
args.arg1 = callback;
args.arg2 = spec;
+ args.arg3 = interactiveRegion;
message.obj = args;
@@ -502,6 +520,7 @@ final class AccessibilityInteractionController {
final IAccessibilityInteractionConnectionCallback callback =
(IAccessibilityInteractionConnectionCallback) args.arg1;
final MagnificationSpec spec = (MagnificationSpec) args.arg2;
+ final Region interactiveRegion = (Region) args.arg3;
args.recycle();
@@ -530,6 +549,7 @@ final class AccessibilityInteractionController {
if (spec != null) {
spec.recycle();
}
+ adjustIsVisibleToUserIfNeeded(next, interactiveRegion);
callback.setFindAccessibilityNodeInfoResult(next, interactionId);
} catch (RemoteException re) {
/* ignore - the other side will time out */
@@ -644,6 +664,30 @@ final class AccessibilityInteractionController {
}
}
+ private void adjustIsVisibleToUserIfNeeded(List<AccessibilityNodeInfo> infos,
+ Region interactiveRegion) {
+ if (interactiveRegion == null || infos == null) {
+ return;
+ }
+ final int infoCount = infos.size();
+ for (int i = 0; i < infoCount; i++) {
+ AccessibilityNodeInfo info = infos.get(i);
+ adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
+ }
+ }
+
+ private void adjustIsVisibleToUserIfNeeded(AccessibilityNodeInfo info,
+ Region interactiveRegion) {
+ if (interactiveRegion == null || info == null) {
+ return;
+ }
+ Rect boundsInScreen = mTempRect;
+ info.getBoundsInScreen(boundsInScreen);
+ if (interactiveRegion.quickReject(boundsInScreen)) {
+ info.setVisibleToUser(false);
+ }
+ }
+
private void applyAppScaleAndMagnificationSpecIfNeeded(AccessibilityNodeInfo info,
MagnificationSpec spec) {
if (info == null) {
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 964b054..0701b53 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -660,8 +660,96 @@ public class KeyEvent extends InputEvent implements Parcelable {
/** Key code constant: Voice Assist key.
* Launches the global voice assist activity. Not delivered to applications. */
public static final int KEYCODE_VOICE_ASSIST = 231;
-
- private static final int LAST_KEYCODE = KEYCODE_VOICE_ASSIST;
+ /** Key code constant: Radio key.
+ * Toggles TV service / Radio service. */
+ public static final int KEYCODE_TV_RADIO_SERVICE = 232;
+ /** Key code constant: Teletext key.
+ * Displays Teletext service. */
+ public static final int KEYCODE_TV_TELETEXT = 233;
+ /** Key code constant: Number entry key.
+ * Initiates to enter multi-digit channel nubmber when each digit key is assigned
+ * for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC
+ * User Control Code. */
+ public static final int KEYCODE_TV_NUMBER_ENTRY = 234;
+ /** Key code constant: Analog Terrestrial key.
+ * Switches to analog terrestrial broadcast service. */
+ public static final int KEYCODE_TV_TERRESTRIAL_ANALOG = 235;
+ /** Key code constant: Digital Terrestrial key.
+ * Switches to digital terrestrial broadcast service. */
+ public static final int KEYCODE_TV_TERRESTRIAL_DIGITAL = 236;
+ /** Key code constant: Satellite key.
+ * Switches to digital satellite broadcast service. */
+ public static final int KEYCODE_TV_SATELLITE = 237;
+ /** Key code constant: BS key.
+ * Switches to BS digital satellite broadcasting service available in Japan. */
+ public static final int KEYCODE_TV_SATELLITE_BS = 238;
+ /** Key code constant: CS key.
+ * Switches to CS digital satellite broadcasting service available in Japan. */
+ public static final int KEYCODE_TV_SATELLITE_CS = 239;
+ /** Key code constant: BS/CS key.
+ * Toggles between BS and CS digital satellite services. */
+ public static final int KEYCODE_TV_SATELLITE_SERVICE = 240;
+ /** Key code constant: Toggle Network key.
+ * Toggles selecting broacast services. */
+ public static final int KEYCODE_TV_NETWORK = 241;
+ /** Key code constant: Antenna/Cable key.
+ * Toggles broadcast input source between antenna and cable. */
+ public static final int KEYCODE_TV_ANTENNA_CABLE = 242;
+ /** Key code constant: HDMI #1 key.
+ * Switches to HDMI input #1. */
+ public static final int KEYCODE_TV_INPUT_HDMI_1 = 243;
+ /** Key code constant: HDMI #2 key.
+ * Switches to HDMI input #2. */
+ public static final int KEYCODE_TV_INPUT_HDMI_2 = 244;
+ /** Key code constant: HDMI #3 key.
+ * Switches to HDMI input #3. */
+ public static final int KEYCODE_TV_INPUT_HDMI_3 = 245;
+ /** Key code constant: HDMI #4 key.
+ * Switches to HDMI input #4. */
+ public static final int KEYCODE_TV_INPUT_HDMI_4 = 246;
+ /** Key code constant: Composite #1 key.
+ * Switches to composite video input #1. */
+ public static final int KEYCODE_TV_INPUT_COMPOSITE_1 = 247;
+ /** Key code constant: Composite #2 key.
+ * Switches to composite video input #2. */
+ public static final int KEYCODE_TV_INPUT_COMPOSITE_2 = 248;
+ /** Key code constant: Component #1 key.
+ * Switches to component video input #1. */
+ public static final int KEYCODE_TV_INPUT_COMPONENT_1 = 249;
+ /** Key code constant: Component #2 key.
+ * Switches to component video input #2. */
+ public static final int KEYCODE_TV_INPUT_COMPONENT_2 = 250;
+ /** Key code constant: VGA #1 key.
+ * Switches to VGA (analog RGB) input #1. */
+ public static final int KEYCODE_TV_INPUT_VGA_1 = 251;
+ /** Key code constant: Audio description key.
+ * Toggles audio description off / on. */
+ public static final int KEYCODE_TV_AUDIO_DESCRIPTION = 252;
+ /** Key code constant: Audio description mixing volume up key.
+ * Louden audio description volume as compared with normal audio volume. */
+ public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253;
+ /** Key code constant: Audio description mixing volume down key.
+ * Lessen audio description volume as compared with normal audio volume. */
+ public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254;
+ /** Key code constant: Zoom mode key.
+ * Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.) */
+ public static final int KEYCODE_TV_ZOOM_MODE = 255;
+ /** Key code constant: Contents menu key.
+ * Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control
+ * Code */
+ public static final int KEYCODE_TV_CONTENTS_MENU = 256;
+ /** Key code constant: Media context menu key.
+ * Goes to the context menu of media contents. Corresponds to Media Context-sensitive
+ * Menu (0x11) of CEC User Control Code. */
+ public static final int KEYCODE_TV_MEDIA_CONTEXT_MENU = 257;
+ /** Key code constant: Timer programming key.
+ * Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of
+ * CEC User Control Code. */
+ public static final int KEYCODE_TV_TIMER_PROGRAMMING = 258;
+ /** Key code constant: Help key. */
+ public static final int KEYCODE_HELP = 259;
+
+ private static final int LAST_KEYCODE = KEYCODE_HELP;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 063a08d..7dcad68 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -149,9 +149,9 @@ public final class PointerIcon implements Parcelable {
* Creates a custom pointer from the given bitmap and hotspot information.
*
* @param bitmap The bitmap for the icon.
- * @param hotspotX The X offset of the pointer icon hotspot in the bitmap.
+ * @param hotSpotX The X offset of the pointer icon hotspot in the bitmap.
* Must be within the [0, bitmap.getWidth()) range.
- * @param hotspotY The Y offset of the pointer icon hotspot in the bitmap.
+ * @param hotSpotY The Y offset of the pointer icon hotspot in the bitmap.
* Must be within the [0, bitmap.getHeight()) range.
* @return A pointer icon for this bitmap.
*
@@ -374,18 +374,18 @@ public final class PointerIcon implements Parcelable {
}
private void loadResource(Context context, Resources resources, int resourceId) {
- XmlResourceParser parser = resources.getXml(resourceId);
+ final XmlResourceParser parser = resources.getXml(resourceId);
final int bitmapRes;
final float hotSpotX;
final float hotSpotY;
try {
XmlUtils.beginDocument(parser, "pointer-icon");
- TypedArray a = resources.obtainAttributes(
+ final TypedArray a = resources.obtainAttributes(
parser, com.android.internal.R.styleable.PointerIcon);
bitmapRes = a.getResourceId(com.android.internal.R.styleable.PointerIcon_bitmap, 0);
- hotSpotX = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0);
- hotSpotY = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0);
+ hotSpotX = a.getDimension(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0);
+ hotSpotY = a.getDimension(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0);
a.recycle();
} catch (Exception ex) {
throw new IllegalArgumentException("Exception parsing pointer icon resource.", ex);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index ca08ecc..5d2822d 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -126,7 +126,7 @@ public class ThreadedRenderer extends HardwareRenderer {
void destroy() {
mInitialized = false;
updateEnabledState(null);
- nDestroyCanvasAndSurface(mNativeProxy);
+ nDestroy(mNativeProxy);
}
private void updateEnabledState(Surface surface) {
@@ -488,7 +488,7 @@ public class ThreadedRenderer extends HardwareRenderer {
private static native void nSetOpaque(long nativeProxy, boolean opaque);
private static native int nSyncAndDrawFrame(long nativeProxy,
long frameTimeNanos, long recordDuration, float density);
- private static native void nDestroyCanvasAndSurface(long nativeProxy);
+ private static native void nDestroy(long nativeProxy);
private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fce6f0b..92ad4e8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -444,16 +444,19 @@ import java.util.concurrent.atomic.AtomicInteger;
* <a name="Drawing"></a>
* <h3>Drawing</h3>
* <p>
- * Drawing is handled by walking the tree and rendering each view that
- * intersects the invalid region. Because the tree is traversed in-order,
- * this means that parents will draw before (i.e., behind) their children, with
- * siblings drawn in the order they appear in the tree.
- * If you set a background drawable for a View, then the View will draw it for you
- * before calling back to its <code>onDraw()</code> method.
+ * Drawing is handled by walking the tree and recording the drawing commands of
+ * any View that needs to update. After this, the drawing commands of the
+ * entire tree are issued to screen, clipped to the newly damaged area.
* </p>
*
* <p>
- * Note that the framework will not draw views that are not in the invalid region.
+ * The tree is largely recorded and drawn in order, with parents drawn before
+ * (i.e., behind) their children, with siblings drawn in the order they appear
+ * in the tree. If you set a background drawable for a View, then the View will
+ * draw it before calling back to its <code>onDraw()</code> method. The child
+ * drawing order can be overridden with
+ * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
+ * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
* </p>
*
* <p>
@@ -4908,36 +4911,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
onFocusChanged(true, direction, previouslyFocusedRect);
- manageFocusHotspot(true, oldFocus);
refreshDrawableState();
}
}
/**
- * Forwards focus information to the background drawable, if necessary. When
- * the view is gaining focus, <code>v</code> is the previous focus holder.
- * When the view is losing focus, <code>v</code> is the next focus holder.
- *
- * @param focused whether this view is focused
- * @param v previous or the next focus holder, or null if none
- */
- private void manageFocusHotspot(boolean focused, View v) {
- final Rect r = new Rect();
- if (v != null && mAttachInfo != null) {
- v.getHotspotBounds(r);
- final int[] location = mAttachInfo.mTmpLocation;
- getLocationOnScreen(location);
- r.offset(-location[0], -location[1]);
- } else {
- r.set(0, 0, mRight - mLeft, mBottom - mTop);
- }
-
- final float x = r.exactCenterX();
- final float y = r.exactCenterY();
- drawableHotspotChanged(x, y);
- }
-
- /**
* Populates <code>outRect</code> with the hotspot bounds. By default,
* the hotspot bounds are identical to the screen bounds.
*
@@ -5060,8 +5038,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
onFocusChanged(false, 0, null);
-
- manageFocusHotspot(false, focused);
refreshDrawableState();
if (propagate && (!refocus || !rootViewRequestFocus())) {
@@ -10852,6 +10828,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Sets whether the View's Outline should be used to clip the contents of the View.
* <p>
+ * Only a single non-rectangular clip can be applied on a View at any time.
+ * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
+ * circular reveal} animation take priority over Outline clipping, and
+ * child Outline clipping takes priority over Outline clipping done by a
+ * parent.
+ * <p>
* Note that this flag will only be respected if the View's Outline returns true from
* {@link Outline#canClip()}.
*
@@ -15118,10 +15100,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
}
+ canvas.save();
canvas.translate(mScrollX, mScrollY);
+ canvas.clipRect(bounds, Region.Op.REPLACE);
drawable.setBounds(bounds);
drawable.draw(canvas);
- canvas.translate(-mScrollX, -mScrollY);
+ canvas.restore();
}
/**
diff --git a/core/java/android/view/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java
index 7ced088..001cd01 100644
--- a/core/java/android/view/ViewAnimationUtils.java
+++ b/core/java/android/view/ViewAnimationUtils.java
@@ -27,9 +27,13 @@ public final class ViewAnimationUtils {
private ViewAnimationUtils() {}
/**
* Returns an Animator which can animate a clipping circle.
- *
+ * <p>
* Any shadow cast by the View will respect the circular clip from this animator.
- *
+ * <p>
+ * Only a single non-rectangular clip can be applied on a View at any time.
+ * Views clipped by a circular reveal animation take priority over
+ * {@link View#setClipToOutline(boolean) View Outline clipping}.
+ * <p>
* Note that the animation returned here is a one-shot animation. It cannot
* be re-used, and once started it cannot be paused or resumed.
*
@@ -39,7 +43,7 @@ public final class ViewAnimationUtils {
* @param startRadius The starting radius of the animating circle.
* @param endRadius The ending radius of the animating circle.
*/
- public static final Animator createCircularReveal(View view,
+ public static Animator createCircularReveal(View view,
int centerX, int centerY, float startRadius, float endRadius) {
return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index adad082..974fe4e 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5034,6 +5034,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
/**
* Tells the ViewGroup whether to draw its children in the order defined by the method
* {@link #getChildDrawingOrder(int, int)}.
+ * <p>
+ * Note that {@link View#getZ() Z} reordering, done by {@link #dispatchDraw(Canvas)},
+ * will override custom child ordering done via this method.
*
* @param enabled true if the order of the children when drawing is determined by
* {@link #getChildDrawingOrder(int, int)}, false otherwise
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 49d925f..4299e2e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -6111,6 +6111,33 @@ public final class ViewRootImpl implements ViewParent,
}
}
} break;
+
+
+ case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
+ if (mAccessibilityFocusedHost != null && mAccessibilityFocusedVirtualView != null) {
+ // We care only for changes rooted in the focused host.
+ final long eventSourceId = event.getSourceNodeId();
+ final int hostViewId = AccessibilityNodeInfo.getAccessibilityViewId(
+ eventSourceId);
+ if (hostViewId != mAccessibilityFocusedHost.getAccessibilityViewId()) {
+ break;
+ }
+
+ // We only care about changes that may change the virtual focused view bounds.
+ final int changes = event.getContentChangeTypes();
+ if ((changes & AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) != 0
+ || changes == AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED) {
+ AccessibilityNodeProvider provider = mAccessibilityFocusedHost
+ .getAccessibilityNodeProvider();
+ if (provider != null) {
+ final int virtualChildId = AccessibilityNodeInfo.getVirtualDescendantId(
+ mAccessibilityFocusedVirtualView.getSourceNodeId());
+ mAccessibilityFocusedVirtualView = provider.createAccessibilityNodeInfo(
+ virtualChildId);
+ }
+ }
+ }
+ } break;
}
mAccessibilityManager.sendAccessibilityEvent(event);
return true;
@@ -6629,14 +6656,15 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
- int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+ Region interactiveRegion, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags,
int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
.findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId,
- interactionId, callback, flags, interrogatingPid, interrogatingTid,
- spec);
+ interactiveRegion, interactionId, callback, flags, interrogatingPid,
+ interrogatingTid, spec);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
@@ -6669,15 +6697,15 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
- String viewId, int interactionId,
+ String viewId, Region interactiveRegion, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
.findAccessibilityNodeInfosByViewIdClientThread(accessibilityNodeId,
- viewId, interactionId, callback, flags, interrogatingPid,
- interrogatingTid, spec);
+ viewId, interactiveRegion, interactionId, callback, flags,
+ interrogatingPid, interrogatingTid, spec);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
@@ -6690,14 +6718,15 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
- int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+ Region interactiveRegion, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags,
int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
.findAccessibilityNodeInfosByTextClientThread(accessibilityNodeId, text,
- interactionId, callback, flags, interrogatingPid, interrogatingTid,
- spec);
+ interactiveRegion, interactionId, callback, flags, interrogatingPid,
+ interrogatingTid, spec);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
@@ -6709,14 +6738,15 @@ public final class ViewRootImpl implements ViewParent,
}
@Override
- public void findFocus(long accessibilityNodeId, int focusType, int interactionId,
- IAccessibilityInteractionConnectionCallback callback, int flags,
+ public void findFocus(long accessibilityNodeId, int focusType, Region interactiveRegion,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
- .findFocusClientThread(accessibilityNodeId, focusType, interactionId, callback,
- flags, interrogatingPid, interrogatingTid, spec);
+ .findFocusClientThread(accessibilityNodeId, focusType, interactiveRegion,
+ interactionId, callback, flags, interrogatingPid, interrogatingTid,
+ spec);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
@@ -6728,14 +6758,15 @@ public final class ViewRootImpl implements ViewParent,
}
@Override
- public void focusSearch(long accessibilityNodeId, int direction, int interactionId,
- IAccessibilityInteractionConnectionCallback callback, int flags,
+ public void focusSearch(long accessibilityNodeId, int direction, Region interactiveRegion,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
- .focusSearchClientThread(accessibilityNodeId, direction, interactionId,
- callback, flags, interrogatingPid, interrogatingTid, spec);
+ .focusSearchClientThread(accessibilityNodeId, direction, interactiveRegion,
+ interactionId, callback, flags, interrogatingPid, interrogatingTid,
+ spec);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 9b6f200..ebc683a 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1430,7 +1430,9 @@ public abstract class Window {
* {@link android.transition.Visibility} as entering is governed by changing visibility from
* {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null,
* entering Views will remain unaffected.
+ *
* @param transition The Transition to use to move Views into the initial Scene.
+ * @attr ref android.R.styleable#Window_windowEnterTransition
*/
public void setEnterTransition(Transition transition) {}
@@ -1444,8 +1446,10 @@ public abstract class Window {
* {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null,
* entering Views will remain unaffected. If nothing is set, the default will be to
* use the same value as set in {@link #setEnterTransition(android.transition.Transition)}.
+ *
* @param transition The Transition to use to move Views out of the Scene when the Window
* is preparing to close.
+ * @attr ref android.R.styleable#Window_windowReturnTransition
*/
public void setReturnTransition(Transition transition) {}
@@ -1456,8 +1460,10 @@ public abstract class Window {
* {@link android.transition.Visibility} as exiting is governed by changing visibility
* from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
* remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
* @param transition The Transition to use to move Views out of the scene when calling a
* new Activity.
+ * @attr ref android.R.styleable#Window_windowExitTransition
*/
public void setExitTransition(Transition transition) {}
@@ -1470,8 +1476,10 @@ public abstract class Window {
* the views will remain unaffected. If nothing is set, the default will be to use the same
* transition as {@link #setExitTransition(android.transition.Transition)}.
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
* @param transition The Transition to use to move Views into the scene when reentering from a
* previously-started Activity.
+ * @attr ref android.R.styleable#Window_windowReenterTransition
*/
public void setReenterTransition(Transition transition) {}
@@ -1484,6 +1492,7 @@ public abstract class Window {
* entering Views will remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
*
* @return the Transition to use to move Views into the initial Scene.
+ * @attr ref android.R.styleable#Window_windowEnterTransition
*/
public Transition getEnterTransition() { return null; }
@@ -1495,8 +1504,10 @@ public abstract class Window {
* {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
* {@link android.transition.Visibility} as entering is governed by changing visibility from
* {@link View#VISIBLE} to {@link View#INVISIBLE}.
+ *
* @return The Transition to use to move Views out of the Scene when the Window
* is preparing to close.
+ * @attr ref android.R.styleable#Window_windowReturnTransition
*/
public Transition getReturnTransition() { return null; }
@@ -1507,8 +1518,10 @@ public abstract class Window {
* {@link android.transition.Visibility} as exiting is governed by changing visibility
* from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
* remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
* @return the Transition to use to move Views out of the scene when calling a
* new Activity.
+ * @attr ref android.R.styleable#Window_windowExitTransition
*/
public Transition getExitTransition() { return null; }
@@ -1519,8 +1532,10 @@ public abstract class Window {
* will extend {@link android.transition.Visibility} as exiting is governed by changing
* visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}.
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
* @return The Transition to use to move Views into the scene when reentering from a
* previously-started Activity.
+ * @attr ref android.R.styleable#Window_windowReenterTransition
*/
public Transition getReenterTransition() { return null; }
@@ -1530,8 +1545,10 @@ public abstract class Window {
* {@link android.transition.ChangeBounds}. A null
* value will cause transferred shared elements to blink to the final position.
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
* @param transition The Transition to use for shared elements transferred into the content
* Scene.
+ * @attr ref android.R.styleable#Window_windowSharedElementEnterTransition
*/
public void setSharedElementEnterTransition(Transition transition) {}
@@ -1543,22 +1560,28 @@ public abstract class Window {
* If no value is set, the default will be to use the same value as
* {@link #setSharedElementEnterTransition(android.transition.Transition)}.
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
* @param transition The Transition to use for shared elements transferred out of the content
* Scene.
+ * @attr ref android.R.styleable#Window_windowSharedElementReturnTransition
*/
public void setSharedElementReturnTransition(Transition transition) {}
/**
* Returns the Transition that will be used for shared elements transferred into the content
* Scene. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
* @return Transition to use for sharend elements transferred into the content Scene.
+ * @attr ref android.R.styleable#Window_windowSharedElementEnterTransition
*/
public Transition getSharedElementEnterTransition() { return null; }
/**
* Returns the Transition that will be used for shared elements transferred back to a
* calling Activity. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
* @return Transition to use for sharend elements transferred into the content Scene.
+ * @attr ref android.R.styleable#Window_windowSharedElementReturnTransition
*/
public Transition getSharedElementReturnTransition() { return null; }
@@ -1568,8 +1591,10 @@ public abstract class Window {
* must animate during the exit transition, this Transition should be used. Upon completion,
* the shared elements may be transferred to the started Activity.
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
* @param transition The Transition to use for shared elements in the launching Window
* prior to transferring to the launched Activity's Window.
+ * @attr ref android.R.styleable#Window_windowSharedElementExitTransition
*/
public void setSharedElementExitTransition(Transition transition) {}
@@ -1579,8 +1604,10 @@ public abstract class Window {
* is set, this will default to
* {@link #setSharedElementExitTransition(android.transition.Transition)}.
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
* @param transition The Transition to use for shared elements in the launching Window
* after the shared element has returned to the Window.
+ * @attr ref android.R.styleable#Window_windowSharedElementReenterTransition
*/
public void setSharedElementReenterTransition(Transition transition) {}
@@ -1591,6 +1618,7 @@ public abstract class Window {
*
* @return the Transition to use for shared elements in the launching Window prior
* to transferring to the launched Activity's Window.
+ * @attr ref android.R.styleable#Window_windowSharedElementExitTransition
*/
public Transition getSharedElementExitTransition() { return null; }
@@ -1601,6 +1629,7 @@ public abstract class Window {
*
* @return the Transition that will be used for shared elements reentering from a started
* Activity after it has returned the shared element to it start location.
+ * @attr ref android.R.styleable#Window_windowSharedElementReenterTransition
*/
public Transition getSharedElementReenterTransition() { return null; }
@@ -1610,8 +1639,10 @@ public abstract class Window {
* transition of the calling Activity. When true, the transition will start as soon as possible.
* When false, the transition will wait until the remote exiting transition completes before
* starting.
+ *
* @param allow true to start the enter transition when possible or false to
* wait until the exiting transition completes.
+ * @attr ref android.R.styleable#Window_windowAllowEnterTransitionOverlap
*/
public void setAllowEnterTransitionOverlap(boolean allow) {}
@@ -1621,8 +1652,10 @@ public abstract class Window {
* transition of the calling Activity. When true, the transition will start as soon as possible.
* When false, the transition will wait until the remote exiting transition completes before
* starting.
+ *
* @return true when the enter transition should start as soon as possible or false to
* when it should wait until the exiting transition completes.
+ * @attr ref android.R.styleable#Window_windowAllowEnterTransitionOverlap
*/
public boolean getAllowEnterTransitionOverlap() { return true; }
@@ -1632,10 +1665,20 @@ public abstract class Window {
* transition of the called Activity when reentering after if finishes. When true,
* the transition will start as soon as possible. When false, the transition will wait
* until the called Activity's exiting transition completes before starting.
+ *
* @param allow true to start the transition when possible or false to wait until the
* called Activity's exiting transition completes.
+ * @attr ref android.R.styleable#Window_windowAllowReturnTransitionOverlap
*/
- public void setAllowExitTransitionOverlap(boolean allow) {}
+ public void setAllowReturnTransitionOverlap(boolean allow) {}
+
+ /**
+ * TODO: remove this.
+ * @hide
+ */
+ public void setAllowExitTransitionOverlap(boolean allow) {
+ setAllowReturnTransitionOverlap(allow);
+ }
/**
* Returns how the transition set in
@@ -1643,10 +1686,18 @@ public abstract class Window {
* transition of the called Activity when reentering after if finishes. When true,
* the transition will start as soon as possible. When false, the transition will wait
* until the called Activity's exiting transition completes before starting.
+ *
* @return true when the transition should start when possible or false when it should wait
* until the called Activity's exiting transition completes.
+ * @attr ref android.R.styleable#Window_windowAllowReturnTransitionOverlap
*/
- public boolean getAllowExitTransitionOverlap() { return true; }
+ public boolean getAllowReturnTransitionOverlap() { return true; }
+
+ /**
+ * TODO: remove this.
+ * @hide
+ */
+ public boolean getAllowExitTransitionOverlap() { return getAllowReturnTransitionOverlap(); }
/**
* Returns the duration, in milliseconds, of the window background fade
@@ -1654,8 +1705,10 @@ public abstract class Window {
* <p>When executing the enter transition, the background starts transparent
* and fades in. This requires {@link #FEATURE_CONTENT_TRANSITIONS}. The default is
* 300 milliseconds.</p>
+ *
* @return The duration of the window background fade to opaque during enter transition.
* @see #getEnterTransition()
+ * @attr ref android.R.styleable#Window_windowTransitionBackgroundFadeDuration
*/
public long getTransitionBackgroundFadeDuration() { return 0; }
@@ -1665,9 +1718,11 @@ public abstract class Window {
* <p>When executing the enter transition, the background starts transparent
* and fades in. This requires {@link #FEATURE_CONTENT_TRANSITIONS}. The default is
* 300 milliseconds.</p>
+ *
* @param fadeDurationMillis The duration of the window background fade to or from opaque
* during enter transition.
* @see #setEnterTransition(android.transition.Transition)
+ * @attr ref android.R.styleable#Window_windowTransitionBackgroundFadeDuration
*/
public void setTransitionBackgroundFadeDuration(long fadeDurationMillis) { }
@@ -1679,6 +1734,7 @@ public abstract class Window {
* @return <code>true</code> when shared elements should use an Overlay during
* shared element transitions or <code>false</code> when they should animate as
* part of the normal View hierarchy.
+ * @attr ref android.R.styleable#Window_windowSharedElementsUseOverlay
*/
public boolean getSharedElementsUseOverlay() { return true; }
@@ -1689,6 +1745,7 @@ public abstract class Window {
* @param sharedElementsUseOverlay <code>true</code> indicates that shared elements should
* be transitioned with an Overlay or <code>false</code>
* to transition within the normal View hierarchy.
+ * @attr ref android.R.styleable#Window_windowSharedElementsUseOverlay
*/
public void setSharedElementsUseOverlay(boolean sharedElementsUseOverlay) { }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 053fdd0..b7b12a8 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -379,6 +379,10 @@ public interface WindowManagerPolicy {
public static final int LID_CLOSED = 0;
public static final int LID_OPEN = 1;
+ public static final int CAMERA_LENS_COVER_ABSENT = -1;
+ public static final int CAMERA_LENS_UNCOVERED = 0;
+ public static final int CAMERA_LENS_COVERED = 1;
+
/**
* Ask the window manager to re-evaluate the system UI flags.
*/
@@ -399,6 +403,11 @@ public interface WindowManagerPolicy {
public int getLidState();
/**
+ * Returns a code that descripbes whether the camera lens is covered or not.
+ */
+ public int getCameraLensCoverState();
+
+ /**
* Switch the keyboard layout for the given device.
* Direction should be +1 or -1 to go to the next or previous keyboard layout.
*/
@@ -951,7 +960,14 @@ public interface WindowManagerPolicy {
* @param lidOpen True if the lid is now open.
*/
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
-
+
+ /**
+ * Tell the policy that the camera lens has been covered or uncovered.
+ * @param whenNanos The time when the change occurred in uptime nanoseconds.
+ * @param lensCovered True if the lens is covered.
+ */
+ public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
+
/**
* Tell the policy if anyone is requesting that keyguard not come on.
*
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 8d15472..faf7789 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -16,6 +16,7 @@
package android.view.accessibility;
+import android.graphics.Region;
import android.os.Bundle;
import android.view.MagnificationSpec;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -29,23 +30,23 @@ import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
*/
oneway interface IAccessibilityInteractionConnection {
- void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int interactionId,
- IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
- long interrogatingTid, in MagnificationSpec spec);
+ void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, in Region bounds,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+ int interrogatingPid, long interrogatingTid, in MagnificationSpec spec);
void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, String viewId,
+ in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+ int flags, int interrogatingPid, long interrogatingTid, in MagnificationSpec spec);
+
+ void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, in Region bounds,
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
int interrogatingPid, long interrogatingTid, in MagnificationSpec spec);
- void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int interactionId,
- IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
- long interrogatingTid, in MagnificationSpec spec);
-
- void findFocus(long accessibilityNodeId, int focusType, int interactionId,
+ void findFocus(long accessibilityNodeId, int focusType, in Region bounds, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
long interrogatingTid, in MagnificationSpec spec);
- void focusSearch(long accessibilityNodeId, int direction, int interactionId,
+ void focusSearch(long accessibilityNodeId, int direction, in Region bounds, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
long interrogatingTid, in MagnificationSpec spec);
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 4d2f57a..20adfe4 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -431,7 +431,15 @@ public class BaseInputConnection implements InputConnection {
/**
* The default implementation does nothing.
*/
- public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+ public boolean requestCursorUpdates(int cursorUpdateMode) {
+ return false;
+ }
+
+ /**
+ * The default implementation does nothing.
+ * @removed
+ */
+ public final boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
return false;
}
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
index 0492824..fe0f5b9 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfo.java
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -45,9 +45,9 @@ public final class CursorAnchorInfo implements Parcelable {
private final CharSequence mComposingText;
/**
- * {@code True} if the insertion marker is partially or entirely clipped by other UI elements.
+ * Flags of the insertion marker. See {@link #FLAG_HAS_VISIBLE_REGION} for example.
*/
- private final boolean mInsertionMarkerClipped;
+ private final int mInsertionMarkerFlags;
/**
* Horizontal position of the insertion marker, in the local coordinates that will be
* transformed with the transformation matrix when rendered on the screen. This should be
@@ -90,27 +90,47 @@ public final class CursorAnchorInfo implements Parcelable {
*/
private final Matrix mMatrix;
+ /**
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+ * insertion marker or character bounds have at least one visible region.
+ */
+ public static final int FLAG_HAS_VISIBLE_REGION = 0x01;
+
+ /**
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+ * insertion marker or character bounds have at least one invisible (clipped) region.
+ */
+ public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
+
+ /**
+ * @removed
+ */
public static final int CHARACTER_RECT_TYPE_MASK = 0x0f;
/**
* Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor did not specify any type of this
* character. Editor authors should not use this flag.
+ * @removed
*/
public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0;
/**
* Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely visible.
+ * @removed
*/
public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1;
/**
* Type for {@link #CHARACTER_RECT_TYPE_MASK}: some area of the character is invisible.
+ * @removed
*/
public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2;
/**
* Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely invisible.
+ * @removed
*/
public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3;
/**
* Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor gave up to calculate the rectangle
* for this character. Input method authors should ignore the returned rectangle.
+ * @removed
*/
public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4;
@@ -119,7 +139,7 @@ public final class CursorAnchorInfo implements Parcelable {
mSelectionEnd = source.readInt();
mComposingTextStart = source.readInt();
mComposingText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- mInsertionMarkerClipped = (source.readInt() != 0);
+ mInsertionMarkerFlags = source.readInt();
mInsertionMarkerHorizontal = source.readFloat();
mInsertionMarkerTop = source.readFloat();
mInsertionMarkerBaseline = source.readFloat();
@@ -141,7 +161,7 @@ public final class CursorAnchorInfo implements Parcelable {
dest.writeInt(mSelectionEnd);
dest.writeInt(mComposingTextStart);
TextUtils.writeToParcel(mComposingText, dest, flags);
- dest.writeInt(mInsertionMarkerClipped ? 1 : 0);
+ dest.writeInt(mInsertionMarkerFlags);
dest.writeFloat(mInsertionMarkerHorizontal);
dest.writeFloat(mInsertionMarkerTop);
dest.writeFloat(mInsertionMarkerBaseline);
@@ -159,7 +179,7 @@ public final class CursorAnchorInfo implements Parcelable {
+ mInsertionMarkerBaseline + mInsertionMarkerBottom;
int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
hash *= 31;
- hash += (mInsertionMarkerClipped ? 2 : 1);
+ hash += mInsertionMarkerFlags;
hash *= 31;
hash += mSelectionStart + mSelectionEnd + mComposingTextStart;
hash *= 31;
@@ -204,7 +224,7 @@ public final class CursorAnchorInfo implements Parcelable {
|| !Objects.equals(mComposingText, that.mComposingText)) {
return false;
}
- if (mInsertionMarkerClipped != that.mInsertionMarkerClipped
+ if (mInsertionMarkerFlags != that.mInsertionMarkerFlags
|| !areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal)
|| !areSameFloatImpl(mInsertionMarkerTop, that.mInsertionMarkerTop)
|| !areSameFloatImpl(mInsertionMarkerBaseline, that.mInsertionMarkerBaseline)
@@ -225,7 +245,7 @@ public final class CursorAnchorInfo implements Parcelable {
return "SelectionInfo{mSelection=" + mSelectionStart + "," + mSelectionEnd
+ " mComposingTextStart=" + mComposingTextStart
+ " mComposingText=" + Objects.toString(mComposingText)
- + " mInsertionMarkerClipped=" + mInsertionMarkerClipped
+ + " mInsertionMarkerFlags=" + mInsertionMarkerFlags
+ " mInsertionMarkerHorizontal=" + mInsertionMarkerHorizontal
+ " mInsertionMarkerTop=" + mInsertionMarkerTop
+ " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
@@ -272,6 +292,20 @@ public final class CursorAnchorInfo implements Parcelable {
private CharSequence mComposingText = null;
/**
+ * @removed
+ */
+ public Builder setInsertionMarkerLocation(final float horizontalPosition,
+ final float lineTop, final float lineBaseline, final float lineBottom,
+ final boolean clipped){
+ mInsertionMarkerHorizontal = horizontalPosition;
+ mInsertionMarkerTop = lineTop;
+ mInsertionMarkerBaseline = lineBaseline;
+ mInsertionMarkerBottom = lineBottom;
+ mInsertionMarkerFlags = clipped ? FLAG_HAS_INVISIBLE_REGION : 0;
+ return this;
+ }
+
+ /**
* Sets the location of the text insertion point (zero width cursor) as a rectangle in
* local coordinates. Calling this can be skipped when there is no text insertion point;
* however if there is an insertion point, editors must call this method.
@@ -288,24 +322,24 @@ public final class CursorAnchorInfo implements Parcelable {
* @param lineBottom vertical position of the insertion marker, in the local coordinates
* that will be transformed with the transformation matrix when rendered on the screen. This
* should be calculated or compatible with {@link Layout#getLineBottom(int)}.
- * @param clipped {@code true} is the insertion marker is partially or entierly clipped by
- * other UI elements.
+ * @param flags flags of the insertion marker. See {@link #FLAG_HAS_VISIBLE_REGION} for
+ * example.
*/
public Builder setInsertionMarkerLocation(final float horizontalPosition,
final float lineTop, final float lineBaseline, final float lineBottom,
- final boolean clipped){
+ final int flags){
mInsertionMarkerHorizontal = horizontalPosition;
mInsertionMarkerTop = lineTop;
mInsertionMarkerBaseline = lineBaseline;
mInsertionMarkerBottom = lineBottom;
- mInsertionMarkerClipped = clipped;
+ mInsertionMarkerFlags = flags;
return this;
}
private float mInsertionMarkerHorizontal = Float.NaN;
private float mInsertionMarkerTop = Float.NaN;
private float mInsertionMarkerBaseline = Float.NaN;
private float mInsertionMarkerBottom = Float.NaN;
- private boolean mInsertionMarkerClipped = false;
+ private int mInsertionMarkerFlags = 0;
/**
* Adds the bounding box of the character specified with the index.
@@ -320,8 +354,8 @@ public final class CursorAnchorInfo implements Parcelable {
* coordinates, that is, right edge for LTR text and left edge for RTL text.
* @param trailingEdgeY y coordinate of the trailing edge of the character in local
* coordinates.
- * @param flags type and flags for this character. See
- * {@link #CHARACTER_RECT_TYPE_FULLY_VISIBLE} for example.
+ * @param flags flags for this character rect. See {@link #FLAG_HAS_VISIBLE_REGION} for
+ * example.
* @throws IllegalArgumentException If the index is a negative value, or not greater than
* all of the previously called indices.
*/
@@ -331,11 +365,6 @@ public final class CursorAnchorInfo implements Parcelable {
if (index < 0) {
throw new IllegalArgumentException("index must not be a negative integer.");
}
- final int type = flags & CHARACTER_RECT_TYPE_MASK;
- if (type == CHARACTER_RECT_TYPE_UNSPECIFIED) {
- throw new IllegalArgumentException("Type except for "
- + "CHARACTER_RECT_TYPE_UNSPECIFIED must be specified.");
- }
if (mCharacterRectBuilder == null) {
mCharacterRectBuilder = new SparseRectFArrayBuilder();
}
@@ -388,7 +417,7 @@ public final class CursorAnchorInfo implements Parcelable {
mSelectionEnd = -1;
mComposingTextStart = -1;
mComposingText = null;
- mInsertionMarkerClipped = false;
+ mInsertionMarkerFlags = 0;
mInsertionMarkerHorizontal = Float.NaN;
mInsertionMarkerTop = Float.NaN;
mInsertionMarkerBaseline = Float.NaN;
@@ -406,7 +435,7 @@ public final class CursorAnchorInfo implements Parcelable {
mSelectionEnd = builder.mSelectionEnd;
mComposingTextStart = builder.mComposingTextStart;
mComposingText = builder.mComposingText;
- mInsertionMarkerClipped = builder.mInsertionMarkerClipped;
+ mInsertionMarkerFlags = builder.mInsertionMarkerFlags;
mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal;
mInsertionMarkerTop = builder.mInsertionMarkerTop;
mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
@@ -449,11 +478,20 @@ public final class CursorAnchorInfo implements Parcelable {
}
/**
+ * Returns the flag of the insertion marker.
+ * @return the flag of the insertion marker. {@code 0} if no flag is specified.
+ */
+ public int getInsertionMarkerFlags() {
+ return mInsertionMarkerFlags;
+ }
+
+ /**
* Returns the visibility of the insertion marker.
* @return {@code true} if the insertion marker is partially or entirely clipped.
+ * @removed
*/
public boolean isInsertionMarkerClipped() {
- return mInsertionMarkerClipped;
+ return (mInsertionMarkerFlags & FLAG_HAS_VISIBLE_REGION) != 0;
}
/**
@@ -522,17 +560,17 @@ public final class CursorAnchorInfo implements Parcelable {
}
/**
- * Returns the flags associated with the character specified with the index.
+ * Returns the flags associated with the character rect specified with the index.
* @param index index of the character in a Java chars.
- * @return {@link #CHARACTER_RECT_TYPE_UNSPECIFIED} if no flag is specified.
+ * @return {@code 0} if no flag is specified.
*/
// TODO: Prepare a document about the expected behavior for surrogate pairs, combining
// characters, and non-graphical chars.
public int getCharacterRectFlags(final int index) {
if (mCharacterRects == null) {
- return CHARACTER_RECT_TYPE_UNSPECIFIED;
+ return 0;
}
- return mCharacterRects.getFlags(index, CHARACTER_RECT_TYPE_UNSPECIFIED);
+ return mCharacterRects.getFlags(index, 0);
}
/**
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index ca094c1..093fb2f 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -728,31 +728,47 @@ public interface InputConnection {
* The editor is requested to call
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at
* once, as soon as possible, regardless of cursor/anchor position changes. This flag can be
- * used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}.
+ * used together with {@link #CURSOR_UPDATE_MONITOR}.
*/
- public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1 << 0;
+ public static final int CURSOR_UPDATE_IMMEDIATE = 1 << 0;
/**
* The editor is requested to call
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}
* whenever cursor/anchor position is changed. To disable monitoring, call
- * {@link InputConnection#requestUpdateCursorAnchorInfo(int)} again with this flag off.
+ * {@link InputConnection#requestCursorUpdates(int)} again with this flag off.
* <p>
- * This flag can be used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE}.
+ * This flag can be used together with {@link #CURSOR_UPDATE_IMMEDIATE}.
* </p>
*/
- public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 1 << 1;
+ public static final int CURSOR_UPDATE_MONITOR = 1 << 1;
/**
* Called by the input method to ask the editor for calling back
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} to
* notify cursor/anchor locations.
*
- * @param cursorUpdateMode {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE} and/or
- * {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}
+ * @param cursorUpdateMode {@link #CURSOR_UPDATE_IMMEDIATE} and/or
+ * {@link #CURSOR_UPDATE_MONITOR}. Pass {@code 0} to disable the effect of
+ * {@link #CURSOR_UPDATE_MONITOR}.
* @return {@code true} if the request is scheduled. {@code false} to indicate that when the
* application will not call
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}.
*/
+ public boolean requestCursorUpdates(int cursorUpdateMode);
+
+ /**
+ * @removed
+ */
+ public static final int REQUEST_UPDATE_CURSOR_UPDATE_IMMEDIATE = 1 << 0;
+
+ /**
+ * @removed
+ */
+ public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 1 << 1;
+
+ /**
+ * @removed
+ */
public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode);
}
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index d95df25..87853de 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -126,7 +126,14 @@ public class InputConnectionWrapper implements InputConnection {
return mTarget.performPrivateCommand(action, data);
}
- public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
- return mTarget.requestUpdateCursorAnchorInfo(cursorUpdateMode);
+ public boolean requestCursorUpdates(int cursorUpdateMode) {
+ return mTarget.requestCursorUpdates(cursorUpdateMode);
}
- }
+
+ /**
+ * @removed
+ */
+ public final boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+ return mTarget.requestCursorUpdates(cursorUpdateMode);
+ }
+}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 0a472c7..b56378f 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1526,7 +1526,7 @@ public final class InputMethodManager {
* Return true if the current input method wants to watch the location
* of the input editor's cursor in its window.
*
- * @deprecated Use {@link InputConnection#requestUpdateCursorAnchorInfo(int)} instead.
+ * @deprecated Use {@link InputConnection#requestCursorUpdates(int)} instead.
*/
@Deprecated
public boolean isWatchingCursor(View view) {
@@ -1542,9 +1542,9 @@ public final class InputMethodManager {
public boolean isCursorAnchorInfoEnabled() {
synchronized (mH) {
final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
- InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
+ InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode &
- InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR) != 0;
+ InputConnection.CURSOR_UPDATE_MONITOR) != 0;
return isImmediate || isMonitoring;
}
}
@@ -1608,7 +1608,7 @@ public final class InputMethodManager {
// If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
// not been changed from the previous call.
final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
- InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
+ InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
// TODO: Consider always emitting this message once we have addressed redundant
// calls of this method from android.widget.Editor.
@@ -1624,7 +1624,7 @@ public final class InputMethodManager {
mCursorAnchorInfo = cursorAnchorInfo;
// Clear immediate bit (if any).
mRequestUpdateCursorAnchorInfoMonitorMode &=
- ~InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE;
+ ~InputConnection.CURSOR_UPDATE_IMMEDIATE;
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
diff --git a/core/java/android/webkit/WebResourceRequest.java b/core/java/android/webkit/WebResourceRequest.java
index dc7c808..b46ac9a 100644
--- a/core/java/android/webkit/WebResourceRequest.java
+++ b/core/java/android/webkit/WebResourceRequest.java
@@ -41,7 +41,7 @@ public interface WebResourceRequest {
boolean isForMainFrame();
/**
- * Gets whether a gesture was associated with the request.
+ * Gets whether a gesture (such as a link click) was associated with the request.
* <p>
* <strong>IMPORTANT:</strong>
* This should not be used to implement any form of security. It is possible for the content
@@ -49,6 +49,11 @@ public interface WebResourceRequest {
*
* @return whether a gesture was associated with the request.
*/
+ boolean hasGesture();
+
+ /*
+ * @removed
+ */
boolean hasUserGestureInsecure();
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index e1f19ee..081bfdf 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1810,21 +1810,6 @@ public class WebView extends AbsoluteLayout
}
/**
- * Sets whether the application wants to opt out from using the Data Reduction Proxy
- * service.
- * Data reduction proxy can only be enabled by the user and will almost always be
- * transparent to the application. In rare cases where using the proxy interferes
- * with the app, the application developer can use this API to opt out from using the
- * proxy. Note that this may increase network bandwidth usage.
- *
- * See <a href=http://developer.chrome.com/multidevice/data-compression>
- * Data Compression Proxy</a>
- */
- public static void optOutDataReductionProxy() {
- getFactory().getStatics().optOutDataReductionProxy();
- }
-
- /**
* Gets the list of currently loaded plugins.
*
* @return the list of currently loaded plugins
@@ -1954,16 +1939,14 @@ public class WebView extends AbsoluteLayout
*
* @param zoomFactor the zoom factor to apply. The zoom factor will be clamped to the Webview's
* zoom limits. This value must be in the range 0.01 to 100.0 inclusive.
- *
- * @return false if no zoom changes, true otherwise.
*/
- public boolean zoomBy(float zoomFactor) {
+ public void zoomBy(float zoomFactor) {
checkThread();
if (zoomFactor < 0.01)
throw new IllegalArgumentException("zoomFactor must be greater than 0.01.");
if (zoomFactor > 100.0)
throw new IllegalArgumentException("zoomFactor must be less than 100.");
- return mProvider.zoomBy(zoomFactor);
+ mProvider.zoomBy(zoomFactor);
}
/**
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 48f3ca3..20bb932 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -61,12 +61,6 @@ public interface WebViewFactoryProvider {
/**
* Implements the API method:
- * {@link android.webkit.WebView#optOutDataReductionProxy() }
- */
- void optOutDataReductionProxy();
-
- /**
- * Implements the API method:
* {@link android.webkit.WebView#setSlowWholeDocumentDrawEnabled(boolean) }
*/
void enableSlowWholeDocumentDraw();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index eb93745..eef8554 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -5717,8 +5717,16 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
@Override
+ public boolean requestCursorUpdates(int cursorUpdateMode) {
+ return getTarget().requestCursorUpdates(cursorUpdateMode);
+ }
+
+ /**
+ * @removed
+ */
+ @Override
public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
- return getTarget().requestUpdateCursorAnchorInfo(cursorUpdateMode);
+ return getTarget().requestCursorUpdates(cursorUpdateMode);
}
}
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 96abf51..6ca4a9e 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -29,6 +29,7 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.internal.view.menu.ActionMenuItemView;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.view.menu.MenuView;
/**
@@ -53,6 +54,8 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
private boolean mReserveOverflow;
private ActionMenuPresenter mPresenter;
+ private MenuPresenter.Callback mActionMenuPresenterCallback;
+ private MenuBuilder.Callback mMenuBuilderCallback;
private boolean mFormatItems;
private int mFormatItemsWidth;
private int mMinCellSize;
@@ -608,7 +611,8 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
mMenu = new MenuBuilder(context);
mMenu.setCallback(new MenuBuilderCallback());
mPresenter = new ActionMenuPresenter(context);
- mPresenter.setCallback(new ActionMenuPresenterCallback());
+ mPresenter.setCallback(mActionMenuPresenterCallback != null
+ ? mActionMenuPresenterCallback : new ActionMenuPresenterCallback());
mMenu.addMenuPresenter(mPresenter, mPopupContext);
mPresenter.setMenuView(this);
}
@@ -617,6 +621,15 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
}
/**
+ * Must be called before the first call to getMenu()
+ * @hide
+ */
+ public void setMenuCallbacks(MenuPresenter.Callback pcb, MenuBuilder.Callback mcb) {
+ mActionMenuPresenterCallback = pcb;
+ mMenuBuilderCallback = mcb;
+ }
+
+ /**
* Returns the current menu or null if one has not yet been configured.
* @hide Internal use only for action bar integration
*/
@@ -719,6 +732,9 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
@Override
public void onMenuModeChange(MenuBuilder menu) {
+ if (mMenuBuilderCallback != null) {
+ mMenuBuilderCallback.onMenuModeChange(menu);
+ }
}
}
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 1da22ca..b9f891c 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -297,10 +297,10 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
public boolean performItemClick(View view, int position, long id) {
if (mOnItemClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
+ mOnItemClickListener.onItemClick(this, view, position, id);
if (view != null) {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
}
- mOnItemClickListener.onItemClick(this, view, position, id);
return true;
}
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 26c1f96..2729bd0 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -71,9 +71,9 @@ import libcore.icu.ICU;
* @attr ref android.R.styleable#DatePicker_minDate
* @attr ref android.R.styleable#DatePicker_spinnersShown
* @attr ref android.R.styleable#DatePicker_calendarViewShown
- * @attr ref android.R.styleable#DatePicker_dayOfWeekBackgroundColor
+ * @attr ref android.R.styleable#DatePicker_dayOfWeekBackground
* @attr ref android.R.styleable#DatePicker_dayOfWeekTextAppearance
- * @attr ref android.R.styleable#DatePicker_headerBackgroundColor
+ * @attr ref android.R.styleable#DatePicker_headerBackground
* @attr ref android.R.styleable#DatePicker_headerMonthTextAppearance
* @attr ref android.R.styleable#DatePicker_headerDayOfMonthTextAppearance
* @attr ref android.R.styleable#DatePicker_headerYearTextAppearance
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 7df1fa3..eed49bf 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -21,7 +21,7 @@ import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.format.DateFormat;
@@ -149,16 +149,12 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
mDayOfWeekView.setTextAppearance(context, dayOfWeekTextAppearanceResId);
}
- final int dayOfWeekBackgroundColor = a.getColor(
- R.styleable.DatePicker_dayOfWeekBackgroundColor, Color.TRANSPARENT);
- mDayOfWeekView.setBackgroundColor(dayOfWeekBackgroundColor);
+ mDayOfWeekView.setBackground(a.getDrawable(R.styleable.DatePicker_dayOfWeekBackground));
+
+ dateLayout.setBackground(a.getDrawable(R.styleable.DatePicker_headerBackground));
final int headerSelectedTextColor = a.getColor(
R.styleable.DatePicker_headerSelectedTextColor, defaultHighlightColor);
- final int headerBackgroundColor = a.getColor(R.styleable.DatePicker_headerBackgroundColor,
- Color.TRANSPARENT);
- dateLayout.setBackgroundColor(headerBackgroundColor);
-
final int monthTextAppearanceResId = a.getResourceId(
R.styleable.DatePicker_headerMonthTextAppearance, -1);
if (monthTextAppearanceResId != -1) {
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 57b8dcb..033b99a 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -52,12 +52,15 @@ public class EdgeEffect {
private static final String TAG = "EdgeEffect";
// Time it will take the effect to fully recede in ms
- private static final int RECEDE_TIME = 1000;
+ private static final int RECEDE_TIME = 600;
// Time it will take before a pulled glow begins receding in ms
private static final int PULL_TIME = 167;
- private static final float MAX_ALPHA = 1.f;
+ // Time it will take in ms for a pulled glow to decay to partial strength before release
+ private static final int PULL_DECAY_TIME = 2000;
+
+ private static final float MAX_ALPHA = 0.5f;
private static final float MAX_GLOW_SCALE = 2.f;
@@ -93,12 +96,9 @@ public class EdgeEffect {
private static final int STATE_RECEDE = 3;
private static final int STATE_PULL_DECAY = 4;
- // How much dragging should effect the height of the glow image.
- // Number determined by user testing.
- private static final int PULL_DISTANCE_GLOW_FACTOR = 7;
- private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 1.1f;
+ private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 0.8f;
- private static final int VELOCITY_GLOW_FACTOR = 12;
+ private static final int VELOCITY_GLOW_FACTOR = 6;
private int mState = STATE_IDLE;
@@ -107,7 +107,7 @@ public class EdgeEffect {
private final Rect mBounds = new Rect();
private final Paint mPaint = new Paint();
private float mRadius;
- private float mBaseGlowHeight;
+ private float mBaseGlowScale;
private float mDisplacement = 0.5f;
private float mTargetDisplacement = 0.5f;
@@ -138,8 +138,12 @@ public class EdgeEffect {
final float r = width * 0.75f / SIN;
final float y = COS * r;
final float h = r - y;
+ final float or = height * 0.75f / SIN;
+ final float oy = COS * or;
+ final float oh = or - oy;
+
mRadius = r;
- mBaseGlowHeight = h;
+ mBaseGlowScale = h > 0 ? Math.min(oh / h, 1.f) : 1.f;
mBounds.set(mBounds.left, mBounds.top, width, (int) Math.min(height, h));
}
@@ -319,13 +323,14 @@ public class EdgeEffect {
final float centerX = mBounds.centerX();
final float centerY = mBounds.height() - mRadius;
- canvas.scale(1.f, Math.min(mGlowScaleY, 1.f), centerX, 0);
+ canvas.scale(1.f, Math.min(mGlowScaleY, 1.f) * mBaseGlowScale, centerX, 0);
final float displacement = Math.max(0, Math.min(mDisplacement, 1.f)) - 0.5f;
float translateX = mBounds.width() * displacement / 2;
canvas.clipRect(mBounds);
canvas.translate(translateX, 0);
+ mPaint.setAlpha((int) (0xff * mGlowAlpha));
canvas.drawCircle(centerX, centerY, mRadius, mPaint);
canvas.restoreToCount(count);
@@ -372,7 +377,16 @@ public class EdgeEffect {
mGlowScaleYFinish = 0.f;
break;
case STATE_PULL:
- // Hold in this state until explicitly released.
+ mState = STATE_PULL_DECAY;
+ mStartTime = AnimationUtils.currentAnimationTimeMillis();
+ mDuration = PULL_DECAY_TIME;
+
+ mGlowAlphaStart = mGlowAlpha;
+ mGlowScaleYStart = mGlowScaleY;
+
+ // After pull, the glow should fade to nothing.
+ mGlowAlphaFinish = 0.f;
+ mGlowScaleYFinish = 0.f;
break;
case STATE_PULL_DECAY:
mState = STATE_RECEDE;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 46b225d..22138d0 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3089,13 +3089,12 @@ public class Editor {
final boolean isLeadingEdgeTopVisible = isPositionVisible(leadingEdgeX, top);
final boolean isTrailingEdgeBottomVisible =
isPositionVisible(trailingEdgeX, bottom);
- final int characterRectFlags;
- if (isLeadingEdgeTopVisible && isTrailingEdgeBottomVisible) {
- characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE;
- } else if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) {
- characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE;
- } else {
- characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE;
+ int characterRectFlags = 0;
+ if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) {
+ characterRectFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+ }
+ if (!isLeadingEdgeTopVisible || !isTrailingEdgeBottomVisible) {
+ characterRectFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
}
// Here offset is the index in Java chars.
// TODO: We must have a well-defined specification. For example, how
@@ -3117,11 +3116,19 @@ public class Editor {
+ viewportToContentVerticalOffset;
final float insertionMarkerBottom = layout.getLineBottom(line)
+ viewportToContentVerticalOffset;
- // Take TextView's padding and scroll into account.
- final boolean isClipped = !isPositionVisible(insertionMarkerX, insertionMarkerTop)
- || !isPositionVisible(insertionMarkerX, insertionMarkerBottom);
+ final boolean isTopVisible =
+ isPositionVisible(insertionMarkerX, insertionMarkerTop);
+ final boolean isBottomVisible =
+ isPositionVisible(insertionMarkerX, insertionMarkerBottom);
+ int insertionMarkerFlags = 0;
+ if (isTopVisible || isBottomVisible) {
+ insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+ }
+ if (!isTopVisible || !isBottomVisible) {
+ insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+ }
builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop,
- insertionMarkerBaseline, insertionMarkerBottom, isClipped);
+ insertionMarkerBaseline, insertionMarkerBottom, insertionMarkerFlags);
}
imm.updateCursorAnchorInfo(mTextView, builder.build());
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index adca4cc..d2f68d0 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -458,6 +458,7 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
a.recycle();
setOnTouchListener(this);
+ setClickable(true);
// Initial values
final Calendar calendar = Calendar.getInstance(Locale.getDefault());
@@ -612,9 +613,9 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
mMinutesTexts[i] = String.format("%02d", MINUTES_NUMBERS[i]);
}
- String[] amPmTexts = new DateFormatSymbols().getAmPmStrings();
- mAmPmText[AM] = amPmTexts[0];
- mAmPmText[PM] = amPmTexts[1];
+ String[] amPmStrings = TimePickerClockDelegate.getAmPmStrings(mContext);
+ mAmPmText[AM] = amPmStrings[0];
+ mAmPmText[PM] = amPmStrings[1];
}
private void initData() {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 69d5f40..90e9c69 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -22,11 +22,13 @@ import android.app.Application;
import android.app.PendingIntent;
import android.appwidget.AppWidgetHostView;
import android.content.Context;
+import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.Rect;
@@ -1653,8 +1655,10 @@ public class RemoteViews implements Parcelable, Filter {
*
* @param application The application whose content is shown by the views.
* @param layoutId The id of the layout resource.
+ *
+ * @hide
*/
- private RemoteViews(ApplicationInfo application, int layoutId) {
+ protected RemoteViews(ApplicationInfo application, int layoutId) {
mApplication = application;
mLayoutId = layoutId;
mBitmapCache = new BitmapCache();
@@ -2515,15 +2519,29 @@ public class RemoteViews implements Parcelable, Filter {
RemoteViews rvToApply = getRemoteViewsToApply(context);
View result;
-
- Context c = prepareContext(context);
+ // RemoteViews may be built by an application installed in another
+ // user. So build a context that loads resources from that user but
+ // still returns the current users userId so settings like data / time formats
+ // are loaded without requiring cross user persmissions.
+ final Context contextForResources = getContextForResources(context);
+ Context inflationContext = new ContextWrapper(context) {
+ @Override
+ public Resources getResources() {
+ return contextForResources.getResources();
+ }
+ @Override
+ public Resources.Theme getTheme() {
+ return contextForResources.getTheme();
+ }
+ };
LayoutInflater inflater = (LayoutInflater)
- c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater = inflater.cloneInContext(c);
+ // Clone inflater so we load resources from correct context and
+ // we don't add a filter to the static version returned by getSystemService.
+ inflater = inflater.cloneInContext(inflationContext);
inflater.setFilter(this);
-
result = inflater.inflate(rvToApply.getLayoutId(), parent, false);
rvToApply.performApply(result, parent, handler);
@@ -2557,7 +2575,6 @@ public class RemoteViews implements Parcelable, Filter {
}
}
- prepareContext(context);
rvToApply.performApply(v, (ViewGroup) v.getParent(), handler);
}
@@ -2572,7 +2589,7 @@ public class RemoteViews implements Parcelable, Filter {
}
}
- private Context prepareContext(Context context) {
+ private Context getContextForResources(Context context) {
if (mApplication != null) {
if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
&& context.getPackageName().equals(mApplication.packageName)) {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 0a3c7ff..0289ccc 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -334,6 +334,10 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
setInputType(inputType);
}
+ boolean focusable = true;
+ focusable = a.getBoolean(R.styleable.SearchView_focusable, focusable);
+ setFocusable(focusable);
+
a.recycle();
// Save voice intent for later queries/launching
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9b3a1e0..3e1b674 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1861,6 +1861,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return getCompoundPaddingTop();
}
+ if (mLayout == null) {
+ assumeLayout();
+ }
+
if (mLayout.getLineCount() <= mMaximum) {
return getCompoundPaddingTop();
}
@@ -1894,6 +1898,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return getCompoundPaddingBottom();
}
+ if (mLayout == null) {
+ assumeLayout();
+ }
+
if (mLayout.getLineCount() <= mMaximum) {
return getCompoundPaddingBottom();
}
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 6169d2e..73e05e8 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -21,7 +21,6 @@ import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.graphics.Color;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -40,7 +39,6 @@ import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.R;
-import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
@@ -71,6 +69,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
private static final int HOURS_IN_HALF_DAY = 12;
+ private View mHeaderView;
private TextView mHourView;
private TextView mMinuteView;
private TextView mAmPmTextView;
@@ -156,11 +155,8 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
mAmPmTextView.setTextAppearance(context, headerAmPmTextAppearance);
}
- final int headerBackgroundColor = a.getColor(
- R.styleable.TimePicker_headerBackgroundColor, Color.TRANSPARENT);
- if (headerBackgroundColor != Color.TRANSPARENT) {
- mainView.findViewById(R.id.time_header).setBackgroundColor(headerBackgroundColor);
- }
+ mHeaderView = mainView.findViewById(R.id.time_header);
+ mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
a.recycle();
@@ -194,14 +190,11 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
}
private void setupListeners() {
- KeyboardListener keyboardListener = new KeyboardListener();
- mDelegator.setOnKeyListener(keyboardListener);
+ mHeaderView.setOnKeyListener(mKeyListener);
+ mHeaderView.setOnFocusChangeListener(mFocusListener);
+ mHeaderView.setFocusable(true);
- mHourView.setOnKeyListener(keyboardListener);
- mMinuteView.setOnKeyListener(keyboardListener);
- mAmPmTextView.setOnKeyListener(keyboardListener);
mRadialTimePickerView.setOnValueSelectedListener(this);
- mRadialTimePickerView.setOnKeyListener(keyboardListener);
mHourView.setOnClickListener(new View.OnClickListener() {
@Override
@@ -641,7 +634,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
if (!isTypedTimeFullyLegal()) {
mTypedTimes.clear();
}
- finishKbMode(true);
+ finishKbMode();
}
}
@@ -776,27 +769,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
* @return true if the key was successfully processed, false otherwise.
*/
private boolean processKeyUp(int keyCode) {
- if (keyCode == KeyEvent.KEYCODE_ESCAPE || keyCode == KeyEvent.KEYCODE_TAB) {
- if(mInKbMode) {
- if (isTypedTimeFullyLegal()) {
- finishKbMode(true);
- }
- return true;
- }
- } else if (keyCode == KeyEvent.KEYCODE_ENTER) {
- if (mInKbMode) {
- if (!isTypedTimeFullyLegal()) {
- return true;
- }
- finishKbMode(false);
- }
- if (mOnTimeChangedListener != null) {
- mOnTimeChangedListener.onTimeChanged(mDelegator,
- mRadialTimePickerView.getCurrentHour(),
- mRadialTimePickerView.getCurrentMinute());
- }
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_DEL) {
+ if (keyCode == KeyEvent.KEYCODE_DEL) {
if (mInKbMode) {
if (!mTypedTimes.isEmpty()) {
int deleted = deleteLastTypedKey();
@@ -925,9 +898,8 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
/**
* Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time.
- * @param updateDisplays If true, update the displays with the relevant time.
*/
- private void finishKbMode(boolean updateDisplays) {
+ private void finishKbMode() {
mInKbMode = false;
if (!mTypedTimes.isEmpty()) {
int values[] = getEnteredTime(null);
@@ -938,10 +910,8 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
}
mTypedTimes.clear();
}
- if (updateDisplays) {
- updateDisplay(false);
- mRadialTimePickerView.setInputEnabled(true);
- }
+ updateDisplay(false);
+ mRadialTimePickerView.setInputEnabled(true);
}
/**
@@ -1261,7 +1231,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
}
}
- private class KeyboardListener implements View.OnKeyListener {
+ private final View.OnKeyListener mKeyListener = new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP) {
@@ -1269,5 +1239,20 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im
}
return false;
}
- }
+ };
+
+ private final View.OnFocusChangeListener mFocusListener = new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (!hasFocus && mInKbMode && isTypedTimeFullyLegal()) {
+ finishKbMode();
+
+ if (mOnTimeChangedListener != null) {
+ mOnTimeChangedListener.onTimeChanged(mDelegator,
+ mRadialTimePickerView.getCurrentHour(),
+ mRadialTimePickerView.getCurrentMinute());
+ }
+ }
+ }
+ };
}
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index ece8aa4..be28199 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -37,6 +37,7 @@ import android.view.View;
import android.view.ViewGroup;
import com.android.internal.R;
+import com.android.internal.app.ToolbarActionBar;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuItemImpl;
import com.android.internal.view.menu.MenuPresenter;
@@ -153,6 +154,8 @@ public class Toolbar extends ViewGroup {
private ToolbarWidgetWrapper mWrapper;
private ActionMenuPresenter mOuterActionMenuPresenter;
private ExpandedActionViewMenuPresenter mExpandedMenuPresenter;
+ private MenuPresenter.Callback mActionMenuPresenterCallback;
+ private MenuBuilder.Callback mMenuBuilderCallback;
private boolean mCollapsible;
@@ -248,11 +251,12 @@ public class Toolbar extends ViewGroup {
final Drawable navIcon = a.getDrawable(R.styleable.Toolbar_navigationIcon);
if (navIcon != null) {
setNavigationIcon(navIcon);
- final CharSequence navDesc = a.getText(
- R.styleable.Toolbar_navigationContentDescription);
- if (!TextUtils.isEmpty(navDesc)) {
- setNavigationContentDescription(navDesc);
- }
+ }
+
+ final CharSequence navDesc = a.getText(
+ R.styleable.Toolbar_navigationContentDescription);
+ if (!TextUtils.isEmpty(navDesc)) {
+ setNavigationContentDescription(navDesc);
}
a.recycle();
}
@@ -824,6 +828,7 @@ public class Toolbar extends ViewGroup {
mMenuView = new ActionMenuView(getContext());
mMenuView.setPopupTheme(mPopupTheme);
mMenuView.setOnMenuItemClickListener(mMenuViewItemClickListener);
+ mMenuView.setMenuCallbacks(mActionMenuPresenterCallback, mMenuBuilderCallback);
final LayoutParams lp = generateDefaultLayoutParams();
lp.gravity = Gravity.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
mMenuView.setLayoutParams(lp);
@@ -1677,6 +1682,15 @@ public class Toolbar extends ViewGroup {
}
/**
+ * Must be called before the menu is accessed
+ * @hide
+ */
+ public void setMenuCallbacks(MenuPresenter.Callback pcb, MenuBuilder.Callback mcb) {
+ mActionMenuPresenterCallback = pcb;
+ mMenuBuilderCallback = mcb;
+ }
+
+ /**
* Interface responsible for receiving menu item click events if the items themselves
* do not have individual item click listeners.
*/
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index c409520..6d5c98e 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -63,63 +63,46 @@ public class AlertController {
private final Context mContext;
private final DialogInterface mDialogInterface;
private final Window mWindow;
-
- private CharSequence mTitle;
+ private CharSequence mTitle;
private CharSequence mMessage;
-
private ListView mListView;
-
private View mView;
private int mViewLayoutResId;
private int mViewSpacingLeft;
-
private int mViewSpacingTop;
-
private int mViewSpacingRight;
-
private int mViewSpacingBottom;
-
private boolean mViewSpacingSpecified = false;
-
- private Button mButtonPositive;
+ private Button mButtonPositive;
private CharSequence mButtonPositiveText;
-
private Message mButtonPositiveMessage;
private Button mButtonNegative;
-
private CharSequence mButtonNegativeText;
-
private Message mButtonNegativeMessage;
private Button mButtonNeutral;
-
private CharSequence mButtonNeutralText;
-
private Message mButtonNeutralMessage;
private ScrollView mScrollView;
-
+
private int mIconId = 0;
-
private Drawable mIcon;
-
+
private ImageView mIconView;
-
private TextView mTitleView;
-
private TextView mMessageView;
-
private View mCustomTitleView;
-
+
private boolean mForceInverseBackground;
-
+
private ListAdapter mAdapter;
-
+
private int mCheckedItem = -1;
private int mAlertDialogLayout;
@@ -130,7 +113,7 @@ public class AlertController {
private int mListItemLayout;
private int mButtonPanelLayoutHint = AlertDialog.LAYOUT_HINT_NONE;
-
+
private Handler mHandler;
private final View.OnClickListener mButtonHandler = new View.OnClickListener() {
@@ -160,7 +143,7 @@ public class AlertController {
private static final class ButtonHandler extends Handler {
// Button clicks have Message.what as the BUTTON{1,2,3} constant
private static final int MSG_DISMISS_DIALOG = 1;
-
+
private WeakReference<DialogInterface> mDialog;
public ButtonHandler(DialogInterface dialog) {
@@ -170,13 +153,13 @@ public class AlertController {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
-
+
case DialogInterface.BUTTON_POSITIVE:
case DialogInterface.BUTTON_NEGATIVE:
case DialogInterface.BUTTON_NEUTRAL:
((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what);
break;
-
+
case MSG_DISMISS_DIALOG:
((DialogInterface) msg.obj).dismiss();
}
@@ -220,16 +203,16 @@ public class AlertController {
a.recycle();
}
-
+
static boolean canTextInput(View v) {
if (v.onCheckIsTextEditor()) {
return true;
}
-
+
if (!(v instanceof ViewGroup)) {
return false;
}
-
+
ViewGroup vg = (ViewGroup)v;
int i = vg.getChildCount();
while (i > 0) {
@@ -239,10 +222,10 @@ public class AlertController {
return true;
}
}
-
+
return false;
}
-
+
public void installContent() {
/* We use a custom title so never request a window title */
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
@@ -262,7 +245,7 @@ public class AlertController {
// TODO: use layout hint side for long messages/lists
return mAlertDialogLayout;
}
-
+
public void setTitle(CharSequence title) {
mTitle = title;
if (mTitleView != null) {
@@ -276,7 +259,7 @@ public class AlertController {
public void setCustomTitle(View customTitleView) {
mCustomTitleView = customTitleView;
}
-
+
public void setMessage(CharSequence message) {
mMessage = message;
if (mMessageView != null) {
@@ -301,7 +284,7 @@ public class AlertController {
mViewLayoutResId = 0;
mViewSpacingSpecified = false;
}
-
+
/**
* Set the view to display in the dialog along with the spacing around that view
*/
@@ -326,7 +309,7 @@ public class AlertController {
/**
* Sets a click listener or a message to be sent when the button is clicked.
* You only need to pass one of {@code listener} or {@code msg}.
- *
+ *
* @param whichButton Which button, can be one of
* {@link DialogInterface#BUTTON_POSITIVE},
* {@link DialogInterface#BUTTON_NEGATIVE}, or
@@ -341,24 +324,24 @@ public class AlertController {
if (msg == null && listener != null) {
msg = mHandler.obtainMessage(whichButton, listener);
}
-
+
switch (whichButton) {
case DialogInterface.BUTTON_POSITIVE:
mButtonPositiveText = text;
mButtonPositiveMessage = msg;
break;
-
+
case DialogInterface.BUTTON_NEGATIVE:
mButtonNegativeText = text;
mButtonNegativeMessage = msg;
break;
-
+
case DialogInterface.BUTTON_NEUTRAL:
mButtonNeutralText = text;
mButtonNeutralMessage = msg;
break;
-
+
default:
throw new IllegalArgumentException("Button does not exist");
}
@@ -416,11 +399,11 @@ public class AlertController {
public void setInverseBackgroundForced(boolean forceInverseBackground) {
mForceInverseBackground = forceInverseBackground;
}
-
+
public ListView getListView() {
return mListView;
}
-
+
public Button getButton(int whichButton) {
switch (whichButton) {
case DialogInterface.BUTTON_POSITIVE:
@@ -433,7 +416,7 @@ public class AlertController {
return null;
}
}
-
+
@SuppressWarnings({"UnusedDeclaration"})
public boolean onKeyDown(int keyCode, KeyEvent event) {
return mScrollView != null && mScrollView.executeKeyEvent(event);
@@ -469,12 +452,12 @@ public class AlertController {
final LinearLayout contentPanel = (LinearLayout) mWindow.findViewById(R.id.contentPanel);
setupContent(contentPanel);
final boolean hasButtons = setupButtons();
-
+
final LinearLayout topPanel = (LinearLayout) mWindow.findViewById(R.id.topPanel);
final TypedArray a = mContext.obtainStyledAttributes(
null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
final boolean hasTitle = setupTitle(topPanel);
-
+
final View buttonPanel = mWindow.findViewById(R.id.buttonPanel);
if (!hasButtons) {
buttonPanel.setVisibility(View.GONE);
@@ -536,14 +519,14 @@ public class AlertController {
private boolean setupTitle(LinearLayout topPanel) {
boolean hasTitle = true;
-
+
if (mCustomTitleView != null) {
// Add the custom title view directly to the topPanel layout
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
-
+
topPanel.addView(mCustomTitleView, 0, lp);
-
+
// Hide the title template
View titleTemplate = mWindow.findViewById(R.id.title_template);
titleTemplate.setVisibility(View.GONE);
@@ -587,19 +570,19 @@ public class AlertController {
private void setupContent(LinearLayout contentPanel) {
mScrollView = (ScrollView) mWindow.findViewById(R.id.scrollView);
mScrollView.setFocusable(false);
-
+
// Special case for users that only want to display a String
mMessageView = (TextView) mWindow.findViewById(R.id.message);
if (mMessageView == null) {
return;
}
-
+
if (mMessage != null) {
mMessageView.setText(mMessage);
} else {
mMessageView.setVisibility(View.GONE);
mScrollView.removeView(mMessageView);
-
+
if (mListView != null) {
contentPanel.removeView(mWindow.findViewById(R.id.scrollView));
contentPanel.addView(mListView,
@@ -664,7 +647,7 @@ public class AlertController {
centerButton(mButtonNeutral);
}
}
-
+
return whichButtons != 0;
}
@@ -694,7 +677,12 @@ public class AlertController {
int centerBright = 0;
int bottomBright = 0;
int bottomMedium = 0;
- if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.KITKAT) {
+
+ // If the needsDefaultBackgrounds attribute is set, we know we're
+ // inheriting from a framework style.
+ final boolean needsDefaultBackgrounds = a.getBoolean(
+ R.styleable.AlertDialog_needsDefaultBackgrounds, true);
+ if (needsDefaultBackgrounds) {
fullDark = R.drawable.popup_full_dark;
topDark = R.drawable.popup_top_dark;
centerDark = R.drawable.popup_center_dark;
@@ -705,12 +693,12 @@ public class AlertController {
bottomBright = R.drawable.popup_bottom_bright;
bottomMedium = R.drawable.popup_bottom_medium;
}
+
topBright = a.getResourceId(R.styleable.AlertDialog_topBright, topBright);
topDark = a.getResourceId(R.styleable.AlertDialog_topDark, topDark);
centerBright = a.getResourceId(R.styleable.AlertDialog_centerBright, centerBright);
centerDark = a.getResourceId(R.styleable.AlertDialog_centerDark, centerDark);
-
/* We now set the background of all of the sections of the alert.
* First collect together each section that is being displayed along
* with whether it is on a light or dark background, then run through
@@ -789,31 +777,6 @@ public class AlertController {
}
}
- /* TODO: uncomment section below. The logic for this should be if
- * it's a Contextual menu being displayed AND only a Cancel button
- * is shown then do this.
- */
-// if (hasButtons && (mListView != null)) {
-
- /* Yet another *special* case. If there is a ListView with buttons
- * don't put the buttons on the bottom but instead put them in the
- * footer of the ListView this will allow more items to be
- * displayed.
- */
-
- /*
- contentPanel.setBackgroundResource(bottomBright);
- buttonPanel.setBackgroundResource(centerMedium);
- ViewGroup parent = (ViewGroup) mWindow.findViewById(R.id.parentPanel);
- parent.removeView(buttonPanel);
- AbsListView.LayoutParams params = new AbsListView.LayoutParams(
- AbsListView.LayoutParams.MATCH_PARENT,
- AbsListView.LayoutParams.MATCH_PARENT);
- buttonPanel.setLayoutParams(params);
- mListView.addFooterView(buttonPanel);
- */
-// }
-
final ListView listView = mListView;
if (listView != null && mAdapter != null) {
listView.setAdapter(mAdapter);
@@ -854,7 +817,7 @@ public class AlertController {
public static class AlertParams {
public final Context mContext;
public final LayoutInflater mInflater;
-
+
public int mIconId = 0;
public Drawable mIcon;
public int mIconAttrId = 0;
@@ -899,20 +862,20 @@ public class AlertController {
* will be bound to an adapter.
*/
public interface OnPrepareListViewListener {
-
+
/**
* Called before the ListView is bound to an adapter.
* @param listView The ListView that will be shown in the dialog.
*/
void onPrepareListView(ListView listView);
}
-
+
public AlertParams(Context context) {
mContext = context;
mCancelable = true;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
-
+
public void apply(AlertController dialog) {
if (mCustomTitleView != null) {
dialog.setCustomTitle(mCustomTitleView);
@@ -972,12 +935,12 @@ public class AlertController {
}
*/
}
-
+
private void createListView(final AlertController dialog) {
final RecycleListView listView = (RecycleListView)
mInflater.inflate(dialog.mListLayout, null);
ListAdapter adapter;
-
+
if (mIsMultiChoice) {
if (mCursor == null) {
adapter = new ArrayAdapter<CharSequence>(
@@ -1012,37 +975,37 @@ public class AlertController {
listView.setItemChecked(cursor.getPosition(),
cursor.getInt(mIsCheckedIndex) == 1);
}
-
+
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(dialog.mMultiChoiceItemLayout,
parent, false);
}
-
+
};
}
} else {
- int layout = mIsSingleChoice
+ int layout = mIsSingleChoice
? dialog.mSingleChoiceItemLayout : dialog.mListItemLayout;
if (mCursor == null) {
adapter = (mAdapter != null) ? mAdapter
: new CheckedItemAdapter(mContext, layout, R.id.text1, mItems);
} else {
- adapter = new SimpleCursorAdapter(mContext, layout,
+ adapter = new SimpleCursorAdapter(mContext, layout,
mCursor, new String[]{mLabelColumn}, new int[]{R.id.text1});
}
}
-
+
if (mOnPrepareListViewListener != null) {
mOnPrepareListViewListener.onPrepareListView(listView);
}
-
+
/* Don't directly set the adapter on the ListView as we might
* want to add a footer to the ListView later.
*/
dialog.mAdapter = adapter;
dialog.mCheckedItem = mCheckedItem;
-
+
if (mOnClickListener != null) {
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
@@ -1065,12 +1028,12 @@ public class AlertController {
}
});
}
-
+
// Attach a given OnItemSelectedListener to the ListView
if (mOnItemSelectedListener != null) {
listView.setOnItemSelectedListener(mOnItemSelectedListener);
}
-
+
if (mIsSingleChoice) {
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
} else if (mIsMultiChoice) {
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index abe8a9f..99c87ea 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -22,6 +22,7 @@ import android.app.ActionBar;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
import android.view.ActionMode;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -32,7 +33,9 @@ import android.view.Window;
import android.view.WindowCallbackWrapper;
import android.widget.SpinnerAdapter;
import android.widget.Toolbar;
+import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.widget.DecorToolbar;
import com.android.internal.widget.ToolbarWidgetWrapper;
@@ -43,6 +46,9 @@ public class ToolbarActionBar extends ActionBar {
private DecorToolbar mDecorToolbar;
private boolean mToolbarMenuPrepared;
private Window.Callback mWindowCallback;
+ private boolean mMenuCallbackSet;
+
+ private CharSequence mHomeDescription;
private boolean mLastMenuVisibility;
private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
@@ -70,6 +76,8 @@ public class ToolbarActionBar extends ActionBar {
mDecorToolbar.setWindowCallback(mWindowCallback);
toolbar.setOnMenuItemClickListener(mMenuClicker);
mDecorToolbar.setWindowTitle(title);
+ mHomeDescription = mToolbar.getNavigationContentDescription();
+ updateNavDescription();
}
public Window.Callback getWrappedWindowCallback() {
@@ -161,6 +169,7 @@ public class ToolbarActionBar extends ActionBar {
@Override
public void setHomeActionContentDescription(CharSequence description) {
mToolbar.setNavigationContentDescription(description);
+ mHomeDescription = description;
}
@Override
@@ -171,6 +180,7 @@ public class ToolbarActionBar extends ActionBar {
@Override
public void setHomeActionContentDescription(int resId) {
mToolbar.setNavigationContentDescription(resId);
+ mHomeDescription = mToolbar.getNavigationContentDescription();
}
@Override
@@ -247,8 +257,22 @@ public class ToolbarActionBar extends ActionBar {
@Override
public void setDisplayOptions(@DisplayOptions int options, @DisplayOptions int mask) {
- mDecorToolbar.setDisplayOptions((options & mask) |
- mDecorToolbar.getDisplayOptions() & ~mask);
+ final int currentOptions = mDecorToolbar.getDisplayOptions();
+ final int changed = (options ^ currentOptions) & mask;
+ mDecorToolbar.setDisplayOptions(options & mask | currentOptions & ~mask);
+ if ((changed & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
+ updateNavDescription();
+ }
+ }
+
+ private void updateNavDescription() {
+ if ((mDecorToolbar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
+ if (TextUtils.isEmpty(mHomeDescription)) {
+ mToolbar.setNavigationContentDescription(R.string.action_bar_up_description);
+ } else {
+ mToolbar.setNavigationContentDescription(mHomeDescription);
+ }
+ }
}
@Override
@@ -431,6 +455,10 @@ public class ToolbarActionBar extends ActionBar {
}
void populateOptionsMenu() {
+ if (!mMenuCallbackSet) {
+ mToolbar.setMenuCallbacks(new ActionMenuPresenterCallback(), new MenuBuilderCallback());
+ mMenuCallbackSet = true;
+ }
final Menu menu = mToolbar.getMenu();
final MenuBuilder mb = menu instanceof MenuBuilder ? (MenuBuilder) menu : null;
if (mb != null) {
@@ -492,4 +520,51 @@ public class ToolbarActionBar extends ActionBar {
return result;
}
}
+
+ private final class ActionMenuPresenterCallback implements MenuPresenter.Callback {
+ private boolean mClosingActionMenu;
+
+ @Override
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
+ if (mWindowCallback != null) {
+ mWindowCallback.onMenuOpened(Window.FEATURE_ACTION_BAR, subMenu);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+ if (mClosingActionMenu) {
+ return;
+ }
+
+ mClosingActionMenu = true;
+ mToolbar.dismissPopupMenus();
+ if (mWindowCallback != null) {
+ mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu);
+ }
+ mClosingActionMenu = false;
+ }
+ }
+
+ private final class MenuBuilderCallback implements MenuBuilder.Callback {
+
+ @Override
+ public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
+ return false;
+ }
+
+ @Override
+ public void onMenuModeChange(MenuBuilder menu) {
+ if (mWindowCallback != null) {
+ if (mToolbar.isOverflowMenuShowing()) {
+ mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu);
+ } else if (mWindowCallback.onPreparePanel(Window.FEATURE_OPTIONS_PANEL,
+ null, menu)) {
+ mWindowCallback.onMenuOpened(Window.FEATURE_ACTION_BAR, menu);
+ }
+ }
+ }
+ }
}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 54c532a..c5211bb 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -20,9 +20,12 @@ package com.android.internal.os;
import dalvik.system.ZygoteHooks;
import android.system.ErrnoException;
import android.system.Os;
+import android.os.SystemClock;
+import android.util.Slog;
/** @hide */
public final class Zygote {
+ private static final String TAG = "Zygote";
/*
* Bit values for "debugFlags" argument. The definitions are duplicated
* in the native code.
@@ -81,10 +84,14 @@ public final class Zygote {
*/
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+ long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.preFork();
+ checkTime(startTime, "Zygote.preFork");
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+ checkTime(startTime, "Zygote.nativeForkAndSpecialize");
VM_HOOKS.postForkCommon();
+ checkTime(startTime, "Zygote.postForkCommon");
return pid;
}
@@ -92,6 +99,18 @@ public final class Zygote {
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
/**
+ * Temporary hack: check time since start time and log if over a fixed threshold.
+ *
+ */
+ private static void checkTime(long startTime, String where) {
+ long now = SystemClock.elapsedRealtime();
+ if ((now-startTime) > 1000) {
+ // If we are taking more than a second, log about it.
+ Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where);
+ }
+ }
+
+ /**
* Special method to start the system server process. In addition to the
* common actions performed in forkAndSpecialize, the pid of the child
* process is recorded such that the death of the child process will cause
@@ -127,7 +146,9 @@ public final class Zygote {
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
private static void callPostForkChildHooks(int debugFlags) {
+ long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.postForkChild(debugFlags);
+ checkTime(startTime, "Zygote.callPostForkChildHooks");
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 43ebb3d..b4c4da6 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -37,6 +37,8 @@ import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import libcore.io.IoUtils;
+import android.os.SystemClock;
+import android.util.Slog;
/**
* A connection that can make spawn requests.
@@ -103,11 +105,23 @@ class ZygoteConnection {
}
/**
+ * Temporary hack: check time since start time and log if over a fixed threshold.
+ *
+ */
+ private void checkTime(long startTime, String where) {
+ long now = SystemClock.elapsedRealtime();
+ if ((now-startTime) > 1000) {
+ // If we are taking more than a second, log about it.
+ Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where);
+ }
+ }
+
+ /**
* Returns the file descriptor of the associated socket.
*
* @return null-ok; file descriptor
*/
- FileDescriptor getFileDesciptor() {
+ FileDescriptor getFileDescriptor() {
return mSocket.getFileDescriptor();
}
@@ -131,6 +145,8 @@ class ZygoteConnection {
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
+ long startTime = SystemClock.elapsedRealtime();
+
try {
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
@@ -140,6 +156,7 @@ class ZygoteConnection {
return true;
}
+ checkTime(startTime, "zygoteConnection.runOnce: readArgumentList");
if (args == null) {
// EOF reached.
closeSocket();
@@ -171,14 +188,19 @@ class ZygoteConnection {
", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
}
+
applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);
+ checkTime(startTime, "zygoteConnection.runOnce: apply security policies");
+
applyDebuggerSystemProperty(parsedArgs);
applyInvokeWithSystemProperty(parsedArgs);
+ checkTime(startTime, "zygoteConnection.runOnce: apply security policies");
+
int[][] rlimits = null;
if (parsedArgs.rlimits != null) {
@@ -220,9 +242,11 @@ class ZygoteConnection {
fd = null;
+ checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose);
+ checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (ErrnoException ex) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 051de6e..0aee0e3 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -770,7 +770,7 @@ public class ZygoteInit {
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
- fds.add(newPeer.getFileDesciptor());
+ fds.add(newPeer.getFileDescriptor());
} else {
boolean done;
done = peers.get(index).runOnce();
diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java
index a5ce6e0..c153904 100644
--- a/core/java/com/android/internal/util/ImageUtils.java
+++ b/core/java/com/android/internal/util/ImageUtils.java
@@ -17,6 +17,10 @@
package com.android.internal.util;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
/**
* Utility class for image analysis and processing.
@@ -31,17 +35,49 @@ public class ImageUtils {
// Alpha amount for which values below are considered transparent.
private static final int ALPHA_TOLERANCE = 50;
+ // Size of the smaller bitmap we're actually going to scan.
+ private static final int COMPACT_BITMAP_SIZE = 64; // pixels
+
private int[] mTempBuffer;
+ private Bitmap mTempCompactBitmap;
+ private Canvas mTempCompactBitmapCanvas;
+ private Paint mTempCompactBitmapPaint;
+ private final Matrix mTempMatrix = new Matrix();
/**
* Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect
* gray".
+ *
+ * Instead of scanning every pixel in the bitmap, we first resize the bitmap to no more than
+ * COMPACT_BITMAP_SIZE^2 pixels using filtering. The hope is that any non-gray color elements
+ * will survive the squeezing process, contaminating the result with color.
*/
public boolean isGrayscale(Bitmap bitmap) {
- final int height = bitmap.getHeight();
- final int width = bitmap.getWidth();
- int size = height*width;
+ int height = bitmap.getHeight();
+ int width = bitmap.getWidth();
+
+ // shrink to a more manageable (yet hopefully no more or less colorful) size
+ if (height > COMPACT_BITMAP_SIZE || width > COMPACT_BITMAP_SIZE) {
+ if (mTempCompactBitmap == null) {
+ mTempCompactBitmap = Bitmap.createBitmap(
+ COMPACT_BITMAP_SIZE, COMPACT_BITMAP_SIZE, Bitmap.Config.ARGB_8888
+ );
+ mTempCompactBitmapCanvas = new Canvas(mTempCompactBitmap);
+ mTempCompactBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mTempCompactBitmapPaint.setFilterBitmap(true);
+ }
+ mTempMatrix.reset();
+ mTempMatrix.setScale(
+ (float) COMPACT_BITMAP_SIZE / width,
+ (float) COMPACT_BITMAP_SIZE / height,
+ 0, 0);
+ mTempCompactBitmapCanvas.drawColor(0, PorterDuff.Mode.SRC); // select all, erase
+ mTempCompactBitmapCanvas.drawBitmap(bitmap, mTempMatrix, mTempCompactBitmapPaint);
+ bitmap = mTempCompactBitmap;
+ width = height = COMPACT_BITMAP_SIZE;
+ }
+ final int size = height*width;
ensureBufferSize(size);
bitmap.getPixels(mTempBuffer, 0, width, 0, 0, width, height);
for (int i = 0; i < size; i++) {
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 665055c..3249ea3 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -50,23 +50,36 @@ public class NotificationColorUtil {
private final WeakHashMap<Bitmap, Pair<Boolean, Integer>> mGrayscaleBitmapCache =
new WeakHashMap<Bitmap, Pair<Boolean, Integer>>();
- public static NotificationColorUtil getInstance() {
+ private final int mGrayscaleIconMaxSize; // @dimen/notification_large_icon_width (64dp)
+
+ public static NotificationColorUtil getInstance(Context context) {
synchronized (sLock) {
if (sInstance == null) {
- sInstance = new NotificationColorUtil();
+ sInstance = new NotificationColorUtil(context);
}
return sInstance;
}
}
+ private NotificationColorUtil(Context context) {
+ mGrayscaleIconMaxSize = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_large_icon_width);
+ }
+
/**
- * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect
- * gray".
+ * Checks whether a Bitmap is a small grayscale icon.
+ * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp".
*
* @param bitmap The bitmap to test.
- * @return Whether the bitmap is grayscale.
+ * @return True if the bitmap is grayscale; false if it is color or too large to examine.
*/
- public boolean isGrayscale(Bitmap bitmap) {
+ public boolean isGrayscaleIcon(Bitmap bitmap) {
+ // quick test: reject large bitmaps
+ if (bitmap.getWidth() > mGrayscaleIconMaxSize
+ || bitmap.getHeight() > mGrayscaleIconMaxSize) {
+ return false;
+ }
+
synchronized (sLock) {
Pair<Boolean, Integer> cached = mGrayscaleBitmapCache.get(bitmap);
if (cached != null) {
@@ -92,22 +105,22 @@ public class NotificationColorUtil {
}
/**
- * Checks whether a drawable is grayscale. Grayscale here means "very close to a perfect
- * gray".
+ * Checks whether a Drawable is a small grayscale icon.
+ * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp".
*
* @param d The drawable to test.
- * @return Whether the drawable is grayscale.
+ * @return True if the bitmap is grayscale; false if it is color or too large to examine.
*/
- public boolean isGrayscale(Drawable d) {
+ public boolean isGrayscaleIcon(Drawable d) {
if (d == null) {
return false;
} else if (d instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) d;
- return bd.getBitmap() != null && isGrayscale(bd.getBitmap());
+ return bd.getBitmap() != null && isGrayscaleIcon(bd.getBitmap());
} else if (d instanceof AnimationDrawable) {
AnimationDrawable ad = (AnimationDrawable) d;
int count = ad.getNumberOfFrames();
- return count > 0 && isGrayscale(ad.getFrame(0));
+ return count > 0 && isGrayscaleIcon(ad.getFrame(0));
} else if (d instanceof VectorDrawable) {
// We just assume you're doing the right thing if using vectors
return true;
@@ -117,16 +130,16 @@ public class NotificationColorUtil {
}
/**
- * Checks whether a drawable with a resoure id is grayscale. Grayscale here means "very close
- * to a perfect gray".
+ * Checks whether a drawable with a resoure id is a small grayscale icon.
+ * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp".
*
* @param context The context to load the drawable from.
- * @return Whether the drawable is grayscale.
+ * @return True if the bitmap is grayscale; false if it is color or too large to examine.
*/
- public boolean isGrayscale(Context context, int drawableResId) {
+ public boolean isGrayscaleIcon(Context context, int drawableResId) {
if (drawableResId != 0) {
try {
- return isGrayscale(context.getDrawable(drawableResId));
+ return isGrayscaleIcon(context.getDrawable(drawableResId));
} catch (Resources.NotFoundException ex) {
Log.e(TAG, "Drawable not found: " + drawableResId);
return false;
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index b1f5d90..e19b2b6 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -437,7 +437,7 @@ public class IInputConnectionWrapper extends IInputContext.Stub {
return;
}
args.callback.setRequestUpdateCursorAnchorInfoResult(
- ic.requestUpdateCursorAnchorInfo(msg.arg1), args.seq);
+ ic.requestCursorUpdates(msg.arg1), args.seq);
} catch (RemoteException e) {
Log.w(TAG, "Got RemoteException calling requestCursorAnchorInfo", e);
}
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index a8526c8..0c65ad1 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -428,7 +428,7 @@ public class InputConnectionWrapper implements InputConnection {
}
}
- public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+ public boolean requestCursorUpdates(int cursorUpdateMode) {
boolean result = false;
try {
InputContextCallback callback = InputContextCallback.getInstance();
@@ -445,4 +445,11 @@ public class InputConnectionWrapper implements InputConnection {
}
return result;
}
+
+ /**
+ * @removed
+ */
+ public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+ return requestCursorUpdates(cursorUpdateMode);
+ }
}
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index c7ac815..062a9b1 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -59,6 +59,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
private int mSubtitleStyleRes;
private Drawable mSplitBackground;
private boolean mTitleOptional;
+ private int mCloseItemLayout;
private Animator mCurrentAnimation;
private boolean mAnimateInOnLayout;
@@ -99,6 +100,10 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
mSplitBackground = a.getDrawable(
com.android.internal.R.styleable.ActionMode_backgroundSplit);
+ mCloseItemLayout = a.getResourceId(
+ com.android.internal.R.styleable.ActionMode_closeItemLayout,
+ R.layout.action_mode_close_item);
+
a.recycle();
}
@@ -120,7 +125,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
LayoutParams.MATCH_PARENT);
if (!split) {
mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
- mMenuView.setBackgroundDrawable(null);
+ mMenuView.setBackground(null);
final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
if (oldParent != null) oldParent.removeView(mMenuView);
addView(mMenuView, layoutParams);
@@ -134,7 +139,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = mContentHeight;
mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
- mMenuView.setBackgroundDrawable(mSplitBackground);
+ mMenuView.setBackground(mSplitBackground);
final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
if (oldParent != null) oldParent.removeView(mMenuView);
mSplitView.addView(mMenuView, layoutParams);
@@ -211,7 +216,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
public void initForMode(final ActionMode mode) {
if (mClose == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
- mClose = inflater.inflate(R.layout.action_mode_close_item, this, false);
+ mClose = inflater.inflate(mCloseItemLayout, this, false);
addView(mClose);
} else if (mClose.getParent() == null) {
addView(mClose);
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index ba236f3..f211ff2 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -188,13 +188,13 @@ public class EditableInputConnection extends BaseInputConnection {
}
@Override
- public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+ public boolean requestCursorUpdates(int cursorUpdateMode) {
if (DEBUG) Log.v(TAG, "requestUpdateCursorAnchorInfo " + cursorUpdateMode);
// It is possible that any other bit is used as a valid flag in a future release.
// We should reject the entire request in such a case.
- final int KNOWN_FLAGS_MASK = InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE |
- InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR;
+ final int KNOWN_FLAGS_MASK = InputConnection.CURSOR_UPDATE_IMMEDIATE |
+ InputConnection.CURSOR_UPDATE_MONITOR;
final int unknownFlags = cursorUpdateMode & ~KNOWN_FLAGS_MASK;
if (unknownFlags != 0) {
if (DEBUG) {
@@ -212,7 +212,7 @@ public class EditableInputConnection extends BaseInputConnection {
return false;
}
mIMM.setUpdateCursorAnchorInfoMode(cursorUpdateMode);
- if ((cursorUpdateMode & InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0) {
+ if ((cursorUpdateMode & InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0) {
if (mTextView == null) {
// In this case, FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE is silently ignored.
// TODO: Return some notification code for the input method that indicates
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2114ff6..c84708e 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1449,7 +1449,7 @@ public class LockPatternUtils {
}
int textId;
- if (getTelecommManager().isInCall()) {
+ if (isInCall()) {
// show "return to call" text and show phone icon
textId = R.string.lockscreen_return_to_call;
int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
@@ -1470,6 +1470,13 @@ public class LockPatternUtils {
getTelecommManager().showInCallScreen(false);
}
+ /**
+ * @return {@code true} if there is a call currently in progress, {@code false} otherwise.
+ */
+ public boolean isInCall() {
+ return getTelecommManager().isInCall();
+ }
+
private TelecommManager getTelecommManager() {
return (TelecommManager) mContext.getSystemService(Context.TELECOMM_SERVICE);
}
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 62ea351..8ea28ec 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -367,6 +367,9 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
peeker.mOpticalInsets[0], peeker.mOpticalInsets[1], peeker.mOpticalInsets[2], peeker.mOpticalInsets[3],
peeker.mOutlineInsets[0], peeker.mOutlineInsets[1], peeker.mOutlineInsets[2], peeker.mOutlineInsets[3],
peeker.mOutlineRadius, peeker.mOutlineAlpha, scale);
+ if (ninePatchInsets == NULL) {
+ return nullObjectReturn("nine patch insets == null");
+ }
if (javaBitmap != NULL) {
env->SetObjectField(javaBitmap, gBitmap_ninePatchInsetsFieldID, ninePatchInsets);
}
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 7c41c2e..d7b75db 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -419,6 +419,7 @@ jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buff
{
SkASSERT(bitmap);
SkASSERT(bitmap->pixelRef());
+ SkASSERT(!env->ExceptionCheck());
bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 1296831..949f4ff 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -458,7 +458,7 @@ static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz,
static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
jlong renderNodePtr) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->animators().endAllAnimators();
+ renderNode->animators().endAllStagingAnimators();
}
#endif // USE_OPENGL_RENDERER
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 99babac..7e6d335 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -166,12 +166,7 @@ public:
// Runs any animations still left in mCurrentFrameAnimations
virtual void runRemainingAnimations(TreeInfo& info) {
AnimationContext::runRemainingAnimations(info);
- // post all the finished stuff
- if (mOnFinishedEvents.size()) {
- sp<InvokeAnimationListeners> message
- = new InvokeAnimationListeners(mOnFinishedEvents);
- mRootNode->sendMessage(message);
- }
+ postOnFinishedEvents();
}
virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
@@ -179,9 +174,22 @@ public:
mOnFinishedEvents.push_back(event);
}
+ virtual void destroy() {
+ AnimationContext::destroy();
+ postOnFinishedEvents();
+ }
+
private:
sp<RootRenderNode> mRootNode;
std::vector<OnFinishedEvent> mOnFinishedEvents;
+
+ void postOnFinishedEvents() {
+ if (mOnFinishedEvents.size()) {
+ sp<InvokeAnimationListeners> message
+ = new InvokeAnimationListeners(mOnFinishedEvents);
+ mRootNode->sendMessage(message);
+ }
+ }
};
class ContextFactoryImpl : public IContextFactory {
@@ -291,10 +299,10 @@ static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject c
return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density);
}
-static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
jlong proxyPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->destroyCanvasAndSurface();
+ proxy->destroy();
}
static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
@@ -430,7 +438,7 @@ static JNINativeMethod gMethods[] = {
{ "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
{ "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
- { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
+ { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
{ "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
{ "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 1f7acec..3d2d471 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -43,6 +43,7 @@
#include <utils/String8.h>
#include <selinux/android.h>
#include <processgroup/processgroup.h>
+#include <inttypes.h>
#include "android_runtime/AndroidRuntime.h"
#include "JNIHelp.h"
@@ -398,6 +399,22 @@ void SetThreadName(const char* thread_name) {
}
}
+ // Temporary timing check.
+uint64_t MsTime() {
+ timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_nsec / UINT64_C(1000000);
+}
+
+
+void ckTime(uint64_t start, const char* where) {
+ uint64_t now = MsTime();
+ if ((now-start) > 1000) {
+ // If we are taking more than a second, log about it.
+ ALOGW("Slow operation: %"PRIu64" ms in %s", (uint64_t)(now-start), where);
+ }
+}
+
// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
@@ -405,7 +422,9 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
jint mount_external,
jstring java_se_info, jstring java_se_name,
bool is_system_server, jintArray fdsToClose) {
+ uint64_t start = MsTime();
SetSigChldHandler();
+ ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler");
pid_t pid = fork();
@@ -413,9 +432,12 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
// The child process.
gMallocLeakZygoteChild = 1;
+
// Clean up any descriptors which must be closed immediately
DetachDescriptors(env, fdsToClose);
+ ckTime(start, "ForkAndSpecializeCommon:Fork and detach");
+
// Keep capabilities across UID change, unless we're staying root.
if (uid != 0) {
EnableKeepCapabilities(env);
@@ -518,7 +540,10 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
UnsetSigChldHandler();
+ ckTime(start, "ForkAndSpecializeCommon:child process setup");
+
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+ ckTime(start, "ForkAndSpecializeCommon:PostForkChildHooks returns");
if (env->ExceptionCheck()) {
ALOGE("Error calling post fork hooks.");
RuntimeAbort(env);
diff --git a/core/res/res/drawable-hdpi/pointer_arrow_icon.xml b/core/res/res/drawable-hdpi/pointer_arrow_icon.xml
deleted file mode 100644
index a4cce5c..0000000
--- a/core/res/res/drawable-hdpi/pointer_arrow_icon.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
- android:bitmap="@drawable/pointer_arrow"
- android:hotSpotX="9"
- android:hotSpotY="9" />
diff --git a/core/res/res/drawable-hdpi/pointer_spot_anchor.png b/core/res/res/drawable-hdpi/pointer_spot_anchor.png
index d7aca36..bdb5311 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_anchor.png
+++ b/core/res/res/drawable-hdpi/pointer_spot_anchor.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/pointer_spot_anchor_icon.xml b/core/res/res/drawable-hdpi/pointer_spot_anchor_icon.xml
deleted file mode 100644
index 2222b8e..0000000
--- a/core/res/res/drawable-hdpi/pointer_spot_anchor_icon.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
- android:bitmap="@drawable/pointer_spot_anchor"
- android:hotSpotX="33"
- android:hotSpotY="33" />
diff --git a/core/res/res/drawable-hdpi/pointer_spot_hover.png b/core/res/res/drawable-hdpi/pointer_spot_hover.png
index 5041aa3..e7f2a0c 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_hover.png
+++ b/core/res/res/drawable-hdpi/pointer_spot_hover.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/pointer_spot_hover_icon.xml b/core/res/res/drawable-hdpi/pointer_spot_hover_icon.xml
deleted file mode 100644
index dc62a69..0000000
--- a/core/res/res/drawable-hdpi/pointer_spot_hover_icon.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
- android:bitmap="@drawable/pointer_spot_hover"
- android:hotSpotX="33"
- android:hotSpotY="33" />
diff --git a/core/res/res/drawable-hdpi/pointer_spot_touch.png b/core/res/res/drawable-hdpi/pointer_spot_touch.png
index 64a42a1..0326f91 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_touch.png
+++ b/core/res/res/drawable-hdpi/pointer_spot_touch.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_arrow_icon.xml b/core/res/res/drawable-mdpi/pointer_arrow_icon.xml
deleted file mode 100644
index 2f5676f..0000000
--- a/core/res/res/drawable-mdpi/pointer_arrow_icon.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
- android:bitmap="@drawable/pointer_arrow"
- android:hotSpotX="6"
- android:hotSpotY="6" />
diff --git a/core/res/res/drawable-mdpi/pointer_spot_anchor.png b/core/res/res/drawable-mdpi/pointer_spot_anchor.png
index d7aca36..4e282e7 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_anchor.png
+++ b/core/res/res/drawable-mdpi/pointer_spot_anchor.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_hover.png b/core/res/res/drawable-mdpi/pointer_spot_hover.png
index 5041aa3..67d0b06 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_hover.png
+++ b/core/res/res/drawable-mdpi/pointer_spot_hover.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_touch.png b/core/res/res/drawable-mdpi/pointer_spot_touch.png
index 64a42a1..45dc5c0 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_touch.png
+++ b/core/res/res/drawable-mdpi/pointer_spot_touch.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml b/core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml
deleted file mode 100644
index 4bffee6..0000000
--- a/core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
- android:bitmap="@drawable/pointer_spot_touch"
- android:hotSpotX="24"
- android:hotSpotY="24" />
diff --git a/core/res/res/drawable-xhdpi/pointer_spot_anchor.png b/core/res/res/drawable-xhdpi/pointer_spot_anchor.png
index ad41c97..fa9226e 100644
--- a/core/res/res/drawable-xhdpi/pointer_spot_anchor.png
+++ b/core/res/res/drawable-xhdpi/pointer_spot_anchor.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_spot_hover.png b/core/res/res/drawable-xhdpi/pointer_spot_hover.png
index e9b98f6..f09a778 100644
--- a/core/res/res/drawable-xhdpi/pointer_spot_hover.png
+++ b/core/res/res/drawable-xhdpi/pointer_spot_hover.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_spot_touch.png b/core/res/res/drawable-xhdpi/pointer_spot_touch.png
index e10d998..53d7a20 100644
--- a/core/res/res/drawable-xhdpi/pointer_spot_touch.png
+++ b/core/res/res/drawable-xhdpi/pointer_spot_touch.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_arrow_icon.xml b/core/res/res/drawable/pointer_arrow_icon.xml
index 2fbe45a..8f7d658 100644
--- a/core/res/res/drawable-xhdpi/pointer_arrow_icon.xml
+++ b/core/res/res/drawable/pointer_arrow_icon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_arrow"
- android:hotSpotX="12"
- android:hotSpotY="12" />
+ android:hotSpotX="6dp"
+ android:hotSpotY="6dp" />
diff --git a/core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml b/core/res/res/drawable/pointer_spot_anchor_icon.xml
index 2222b8e..73c0c11 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml
+++ b/core/res/res/drawable/pointer_spot_anchor_icon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_spot_anchor"
- android:hotSpotX="33"
- android:hotSpotY="33" />
+ android:hotSpotX="22dp"
+ android:hotSpotY="22dp" />
diff --git a/core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml b/core/res/res/drawable/pointer_spot_hover_icon.xml
index dc62a69..1d7440b 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml
+++ b/core/res/res/drawable/pointer_spot_hover_icon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_spot_hover"
- android:hotSpotX="33"
- android:hotSpotY="33" />
+ android:hotSpotX="22dp"
+ android:hotSpotY="22dp" />
diff --git a/core/res/res/drawable-hdpi/pointer_spot_touch_icon.xml b/core/res/res/drawable/pointer_spot_touch_icon.xml
index 4bffee6..f4f0639 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_touch_icon.xml
+++ b/core/res/res/drawable/pointer_spot_touch_icon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_spot_touch"
- android:hotSpotX="24"
- android:hotSpotY="24" />
+ android:hotSpotX="16dp"
+ android:hotSpotY="16dp" />
diff --git a/core/res/res/drawable/stat_sys_tether_wifi.xml b/core/res/res/drawable/stat_sys_tether_wifi.xml
index a816db8..4396962 100644
--- a/core/res/res/drawable/stat_sys_tether_wifi.xml
+++ b/core/res/res/drawable/stat_sys_tether_wifi.xml
@@ -14,11 +14,12 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="26.0dp"
+ android:width="24.0dp"
android:height="24.0dp"
- android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+ android:pathData="M24.000000,22.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000C28.000000,23.799999 26.200001,22.000000 24.000000,22.000000zM36.000000,26.000000c0.000000,-6.600000 -5.400000,-12.000000 -12.000000,-12.000000c-6.600000,0.000000 -12.000000,5.400000 -12.000000,12.000000c0.000000,4.400000 2.400000,8.300000 6.000000,10.400000l2.000000,-3.500000c-2.400000,-1.400000 -4.000000,-3.900000 -4.000000,-6.900000c0.000000,-4.400000 3.600000,-8.000000 8.000000,-8.000000s8.000000,3.600000 8.000000,8.000000c0.000000,3.000000 -1.600000,5.500000 -4.000000,6.900000l2.000000,3.500000C33.599998,34.299999 36.000000,30.400000 36.000000,26.000000zM24.000000,6.000000C13.000000,6.000000 4.000000,15.000000 4.000000,26.000000c0.000000,7.400000 4.000000,13.800000 10.000000,17.299999l2.000000,-3.500000c-4.800000,-2.800000 -8.000000,-7.900000 -8.000000,-13.800000c0.000000,-8.800000 7.200000,-16.000000 16.000000,-16.000000s16.000000,7.200000 16.000000,16.000000c0.000000,5.900000 -3.200000,11.100000 -8.000000,13.800000l2.000000,3.500000c6.000000,-3.500000 10.000000,-9.900000 10.000000,-17.299999C44.000000,15.000000 35.000000,6.000000 24.000000,6.000000z"/>
</vector>
diff --git a/core/res/res/drawable/ic_cab_done_material.xml b/core/res/res/drawable/time_picker_header_material.xml
index a370288..cdb92b6 100644
--- a/core/res/res/drawable/ic_cab_done_material.xml
+++ b/core/res/res/drawable/time_picker_header_material.xml
@@ -14,6 +14,9 @@
limitations under the License.
-->
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_cab_done_mtrl_alpha"
- android:tint="?attr/colorControlNormal" />
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?attr/colorControlHighlight">
+ <item>
+ <color android:color="?attr/colorAccent" />
+ </item>
+</ripple>
diff --git a/core/res/res/layout-land/time_picker_holo.xml b/core/res/res/layout-land/time_picker_holo.xml
index f316f1b..ce90a5b 100644
--- a/core/res/res/layout-land/time_picker_holo.xml
+++ b/core/res/res/layout-land/time_picker_holo.xml
@@ -21,7 +21,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
- android:focusable="true"
android:layout_marginLeft="@dimen/timepicker_minimum_margin_sides"
android:layout_marginRight="@dimen/timepicker_minimum_margin_sides"
android:layout_marginTop="@dimen/timepicker_minimum_margin_top_bottom"
@@ -42,7 +41,5 @@
android:id="@+id/radial_picker"
android:layout_width="@dimen/timepicker_radial_picker_dimen"
android:layout_height="match_parent"
- android:layout_gravity="center"
- android:focusable="true"
- android:focusableInTouchMode="true" />
+ android:layout_gravity="center" />
</LinearLayout>
diff --git a/core/res/res/layout/action_mode_close_item_material.xml b/core/res/res/layout/action_mode_close_item_material.xml
new file mode 100644
index 0000000..8eb780b
--- /dev/null
+++ b/core/res/res/layout/action_mode_close_item_material.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/action_mode_close_button"
+ android:focusable="true"
+ android:clickable="true"
+ android:paddingStart="8dip"
+ android:src="?android:attr/actionModeCloseDrawable"
+ style="?android:attr/actionModeCloseButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="16dip" />
diff --git a/core/res/res/layout/preference_material.xml b/core/res/res/layout/preference_material.xml
index 778e70a..a137149 100644
--- a/core/res/res/layout/preference_material.xml
+++ b/core/res/res/layout/preference_material.xml
@@ -24,7 +24,8 @@
android:gravity="center_vertical"
android:paddingStart="?attr/listPreferredItemPaddingStart"
android:paddingEnd="?attr/listPreferredItemPaddingEnd"
- android:background="?attr/activatedBackgroundIndicator">
+ android:background="?attr/activatedBackgroundIndicator"
+ android:clipToPadding="false">
<LinearLayout
android:id="@+id/icon_frame"
diff --git a/core/res/res/layout/screen_toolbar.xml b/core/res/res/layout/screen_toolbar.xml
index 039e89f..88c9cf6 100644
--- a/core/res/res/layout/screen_toolbar.xml
+++ b/core/res/res/layout/screen_toolbar.xml
@@ -41,6 +41,7 @@ This is an optimized layout for a screen with a toolbar enabled.
android:id="@+id/action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:navigationContentDescription="@string/action_bar_up_description"
style="?attr/toolbarStyle" />
<com.android.internal.widget.ActionBarContextView
android:id="@+id/action_context_bar"
diff --git a/core/res/res/layout/time_picker_holo.xml b/core/res/res/layout/time_picker_holo.xml
index 483eb6d..08d2211 100644
--- a/core/res/res/layout/time_picker_holo.xml
+++ b/core/res/res/layout/time_picker_holo.xml
@@ -18,20 +18,17 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:focusable="true" >
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
<include
- layout="@layout/time_header_label"
- android:layout_width="match_parent"
- android:layout_height="@dimen/timepicker_header_height"
- android:layout_gravity="center" />
+ layout="@layout/time_header_label"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/timepicker_header_height"
+ android:layout_gravity="center" />
<android.widget.RadialTimePickerView
- android:id="@+id/radial_picker"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/timepicker_radial_picker_dimen"
- android:layout_gravity="center"
- android:focusable="true"
- android:focusableInTouchMode="true" />
+ android:id="@+id/radial_picker"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/timepicker_radial_picker_dimen"
+ android:layout_gravity="center" />
</LinearLayout>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b6c876d..35ff766 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1228,9 +1228,9 @@
<string name="smv_application" msgid="3307209192155442829">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) porušila své vlastní vynucené zásady StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> porušil své vlastní vynucené zásady StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android se upgraduje..."</string>
- <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimalizace aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimalizování aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Spouštění aplikací."</string>
- <string name="android_upgrading_complete" msgid="1405954754112999229">"Probíhá dokončování spouštění."</string>
+ <string name="android_upgrading_complete" msgid="1405954754112999229">"Dokončování inicializace."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"Běží aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="heavy_weight_notification_detail" msgid="1721681741617898865">"Dotykem přepnete aplikaci"</string>
<string name="heavy_weight_switcher_title" msgid="7153167085403298169">"Přepnout aplikace?"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 451ac5d..fb635dd 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1294,7 +1294,7 @@
<string name="sms_control_yes" msgid="3663725993855816807">"Autoriser"</string>
<string name="sms_control_no" msgid="625438561395534982">"Refuser"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; souhaite envoyer un message à &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
- <string name="sms_short_code_details" msgid="5873295990846059400">"Ce "<b>"peut entraîner des frais"</b>" sur votre compte."</string>
+ <string name="sms_short_code_details" msgid="5873295990846059400">"Ceci "<b>"peut entraîner des frais"</b>" sur votre compte."</string>
<string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Cela entraînera des frais sur votre compte."</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Envoyer"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Annuler"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 88adba5..7add9a6 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1294,8 +1294,8 @@
<string name="sms_control_yes" msgid="3663725993855816807">"Izinkan"</string>
<string name="sms_control_no" msgid="625438561395534982">"Tolak"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingin mengirim pesan kepada &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
- <string name="sms_short_code_details" msgid="5873295990846059400">"Tindakan ini "<b>"dapat menimbulkan tagihan"</b>" terhadap akun seluler Anda."</string>
- <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Tindakan ini akan menimbulkan tagihan terhadap akun seluler Anda."</b></string>
+ <string name="sms_short_code_details" msgid="5873295990846059400">"Tindakan ini "<b>"dapat menimbulkan tagihan"</b>" untuk ponsel Anda."</string>
+ <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Tindakan ini akan menimbulkan tagihan untuk ponsel Anda."</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Kirim"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Batal"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Ingat pilihan saya"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 3120104..7a72fd3 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1588,7 +1588,7 @@
<string name="media_route_status_in_use" msgid="4533786031090198063">"בשימוש"</string>
<string name="display_manager_built_in_display_name" msgid="2583134294292563941">"מסך מובנה"</string>
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"‏מסך HDMI"</string>
- <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"שכבת על #<xliff:g id="ID">%1$d</xliff:g>"</string>
+ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"שכבת-על #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"‏<xliff:g id="NAME">%1$s</xliff:g>: ‎<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>‎, ‏<xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
<string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", מאובטח"</string>
<string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"העברת מסך מתבצעת"</string>
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index 423e250..2778b6e 100644
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -34,4 +34,11 @@
</string-array>
<bool name="config_auto_attach_data_on_creation">false</bool>
+
+ <!-- Values for GPS configuration (Verizon) -->
+ <string-array translatable="false" name="config_gpsParameters">
+ <item>CAPABILITIES=0x31</item>
+ <item>LPP_PROFILE=3</item>
+ <item>GPS_LOCK=3</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values-mcc310-mnc120/config.xml b/core/res/res/values-mcc310-mnc120/config.xml
index 62001d9..3b95db5 100644
--- a/core/res/res/values-mcc310-mnc120/config.xml
+++ b/core/res/res/values-mcc310-mnc120/config.xml
@@ -25,4 +25,10 @@
-->
<integer name="config_mobile_mtu">1422</integer>
+ <!-- Values for GPS configuration (Sprint) -->
+ <string-array translatable="false" name="config_gpsParameters">
+ <item>CAPABILITIES=0x31</item>
+ <item>GPS_LOCK=3</item>
+ <item>LPP_PROFILE=2</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values-mcc310-mnc150/config.xml b/core/res/res/values-mcc310-mnc150/config.xml
index f1936f4..00d2db8 100644
--- a/core/res/res/values-mcc310-mnc150/config.xml
+++ b/core/res/res/values-mcc310-mnc150/config.xml
@@ -33,4 +33,10 @@
<item>315</item>
<item>316</item>
</string-array>
+ <!-- Values for GPS configuration (AT&T) -->
+ <string-array translatable="false" name="config_gpsParameters">
+ <item>CAPABILITIES=0x33</item>
+ <item>LPP_PROFILE=3</item>
+ <item>GPS_LOCK=1</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml
index 00cdaeb..2f9394a 100644
--- a/core/res/res/values-mcc310-mnc260/config.xml
+++ b/core/res/res/values-mcc310-mnc260/config.xml
@@ -25,9 +25,10 @@
-->
<integer name="config_mobile_mtu">1440</integer>
- <!-- Values for GPS configuration -->
+ <!-- Values for GPS configuration (T-Mobile) -->
<string-array translatable="false" name="config_gpsParameters">
- <item>"SUPL_PORT=7279"</item>
+ <item>CAPABILITEIS=0x33</item>
<item>GPS_LOCK=1</item>
+ <item>LPP_PROFILE=2</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc410/config.xml
index 9e63047..edf6d9f 100644
--- a/core/res/res/values-mcc310-mnc410/config.xml
+++ b/core/res/res/values-mcc310-mnc410/config.xml
@@ -40,8 +40,15 @@
<item>315</item>
<item>316</item>
</string-array>
- <!-- Values for GPS configuration -->
+ <!-- Values for GPS configuration (AT&T) -->
<string-array translatable="false" name="config_gpsParameters">
- <item>"SUPL_HOST=supl.google.com"</item>
+ <item>CAPABILITIES=0x33</item>
+ <item>GPS_LOCK=1</item>
+ <item>LPP_PROFILE=3</item>
+ </string-array>
+ <!-- Do not translate. Defines the slots is Two Digit Number for dialing normally not USSD -->
+ <string-array name="config_twoDigitNumberPattern">
+ <item>"0"</item>
+ <item>"00"</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc311-mnc190/config.xml b/core/res/res/values-mcc311-mnc190/config.xml
index a6c4d1b..b4e436d 100644
--- a/core/res/res/values-mcc311-mnc190/config.xml
+++ b/core/res/res/values-mcc311-mnc190/config.xml
@@ -37,4 +37,11 @@
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string translatable="false" name="config_tether_apndata">Tether,broadband.cellular1.net,,,,,,,,,311,190,,DUN</string>
+ <!-- Values for GPS configuration (Sprint) -->
+ <string-array translatable="false" name="config_gpsParameters">
+ <item>CAPABILITIES=0x31</item>
+ <item>GPS_LOCK=3</item>
+ <item>LPP_PROFILE=2</item>
+ </string-array>
+
</resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index e5af60b..cd5d55b 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -44,4 +44,11 @@
<bool name="config_mobile_allow_volte_vt">false</bool>
<bool name="config_auto_attach_data_on_creation">false</bool>
+
+ <!-- Values for GPS configuration (Verizon) -->
+ <string-array translatable="false" name="config_gpsParameters">
+ <item>CAPABILITIES=0x31</item>
+ <item>GPS_LOCK=3</item>
+ <item>LPP_PROFILE=3</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 0a109ba..2e0792a 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1774,6 +1774,6 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
- <string name="battery_saver_description" msgid="2510530476513605742">"Para ajudar a melhorar a vida útil da bateria, a economia de bateria reduz o desempenho do dispositivo e restringe a vibração e a maioria dos dados em segundo plano. É possível que apps de e-mail, mensagens, entre outros, que dependem de sincronização não sejam atualizados a menos que sejam abertos.\n\nA economia de bateria é desativada automaticamente quando o dispositivo estiver carregando."</string>
+ <string name="battery_saver_description" msgid="2510530476513605742">"Para ajudar a melhorar a vida útil da bateria, a economia de bateria reduz o desempenho do dispositivo e restringe a vibração e a maioria dos dados em segundo plano. É possível que apps de e-mail, mensagens, entre outros que dependem de sincronização não sejam atualizados a menos que sejam abertos.\n\nA economia de bateria é desativada automaticamente quando o dispositivo estiver carregando."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Até o período de inatividade terminar às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index daad675..f95d29d 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1295,7 +1295,7 @@
<string name="sms_control_no" msgid="625438561395534982">"Kataza"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingependa kutuma ujumbe kwa &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
<string name="sms_short_code_details" msgid="5873295990846059400">"Hii "<b>"huenda ikasababisha ulipe gharama"</b>" kwenye akaunti ya kifaa chako cha mkononi."</string>
- <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Hii itasababisha ulipe gharama kwenye akaunti ya kifaa chako cha mkononi."</b></string>
+ <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Hii itafanya ulipe gharama kwenye akaunti ya kifaa chako cha mkononi."</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Tuma"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Ghairi"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Kumbuka chaguo yangu"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 516bea4..2c0ed15 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -54,17 +54,17 @@
<string name="serviceErased" msgid="1288584695297200972">"அழித்தல் வெற்றியடைந்தது."</string>
<string name="passwordIncorrect" msgid="7612208839450128715">"தவறான கடவுச்சொல்."</string>
<string name="mmiComplete" msgid="8232527495411698359">"MMI நிறைவடைந்தது."</string>
- <string name="badPin" msgid="9015277645546710014">"உள்ளிட்ட பழைய PIN தவறானது."</string>
+ <string name="badPin" msgid="9015277645546710014">"உள்ளிட்ட பழைய பின் தவறானது."</string>
<string name="badPuk" msgid="5487257647081132201">"உள்ளிட்ட PUK2 தவறானது."</string>
<string name="mismatchPin" msgid="609379054496863419">"உள்ளிட்ட PINகள் பொருந்தவில்லை."</string>
- <string name="invalidPin" msgid="3850018445187475377">"4 இலிருந்து 8 எண்கள் வரையுள்ள PIN ஐத் தட்டச்சு செய்யவும்."</string>
+ <string name="invalidPin" msgid="3850018445187475377">"4 இலிருந்து 8 எண்கள் வரையுள்ள பின் ஐத் தட்டச்சு செய்யவும்."</string>
<string name="invalidPuk" msgid="8761456210898036513">"8 அல்லது அதற்கு மேல் எண்கள் உள்ள PUK ஐத் தட்டச்சு செய்யவும்."</string>
- <string name="needPuk" msgid="919668385956251611">"உங்கள் SIM கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது. அதைத் திறக்க PUK குறியீட்டைத் உள்ளிடவும்."</string>
- <string name="needPuk2" msgid="4526033371987193070">"SIM கார்டைத் தடுப்பு நீக்க PUK2 ஐ உள்ளிடவும்."</string>
- <string name="enablePin" msgid="209412020907207950">"தோல்வி, SIM/RUIM பூட்டை இயக்கவும்."</string>
+ <string name="needPuk" msgid="919668385956251611">"உங்கள் சிம் கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது. அதைத் திறக்க PUK குறியீட்டைத் உள்ளிடவும்."</string>
+ <string name="needPuk2" msgid="4526033371987193070">"சிம் கார்டைத் தடுப்பு நீக்க PUK2 ஐ உள்ளிடவும்."</string>
+ <string name="enablePin" msgid="209412020907207950">"தோல்வி, சிம்/RUIM பூட்டை இயக்கவும்."</string>
<plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"SIM பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
- <item quantity="other" msgid="7530597808358774740">"SIM பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
+ <item quantity="one" msgid="6596245285809790142">"சிம் பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
+ <item quantity="other" msgid="7530597808358774740">"சிம் பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
</plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
@@ -76,7 +76,7 @@
<string name="CwMmi" msgid="9129678056795016867">"அழைப்பு காத்திருப்பு"</string>
<string name="BaMmi" msgid="455193067926770581">"அழைப்புத் தவிர்ப்பு"</string>
<string name="PwdMmi" msgid="7043715687905254199">"கடவுச்சொல்லை மாற்று"</string>
- <string name="PinMmi" msgid="3113117780361190304">"PIN ஐ மாற்று"</string>
+ <string name="PinMmi" msgid="3113117780361190304">"பின்னை மாற்று"</string>
<string name="CnipMmi" msgid="3110534680557857162">"இருக்கும் எண்ணை அழைக்கிறது"</string>
<string name="CnirMmi" msgid="3062102121430548731">"அழைப்பு எண் வரையறுக்கப்பட்டது"</string>
<string name="ThreeWCMmi" msgid="9051047170321190368">"மும்முனை அழைப்பு"</string>
@@ -289,11 +289,11 @@
<string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"நிகழ்வுகளுக்குச் செய்தி வழியாகப் பதிலை அனுப்புதல்"</string>
<string name="permdesc_sendRespondViaMessageRequest" msgid="7107648548468778734">"உள்வரும் அழைப்புகளுக்கான நிகழ்வுகளுக்கு, செய்தி வழியாகப் பதிலளிப்பதை நிர்வகிப்பதற்கு, பிற மெசேஜ் பயன்பாடுகளுக்குக் கோரிக்கைகளை அனுப்புவதற்குப் பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_readSms" msgid="8745086572213270480">"உங்கள் உரைச் செய்திகளை (SMS அல்லது MMS) படித்தல்"</string>
- <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"உங்கள் டேப்லெட் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
- <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"உங்கள் மொபைல் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்கப் பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"உங்கள் டேப்லெட் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
+ <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"உங்கள் மொபைல் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்கப் பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
<string name="permlab_writeSms" msgid="3216950472636214774">"உங்கள் உரைச் செய்திகளைத் (SMS அல்லது MMS) திருத்துதல்"</string>
- <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"டேப்லெட் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
- <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"ஃபோன் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"டேப்லெட் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
+ <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"ஃபோன் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"உரைச் செய்திகளைப் (WAP) பெறுதல்"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAP செய்திகளைப் பெற, செயற்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது. உங்களுக்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிக்க அல்லது நீக்குவதற்கான திறன் இந்த அனுமதியில் உள்ளடங்கும்."</string>
<string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetooth செய்திகளைப் (MAP) பெறுதல்"</string>
@@ -541,8 +541,8 @@
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ஒலியளவு மற்றும் வெளியீட்டிற்கு ஸ்பீக்கர்கள் பயன்படுத்தப்படுவது போன்ற ஒட்டுமொத்த ஆடியோ அமைப்புகளைக் கட்டுப்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"ஆடியோவைப் பதிவுசெய்தல்"</string>
<string name="permdesc_recordAudio" msgid="4906839301087980680">"மைக்ரோஃபோன் மூலம் ஆடியோவைப் பதிவுசெய்ய பயன்பாட்டை அனுமதிக்கிறது. உங்கள் உறுதிப்படுத்தல் இல்லாமல் எந்நேரத்திலும் ஆடியோவைப் பதிவுசெய்ய இந்த அனுமதி பயன்பாட்டை அனுமதிக்கிறது."</string>
- <string name="permlab_sim_communication" msgid="1180265879464893029">"SIM தகவல்தொடர்பு"</string>
- <string name="permdesc_sim_communication" msgid="5725159654279639498">"SIM க்குக் கட்டளைகளை அனுப்ப பயன்பாட்டை அனுமதிக்கிறது. இது மிகவும் ஆபத்தானதாகும்."</string>
+ <string name="permlab_sim_communication" msgid="1180265879464893029">"சிம் தகவல்தொடர்பு"</string>
+ <string name="permdesc_sim_communication" msgid="5725159654279639498">"சிம் க்குக் கட்டளைகளை அனுப்ப பயன்பாட்டை அனுமதிக்கிறது. இது மிகவும் ஆபத்தானதாகும்."</string>
<string name="permlab_camera" msgid="3616391919559751192">"படங்கள் மற்றும் வீடியோக்களை எடுத்தல்"</string>
<string name="permdesc_camera" msgid="8497216524735535009">"கேமரா மூலமாகப் படங்களையும், வீடியோக்களையும் எடுக்க பயன்பாட்டை அனுமதிக்கிறது. உங்கள் உறுதிப்படுத்தல் இன்றி கேமராவை எந்நேரத்திலும் பயன்படுத்தப் பயன்பாட்டை இது அனுமதிக்கிறது."</string>
<string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"கேமரா பயன்பாட்டில் இருக்கும்போது டிரான்ஸ்மிட் இன்டிகேட்டர் LED ஐ முடக்குதல்"</string>
@@ -882,14 +882,14 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"அலுவலகம்"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"மற்றவை"</string>
<string name="quick_contacts_not_available" msgid="746098007828579688">"இதைப் பார்ப்பதற்குகந்த பயன்பாடு எதுவும் நிறுவப்படவில்லை."</string>
- <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN குறியீட்டை உள்ளிடவும்"</string>
- <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK மற்றும் புதிய PIN குறியீட்டை உள்ளிடவும்"</string>
+ <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"பின் குறியீட்டை உள்ளிடவும்"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK மற்றும் புதிய பின் குறியீட்டை உள்ளிடவும்"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK குறியீடு"</string>
- <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"புதிய PIN குறியீடு"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"புதிய பின் குறியீடு"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"கடவுச்சொல்லை உள்ளிட, தொடவும்"</font></string>
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"திறக்க, கடவுச்சொல்லை உள்ளிடவும்"</string>
- <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"திறக்க, PIN ஐ உள்ளிடவும்"</string>
- <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"தவறான PIN குறியீடு."</string>
+ <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"திறக்க, பின்னை உள்ளிடவும்"</string>
+ <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"தவறான பின் குறியீடு."</string>
<string name="keyguard_label_text" msgid="861796461028298424">"தடைநீக்க, மெனுவை அழுத்தி பின்பு 0 ஐ அழுத்தவும்."</string>
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"அவசர எண்"</string>
<string name="lockscreen_carrier_default" msgid="8963839242565653192">"சேவை இல்லை."</string>
@@ -907,13 +907,13 @@
<string name="lockscreen_charged" msgid="321635745684060624">"சார்ஜ் செய்யப்பட்டது"</string>
<string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_low_battery" msgid="1482873981919249740">"உங்கள் சார்ஜரை இணைக்கவும்."</string>
- <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM கார்டு இல்லை"</string>
- <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"டேப்லெட்டில் SIM கார்டு இல்லை."</string>
- <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"தொலைபேசியில் SIM கார்டு இல்லை."</string>
- <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"SIM கார்டைச் செருகவும்."</string>
- <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM கார்டு இல்லை அல்லது படிக்கக்கூடியதாக இல்லை. SIM கார்டைச் செருகவும்."</string>
- <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"பயன்படுத்த முடியாத SIM கார்டு."</string>
- <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"உங்கள் SIM கார்டு நிரந்தரமாக முடக்கப்பட்டது.\n மற்றொரு SIM கார்டிற்காக உங்கள் வயர்லெஸ் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string>
+ <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"சிம் கார்டு இல்லை"</string>
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"டேப்லெட்டில் சிம் கார்டு இல்லை."</string>
+ <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"தொலைபேசியில் சிம் கார்டு இல்லை."</string>
+ <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"சிம் கார்டைச் செருகவும்."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"சிம் கார்டு இல்லை அல்லது படிக்கக்கூடியதாக இல்லை. சிம் கார்டைச் செருகவும்."</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"பயன்படுத்த முடியாத சிம் கார்டு."</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"உங்கள் சிம் கார்டு நிரந்தரமாக முடக்கப்பட்டது.\n மற்றொரு சிம் கார்டிற்காக உங்கள் வயர்லெஸ் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string>
<string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"முந்தைய ட்ராக்"</string>
<string name="lockscreen_transport_next_description" msgid="573285210424377338">"அடுத்த ட்ராக்"</string>
<string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"இடைநிறுத்து"</string>
@@ -923,13 +923,13 @@
<string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"வேகமாக முன்செல்"</string>
<string name="emergency_calls_only" msgid="6733978304386365407">"அவசர அழைப்புகள் மட்டும்"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"நெட்வொர்க் பூட்டப்பட்டது"</string>
- <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது."</string>
+ <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"சிம் கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"பயனர் கையேட்டைப் பார்க்கவும் அல்லது வாடிக்கையாளர் சேவையைத் தொடர்புகொள்ளவும்."</string>
- <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM கார்டு பூட்டப்பட்டுள்ளது."</string>
- <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM கார்டைத் திறக்கிறது..."</string>
+ <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"சிம் கார்டு பூட்டப்பட்டுள்ளது."</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"சிம் கார்டைத் திறக்கிறது..."</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
- <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"உங்கள் PIN ஐ <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
+ <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> முறை தவறாக வரைந்தால், உங்கள் Google உள்நுழைவைப் பயன்படுத்தி டேப்லெட்டைத் திறக்குமாறு கேட்கப்படுவீர்கள். \n\n <xliff:g id="NUMBER_2">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> முறை தவறாக வரைந்தால், உங்கள் Google உள்நுழைவைப் பயன்படுத்தி மொபைலைத் திறக்குமாறு கேட்கப்படுவீர்கள். \n\n <xliff:g id="NUMBER_2">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"டேப்லெட்டைத் தடைநீக்க <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக முயற்சித்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, டேப்லெட்டானது ஆரம்ப இயல்புநிலைக்கு மீட்டமைக்கப்பட்டு, எல்லா பயனர் தரவும் இழக்கப்படும்."</string>
@@ -1284,8 +1284,8 @@
<string name="wifi_p2p_invitation_to_connect_title" msgid="4958803948658533637">"இணைவதற்கான அழைப்பு"</string>
<string name="wifi_p2p_from_message" msgid="570389174731951769">"அனுப்புநர்:"</string>
<string name="wifi_p2p_to_message" msgid="248968974522044099">"பெறுநர்:"</string>
- <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"பின்வரும் அவசியமான PIN ஐ உள்ளிடவும்:"</string>
- <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+ <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"பின்வரும் அவசியமான பின்னை உள்ளிடவும்:"</string>
+ <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"பின்:"</string>
<string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> உடன் டேப்லெட் இணைக்கப்படும்போது, வைஃபையிலிருந்து தற்காலிகமாகத் துண்டிக்கப்படும்."</string>
<string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> உடன் மொபைல் இணைக்கப்படும்போது, வைஃபையிலிருந்து தற்காலிகமாகத் துண்டிக்கப்படும்."</string>
<string name="select_character" msgid="3365550120617701745">"எழுத்துக்குறியைச் செருகு"</string>
@@ -1302,10 +1302,10 @@
<string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"அமைப்பு &gt; பயன்பாடுகள் என்பதில் பிறகு நீங்கள் மாற்றலாம்"</string>
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"எப்போதும் அனுமதி"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"ஒருபோதும் அனுமதிக்காதே"</string>
- <string name="sim_removed_title" msgid="6227712319223226185">"SIM கார்டு அகற்றப்பட்டது"</string>
- <string name="sim_removed_message" msgid="5450336489923274918">"சரியான SIM கார்டைச் செருகி, மறுதொடக்கம் செய்யும் வரை செல்லுலார் நெட்வொர்க் கிடைக்காது."</string>
+ <string name="sim_removed_title" msgid="6227712319223226185">"சிம் கார்டு அகற்றப்பட்டது"</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"சரியான சிம் கார்டைச் செருகி, மறுதொடக்கம் செய்யும் வரை செல்லுலார் நெட்வொர்க் கிடைக்காது."</string>
<string name="sim_done_button" msgid="827949989369963775">"முடிந்தது"</string>
- <string name="sim_added_title" msgid="3719670512889674693">"SIM கார்டு சேர்க்கப்பட்டது"</string>
+ <string name="sim_added_title" msgid="3719670512889674693">"சிம் கார்டு சேர்க்கப்பட்டது"</string>
<string name="sim_added_message" msgid="7797975656153714319">"செல்லுலார் நெட்வொர்க்கை அணுக உங்கள் சாதனத்தை மறுதொடக்கம் செய்யவும்."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"மறுதொடக்கம்"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"நேரத்தை அமை"</string>
@@ -1568,7 +1568,7 @@
<string name="activity_resolver_use_once" msgid="2404644797149173758">"இப்போது மட்டும்"</string>
<string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s பணி சுயவிவரத்தை ஆதரிக்காது"</string>
<string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"டேப்லெட்"</string>
- <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"மொபைல்"</string>
+ <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ஃபோன்"</string>
<string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ஹெட்ஃபோன்கள்"</string>
<string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"மொபைல் வைக்கும் கருவியின் ஸ்பீக்கர்கள்"</string>
<string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
@@ -1600,21 +1600,21 @@
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"வடிவத்தை மறந்துவிட்டீர்களா"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"தவறான வடிவம்"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"தவறான கடவுச்சொல்"</string>
- <string name="kg_wrong_pin" msgid="1131306510833563801">"தவறான PIN"</string>
+ <string name="kg_wrong_pin" msgid="1131306510833563801">"தவறான பின்"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_pattern_instructions" msgid="398978611683075868">"உங்கள் வடிவத்தை வரையவும்"</string>
- <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PIN ஐ உள்ளிடவும்"</string>
- <string name="kg_pin_instructions" msgid="2377242233495111557">"PIN ஐ உள்ளிடுக"</string>
+ <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"சிம் பின்னை உள்ளிடவும்"</string>
+ <string name="kg_pin_instructions" msgid="2377242233495111557">"பின்னை உள்ளிடுக"</string>
<string name="kg_password_instructions" msgid="5753646556186936819">"கடவுச்சொல்லை உள்ளிடவும்"</string>
- <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு மொபைல் நிறுவனங்களைத் தொடர்புகொள்ளவும்."</string>
- <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"விரும்பிய PIN குறியீட்டை உள்ளிடவும்"</string>
- <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"விரும்பிய PIN குறியீட்டை உறுதிப்படுத்தவும்"</string>
- <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM கார்டின் தடையைநீக்குகிறது..."</string>
- <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"தவறான PIN குறியீடு."</string>
- <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 இலிருந்து 8 எண்கள் வரையுள்ள PIN ஐ உள்ளிடவும்."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு மொபைல் நிறுவனங்களைத் தொடர்புகொள்ளவும்."</string>
+ <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"விரும்பிய பின் குறியீட்டை உள்ளிடவும்"</string>
+ <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"விரும்பிய பின் குறியீட்டை உறுதிப்படுத்தவும்"</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"சிம் கார்டின் தடையைநீக்குகிறது..."</string>
+ <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"தவறான பின் குறியீடு."</string>
+ <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 இலிருந்து 8 எண்கள் வரையுள்ள பின்னை உள்ளிடவும்."</string>
<string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"PUK குறியீட்டில் 8 எழுத்துக்குறிகள் இருக்க வேண்டும்."</string>
- <string name="kg_invalid_puk" msgid="3638289409676051243">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் SIM ஐ நிரந்தரமாக முடக்கிவிடும்."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN குறியீடுகள் பொருந்தவில்லை"</string>
+ <string name="kg_invalid_puk" msgid="3638289409676051243">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் சிம் ஐ நிரந்தரமாக முடக்கிவிடும்."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"பின் குறியீடுகள் பொருந்தவில்லை"</string>
<string name="kg_login_too_many_attempts" msgid="6486842094005698475">"அதிகமான வடிவ முயற்சிகள்"</string>
<string name="kg_login_instructions" msgid="1100551261265506448">"திறக்க, உங்கள் Google கணக்கு மூலம் உள்நுழையவும்."</string>
<string name="kg_login_username_hint" msgid="5718534272070920364">"பயனர்பெயர் (மின்னஞ்சல்)"</string>
@@ -1623,7 +1623,7 @@
<string name="kg_login_invalid_input" msgid="5754664119319872197">"தவறான பயனர்பெயர் அல்லது கடவுச்சொல்."</string>
<string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"உங்கள் பயனர்பெயர் அல்லது கடவுச்சொல்லை மறந்துவிட்டீர்களா?\n"<b>"google.com/accounts/recovery"</b>" ஐப் பார்வையிடவும்."</string>
<string name="kg_login_checking_password" msgid="1052685197710252395">"கணக்கைச் சரிபார்க்கிறது…"</string>
- <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"உங்கள் PIN ஐ <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகளில் மீண்டும் முயற்சிக்கவும்."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"டேப்லெட்டைத் திறக்க <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக முயற்சித்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, டேப்லெட்டானது ஆரம்பநிலைக்கு மீட்டமைக்கப்பட்டு, எல்லா பயனர் தரவையும் இழப்பீர்கள்."</string>
@@ -1734,15 +1734,15 @@
<string name="reason_service_unavailable" msgid="7824008732243903268">"பிரிண்டர் இயக்கத்தில் இல்லை"</string>
<string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> சேவை நிறுவப்பட்டது"</string>
<string name="print_service_installed_message" msgid="5897362931070459152">"இயக்குவதற்குத் தட்டவும்"</string>
- <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"நிர்வாகி PIN ஐ உள்ளிடவும்"</string>
- <string name="restr_pin_enter_pin" msgid="3395953421368476103">"PIN ஐ உள்ளிடவும்"</string>
+ <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"நிர்வாகி பின்னை உள்ளிடவும்"</string>
+ <string name="restr_pin_enter_pin" msgid="3395953421368476103">"பின்னை உள்ளிடவும்"</string>
<string name="restr_pin_incorrect" msgid="8571512003955077924">"தவறானது"</string>
- <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"நடப்பு PIN"</string>
- <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"புதிய PIN"</string>
- <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"புதிய PIN ஐ உறுதிப்படுத்தவும்"</string>
- <string name="restr_pin_create_pin" msgid="8017600000263450337">"வரம்புகளைத் திருத்துவதற்கு PIN ஐ உருவாக்கவும்"</string>
+ <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"நடப்பு பின்"</string>
+ <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"புதிய பின்"</string>
+ <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"புதிய பின்னை உறுதிப்படுத்தவும்"</string>
+ <string name="restr_pin_create_pin" msgid="8017600000263450337">"வரம்புகளைத் திருத்துவதற்கு பின்னை உருவாக்கவும்"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PINகள் பொருந்தவில்லை. மீண்டும் முயற்சிக்கவும்."</string>
- <string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN மிகவும் சிறியதாக உள்ளது. குறைந்தது 4 இலக்கங்கள் இருக்க வேண்டும்."</string>
+ <string name="restr_pin_error_too_short" msgid="8173982756265777792">"பின் மிகவும் சிறியதாக உள்ளது. குறைந்தது 4 இலக்கங்கள் இருக்க வேண்டும்."</string>
<plurals name="restr_pin_countdown">
<item quantity="one" msgid="311050995198548675">"1 வினாடி கழித்து முயற்சிக்கவும்"</item>
<item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்"</item>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index c4a6e53c..cd0ef0b 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1294,8 +1294,8 @@
<string name="sms_control_yes" msgid="3663725993855816807">"允許"</string>
<string name="sms_control_no" msgid="625438561395534982">"拒絕"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 要求將訊息傳送至 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;。"</string>
- <string name="sms_short_code_details" msgid="5873295990846059400">"這"<b>"可能會將收費計入"</b>"您的流動服務帳戶中。"</string>
- <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"這會將收費計入您的流動服務帳戶中。"</b></string>
+ <string name="sms_short_code_details" msgid="5873295990846059400">"您的流動服務帳戶"<b>"可能因此繳付費用"</b>"。"</string>
+ <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"您的流動服務帳戶將因此繳付費用。"</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"發送"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"取消"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"記住我的選擇"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 093ce63..fdb54ec 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -376,7 +376,7 @@
<string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"允許應用程式啟動完整備份確認使用者介面 (不建議任何應用程式使用)。"</string>
<string name="permlab_internalSystemWindow" msgid="2148563628140193231">"顯示未授權視窗"</string>
<string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"允許應用程式為內部系統使用者介面建立視窗 (不建議一般應用程式使用)。"</string>
- <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"在其他應用程式之上顯示内容"</string>
+ <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"在其他應用程式之上顯示內容"</string>
<string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"允許應用程式在其他應用程式頂層或使用者介面的特定部分繪圖。這可能會干擾您在所有應用程式中的介面使用行為,或是使您在其他應用程式中預期看到的內容發生變化。"</string>
<string name="permlab_setAnimationScale" msgid="2805103241153907174">"編輯全域動畫速度"</string>
<string name="permdesc_setAnimationScale" msgid="7690063428924343571">"允許應用程式隨時變更全域的動畫速度 (更快或更慢)。"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a798d2e..3629cbb 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -514,8 +514,8 @@
<!-- Flag indicating whether this Window's transition should overlap with
the exiting transition of the called Activity when the called Activity
finishes. Corresponds to
- {@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
- <attr name="windowAllowExitTransitionOverlap" format="boolean"/>
+ {@link android.view.Window#setAllowReturnTransitionOverlap(boolean)}. -->
+ <attr name="windowAllowReturnTransitionOverlap" format="boolean"/>
<!-- Indicates whether or not shared elements should use an overlay
during transitions. The default value is true. -->
@@ -1726,6 +1726,34 @@
<enum name="KEYCODE_LAST_CHANNEL" value="229" />
<enum name="KEYCODE_TV_DATA_SERVICE" value="230" />
<enum name="KEYCODE_VOICE_ASSIST" value="231" />
+ <enum name="KEYCODE_TV_RADIO_SERVICE" value="232" />
+ <enum name="KEYCODE_TV_TELETEXT" value="233" />
+ <enum name="KEYCODE_TV_NUMBER_ENTRY" value="234" />
+ <enum name="KEYCODE_TV_TERRESTRIAL_ANALOG" value="235" />
+ <enum name="KEYCODE_TV_TERRESTRIAL_DIGITAL" value="236" />
+ <enum name="KEYCODE_TV_SATELLITE" value="237" />
+ <enum name="KEYCODE_TV_SATELLITE_BS" value="238" />
+ <enum name="KEYCODE_TV_SATELLITE_CS" value="239" />
+ <enum name="KEYCODE_TV_SATELLITE_SERVICE" value="240" />
+ <enum name="KEYCODE_TV_NETWORK" value="241" />
+ <enum name="KEYCODE_TV_ANTENNA_CABLE" value="242" />
+ <enum name="KEYCODE_TV_INPUT_HDMI_1" value="243" />
+ <enum name="KEYCODE_TV_INPUT_HDMI_2" value="244" />
+ <enum name="KEYCODE_TV_INPUT_HDMI_3" value="245" />
+ <enum name="KEYCODE_TV_INPUT_HDMI_4" value="246" />
+ <enum name="KEYCODE_TV_INPUT_COMPOSITE_1" value="247" />
+ <enum name="KEYCODE_TV_INPUT_COMPOSITE_2" value="248" />
+ <enum name="KEYCODE_TV_INPUT_COMPONENT_1" value="249" />
+ <enum name="KEYCODE_TV_INPUT_COMPONENT_2" value="250" />
+ <enum name="KEYCODE_TV_INPUT_VGA_1" value="251" />
+ <enum name="KEYCODE_TV_AUDIO_DESCRIPTION" value="252" />
+ <enum name="KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP" value="253" />
+ <enum name="KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN" value="254" />
+ <enum name="KEYCODE_TV_ZOOM_MODE" value="255" />
+ <enum name="KEYCODE_TV_CONTENTS_MENU" value="256" />
+ <enum name="KEYCODE_TV_MEDIA_CONTEXT_MENU" value="257" />
+ <enum name="KEYCODE_TV_TIMER_PROGRAMMING" value="258" />
+ <enum name="KEYCODE_HELP" value="259" />
</attr>
<!-- ***************************************************************** -->
@@ -1853,8 +1881,8 @@
<!-- Flag indicating whether this Window's transition should overlap with
the exiting transition of the called Activity when the called Activity
finishes. Corresponds to
- {@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
- <attr name="windowAllowExitTransitionOverlap"/>
+ {@link android.view.Window#setAllowReturnTransitionOverlap(boolean)}. -->
+ <attr name="windowAllowReturnTransitionOverlap"/>
<!-- Indicates whether or not shared elements should use an overlay
during transitions. The default value is true. -->
@@ -1921,6 +1949,8 @@
<attr name="listItemLayout" format="reference" />
<attr name="progressLayout" format="reference" />
<attr name="horizontalProgressLayout" format="reference" />
+ <!-- @hide Whether fullDark, etc. should use default values if null. -->
+ <attr name="needsDefaultBackgrounds" format="boolean" />
</declare-styleable>
<!-- Fragment animation class attributes. -->
@@ -4316,7 +4346,7 @@
<!-- @hide The layout of the legacy DatePicker. -->
<attr name="legacyLayout" />
<!-- The background color for the date selector 's day of week. -->
- <attr name="dayOfWeekBackgroundColor" format="color" />
+ <attr name="dayOfWeekBackground" format="color|reference" />
<!-- The text color for the date selector's day of week. -->
<attr name="dayOfWeekTextAppearance" format="reference" />
<!-- The month's text appearance in the date selector. -->
@@ -4325,8 +4355,8 @@
<attr name="headerDayOfMonthTextAppearance" format="reference" />
<!-- The year's text appearance in the date selector. -->
<attr name="headerYearTextAppearance" format="reference" />
- <!-- The background color for the date selector. -->
- <attr name="headerBackgroundColor" />
+ <!-- The background for the date selector. -->
+ <attr name="headerBackground" />
<!-- @hide The selected text color for the date selector. Used as a
backup if the text appearance does not explicitly have a color
set for the selected state. -->
@@ -4623,29 +4653,29 @@
<attr name="legacyLayout" format="reference" />
<!-- @hide The layout of the time picker. -->
<attr name="internalLayout" />
- <!-- The text appearance for the AM/PM header of the TimePicker. -->
+ <!-- The text appearance for the AM/PM header. -->
<attr name="headerAmPmTextAppearance" format="reference" />
- <!-- The text appearance for the time header of the TimePicker. -->
+ <!-- The text appearance for the time header. -->
<attr name="headerTimeTextAppearance" format="reference" />
<!-- @hide The text color for selected time header of the TimePicker.
This will override the value from the text appearance if it does
not explicitly have a color set for the selected state. -->
<attr name="headerSelectedTextColor" format="color" />
- <!-- The background color for the header of the TimePicker. -->
- <attr name="headerBackgroundColor" format="color" />
- <!-- The color for the hours/minutes numbers of the TimePicker. -->
+ <!-- The background for the header containing the currently selected time. -->
+ <attr name="headerBackground" />
+ <!-- The color for the hours/minutes numbers. -->
<attr name="numbersTextColor" format="color" />
- <!-- The background color for the hours/minutes numbers of the TimePicker. -->
+ <!-- The background color for the hours/minutes numbers. -->
<attr name="numbersBackgroundColor" format="color" />
- <!-- The color for the AM/PM selectors of the TimePicker. -->
+ <!-- The color for the AM/PM selectors. -->
<attr name="amPmTextColor" format="color" />
- <!-- The background color state list for the AM/PM selectors of the TimePicker. -->
+ <!-- The background color state list for the AM/PM selectors. -->
<attr name="amPmBackgroundColor" format="color" />
<!-- @hide The background color for the AM/PM selectors of the
TimePicker when selected. Used if the background color does not
explicitly have a color set for the selected state. -->
<attr name="amPmSelectedBackgroundColor" format="color" />
- <!-- The color for the hours/minutes selector of the TimePicker. -->
+ <!-- The color for the hours/minutes selector. -->
<attr name="numbersSelectorColor" format="color" />
<!-- Defines the look of the widget. Prior to the L release, the only choice was
spinner. As of L, with the Material theme selected, the default layout is clock,
@@ -6570,12 +6600,12 @@
<flag name="vertical" value="0x2" />
</attr>
<!-- Optional parameter which indicates where this widget can be shown,
- ie. home screen, keyguard, recents or any combination thereof.
+ ie. home screen, keyguard, search bar or any combination thereof.
Supports combined values using | operator. -->
<attr name="widgetCategory" format="integer">
<flag name="home_screen" value="0x1" />
<flag name="keyguard" value="0x2" />
- <flag name="recents" value="0x4" />
+ <flag name="searchbox" value="0x4" />
</attr>
</declare-styleable>
@@ -6627,6 +6657,53 @@
IDs (through the android:id attribute) instead of tags because
they are faster and allow for compile-time type checking. -->
<attr name="tag" />
+
+ <!-- The Transition that will be used to move Views out of the scene when the
+ fragment is removed, hidden, or detached when not popping the back stack.
+ Corresponds to {@link android.app.Fragment#setExitTransition(
+ android.transition.Transition)} -->
+ <attr name="fragmentExitTransition" format="reference"/>
+
+ <!-- The Transition that will be used to move Views into the initial scene.
+ Corresponds to {@link android.app.Fragment#setEnterTransition(
+ android.transition.Transition)} -->
+ <attr name="fragmentEnterTransition" format="reference"/>
+
+ <!-- The Transition that will be used for shared elements transferred into the content
+ Scene.
+ Corresponds to {@link android.app.Fragment#setSharedElementEnterTransition(
+ android.transition.Transition)} -->
+ <attr name="fragmentSharedElementEnterTransition" format="reference"/>
+
+ <!-- The Transition that will be used to move Views out of the scene when the Fragment is
+ preparing to be removed, hidden, or detached because of popping the back stack.
+ Corresponds to {@link android.app.Fragment#setReturnTransition(
+ android.transition.Transition)} -->
+ <attr name="fragmentReturnTransition" format="reference"/>
+
+ <!-- The Transition that will be used for shared elements transferred back during a
+ pop of the back stack. This Transition acts in the leaving Fragment.
+ Corresponds to {@link android.app.Fragment#setSharedElementReturnTransition(
+ android.transition.Transition)} -->
+ <attr name="fragmentSharedElementReturnTransition" format="reference"/>
+
+ <!-- The Transition that will be used to move Views in to the scene when returning due
+ to popping a back stack.
+ Corresponds to {@link android.app.Fragment#setReenterTransition(
+ android.transition.Transition)} -->
+ <attr name="fragmentReenterTransition" format="reference"/>
+
+ <!-- Sets whether the enter and exit transitions should overlap when transitioning
+ forward.
+ Corresponds to {@link android.app.Fragment#setAllowEnterTransitionOverlap(
+ boolean)} -->
+ <attr name="fragmentAllowEnterTransitionOverlap" format="reference"/>
+
+ <!-- Sets whether the enter and exit transitions should overlap when transitioning
+ because of popping the back stack.
+ Corresponds to {@link android.app.Fragment#setAllowReturnTransitionOverlap(
+ boolean)} -->
+ <attr name="fragmentAllowReturnTransitionOverlap" format="reference"/>
</declare-styleable>
<!-- Use <code>device-admin</code> as the root tag of the XML resource that
@@ -7040,6 +7117,8 @@
<attr name="backgroundSplit" />
<!-- Specifies a fixed height for the action mode bar. -->
<attr name="height" />
+ <!-- Specifies a layout to use for the "close" item at the starting edge. -->
+ <attr name="closeItemLayout" format="reference" />
</declare-styleable>
<declare-styleable name="SearchView">
@@ -7072,6 +7151,7 @@
<attr name="queryBackground" format="reference" />
<!-- Background for the section containing the action (e.g. voice search) -->
<attr name="submitBackground" format="reference" />
+ <attr name="focusable" />
</declare-styleable>
<declare-styleable name="Switch">
@@ -7112,9 +7192,9 @@
<!-- Drawable to use as the icon bitmap. -->
<attr name="bitmap" format="reference" />
<!-- X coordinate of the icon hot spot. -->
- <attr name="hotSpotX" format="float" />
+ <attr name="hotSpotX" format="dimension" />
<!-- Y coordinate of the icon hot spot. -->
- <attr name="hotSpotY" format="float" />
+ <attr name="hotSpotY" format="dimension" />
</declare-styleable>
<declare-styleable name="Storage">
@@ -7355,6 +7435,9 @@
<!-- @removed -->
<attr name="__removed1" format="reference" />
+ <!-- TODO: Spacer to be removed from here and public.xml -->
+ <attr name="__removed2" format="reference" />
+
<!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
XML resource that describes TV content rating of a {@link android.media.tv.TvInputService},
which is referenced from its
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f5f079c..b63b91d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -374,7 +374,7 @@
<bool name="config_useAttentionLight">false</bool>
<!-- If this is true, the screen will fade off. -->
- <bool name="config_animateScreenLights">true</bool>
+ <bool name="config_animateScreenLights">false</bool>
<!-- If this is true, key chords can be used to take a screenshot on the device. -->
<bool name="config_enableScreenshotChord">true</bool>
@@ -628,7 +628,7 @@
<integer name="config_notificationsBatteryLedOff">2875</integer>
<!-- Number of notifications to keep in the notification service historical archive -->
- <integer name="config_notificationServiceArchiveSize">250</integer>
+ <integer name="config_notificationServiceArchiveSize">100</integer>
<!-- Allow the menu hard key to be disabled in LockScreen on some devices -->
<bool name="config_disableMenuKeyInLockScreen">false</bool>
@@ -1456,6 +1456,10 @@
<!-- Set to true if after a provisioning apn the radio should be restarted -->
<bool name="config_restartRadioAfterProvisioning">false</bool>
+ <!-- Boolean indicating if RADIO POWER OFF is required on receiving SIM REFRESH with RESET.
+ This will be handled by modem if it is false. -->
+ <bool name="config_requireRadioPowerOffOnSimRefreshReset">false</bool>
+
<!-- Vibrator pattern to be used as the default for notifications
that specify DEFAULT_VIBRATE.
-->
@@ -1533,6 +1537,7 @@
<item>com.android.server.notification.ValidateNotificationPeople</item>
<item>com.android.server.notification.PackagePriorityExtractor</item>
<item>com.android.server.notification.NotificationIntrusivenessExtractor</item>
+ <item>com.android.server.notification.PackageVisibilityExtractor</item>
</string-array>
<!-- Flag indicating that this device does not rotate and will always remain in its default
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5e76a87..4bf4531 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2146,7 +2146,7 @@
<public type="attr" name="windowExitTransition" />
<public type="attr" name="windowSharedElementEnterTransition" />
<public type="attr" name="windowSharedElementExitTransition" />
- <public type="attr" name="windowAllowExitTransitionOverlap" />
+ <public type="attr" name="windowAllowReturnTransitionOverlap" />
<public type="attr" name="windowAllowEnterTransitionOverlap" />
<public type="attr" name="sessionService" />
<public type="attr" name="stackViewStyle" />
@@ -2235,7 +2235,7 @@
<public type="attr" name="launchTaskBehindTargetAnimation" />
<public type="attr" name="launchTaskBehindSourceAnimation" />
<public type="attr" name="restrictionType" />
- <public type="attr" name="dayOfWeekBackgroundColor" />
+ <public type="attr" name="dayOfWeekBackground" />
<public type="attr" name="dayOfWeekTextAppearance" />
<public type="attr" name="headerMonthTextAppearance" />
<public type="attr" name="headerDayOfMonthTextAppearance" />
@@ -2248,7 +2248,7 @@
<public type="attr" name="timePickerDialogTheme" />
<public type="attr" name="headerTimeTextAppearance" />
<public type="attr" name="headerAmPmTextAppearance" />
- <public type="attr" name="headerBackgroundColor" />
+ <public type="attr" name="__removed2" />
<public type="attr" name="numbersTextColor" />
<public type="attr" name="numbersBackgroundColor" />
<public type="attr" name="numbersSelectorColor" />
@@ -2282,6 +2282,14 @@
<public type="attr" name="spotShadowAlpha" />
<public type="attr" name="navigationIcon" />
<public type="attr" name="navigationContentDescription" />
+ <public type="attr" name="fragmentExitTransition" />
+ <public type="attr" name="fragmentEnterTransition" />
+ <public type="attr" name="fragmentSharedElementEnterTransition" />
+ <public type="attr" name="fragmentReturnTransition" />
+ <public type="attr" name="fragmentSharedElementReturnTransition" />
+ <public type="attr" name="fragmentReenterTransition" />
+ <public type="attr" name="fragmentAllowEnterTransitionOverlap" />
+ <public type="attr" name="fragmentAllowReturnTransitionOverlap" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 4aed037..c6d0b0b 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -62,6 +62,7 @@ please see styles_device_defaults.xml.
<item name="centerMedium">@drawable/popup_center_medium</item>
<item name="progressLayout">@layout/progress_dialog</item>
<item name="horizontalProgressLayout">@layout/alert_dialog_progress</item>
+ <item name="needsDefaultBackgrounds">false</item>
</style>
<style name="Widget.PreferenceFrameLayout">
diff --git a/core/res/res/values/styles_holo.xml b/core/res/res/values/styles_holo.xml
index 2a54ccf..c7d2db1 100644
--- a/core/res/res/values/styles_holo.xml
+++ b/core/res/res/values/styles_holo.xml
@@ -468,7 +468,7 @@ please see styles_device_defaults.xml.
<item name="internalLayout">@layout/time_picker_holo</item>
<item name="headerTimeTextAppearance">@style/TextAppearance.Holo.TimePicker.TimeLabel</item>
<item name="headerAmPmTextAppearance">@style/TextAppearance.Holo.TimePicker.AmPmLabel</item>
- <item name="headerBackgroundColor">@color/timepicker_default_background_holo_dark</item>
+ <item name="headerBackground">@color/timepicker_default_background_holo_dark</item>
<item name="headerSelectedTextColor">@color/holo_blue_light</item>
<item name="numbersTextColor">@color/timepicker_default_text_color_holo_dark</item>
<item name="numbersBackgroundColor">@color/timepicker_default_background_holo_dark</item>
@@ -484,9 +484,9 @@ please see styles_device_defaults.xml.
<item name="internalLayout">@layout/date_picker_holo</item>
<item name="calendarViewShown">true</item>
<!-- New-style date picker attributes. -->
- <item name="dayOfWeekBackgroundColor">@color/datepicker_default_header_dayofweek_background_color_holo_dark</item>
+ <item name="dayOfWeekBackground">@color/datepicker_default_header_dayofweek_background_color_holo_dark</item>
<item name="dayOfWeekTextAppearance">@style/TextAppearance.Holo.DatePicker.DayOfWeekLabel</item>
- <item name="headerBackgroundColor">@color/datepicker_default_header_selector_background_holo_dark</item>
+ <item name="headerBackground">@color/datepicker_default_header_selector_background_holo_dark</item>
<item name="headerMonthTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.MonthLabel</item>
<item name="headerDayOfMonthTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.DayOfMonthLabel</item>
<item name="headerYearTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.YearLabel</item>
@@ -892,7 +892,7 @@ please see styles_device_defaults.xml.
<item name="internalLayout">@layout/time_picker_holo</item>
<item name="headerTimeTextAppearance">@style/TextAppearance.Holo.Light.TimePicker.TimeLabel</item>
<item name="headerAmPmTextAppearance">@style/TextAppearance.Holo.Light.TimePicker.AmPmLabel</item>
- <item name="headerBackgroundColor">@color/timepicker_default_background_holo_light</item>
+ <item name="headerBackground">@color/timepicker_default_background_holo_light</item>
<item name="headerSelectedTextColor">@color/holo_blue_light</item>
<item name="numbersTextColor">@color/timepicker_default_text_color_holo_light</item>
<item name="numbersBackgroundColor">@color/timepicker_default_background_holo_light</item>
@@ -908,12 +908,12 @@ please see styles_device_defaults.xml.
<item name="internalLayout">@layout/date_picker_holo</item>
<item name="calendarViewShown">true</item>
<!-- New-style date picker attributes. -->
- <item name="dayOfWeekBackgroundColor">@color/datepicker_default_header_dayofweek_background_color_holo_light</item>
+ <item name="dayOfWeekBackground">@color/datepicker_default_header_dayofweek_background_color_holo_light</item>
<item name="dayOfWeekTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.DayOfWeekLabel</item>
<item name="headerMonthTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.MonthLabel</item>
<item name="headerDayOfMonthTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.DayOfMonthLabel</item>
<item name="headerYearTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.YearLabel</item>
- <item name="headerBackgroundColor">@color/datepicker_default_header_selector_background_holo_light</item>
+ <item name="headerBackground">@color/datepicker_default_header_selector_background_holo_light</item>
<item name="headerSelectedTextColor">@color/holo_blue_light</item>
<item name="yearListItemTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.List.YearLabel</item>
<item name="yearListSelectorColor">@color/datepicker_default_circle_background_color_holo_light</item>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 8b3cbaf..a7335af 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -619,7 +619,7 @@ please see styles_device_defaults.xml.
<item name="headerTimeTextAppearance">@style/TextAppearance.Material.TimePicker.TimeLabel</item>
<item name="headerAmPmTextAppearance">@style/TextAppearance.Material.TimePicker.AmPmLabel</item>
<item name="headerSelectedTextColor">?attr/textColorPrimaryInverse</item>
- <item name="headerBackgroundColor">?attr/colorAccent</item>
+ <item name="headerBackground">@drawable/time_picker_header_material</item>
<item name="numbersTextColor">?attr/textColorSecondary</item>
<item name="numbersBackgroundColor">#10ffffff</item>
<item name="amPmTextColor">?attr/textColorSecondary</item>
@@ -634,13 +634,13 @@ please see styles_device_defaults.xml.
<!-- Attributes for new-style DatePicker. -->
<item name="internalLayout">@layout/date_picker_holo</item>
<item name="calendarViewShown">true</item>
- <item name="dayOfWeekBackgroundColor">#10000000</item>
+ <item name="dayOfWeekBackground">#10000000</item>
<item name="dayOfWeekTextAppearance">@style/TextAppearance.Material.DatePicker.DayOfWeekLabel</item>
<item name="headerMonthTextAppearance">@style/TextAppearance.Material.DatePicker.MonthLabel</item>
<item name="headerDayOfMonthTextAppearance">@style/TextAppearance.Material.DatePicker.DayOfMonthLabel</item>
<item name="headerYearTextAppearance">@style/TextAppearance.Material.DatePicker.YearLabel</item>
<item name="headerSelectedTextColor">?attr/textColorPrimaryInverse</item>
- <item name="headerBackgroundColor">?attr/colorAccent</item>
+ <item name="headerBackground">?attr/colorAccent</item>
<item name="yearListItemTextAppearance">@style/TextAppearance.Material.DatePicker.List.YearLabel</item>
<item name="yearListSelectorColor">?attr/colorControlActivated</item>
<item name="calendarTextColor">?attr/textColorSecondary</item>
@@ -838,7 +838,7 @@ please see styles_device_defaults.xml.
</style>
<style name="Widget.Material.ActionButton.CloseMode">
- <item name="background">@drawable/btn_cab_done_material</item>
+ <item name="background">?attr/selectableItemBackgroundBorderless</item>
</style>
<style name="Widget.Material.ActionButton.Overflow">
@@ -901,6 +901,7 @@ please see styles_device_defaults.xml.
<style name="Widget.Material.ActionMode" parent="Widget.ActionMode">
<item name="titleTextStyle">@style/TextAppearance.Material.Widget.ActionMode.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Material.Widget.ActionMode.Subtitle</item>
+ <item name="closeItemLayout">@layout/action_mode_close_item_material</item>
</style>
<style name="Widget.Material.FastScroll" parent="Widget.FastScroll">
@@ -1068,16 +1069,16 @@ please see styles_device_defaults.xml.
<!-- Dialog styles -->
<style name="AlertDialog.Material" parent="AlertDialog">
- <item name="fullDark">@color/transparent</item>
- <item name="topDark">@color/transparent</item>
- <item name="centerDark">@color/transparent</item>
- <item name="bottomDark">@color/transparent</item>
- <item name="fullBright">@color/transparent</item>
- <item name="topBright">@color/transparent</item>
- <item name="centerBright">@color/transparent</item>
- <item name="bottomBright">@color/transparent</item>
- <item name="bottomMedium">@color/transparent</item>
- <item name="centerMedium">@color/transparent</item>
+ <item name="fullDark">@null</item>
+ <item name="topDark">@null</item>
+ <item name="centerDark">@null</item>
+ <item name="bottomDark">@null</item>
+ <item name="fullBright">@null</item>
+ <item name="topBright">@null</item>
+ <item name="centerBright">@null</item>
+ <item name="bottomBright">@null</item>
+ <item name="bottomMedium">@null</item>
+ <item name="centerMedium">@null</item>
<item name="layout">@layout/alert_dialog_material</item>
<item name="listLayout">@layout/select_dialog_material</item>
<item name="progressLayout">@layout/progress_dialog_material</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 06bd2ec..1b0f9c4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -283,6 +283,7 @@
<java-symbol type="bool" name="config_camera_sound_forced" />
<java-symbol type="bool" name="config_dontPreferApn" />
<java-symbol type="bool" name="config_restartRadioAfterProvisioning" />
+ <java-symbol type="bool" name="config_requireRadioPowerOffOnSimRefreshReset" />
<java-symbol type="bool" name="config_speed_up_audio_on_mt_calls" />
<java-symbol type="bool" name="config_useFixedVolume" />
<java-symbol type="bool" name="config_forceDefaultOrientation" />
@@ -2000,4 +2001,5 @@
<java-symbol type="id" name="parentMatrix" />
<java-symbol type="bool" name="config_auto_attach_data_on_creation" />
<java-symbol type="id" name="date_picker_month_day_year_layout" />
+ <java-symbol type="attr" name="closeItemLayout" />
</resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 2296a12..ab5cd5a 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -306,7 +306,7 @@ please see themes_device_defaults.xml.
<item name="actionOverflowMenuStyle">@style/Widget.Material.PopupMenu.Overflow</item>
<item name="actionModeBackground">@drawable/cab_background_top_material</item>
<item name="actionModeSplitBackground">@drawable/cab_background_bottom_material</item>
- <item name="actionModeCloseDrawable">@drawable/ic_cab_done_material</item>
+ <item name="actionModeCloseDrawable">@drawable/ic_ab_back_material</item>
<item name="actionBarTabStyle">@style/Widget.Material.ActionBar.TabView</item>
<item name="actionBarTabBarStyle">@style/Widget.Material.ActionBar.TabBar</item>
<item name="actionBarTabTextStyle">@style/Widget.Material.ActionBar.TabText</item>
@@ -652,7 +652,7 @@ please see themes_device_defaults.xml.
<item name="actionOverflowMenuStyle">@style/Widget.Material.Light.PopupMenu.Overflow</item>
<item name="actionModeBackground">@drawable/cab_background_top_material</item>
<item name="actionModeSplitBackground">@drawable/cab_background_bottom_material</item>
- <item name="actionModeCloseDrawable">@drawable/ic_cab_done_material</item>
+ <item name="actionModeCloseDrawable">@drawable/ic_ab_back_material</item>
<item name="actionBarTabStyle">@style/Widget.Material.Light.ActionBar.TabView</item>
<item name="actionBarTabBarStyle">@style/Widget.Material.Light.ActionBar.TabBar</item>
<item name="actionBarTabTextStyle">@style/Widget.Material.Light.ActionBar.TabText</item>
diff --git a/core/tests/ConnectivityManagerTest/assets/accesspoints.xml b/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
deleted file mode 100644
index ce6eebc..0000000
--- a/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <accesspoint>
- <ssid>opennet</ssid>
- <security>NONE</security>
- </accesspoint>
- <accesspoint>
- <ssid>GoogleGuest</ssid>
- <security>NONE</security>
- </accesspoint>
- <accesspoint>
- <ssid>securenetdhcp</ssid>
- <security>PSK</security>
- <password>androidwifi</password>
- </accesspoint>
- <accesspoint>
- <ssid>securenetstatic</ssid>
- <security>PSK</security>
- <password>androidwifi</password>
- <ip>192.168.14.2</ip>
- <gateway>192.168.14.1</gateway>
- <networkprefixlength>24</networkprefixlength>
- <dns1>192.168.14.1</dns1>
- <dns2>192.168.1.9</dns2>
- </accesspoint>
-<!-- TODO: This AP is outdated and only supports 2.4GHz.
- Need to switch to a new dual-band AP.
- Enable this test case again once the configuration is completed.
- bug#: 9470594
- <accesspoint>
- <ssid>botnet</ssid>
- <security>EAP</security>
- <eap>PEAP</eap>
- <phase2>MSCHAPV2</phase2>
- <identity>donut</identity>
- <password>android</password>
- </accesspoint>
--->
-</resources>
-
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
deleted file mode 100644
index 1222c8b..0000000
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ /dev/null
@@ -1,373 +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.connectivitymanagertest;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
-import android.net.LinkAddress;
-import android.net.RouteInfo;
-import android.net.StaticIpConfiguration;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.AuthAlgorithm;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiEnterpriseConfig;
-
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.List;
-
-
-/**
- * Help class to process configurations of access points saved in an XML file.
- * The configurations of an access point is included in tag
- * <accesspoint></accesspoint>. The supported configuration includes: ssid,
- * security, eap, phase2, identity, password, anonymousidentity, cacert, usercert,
- * in which each is included in the corresponding tags. Static IP setting is also supported.
- * Tags that can be used include: ip, gateway, networkprefixlength, dns1, dns2. All access points
- * have to be enclosed in tags of <resources></resources>.
- *
- * The following is a sample configuration file for an access point using EAP-PEAP with MSCHAP2.
- * <resources>
- * <accesspoint>
- * <ssid>testnet</ssid>
- * <security>EAP</security>
- * <eap>PEAP</eap>
- * <phase2>MSCHAP2</phase2>
- * <identity>donut</identity</identity>
- * <password>abcdefgh</password>
- * </accesspoint>
- * </resources>
- *
- * Note:ssid and security have to be the first two tags
- * for static ip setting, tag "ip" should be listed before other fields: dns, gateway,
- * networkprefixlength.
- */
-public class AccessPointParserHelper {
- static final int NONE = 0;
- static final int WEP = 1;
- static final int PSK = 2;
- static final int EAP = 3;
-
- List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
-
- private int getSecurityType (String security) {
- if (security.equalsIgnoreCase("NONE")) {
- return NONE;
- } else if (security.equalsIgnoreCase("WEP")) {
- return WEP;
- } else if (security.equalsIgnoreCase("PSK")) {
- return PSK;
- } else if (security.equalsIgnoreCase("EAP")) {
- return EAP;
- } else {
- return -1;
- }
- }
-
- private boolean validateEapValue(String value) {
- if (value.equalsIgnoreCase("PEAP") ||
- value.equalsIgnoreCase("TLS") ||
- value.equalsIgnoreCase("TTLS")) {
- return true;
- } else {
- return false;
- }
- }
-
- DefaultHandler mHandler = new DefaultHandler() {
-
- boolean ssid = false;
- boolean security = false;
- boolean password = false;
- boolean ip = false;
- boolean gateway = false;
- boolean networkprefix = false;
- boolean dns1 = false;
- boolean dns2 = false;
- boolean eap = false;
- boolean phase2 = false;
- boolean identity = false;
- boolean anonymousidentity = false;
- boolean cacert = false;
- boolean usercert = false;
- WifiConfiguration config = null;
- int securityType = NONE;
- StaticIpConfiguration mStaticIpConfiguration = null;
- InetAddress mInetAddr = null;
-
- @Override
- public void startElement(String uri, String localName, String tagName,
- Attributes attributes) throws SAXException {
- if (tagName.equalsIgnoreCase("accesspoint")) {
- config = new WifiConfiguration();
- }
- if (tagName.equalsIgnoreCase("ssid")) {
- ssid = true;
- }
- if (tagName.equalsIgnoreCase("security")) {
- security = true;
- }
- if (tagName.equalsIgnoreCase("password")) {
- password = true;
- }
- if (tagName.equalsIgnoreCase("eap")) {
- eap = true;
- }
- if (tagName.equalsIgnoreCase("phase2")) {
- phase2 = true;
- }
- if (tagName.equalsIgnoreCase("identity")) {
- identity = true;
- }
- if (tagName.equalsIgnoreCase("anonymousidentity")) {
- anonymousidentity = true;
- }
- if (tagName.equalsIgnoreCase("cacert")) {
- cacert = true;
- }
- if (tagName.equalsIgnoreCase("usercert")) {
- usercert = true;
- }
- if (tagName.equalsIgnoreCase("ip")) {
- mStaticIpConfiguration = new StaticIpConfiguration();
- ip = true;
- }
- if (tagName.equalsIgnoreCase("gateway")) {
- gateway = true;
- }
- if (tagName.equalsIgnoreCase("networkprefixlength")) {
- networkprefix = true;
- }
- if (tagName.equalsIgnoreCase("dns1")) {
- dns1 = true;
- }
- if (tagName.equalsIgnoreCase("dns2")) {
- dns2 = true;
- }
- }
-
- @Override
- public void endElement(String uri, String localName, String tagName) throws SAXException {
- if (tagName.equalsIgnoreCase("accesspoint")) {
- if (mStaticIpConfiguration != null) {
- config.setIpAssignment(IpAssignment.STATIC);
- config.setStaticIpConfiguration(mStaticIpConfiguration);
- } else {
- config.setIpAssignment(IpAssignment.DHCP);
- }
- config.setProxySettings(ProxySettings.NONE);
- networks.add(config);
- mStaticIpConfiguration = null;
- }
- }
-
- @Override
- public void characters(char ch[], int start, int length) throws SAXException {
- if (ssid) {
- config.SSID = new String(ch, start, length);
- ssid = false;
- }
- if (security) {
- String securityStr = (new String(ch, start, length)).toUpperCase();
- securityType = getSecurityType(securityStr);
- switch (securityType) {
- case NONE:
- config.allowedKeyManagement.set(KeyMgmt.NONE);
- break;
- case WEP:
- config.allowedKeyManagement.set(KeyMgmt.NONE);
- config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
- config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
- break;
- case PSK:
- config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
- break;
- case EAP:
- config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
- config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
- // Initialize other fields.
- config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
- config.enterpriseConfig.setCaCertificateAlias("");
- config.enterpriseConfig.setClientCertificateAlias("");
- config.enterpriseConfig.setIdentity("");
- config.enterpriseConfig.setAnonymousIdentity("");
- break;
- default:
- throw new SAXException();
- }
- security = false;
- }
- if (password) {
- String passwordStr = new String(ch, start, length);
- int len = passwordStr.length();
- if (len == 0) {
- throw new SAXException();
- }
- if (securityType == WEP) {
- if ((len == 10 || len == 26 || len == 58) &&
- passwordStr.matches("[0-9A-Fa-f]*")) {
- config.wepKeys[0] = passwordStr;
- } else {
- config.wepKeys[0] = '"' + passwordStr + '"';
- }
- } else if (securityType == PSK) {
- if (passwordStr.matches("[0-9A-Fa-f]{64}")) {
- config.preSharedKey = passwordStr;
- } else {
- config.preSharedKey = '"' + passwordStr + '"';
- }
- } else if (securityType == EAP) {
- config.enterpriseConfig.setPassword(passwordStr);
- } else {
- throw new SAXException();
- }
- password = false;
- }
- if (eap) {
- String eapValue = new String(ch, start, length);
- if (!validateEapValue(eapValue)) {
- throw new SAXException();
- }
- if (eapValue.equals("TLS")) {
- config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
- } else if (eapValue.equals("TTLS")) {
- config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
- } else if (eapValue.equals("PEAP")) {
- config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
- }
- eap = false;
- }
- if (phase2) {
- String phase2Value = new String(ch, start, length);
- if (phase2Value.equals("PAP")) {
- config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP);
- } else if (phase2Value.equals("MSCHAP")) {
- config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAP);
- } else if (phase2Value.equals("MSCHAPV2")) {
- config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
- } else if (phase2Value.equals("GTC")) {
- config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
- }
- phase2 = false;
- }
- if (identity) {
- String identityValue = new String(ch, start, length);
- config.enterpriseConfig.setIdentity(identityValue);
- identity = false;
- }
- if (anonymousidentity) {
- String anonyId = new String(ch, start, length);
- config.enterpriseConfig.setAnonymousIdentity(anonyId);
- anonymousidentity = false;
- }
- if (cacert) {
- String cacertValue = new String(ch, start, length);
- config.enterpriseConfig.setCaCertificateAlias(cacertValue);
- cacert = false;
- }
- if (usercert) {
- String usercertValue = new String(ch, start, length);
- config.enterpriseConfig.setClientCertificateAlias(usercertValue);
- usercert = false;
- }
- if (ip) {
- try {
- String ipAddr = new String(ch, start, length);
- if (!InetAddress.isNumeric(ipAddr)) {
- throw new SAXException();
- }
- mInetAddr = InetAddress.getByName(ipAddr);
- } catch (UnknownHostException e) {
- throw new SAXException();
- }
- ip = false;
- }
- if (gateway) {
- try {
- String gwAddr = new String(ch, start, length);
- if (!InetAddress.isNumeric(gwAddr)) {
- throw new SAXException();
- }
- mStaticIpConfiguration.gateway = InetAddress.getByName(gwAddr);
- } catch (UnknownHostException e) {
- throw new SAXException();
- }
- gateway = false;
- }
- if (networkprefix) {
- try {
- int nwPrefixLength = Integer.parseInt(new String(ch, start, length));
- if ((nwPrefixLength < 0) || (nwPrefixLength > 32)) {
- throw new SAXException();
- }
- mStaticIpConfiguration.ipAddress = new LinkAddress(mInetAddr, nwPrefixLength);
- } catch (NumberFormatException e) {
- throw new SAXException();
- }
- networkprefix = false;
- }
- if (dns1) {
- try {
- String dnsAddr = new String(ch, start, length);
- if (!InetAddress.isNumeric(dnsAddr)) {
- throw new SAXException();
- }
- mStaticIpConfiguration.dnsServers.add(InetAddress.getByName(dnsAddr));
- } catch (UnknownHostException e) {
- throw new SAXException();
- }
- dns1 = false;
- }
- if (dns2) {
- try {
- String dnsAddr = new String(ch, start, length);
- if (!InetAddress.isNumeric(dnsAddr)) {
- throw new SAXException();
- }
- mStaticIpConfiguration.dnsServers.add(InetAddress.getByName(dnsAddr));
- } catch (UnknownHostException e) {
- throw new SAXException();
- }
- dns2 = false;
- }
- }
- };
-
- /**
- * Process the InputStream in
- * @param in is the InputStream that can be used for XML parsing
- * @throws Exception
- */
- public AccessPointParserHelper(InputStream in) throws Exception {
- SAXParserFactory factory = SAXParserFactory.newInstance();
- SAXParser saxParser = factory.newSAXParser();
- saxParser.parse(in, mHandler);
- }
-
- public List<WifiConfiguration> getNetworkConfigurations() throws Exception {
- return networks;
- }
-}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
index 0f9d8e9..a3c5351 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
@@ -26,7 +26,6 @@ import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -35,10 +34,8 @@ import android.util.Log;
import android.view.KeyEvent;
import java.io.IOException;
-import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.List;
-import java.util.regex.Pattern;
/**
@@ -52,8 +49,6 @@ import java.util.regex.Pattern;
*/
public class ConnectivityManagerTestBase extends InstrumentationTestCase {
- private static final String LOG_TAG = "ConnectivityManagerTestBase";
- private static final String ACCESS_POINT_FILE = "accesspoints.xml";
private static final String PING_IP_ADDR = "8.8.8.8";
protected static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
@@ -69,9 +64,10 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
protected static final int FAILURE = 1;
protected static final int INIT = -1;
+ protected final String mLogTag;
+
private ConnectivityReceiver mConnectivityReceiver = null;
private WifiReceiver mWifiReceiver = null;
- private AccessPointParserHelper mParseHelper = null;
private long mLastConnectivityChangeTime = -1;
protected ConnectivityManager mCm;
@@ -82,6 +78,11 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
/* Control Wifi States */
public WifiManager mWifiManager;
+ public ConnectivityManagerTestBase(String logTag) {
+ super();
+ mLogTag = logTag;
+ }
+
protected long getLastConnectivityChangeTime() {
return mLastConnectivityChangeTime;
}
@@ -94,7 +95,7 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
@Override
public void onReceive(Context context, Intent intent) {
mLastConnectivityChangeTime = SystemClock.uptimeMillis();
- log("ConnectivityReceiver: " + intent);
+ logv("ConnectivityReceiver: " + intent);
String action = intent.getAction();
if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
@@ -108,7 +109,7 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
String action = intent.getAction();
Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
- log("scan results are available");
+ logv("scan results are available");
synchronized (mWifiScanResultLock) {
mLastScanResult = mWifiManager.getScanResults();
mWifiScanResultLock.notifyAll();
@@ -130,7 +131,7 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
if (mWifiManager.isWifiApEnabled()) {
// if soft AP is enabled, disable it
mWifiManager.setWifiApEnabled(null, false);
- log("Disable soft ap");
+ logv("Disable soft ap");
}
// register a connectivity receiver for CONNECTIVITY_ACTION;
@@ -148,32 +149,25 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
mIntentFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
mContext.registerReceiver(mWifiReceiver, mIntentFilter);
- log("Clear Wifi before we start the test.");
+ logv("Clear Wifi before we start the test.");
removeConfiguredNetworksAndDisableWifi();
}
- protected List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
- InputStream in = mContext.getAssets().open(ACCESS_POINT_FILE);
- mParseHelper = new AccessPointParserHelper(in);
- return mParseHelper.getNetworkConfigurations();
- }
-
// wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING,
// DISCONNECTED, UNKNOWN
protected boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
long startTime = SystemClock.uptimeMillis();
while (true) {
NetworkInfo ni = mCm.getNetworkInfo(networkType);
- String niString = ni == null ? "null" : ni.toString();
if (ni != null && expectedState.equals(ni.getState())) {
- log("waitForNetworkState success: " + niString);
+ logv("waitForNetworkState success: %s", ni);
return true;
}
if ((SystemClock.uptimeMillis() - startTime) > timeout) {
- log("waitForNetworkState timeout: " + niString);
+ logv("waitForNetworkState timeout: %s", ni);
return false;
}
- log("waitForNetworkState interim: " + niString);
+ logv("waitForNetworkState interim: %s", ni);
SystemClock.sleep(SHORT_TIMEOUT);
}
}
@@ -185,16 +179,14 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
while (true) {
int state = mWifiManager.getWifiState();
if (state == expectedState) {
- log("waitForWifiState success: state=" + state);
+ logv("waitForWifiState success: state=" + state);
return true;
}
if ((SystemClock.uptimeMillis() - startTime) > timeout) {
- log(String.format("waitForWifiState timeout: expected=%d, actual=%d",
- expectedState, state));
+ logv("waitForWifiState timeout: expected=%d, actual=%d", expectedState, state);
return false;
}
- log(String.format("waitForWifiState interim: expected=%d, actual=%d",
- expectedState, state));
+ logv("waitForWifiState interim: expected=%d, actual=%d", expectedState, state);
SystemClock.sleep(SHORT_TIMEOUT);
}
}
@@ -206,15 +198,15 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
while (true) {
int state = mWifiManager.getWifiApState();
if (state == expectedState) {
- log("waitForWifiAPState success: state=" + state);
+ logv("waitForWifiAPState success: state=" + state);
return true;
}
if ((SystemClock.uptimeMillis() - startTime) > timeout) {
- log(String.format("waitForWifiAPState timeout: expected=%d, actual=%d",
+ logv(String.format("waitForWifiAPState timeout: expected=%d, actual=%d",
expectedState, state));
return false;
}
- log(String.format("waitForWifiAPState interim: expected=%d, actual=%d",
+ logv(String.format("waitForWifiAPState interim: expected=%d, actual=%d",
expectedState, state));
SystemClock.sleep(SHORT_TIMEOUT);
}
@@ -269,7 +261,7 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
// Turn screen off
protected void turnScreenOff() {
- log("Turn screen off");
+ logv("Turn screen off");
PowerManager pm =
(PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
pm.goToSleep(SystemClock.uptimeMillis());
@@ -277,7 +269,7 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
// Turn screen on
protected void turnScreenOn() {
- log("Turn screen on");
+ logv("Turn screen on");
PowerManager pm =
(PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
pm.wakeUp(SystemClock.uptimeMillis());
@@ -305,7 +297,7 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
// assume the chance that all servers are down is very small
for (int i = 0; i < hostList.length; i++ ) {
String host = hostList[i];
- log("Start ping test, ping " + host);
+ logv("Start ping test, ping " + host);
Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
int status = p.waitFor();
if (status == 0) {
@@ -314,11 +306,11 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
}
}
} catch (UnknownHostException e) {
- log("Ping test Fail: Unknown Host");
+ logv("Ping test Fail: Unknown Host");
} catch (IOException e) {
- log("Ping test Fail: IOException");
+ logv("Ping test Fail: IOException");
} catch (InterruptedException e) {
- log("Ping test Fail: InterruptedException");
+ logv("Ping test Fail: InterruptedException");
}
}
// ping test timeout
@@ -331,29 +323,22 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
* We don't verify whether the connection is successful or not, leave this to the test
*/
protected boolean connectToWifi(String knownSSID) {
- WifiConfiguration config = new WifiConfiguration();
- config.SSID = knownSSID;
- config.allowedKeyManagement.set(KeyMgmt.NONE);
+ WifiConfiguration config = WifiConfigurationHelper.createOpenConfig(knownSSID);
return connectToWifiWithConfiguration(config);
}
/**
* Connect to Wi-Fi with the given configuration. Note the SSID in the configuration
* is pure string, we need to convert it to quoted string.
- * @param config
- * @return
*/
protected boolean connectToWifiWithConfiguration(WifiConfiguration config) {
- String ssid = config.SSID;
- config.SSID = convertToQuotedString(ssid);
-
// If Wifi is not enabled, enable it
if (!mWifiManager.isWifiEnabled()) {
- log("Wifi is not enabled, enable it");
+ logv("Wifi is not enabled, enable it");
mWifiManager.setWifiEnabled(true);
// wait for the wifi state change before start scanning.
if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT)) {
- log("wait for WIFI_STATE_ENABLED failed");
+ logv("wait for WIFI_STATE_ENABLED failed");
return false;
}
}
@@ -361,10 +346,13 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
// Save network configuration and connect to network without scanning
mWifiManager.connect(config,
new WifiManager.ActionListener() {
+ @Override
public void onSuccess() {
}
+
+ @Override
public void onFailure(int reason) {
- log("connect failure " + reason);
+ logv("connect failure " + reason);
}
});
return true;
@@ -376,25 +364,28 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
protected boolean disconnectAP() {
// remove saved networks
if (!mWifiManager.isWifiEnabled()) {
- log("Enabled wifi before remove configured networks");
+ logv("Enabled wifi before remove configured networks");
mWifiManager.setWifiEnabled(true);
SystemClock.sleep(SHORT_TIMEOUT);
}
List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks();
if (wifiConfigList == null) {
- log("no configuration list is null");
+ logv("no configuration list is null");
return true;
}
- log("size of wifiConfigList: " + wifiConfigList.size());
+ logv("size of wifiConfigList: " + wifiConfigList.size());
for (WifiConfiguration wifiConfig: wifiConfigList) {
- log("remove wifi configuration: " + wifiConfig.networkId);
+ logv("remove wifi configuration: " + wifiConfig.networkId);
int netId = wifiConfig.networkId;
mWifiManager.forget(netId, new WifiManager.ActionListener() {
+ @Override
public void onSuccess() {
}
+
+ @Override
public void onFailure(int reason) {
- log("Failed to forget " + reason);
+ logv("Failed to forget " + reason);
}
});
}
@@ -431,15 +422,14 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
long startTime = SystemClock.uptimeMillis();
while (true) {
NetworkInfo ni = mCm.getActiveNetworkInfo();
- String niString = ni == null ? "null" : ni.toString();
if (ni != null && ni.isConnected()) {
return true;
}
if ((SystemClock.uptimeMillis() - startTime) > timeout) {
- log("waitForActiveNetworkConnection timeout: " + niString);
+ logv("waitForActiveNetworkConnection timeout: %s", ni);
return false;
}
- log("waitForActiveNetworkConnection interim: " + niString);
+ logv("waitForActiveNetworkConnection interim: %s", ni);
SystemClock.sleep(SHORT_TIMEOUT);
}
}
@@ -451,12 +441,11 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
if (ni == null) {
return true;
}
- String niString = ni.toString();
if ((SystemClock.uptimeMillis() - startTime) > timeout) {
- log("waitForActiveNetworkConnection timeout: " + niString);
+ logv("waitForActiveNetworkConnection timeout: %s", ni);
return false;
}
- log("waitForActiveNetworkConnection interim: " + niString);
+ logv("waitForActiveNetworkConnection interim: %s", ni);
SystemClock.sleep(SHORT_TIMEOUT);
}
}
@@ -467,12 +456,9 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
try {
Process proc = Runtime.getRuntime().exec(new String[]{
"/system/bin/ping", "-W", "30", "-c", "1", PING_IP_ADDR});
- int exitCode = proc.waitFor();
- return exitCode == 0;
- } catch (InterruptedException ie) {
- Log.e(LOG_TAG, "InterruptedException while waiting for ping");
- } catch (IOException ioe) {
- Log.e(LOG_TAG, "IOException during ping", ioe);
+ return proc.waitFor() == 0;
+ } catch (InterruptedException | IOException e) {
+ Log.e(mLogTag, "Ping failed", e);
}
return false;
}
@@ -489,8 +475,8 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
super.tearDown();
}
- private void log(String message) {
- Log.v(LOG_TAG, message);
+ protected void logv(String format, Object... args) {
+ Log.v(mLogTag, String.format(format, args));
}
/**
@@ -506,22 +492,10 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase {
// step 2: verify Wifi state and network state;
assertTrue("wifi state not connected with " + config.SSID,
waitForNetworkState(ConnectivityManager.TYPE_WIFI,
- State.CONNECTED, LONG_TIMEOUT));
+ State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
// step 3: verify the current connected network is the given SSID
assertNotNull("no active wifi info", mWifiManager.getConnectionInfo());
assertEquals("SSID mismatch", config.SSID, mWifiManager.getConnectionInfo().getSSID());
}
-
- /**
- * checks if the input is a hexadecimal string of given length
- *
- * @param input string to be checked
- * @param length required length of the string
- * @return
- */
- protected static boolean isHex(String input, int length) {
- Pattern p = Pattern.compile(String.format("[0-9A-Fa-f]{%d}", length));
- return p.matcher(input).matches();
- }
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java
new file mode 100644
index 0000000..f0a8367
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java
@@ -0,0 +1,364 @@
+/*
+ * 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.connectivitymanagertest;
+
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.LinkAddress;
+import android.net.StaticIpConfiguration;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiEnterpriseConfig;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helper for dealing with creating {@link WifiConfiguration} objects.
+ */
+public class WifiConfigurationHelper {
+ private static final int NONE = 0;
+ private static final int WEP = 1;
+ private static final int PSK = 2;
+ private static final int EAP = 3;
+
+ /**
+ * Private constructor since this a static class.
+ */
+ private WifiConfigurationHelper() {}
+
+ /**
+ * Create a {@link WifiConfiguration} for an open network
+ *
+ * @param ssid The SSID of the wifi network
+ * @return The {@link WifiConfiguration}
+ */
+ public static WifiConfiguration createOpenConfig(String ssid) {
+ WifiConfiguration config = createGenericConfig(ssid);
+
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ return config;
+ }
+
+ /**
+ * Create a {@link WifiConfiguration} for a WEP secured network
+ *
+ * @param ssid The SSID of the wifi network
+ * @param password Either a 10, 26, or 58 character hex string or the plain text password
+ * @return The {@link WifiConfiguration}
+ */
+ public static WifiConfiguration createWepConfig(String ssid, String password) {
+ WifiConfiguration config = createGenericConfig(ssid);
+
+ if (isHex(password, 10) || isHex(password, 26) || isHex(password, 58)) {
+ config.wepKeys[0] = password;
+ } else {
+ config.wepKeys[0] = quotedString(password);
+ }
+
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
+ config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+ return config;
+ }
+
+ /**
+ * Create a {@link WifiConfiguration} for a PSK secured network
+ *
+ * @param ssid The SSID of the wifi network
+ * @param password Either a 64 character hex string or the plain text password
+ * @return The {@link WifiConfiguration}
+ */
+ public static WifiConfiguration createPskConfig(String ssid, String password) {
+ WifiConfiguration config = createGenericConfig(ssid);
+
+ if (isHex(password, 64)) {
+ config.preSharedKey = password;
+ } else {
+ config.preSharedKey = quotedString(password);
+ }
+ config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ return config;
+ }
+
+ /**
+ * Create a {@link WifiConfiguration} for an EAP secured network
+ *
+ * @param ssid The SSID of the wifi network
+ * @param password The password
+ * @param eapMethod The EAP method
+ * @param phase2 The phase 2 method or null
+ * @param identity The identity or null
+ * @param anonymousIdentity The anonymous identity or null
+ * @param caCert The CA certificate or null
+ * @param clientCert The client certificate or null
+ * @return The {@link WifiConfiguration}
+ */
+ public static WifiConfiguration createEapConfig(String ssid, String password, int eapMethod,
+ Integer phase2, String identity, String anonymousIdentity, String caCert,
+ String clientCert) {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = quotedString(ssid);
+
+ config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+
+ // Set defaults
+ if (phase2 == null) phase2 = WifiEnterpriseConfig.Phase2.NONE;
+ if (identity == null) identity = "";
+ if (anonymousIdentity == null) anonymousIdentity = "";
+ if (caCert == null) caCert = "";
+ if (clientCert == null) clientCert = "";
+
+ config.enterpriseConfig.setPassword(password);
+ config.enterpriseConfig.setEapMethod(eapMethod);
+ config.enterpriseConfig.setPhase2Method(phase2);
+ config.enterpriseConfig.setIdentity(identity);
+ config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity);
+ config.enterpriseConfig.setCaCertificateAlias(caCert);
+ config.enterpriseConfig.setClientCertificateAlias(clientCert);
+ return config;
+ }
+
+ /**
+ * Create a generic {@link WifiConfiguration} used by the other create methods.
+ */
+ private static WifiConfiguration createGenericConfig(String ssid) {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = quotedString(ssid);
+ config.setIpAssignment(IpAssignment.DHCP);
+ config.setProxySettings(ProxySettings.NONE);
+ return config;
+ }
+
+ /**
+ * Parse a JSON string for WiFi configurations stored as a JSON string.
+ * <p>
+ * This json string should be a list of dictionaries, with each dictionary containing a single
+ * wifi configuration. The wifi configuration requires the fields "ssid" and "security" with
+ * security being one of NONE, WEP, PSK, or EAP. If WEP, PSK, or EAP are selected, the field
+ * "password" must also be provided. If EAP is selected, then the fiels "eap", "phase2",
+ * "identity", "ananymous_identity", "ca_cert", and "client_cert" are also required. Lastly,
+ * static IP settings are also supported. If the field "ip" is set, then the fields "gateway",
+ * "prefix_length", "dns1", and "dns2" are required.
+ * </p>
+ * @throws IllegalArgumentException if the input string was not valid JSON or if any mandatory
+ * fields are missing.
+ */
+ public static List<WifiConfiguration> parseJson(String in) {
+ try {
+ JSONArray jsonConfigs = new JSONArray(in);
+ List<WifiConfiguration> wifiConfigs = new ArrayList<>(jsonConfigs.length());
+
+ for (int i = 0; i < jsonConfigs.length(); i++) {
+ JSONObject jsonConfig = jsonConfigs.getJSONObject(i);
+
+ wifiConfigs.add(getWifiConfiguration(jsonConfig));
+ }
+ return wifiConfigs;
+ } catch (JSONException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Parse a {@link JSONObject} and return the wifi configuration.
+ *
+ * @throws IllegalArgumentException if any mandatory fields are missing.
+ */
+ private static WifiConfiguration getWifiConfiguration(JSONObject jsonConfig)
+ throws JSONException {
+ String ssid = jsonConfig.getString("ssid");
+ String password = null;
+ WifiConfiguration config;
+
+ int securityType = getSecurityType(jsonConfig.getString("security"));
+ switch (securityType) {
+ case NONE:
+ config = createOpenConfig(ssid);
+ break;
+ case WEP:
+ password = jsonConfig.getString("password");
+ config = createWepConfig(ssid, password);
+ break;
+ case PSK:
+ password = jsonConfig.getString("password");
+ config = createPskConfig(ssid, password);
+ break;
+ case EAP:
+ password = jsonConfig.getString("password");
+ int eapMethod = getEapMethod(jsonConfig.getString("eap"));
+ Integer phase2 = null;
+ if (jsonConfig.has("phase2")) {
+ phase2 = getPhase2(jsonConfig.getString("phase2"));
+ }
+ String identity = null;
+ if (jsonConfig.has("identity")) {
+ identity = jsonConfig.getString("identity");
+ }
+ String anonymousIdentity = null;
+ if (jsonConfig.has("anonymous_identity")) {
+ anonymousIdentity = jsonConfig.getString("anonymous_identity");
+ }
+ String caCert = null;
+ if (jsonConfig.has("ca_cert")) {
+ caCert = (jsonConfig.getString("ca_cert"));
+ }
+ String clientCert = null;
+ if (jsonConfig.has("client_cert")) {
+ clientCert = jsonConfig.getString("client_cert");
+ }
+ config = createEapConfig(ssid, password, eapMethod, phase2, identity,
+ anonymousIdentity, caCert, clientCert);
+ break;
+ default:
+ // Should never reach here as getSecurityType will already throw an exception
+ throw new IllegalArgumentException();
+ }
+
+ if (jsonConfig.has("ip")) {
+ StaticIpConfiguration staticIpConfig = new StaticIpConfiguration();
+
+ InetAddress ipAddress = getInetAddress(jsonConfig.getString("ip"));
+ int prefixLength = getPrefixLength(jsonConfig.getInt("prefix_length"));
+ staticIpConfig.ipAddress = new LinkAddress(ipAddress, prefixLength);
+ staticIpConfig.gateway = getInetAddress(jsonConfig.getString("gateway"));
+ staticIpConfig.dnsServers.add(getInetAddress(jsonConfig.getString("dns1")));
+ staticIpConfig.dnsServers.add(getInetAddress(jsonConfig.getString("dns2")));
+
+ config.setIpAssignment(IpAssignment.STATIC);
+ config.setStaticIpConfiguration(staticIpConfig);
+ } else {
+ config.setIpAssignment(IpAssignment.DHCP);
+ }
+
+ config.setProxySettings(ProxySettings.NONE);
+ return config;
+ }
+
+ private static String quotedString(String s) {
+ return String.format("\"%s\"", s);
+ }
+
+ /**
+ * Get the security type from a string.
+ *
+ * @throws IllegalArgumentException if the string is not a supported security type.
+ */
+ private static int getSecurityType(String security) {
+ if ("NONE".equalsIgnoreCase(security)) {
+ return NONE;
+ }
+ if ("WEP".equalsIgnoreCase(security)) {
+ return WEP;
+ }
+ if ("PSK".equalsIgnoreCase(security)) {
+ return PSK;
+ }
+ if ("EAP".equalsIgnoreCase(security)) {
+ return EAP;
+ }
+ throw new IllegalArgumentException("Security type must be one of NONE, WEP, PSK, or EAP");
+ }
+
+ /**
+ * Get the EAP method from a string.
+ *
+ * @throws IllegalArgumentException if the string is not a supported EAP method.
+ */
+ private static int getEapMethod(String eapMethod) {
+ if ("TLS".equalsIgnoreCase(eapMethod)) {
+ return WifiEnterpriseConfig.Eap.TLS;
+ }
+ if ("TTLS".equalsIgnoreCase(eapMethod)) {
+ return WifiEnterpriseConfig.Eap.TTLS;
+ }
+ if ("PEAP".equalsIgnoreCase(eapMethod)) {
+ return WifiEnterpriseConfig.Eap.PEAP;
+ }
+ throw new IllegalArgumentException("EAP method must be one of TLS, TTLS, or PEAP");
+ }
+
+ /**
+ * Get the phase 2 method from a string.
+ *
+ * @throws IllegalArgumentException if the string is not a supported phase 2 method.
+ */
+ private static int getPhase2(String phase2) {
+ if ("PAP".equalsIgnoreCase(phase2)) {
+ return WifiEnterpriseConfig.Phase2.PAP;
+ }
+ if ("MSCHAP".equalsIgnoreCase(phase2)) {
+ return WifiEnterpriseConfig.Phase2.MSCHAP;
+ }
+ if ("MSCHAPV2".equalsIgnoreCase(phase2)) {
+ return WifiEnterpriseConfig.Phase2.MSCHAPV2;
+ }
+ if ("GTC".equalsIgnoreCase(phase2)) {
+ return WifiEnterpriseConfig.Phase2.GTC;
+ }
+ throw new IllegalArgumentException("Phase2 must be one of PAP, MSCHAP, MSCHAPV2, or GTC");
+ }
+
+ /**
+ * Get an {@link InetAddress} from a string
+ *
+ * @throws IllegalArgumentException if the string is not a valid IP address.
+ */
+ private static InetAddress getInetAddress(String ipAddress) {
+ if (!InetAddress.isNumeric(ipAddress)) {
+ throw new IllegalArgumentException(
+ String.format("IP address %s is not numeric", ipAddress));
+ }
+
+ try {
+ return InetAddress.getByName(ipAddress);
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException(
+ String.format("IP address %s could not be resolved", ipAddress));
+ }
+ }
+
+ /**
+ * Get the prefix length from an int.
+ *
+ * @throws IllegalArgumentException if the prefix length is less than 0 or greater than 32.
+ */
+ private static int getPrefixLength(int prefixLength) {
+ if (prefixLength < 0 || prefixLength > 32) {
+ throw new IllegalArgumentException("Prefix length cannot be less than 0 or more than 32");
+ }
+ return prefixLength;
+ }
+
+ /**
+ * Utility method to check if a given string is a hexadecimal string of given length
+ */
+ public static boolean isHex(String input, int length) {
+ if (input == null || length < 0) {
+ return false;
+ }
+ return input.matches(String.format("[0-9A-Fa-f]{%d}", length));
+ }
+}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index 01995c7..b280106 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -23,14 +23,15 @@ import android.net.wifi.WifiManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
-public class ConnectivityManagerMobileTest extends
- ConnectivityManagerTestBase {
- private static final String TAG = "ConnectivityManagerMobileTest";
+public class ConnectivityManagerMobileTest extends ConnectivityManagerTestBase {
+
+ public ConnectivityManagerMobileTest() {
+ super(ConnectivityManagerMobileTest.class.getSimpleName());
+ }
private String mTestAccessPoint;
private boolean mWifiOnlyFlag;
@@ -46,7 +47,7 @@ public class ConnectivityManagerMobileTest extends
// Each test case will start with cellular connection
if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON) == 1) {
- log("airplane is not disabled, disable it.");
+ logv("airplane is not disabled, disable it.");
mCm.setAirplaneMode(false);
}
@@ -77,16 +78,14 @@ public class ConnectivityManagerMobileTest extends
assertTrue("not connected to cellular network", extraNetInfo.isConnected());
}
- private void log(String message) {
- Log.v(TAG, message);
- }
+
// Test case 1: Test enabling Wifi without associating with any AP, no broadcast on network
// event should be expected.
@LargeTest
public void test3GToWifiNotification() {
if (mWifiOnlyFlag) {
- Log.v(TAG, getName() + " is excluded for wifi-only test");
+ logv(getName() + " is excluded for wifi-only test");
return;
}
@@ -225,7 +224,7 @@ public class ConnectivityManagerMobileTest extends
@LargeTest
public void testDataConnectionWith3GToAmTo3G() {
if (mWifiOnlyFlag) {
- Log.v(TAG, getName() + " is excluded for wifi-only test");
+ logv(getName() + " is excluded for wifi-only test");
return;
}
// disable wifi
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
index eb75b0d..c2b80dc 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
@@ -21,16 +21,15 @@ import android.net.NetworkInfo.State;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.GroupCipher;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.PairwiseCipher;
import android.net.wifi.WifiConfiguration.Protocol;
import android.net.wifi.WifiInfo;
import android.os.Bundle;
import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
import com.android.connectivitymanagertest.WifiAssociationTestRunner;
+import com.android.connectivitymanagertest.WifiConfigurationHelper;
/**
* Test Wi-Fi connection with different configuration
@@ -40,7 +39,6 @@ import com.android.connectivitymanagertest.WifiAssociationTestRunner;
* -w com.android.connectivitymanagertest/.WifiAssociationTestRunner"
*/
public class WifiAssociationTest extends ConnectivityManagerTestBase {
- private static final String TAG = "WifiAssociationTest";
private String mSsid = null;
private String mPassword = null;
private String mSecurityType = null;
@@ -51,6 +49,10 @@ public class WifiAssociationTest extends ConnectivityManagerTestBase {
OPEN, WEP64, WEP128, WPA_TKIP, WPA2_AES
}
+ public WifiAssociationTest() {
+ super(WifiAssociationTest.class.getSimpleName());
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -77,90 +79,58 @@ public class WifiAssociationTest extends ConnectivityManagerTestBase {
private void validateFrequencyBand() {
if (mFrequencyBand != null) {
int currentFreq = mWifiManager.getFrequencyBand();
- Log.v(TAG, "read frequency band: " + currentFreq);
+ logv("read frequency band: " + currentFreq);
assertEquals("specified frequency band does not match operational band of WifiManager",
currentFreq, mBand);
}
}
- private void log(String message) {
- Log.v(TAG, message);
- }
-
@LargeTest
public void testWifiAssociation() {
assertNotNull("no test ssid", mSsid);
- WifiConfiguration config = new WifiConfiguration();
- config.SSID = mSsid;
+ WifiConfiguration config = null;
SECURITY_TYPE security = SECURITY_TYPE.valueOf(mSecurityType);
- log("Security type is " + security.toString());
+ logv("Security type is " + security.toString());
switch (security) {
// set network configurations
case OPEN:
- config.allowedKeyManagement.set(KeyMgmt.NONE);
+ config = WifiConfigurationHelper.createOpenConfig(mSsid);
break;
case WEP64:
assertNotNull("password is empty", mPassword);
- config.allowedKeyManagement.set(KeyMgmt.NONE);
- config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
- config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+ // always use hex pair for WEP-40
+ assertTrue(WifiConfigurationHelper.isHex(mPassword, 10));
+ config = WifiConfigurationHelper.createWepConfig(mSsid, mPassword);
config.allowedGroupCiphers.set(GroupCipher.WEP40);
- if (mPassword != null) {
- // always use hex pair for WEP-40
- if (isHex(mPassword, 10)) {
- config.wepKeys[0] = mPassword;
- } else {
- fail("password should be 10-character hex");
- }
- }
break;
case WEP128:
assertNotNull("password is empty", mPassword);
- config.allowedKeyManagement.set(KeyMgmt.NONE);
- config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
- config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+ // always use hex pair for WEP-104
+ assertTrue(WifiConfigurationHelper.isHex(mPassword, 26));
+ config = WifiConfigurationHelper.createWepConfig(mSsid, mPassword);
config.allowedGroupCiphers.set(GroupCipher.WEP104);
- if (mPassword != null) {
- // always use hex pair for WEP-104
- if (isHex(mPassword, 26)) {
- config.wepKeys[0] = mPassword;
- } else {
- fail("password should be 26-character hex");
- }
- }
break;
case WPA_TKIP:
assertNotNull("password is empty", mPassword);
- config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ config = WifiConfigurationHelper.createPskConfig(mSsid, mPassword);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedProtocols.set(Protocol.WPA);
config.allowedPairwiseCiphers.set(PairwiseCipher.TKIP);
config.allowedGroupCiphers.set(GroupCipher.TKIP);
- if (isHex(mPassword, 64)) {
- config.preSharedKey = mPassword;
- } else {
- config.preSharedKey = '"' + mPassword + '"';
- }
break;
case WPA2_AES:
assertNotNull("password is empty", mPassword);
- config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ config = WifiConfigurationHelper.createPskConfig(mSsid, mPassword);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedProtocols.set(Protocol.RSN);
config.allowedPairwiseCiphers.set(PairwiseCipher.CCMP);
config.allowedGroupCiphers.set(GroupCipher.CCMP);
- config.allowedProtocols.set(Protocol.RSN);
- if (isHex(mPassword, 64)) {
- config.preSharedKey = mPassword;
- } else {
- config.preSharedKey = '"' + mPassword + '"';
- }
break;
default:
fail("Not a valid security type: " + mSecurityType);
break;
}
- Log.v(TAG, "network config: " + config.toString());
+ logv("network config: %s", config.toString());
connectToWifi(config);
// verify that connection actually works
assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
index 740ffb8..b37daa3 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -16,54 +16,38 @@
package com.android.connectivitymanagertest.functional;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo.State;
import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
+import android.os.SystemClock;
import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
+import com.android.connectivitymanagertest.WifiConfigurationHelper;
-import java.util.ArrayList;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
import java.util.List;
/**
* Test Wi-Fi connection with different configuration
* To run this tests:
- * adb shell am instrument -e class
- * com.android.connectivitymanagertest.functional.WifiConnectionTest
- * -w com.android.connectivitymanagertest/.ConnectivityManagerTestRunner
+ * adb shell am instrument \
+ * -e class com.android.connectivitymanagertest.functional.WifiConnectionTest \
+ * -w com.android.connectivitymanagertest/.ConnectivityManagerTestRunner
*/
-public class WifiConnectionTest
- extends ConnectivityManagerTestBase {
- private static final String TAG = "WifiConnectionTest";
- private static final boolean DEBUG = false;
- private List<WifiConfiguration> mNetworks = new ArrayList<WifiConfiguration>();
+public class WifiConnectionTest extends ConnectivityManagerTestBase {
+ private static final String WIFI_CONFIG_FILE = "/data/wifi_configs.json";
+ private static final long PAUSE_DURATION_MS = 60 * 1000;
+
+ public WifiConnectionTest() {
+ super(WifiConnectionTest.class.getSimpleName());
+ }
@Override
public void setUp() throws Exception {
super.setUp();
- mNetworks = loadNetworkConfigurations();
- if (DEBUG) {
- printNetworkConfigurations();
- }
-
- // enable wifi and verify wpa_supplicant is started
- assertTrue("enable Wifi failed", enableWifi());
- assertTrue("wifi not connected", waitForNetworkState(
- ConnectivityManager.TYPE_WIFI, State.CONNECTED, LONG_TIMEOUT));
- WifiInfo wi = mWifiManager.getConnectionInfo();
- assertNotNull("no active wifi info", wi);
- assertTrue("failed to ping wpa_supplicant ", mWifiManager.pingSupplicant());
- }
-
- private void printNetworkConfigurations() {
- log("==== print network configurations parsed from XML file ====");
- log("number of access points: " + mNetworks.size());
- for (WifiConfiguration config : mNetworks) {
- log(config.toString());
- }
+ assertTrue("Failed to enable wifi", enableWifi());
}
@Override
@@ -72,25 +56,67 @@ public class WifiConnectionTest
super.tearDown();
}
- private void log(String message) {
- Log.v(TAG, message);
- }
-
@LargeTest
public void testWifiConnections() {
- for (int i = 0; i < mNetworks.size(); i++) {
- String ssid = mNetworks.get(i).SSID;
- log("-- START Wi-Fi connection test to : " + ssid + " --");
- connectToWifi(mNetworks.get(i));
+ List<WifiConfiguration> wifiConfigs = loadConfigurations();
+
+ printWifiConfigurations(wifiConfigs);
+
+ assertFalse("No configurations to test against", wifiConfigs.isEmpty());
+
+ boolean shouldPause = false;
+ for (WifiConfiguration config : wifiConfigs) {
+ if (shouldPause) {
+ logv("Pausing for %d seconds", PAUSE_DURATION_MS / 1000);
+ SystemClock.sleep(PAUSE_DURATION_MS);
+ }
+ logv("Start wifi connection test to: %s", config.SSID);
+ connectToWifi(config);
+
// verify that connection actually works
- assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
- log("-- END Wi-Fi connection test to " + ssid + " -- ");
- log("pausing for 1 minute");
- try {
- Thread.sleep(60 * 1000);
- } catch (InterruptedException e) {
- // ignore
+ assertTrue("No connectivity at end of test", checkNetworkConnectivity());
+
+ // Disconnect and remove the network
+ assertTrue("Unable to remove network", disconnectAP());
+ logv("End wifi connection test to: %s", config.SSID);
+
+ shouldPause = true;
+ }
+ }
+
+ /**
+ * Load the configuration file from the root of the data partition
+ */
+ private List<WifiConfiguration> loadConfigurations() {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(new File(WIFI_CONFIG_FILE)));
+ StringBuffer jsonBuffer = new StringBuffer();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ jsonBuffer.append(line);
+ }
+ return WifiConfigurationHelper.parseJson(jsonBuffer.toString());
+ } catch (IllegalArgumentException | IOException e) {
+ throw new AssertionError("Error parsing file", e);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ // Ignore
+ }
}
}
}
+
+ /**
+ * Print the wifi configurations to test against.
+ */
+ private void printWifiConfigurations(List<WifiConfiguration> wifiConfigs) {
+ logv("Wifi configurations to be tested");
+ for (WifiConfiguration config : wifiConfigs) {
+ logv(config.toString());
+ }
+ }
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index aead65b..41f01e6 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -17,16 +17,15 @@
package com.android.connectivitymanagertest.stress;
-import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
-import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
-
import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
+
+import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
+import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
import java.io.BufferedWriter;
import java.io.File;
@@ -35,9 +34,7 @@ import java.io.FileWriter;
/**
* Stress test setting up device as wifi hotspot
*/
-public class WifiApStress
- extends ConnectivityManagerTestBase {
- private final static String TAG = "WifiApStress";
+public class WifiApStress extends ConnectivityManagerTestBase {
private static String NETWORK_ID = "AndroidAPTest";
private static String PASSWD = "androidwifi";
private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
@@ -46,6 +43,10 @@ public class WifiApStress
private int mLastIteration = 0;
private boolean mWifiOnlyFlag;
+ public WifiApStress() {
+ super(WifiApStress.class.getSimpleName());
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -71,7 +72,7 @@ public class WifiApStress
@LargeTest
public void testWifiHotSpot() {
if (mWifiOnlyFlag) {
- Log.v(TAG, this.getName() + " is excluded for wi-fi only test");
+ logv(getName() + " is excluded for wi-fi only test");
return;
}
WifiConfiguration config = new WifiConfiguration();
@@ -95,7 +96,7 @@ public class WifiApStress
}
int i;
for (i = 0; i < mTotalIterations; i++) {
- Log.v(TAG, "iteration: " + i);
+ logv("iteration: " + i);
mLastIteration = i;
// enable Wifi tethering
assertTrue("failed to enable wifi hotspot",
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 6ef4f06..fbd4669 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -19,13 +19,10 @@ package com.android.connectivitymanagertest.stress;
import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
@@ -37,6 +34,7 @@ import android.util.Log;
import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
+import com.android.connectivitymanagertest.WifiConfigurationHelper;
import java.io.BufferedWriter;
import java.io.File;
@@ -52,8 +50,6 @@ import java.util.List;
* -w com.android.connectivitymanagertest/.ConnectivityManagerStressTestRunner
*/
public class WifiStressTest extends ConnectivityManagerTestBase {
- private final static String TAG = "WifiStressTest";
-
private final static long SCREEN_OFF_TIMER = 500; //500ms
/**
* Wi-Fi idle time for default sleep policy
@@ -78,6 +74,10 @@ public class WifiStressTest extends ConnectivityManagerTestBase {
private BufferedWriter mOutputWriter = null;
private boolean mWifiOnlyFlag;
+ public WifiStressTest() {
+ super(WifiStressTest.class.getSimpleName());
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -89,14 +89,14 @@ public class WifiStressTest extends ConnectivityManagerTestBase {
mScanIterations = mRunner.getScanIterations();
mWifiSleepTime = mRunner.getSleepTime();
mWifiOnlyFlag = mRunner.isWifiOnly();
- log(String.format("mReconnectIterations(%d), mSsid(%s), mPassword(%s),"
+ logv(String.format("mReconnectIterations(%d), mSsid(%s), mPassword(%s),"
+ "mScanIterations(%d), mWifiSleepTime(%d)", mReconnectIterations, mSsid,
mPassword, mScanIterations, mWifiSleepTime));
mOutputWriter = new BufferedWriter(new FileWriter(new File(
Environment.getExternalStorageDirectory(), OUTPUT_FILE), true));
turnScreenOn();
if (!mWifiManager.isWifiEnabled()) {
- log("Enable wi-fi before stress tests.");
+ logv("Enable wi-fi before stress tests.");
if (!enableWifi()) {
tearDown();
fail("enable wifi failed.");
@@ -107,7 +107,7 @@ public class WifiStressTest extends ConnectivityManagerTestBase {
@Override
protected void tearDown() throws Exception {
- log("tearDown()");
+ logv("tearDown()");
if (mOutputWriter != null) {
mOutputWriter.close();
}
@@ -115,23 +115,19 @@ public class WifiStressTest extends ConnectivityManagerTestBase {
}
private void writeOutput(String s) {
- log("write message: " + s);
+ logv("write message: " + s);
if (mOutputWriter == null) {
- log("no writer attached to file " + OUTPUT_FILE);
+ logv("no writer attached to file " + OUTPUT_FILE);
return;
}
try {
mOutputWriter.write(s + "\n");
mOutputWriter.flush();
} catch (IOException e) {
- log("failed to write output.");
+ logv("failed to write output.");
}
}
- public void log(String message) {
- Log.v(TAG, message);
- }
-
private void sleep(long sometime, String errorMsg) {
try {
Thread.sleep(sometime);
@@ -149,7 +145,7 @@ public class WifiStressTest extends ConnectivityManagerTestBase {
long scanTimeSum = 0, i, averageScanTime = -1;
int ssidAppearInScanResultsCount = 0; // count times of given ssid appear in scan results.
for (i = 1; i <= mScanIterations; i++) {
- log("testWifiScanning: iteration: " + i);
+ logv("testWifiScanning: iteration: " + i);
averageScanTime = scanTimeSum / i;
writeOutput(String.format("iteration %d out of %d", i, mScanIterations));
writeOutput(String.format("average scanning time is %d", averageScanTime));
@@ -173,9 +169,9 @@ public class WifiStressTest extends ConnectivityManagerTestBase {
if (scanResultLocal == null || scanResultLocal.isEmpty()) {
fail("Scan results are empty ");
}
- log("size of scan result list: " + scanResultLocal.size());
+ logv("size of scan result list: " + scanResultLocal.size());
for (ScanResult sr : scanResultLocal) {
- log(String.format("scan result: " + sr.toString()));
+ logv(String.format("scan result: " + sr.toString()));
if (mSsid.equals(sr.SSID)) {
ssidAppearInScanResultsCount += 1;
break;
@@ -208,21 +204,12 @@ public class WifiStressTest extends ConnectivityManagerTestBase {
Settings.Global.putLong(mRunner.getContext().getContentResolver(),
Settings.Global.WIFI_IDLE_MS, WIFI_IDLE_MS);
- // Connect to a Wi-Fi network
- WifiConfiguration config = new WifiConfiguration();
- config.SSID = mSsid;
- if (mPassword != null) {
- config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
- if (isHex(mPassword, 64)) {
- config.preSharedKey = mPassword;
- } else {
- config.preSharedKey = '"' + mPassword + '"';
- }
+ WifiConfiguration config;
+ if (mPassword == null) {
+ config = WifiConfigurationHelper.createOpenConfig(mSsid);
} else {
- config.allowedKeyManagement.set(KeyMgmt.NONE);
+ config = WifiConfigurationHelper.createPskConfig(mSsid, mPassword);
}
- config.setIpAssignment(IpAssignment.DHCP);
- config.setProxySettings(ProxySettings.NONE);
assertTrue("Failed to connect to Wi-Fi network: " + mSsid,
connectToWifiWithConfiguration(config));
@@ -240,7 +227,7 @@ public class WifiStressTest extends ConnectivityManagerTestBase {
// 5. Wake up the device, verify Wi-Fi is enabled and connected.
writeOutput(String.format("iteration %d out of %d",
i, mReconnectIterations));
- log("iteration: " + i);
+ logv("iteration: " + i);
turnScreenOff();
// Use clock time since boot for intervals.
long start = SystemClock.uptimeMillis();
@@ -271,7 +258,7 @@ public class WifiStressTest extends ConnectivityManagerTestBase {
if (mWifiOnlyFlag) {
NetworkInfo ni = mCm.getActiveNetworkInfo();
if (ni != null) {
- Log.e(TAG, "has active network while in wifi sleep: " + ni.toString());
+ Log.e(mLogTag, "has active network while in wifi sleep: " + ni.toString());
fail("active network detected");
}
} else {
@@ -292,7 +279,7 @@ public class WifiStressTest extends ConnectivityManagerTestBase {
long connectionTime = SystemClock.uptimeMillis() - startTime;
sum += connectionTime;
avgReconnectTime = sum / i;
- log("average reconnection time is: " + avgReconnectTime);
+ logv("average reconnection time is: " + avgReconnectTime);
assertTrue("Reconnect to Wi-Fi network, but no data connection.", pingTest(null));
}