Merge "Import translations. DO NOT MERGE" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index f134786..259b3f6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -29701,7 +29701,6 @@
method protected void onClick();
method protected android.view.View onCreateView(android.view.ViewGroup);
method public void onDependencyChanged(android.preference.Preference, boolean);
- method protected void onDetachedFromActivity();
method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
method public void onParentChanged(android.preference.Preference, boolean);
method protected void onPrepareForRemoval();
diff --git a/api/system-current.txt b/api/system-current.txt
index 6414cd1..db27d8e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -32005,7 +32005,6 @@
method protected void onClick();
method protected android.view.View onCreateView(android.view.ViewGroup);
method public void onDependencyChanged(android.preference.Preference, boolean);
- method protected void onDetachedFromActivity();
method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
method public void onParentChanged(android.preference.Preference, boolean);
method protected void onPrepareForRemoval();
diff --git a/api/test-current.txt b/api/test-current.txt
index 4d860e8..bf29b40 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -29767,7 +29767,6 @@
method protected void onClick();
method protected android.view.View onCreateView(android.view.ViewGroup);
method public void onDependencyChanged(android.preference.Preference, boolean);
- method protected void onDetachedFromActivity();
method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
method public void onParentChanged(android.preference.Preference, boolean);
method protected void onPrepareForRemoval();
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 45aa6b4..b924327 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2185,9 +2185,6 @@
* Force a new device unlock password (the password needed to access the entire device, not for
* individual accounts) on the user. This takes effect immediately.
* <p>
- * Calling this from a managed profile that shares the password with the owner profile will
- * throw a security exception.
- * <p>
* <em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for
* device admins that are not device owner and not profile owner.
* The password can now only be changed if there is currently no password set. Device owner
@@ -2201,10 +2198,10 @@
* case the currently active quality will be increased to match.
* <p>
* Calling with a null or empty password will clear any existing PIN, pattern or password if the
- * current password constraints allow it. <em>Note: This will not
- * work in {@link android.os.Build.VERSION_CODES#N} and later for device admins that are not
- * device owner and not profile owner. Once set, the password cannot be changed to null or
- * empty, except by device owner or profile owner.</em>
+ * current password constraints allow it. <em>Note: This will not work in
+ * {@link android.os.Build.VERSION_CODES#N} and later for managed profiles, or for device admins
+ * that are not device owner or profile owner. Once set, the password cannot be changed to null
+ * or empty except by these admins.</em>
* <p>
* The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call this method; if it has
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index d41bc07..b1cad05 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -1184,10 +1184,9 @@
/**
* Called when the Preference hierarchy has been attached to the
- * {@link PreferenceActivity} or {@link PreferenceFragment}. This can
- * also be called when this Preference has been attached to a group
- * that was already attached to the {@link PreferenceActivity} or
- * {@link PreferenceFragment}.
+ * {@link PreferenceActivity}. This can also be called when this
+ * Preference has been attached to a group that was already attached
+ * to the {@link PreferenceActivity}.
*/
protected void onAttachedToActivity() {
// At this point, the hierarchy that this preference is in is connected
@@ -1195,16 +1194,6 @@
registerDependency();
}
- /**
- * Called when the Preference hierarchy has been detached from the
- * {@link PreferenceActivity} or {@link PreferenceFragment}. This can
- * also be called when this Preference has been removed from a group
- * that was already attached to the {@link PreferenceActivity} or
- * {@link PreferenceFragment}.
- */
- protected void onDetachedFromActivity() {
- }
-
private void registerDependency() {
if (TextUtils.isEmpty(mDependencyKey)) return;
diff --git a/core/java/android/preference/PreferenceGroup.java b/core/java/android/preference/PreferenceGroup.java
index 13c3661..f17506b 100644
--- a/core/java/android/preference/PreferenceGroup.java
+++ b/core/java/android/preference/PreferenceGroup.java
@@ -186,11 +186,7 @@
private boolean removePreferenceInt(Preference preference) {
synchronized(this) {
preference.onPrepareForRemoval();
- boolean success = mPreferenceList.remove(preference);
- if (mAttachedToActivity) {
- preference.onDetachedFromActivity();
- }
- return success;
+ return mPreferenceList.remove(preference);
}
}
@@ -266,7 +262,7 @@
protected boolean isOnSameScreenAsChildren() {
return true;
}
-
+
@Override
protected void onAttachedToActivity() {
super.onAttachedToActivity();
@@ -283,17 +279,11 @@
}
@Override
- protected void onDetachedFromActivity() {
- super.onDetachedFromActivity();
-
+ protected void onPrepareForRemoval() {
+ super.onPrepareForRemoval();
+
// We won't be attached to the activity anymore
mAttachedToActivity = false;
-
- // Dispatch to all contained preferences
- final int preferenceCount = getPreferenceCount();
- for (int i = 0; i < preferenceCount; i++) {
- getPreference(i).onDetachedFromActivity();
- }
}
@Override
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index 73174e3..1a6b06f 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -519,9 +519,6 @@
*/
boolean setPreferences(PreferenceScreen preferenceScreen) {
if (preferenceScreen != mPreferenceScreen) {
- if (mPreferenceScreen != null) {
- mPreferenceScreen.onDetachedFromActivity();
- }
mPreferenceScreen = preferenceScreen;
return true;
}
@@ -830,11 +827,7 @@
*/
void dispatchActivityDestroy() {
List<OnActivityDestroyListener> list = null;
-
- if (mPreferenceScreen != null) {
- mPreferenceScreen.onDetachedFromActivity();
- mPreferenceScreen = null;
- }
+
synchronized (this) {
if (mActivityDestroyListeners != null) {
list = new ArrayList<OnActivityDestroyListener>(mActivityDestroyListeners);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 6585fd8..7055f78 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1863,9 +1863,9 @@
if (hasSelection) {
hideInsertionPointCursorController();
if (mTextActionMode == null) {
- if (mRestartActionModeOnNextRefresh || mTextView.isInExtractedMode()) {
+ if (mRestartActionModeOnNextRefresh) {
// To avoid distraction, newly start action mode only when selection action
- // mode is being restarted or in full screen extracted mode.
+ // mode is being restarted.
startSelectionActionMode();
}
} else if (selectionController == null || !selectionController.isActive()) {
@@ -4875,11 +4875,12 @@
@Override
protected int getOffsetAtCoordinate(@NonNull Layout layout, int line, float x) {
- final int primaryOffset = layout.getOffsetForHorizontal(line, x, true);
+ final float localX = mTextView.convertToLocalHorizontalCoordinate(x);
+ final int primaryOffset = layout.getOffsetForHorizontal(line, localX, true);
if (!layout.isLevelBoundary(primaryOffset)) {
return primaryOffset;
}
- final int secondaryOffset = layout.getOffsetForHorizontal(line, x, false);
+ final int secondaryOffset = layout.getOffsetForHorizontal(line, localX, false);
final int currentOffset = getCurrentCursorOffset();
final int primaryDiff = Math.abs(primaryOffset - currentOffset);
final int secondaryDiff = Math.abs(secondaryOffset - currentOffset);
diff --git a/core/java/com/android/server/net/NetlinkTracker.java b/core/java/com/android/server/net/NetlinkTracker.java
index d45982e..5b421d9 100644
--- a/core/java/com/android/server/net/NetlinkTracker.java
+++ b/core/java/com/android/server/net/NetlinkTracker.java
@@ -102,6 +102,19 @@
}
@Override
+ public void interfaceRemoved(String iface) {
+ maybeLog("interfaceRemoved", iface);
+ if (mInterfaceName.equals(iface)) {
+ // Our interface was removed. Clear our LinkProperties and tell our owner that they are
+ // now empty. Note that from the moment that the interface is removed, any further
+ // interface-specific messages (e.g., RTM_DELADDR) will not reach us, because the netd
+ // code that parses them will not be able to resolve the ifindex to an interface name.
+ clearLinkProperties();
+ mCallback.update();
+ }
+ }
+
+ @Override
public void addressUpdated(String iface, LinkAddress address) {
if (mInterfaceName.equals(iface)) {
maybeLog("addressUpdated", iface, address);
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index d10df02..2cba93fd 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1211,6 +1211,11 @@
Log.e(TAG, "Error Tethering: " + e.toString());
setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
+ try {
+ mNMService.untetherInterface(mIfaceName);
+ } catch (Exception ee) {
+ Log.e(TAG, "Error untethering after failure!" + ee.toString());
+ }
transitionTo(mInitialState);
return;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6fe5c16..37f2302 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3740,32 +3740,26 @@
final int callingUid = mInjector.binderGetCallingUid();
final int userHandle = mInjector.userHandleGetCallingUserId();
- if (getCredentialOwner(userHandle, /* parent */ false) != userHandle) {
- throw new SecurityException("You can not change password for this profile because"
- + " it shares the password with the owner profile");
- }
-
String password = passwordOrNull != null ? passwordOrNull : "";
+ // Password resetting to empty/null is not allowed for managed profiles.
+ if (TextUtils.isEmpty(password)) {
+ enforceNotManagedProfile(userHandle, "clear the active password");
+ }
+
int quality;
synchronized (this) {
- // If caller has PO (or DO), it can clear the password, so see if that's the case
- // first.
+ // If caller has PO (or DO) it can change the password, so see if that's the case first.
ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
if (admin == null) {
// Otherwise, make sure the caller has any active admin with the right policy.
admin = getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
- }
- final ComponentName adminComponent = admin.info.getComponent();
-
- // As of N, only profile owners and device owners can reset the password.
- if (!(isProfileOwner(adminComponent, userHandle)
- || isDeviceOwner(adminComponent, userHandle))) {
final boolean preN = getTargetSdk(admin.info.getPackageName(), userHandle)
<= android.os.Build.VERSION_CODES.M;
+
// As of N, password resetting to empty/null is not allowed anymore.
// TODO Should we allow DO/PO to set an empty password?
if (TextUtils.isEmpty(password)) {
@@ -3894,6 +3888,9 @@
// back in to the service.
final long ident = mInjector.binderClearCallingIdentity();
try {
+ if (isManagedProfile(userHandle)) {
+ mLockPatternUtils.setSeparateProfileChallengeEnabled(userHandle, true);
+ }
if (!TextUtils.isEmpty(password)) {
mLockPatternUtils.saveLockPassword(password, null, quality, userHandle);
} else {
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 4a83c6f..54aeb3d 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -302,6 +302,7 @@
}) {
@Override
public void interfaceAdded(String iface) {
+ super.interfaceAdded(iface);
if (mClatInterfaceName.equals(iface)) {
mCallback.setNeighborDiscoveryOffload(false);
}
@@ -309,6 +310,7 @@
@Override
public void interfaceRemoved(String iface) {
+ super.interfaceRemoved(iface);
if (mClatInterfaceName.equals(iface)) {
// TODO: consider sending a message to the IpManager main
// StateMachine thread, in case "NDO enabled" state becomes
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index c8e3d03..9e50ee8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -24,6 +24,7 @@
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.Result.Status;
import com.android.ide.common.rendering.api.SessionParams;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.impl.RenderDrawable;
import com.android.layoutlib.bridge.impl.RenderSessionImpl;
import com.android.layoutlib.bridge.util.DynamicIdMap;
@@ -408,7 +409,9 @@
/**
* Starts a layout session by inflating and rendering it. The method returns a
* {@link RenderSession} on which further actions can be taken.
- *
+ * <p/>
+ * If {@link SessionParams} includes the {@link RenderParamsFlags#FLAG_DO_NOT_RENDER_ON_CREATE},
+ * this method will only inflate the layout but will NOT render it.
* @param params the {@link SessionParams} object with all the information necessary to create
* the scene.
* @return a new {@link RenderSession} object that contains the result of the layout.
@@ -424,7 +427,10 @@
lastResult = scene.init(params.getTimeout());
if (lastResult.isSuccess()) {
lastResult = scene.inflate();
- if (lastResult.isSuccess()) {
+
+ boolean doNotRenderOnCreate = Boolean.TRUE.equals(
+ params.getFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE));
+ if (lastResult.isSuccess() && !doNotRenderOnCreate) {
lastResult = scene.render(true /*freshRender*/);
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
index bd17a2f..051de90 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
@@ -53,6 +53,12 @@
*/
public static final Key<Boolean> FLAG_KEY_XML_FILE_PARSER_SUPPORT =
new Key<Boolean>("xmlFileParser", Boolean.class);
+ /**
+ * To tell LayoutLib to not render when creating a new session. This allows controlling when the first
+ * layout rendering will happen.
+ */
+ public static final Key<Boolean> FLAG_DO_NOT_RENDER_ON_CREATE =
+ new Key<Boolean>("doNotRenderOnCreate", Boolean.class);
// Disallow instances.
private RenderParamsFlags() {}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 016825a..ce7104e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -267,6 +267,34 @@
}
/**
+ * Renders the given view hierarchy to the passed canvas and returns the result of the render
+ * operation.
+ * @param canvas an optional canvas to render the views to. If null, only the measure and
+ * layout steps will be executed.
+ */
+ private static Result render(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot,
+ @Nullable Canvas canvas, int width, int height) {
+ // measure again with the size we need
+ // This must always be done before the call to layout
+ measureView(viewRoot, null /*measuredView*/,
+ width, MeasureSpec.EXACTLY,
+ height, MeasureSpec.EXACTLY);
+
+ // now do the layout.
+ viewRoot.layout(0, 0, width, height);
+ handleScrolling(context, viewRoot);
+
+ if (canvas == null) {
+ return SUCCESS.createResult();
+ }
+
+ AttachInfo_Accessor.dispatchOnPreDraw(viewRoot);
+ viewRoot.draw(canvas);
+
+ return SUCCESS.createResult();
+ }
+
+ /**
* Renders the scene.
* <p>
* {@link #acquire(long)} must have been called before this.
@@ -367,24 +395,12 @@
}
}
- // measure again with the size we need
- // This must always be done before the call to layout
- measureView(mViewRoot, null /*measuredView*/,
- mMeasuredScreenWidth, MeasureSpec.EXACTLY,
- mMeasuredScreenHeight, MeasureSpec.EXACTLY);
-
- // now do the layout.
- mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
-
- handleScrolling(mViewRoot);
-
+ Result renderResult = SUCCESS.createResult();
if (params.isLayoutOnly()) {
// delete the canvas and image to reset them on the next full rendering
mImage = null;
mCanvas = null;
} else {
- AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
-
// draw the views
// create the BufferedImage into which the layout will be rendered.
boolean newImage = false;
@@ -446,6 +462,9 @@
if (mElapsedFrameTimeNanos >= 0) {
long initialTime = System_Delegate.nanoTime();
if (!mFirstFrameExecuted) {
+ // We need to run an initial draw call to initialize the animations
+ render(getContext(), mViewRoot, mCanvas, 0, 0);
+
// The first frame will initialize the animations
Choreographer_Delegate.doFrame(initialTime);
mFirstFrameExecuted = true;
@@ -453,14 +472,15 @@
// Second frame will move the animations
Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos);
}
- mViewRoot.draw(mCanvas);
+ renderResult = render(getContext(), mViewRoot, mCanvas, mMeasuredScreenWidth,
+ mMeasuredScreenHeight);
}
mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
false);
// success!
- return SUCCESS.createResult();
+ return renderResult;
} catch (Throwable e) {
// get the real cause of the exception.
Throwable t = e;
@@ -488,7 +508,7 @@
* @return the measured width/height if measuredView is non-null, null otherwise.
*/
@SuppressWarnings("deprecation") // For the use of Pair
- private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
+ private static Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
int width, int widthMode, int height, int heightMode) {
int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
@@ -1061,8 +1081,7 @@
* the component supports nested scrolling attempt that first, then use the unconsumed scroll
* part to scroll the content in the component.
*/
- private void handleScrolling(View view) {
- BridgeContext context = getContext();
+ private static void handleScrolling(BridgeContext context, View view) {
int scrollPosX = context.getScrollXPos(view);
int scrollPosY = context.getScrollYPos(view);
if (scrollPosX != 0 || scrollPosY != 0) {
@@ -1080,7 +1099,7 @@
}
}
if (scrollPosX != 0 || scrollPosY != 0) {
- view.scrollBy(scrollPosX, scrollPosY);
+ view.scrollTo(scrollPosX, scrollPosY);
}
}
@@ -1090,7 +1109,7 @@
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
View child = group.getChildAt(i);
- handleScrolling(child);
+ handleScrolling(context, child);
}
}
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml
index a5ebc2e..a07498c 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml
@@ -2,8 +2,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:scrollX="10px"
- android:scrollY="30px">
+ android:scrollX="30px"
+ android:scrollY="90px">
<LinearLayout
android:layout_width="60dp"
android:layout_height="60dp"
@@ -29,8 +29,8 @@
android:layout_width="200dp"
android:layout_height="400dp"
android:orientation="vertical"
- android:scrollX="-30px"
- android:scrollY="150px">
+ android:scrollX="-90px"
+ android:scrollY="450px">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="60dp"
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index 09dd5f0..034c8b2 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -30,6 +30,7 @@
import com.android.io.FolderWrapper;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.impl.RenderAction;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
@@ -564,7 +565,7 @@
sFrameworkRepo.getConfiguredResources(config),
themeName, isProjectTheme);
- return new SessionParams(
+ SessionParams sessionParams = new SessionParams(
layoutParser,
renderingMode,
null /*used for caching*/,
@@ -574,6 +575,8 @@
0,
targetSdk,
getLayoutLog());
+ sessionParams.setFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE, true);
+ return sessionParams;
}
private static LayoutLog getLayoutLog() {