diff options
Diffstat (limited to 'core/java')
24 files changed, 622 insertions, 89 deletions
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java index 224e8e9..e47d017 100644 --- a/core/java/android/animation/AnimatorInflater.java +++ b/core/java/android/animation/AnimatorInflater.java @@ -790,6 +790,31 @@ public class AnimatorInflater { return valuesArray; } + // When no value type is provided in keyframe, we need to infer the type from the value. i.e. + // if value is defined in the style of a color value, then the color type is returned. + // Otherwise, default float type is returned. + private static int inferValueTypeOfKeyframe(Resources res, Theme theme, AttributeSet attrs) { + int valueType; + TypedArray a; + if (theme != null) { + a = theme.obtainStyledAttributes(attrs, R.styleable.Keyframe, 0, 0); + } else { + a = res.obtainAttributes(attrs, R.styleable.Keyframe); + } + + TypedValue keyframeValue = a.peekValue(R.styleable.Keyframe_value); + boolean hasValue = (keyframeValue != null); + // When no value type is provided, check whether it's a color type first. + // If not, fall back to default value type (i.e. float type). + if (hasValue && isColorType(keyframeValue.type)) { + valueType = VALUE_TYPE_COLOR; + } else { + valueType = VALUE_TYPE_FLOAT; + } + a.recycle(); + return valueType; + } + private static void dumpKeyframes(Object[] keyframes, String header) { if (keyframes == null || keyframes.length == 0) { return; @@ -817,6 +842,9 @@ public class AnimatorInflater { type != XmlPullParser.END_DOCUMENT) { String name = parser.getName(); if (name.equals("keyframe")) { + if (valueType == VALUE_TYPE_UNDEFINED) { + valueType = inferValueTypeOfKeyframe(res, theme, Xml.asAttributeSet(parser)); + } Keyframe keyframe = loadKeyframe(res, theme, Xml.asAttributeSet(parser), valueType); if (keyframe != null) { if (keyframes == null) { diff --git a/core/java/android/annotation/BinderThread.java b/core/java/android/annotation/BinderThread.java new file mode 100644 index 0000000..c69ba10 --- /dev/null +++ b/core/java/android/annotation/BinderThread.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that the annotated method should only be called on the binder thread. + * If the annotated element is a class, then all methods in the class should be called + * on the binder thread. + * <p> + * Example: + * <pre>{@code + * (@BinderThread + * public BeamShareData createBeamShareData() { ... } + * }</pre> + * + * {@hide} + */ +@Retention(SOURCE) +@Target({METHOD,CONSTRUCTOR,TYPE}) +public @interface BinderThread { +}
\ No newline at end of file diff --git a/core/java/android/annotation/MainThread.java b/core/java/android/annotation/MainThread.java new file mode 100644 index 0000000..18a4283 --- /dev/null +++ b/core/java/android/annotation/MainThread.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that the annotated method should only be called on the main thread. + * If the annotated element is a class, then all methods in the class should be called + * on the main thread. + * <p> + * Example: + * <pre>{@code + * @MainThread + * public void deliverResult(D data) { ... } + * }</pre> + * + * {@hide} + */ +@Retention(SOURCE) +@Target({METHOD,CONSTRUCTOR,TYPE}) +public @interface MainThread { +}
\ No newline at end of file diff --git a/core/java/android/annotation/RequiresPermission.java b/core/java/android/annotation/RequiresPermission.java new file mode 100644 index 0000000..4aed5c1 --- /dev/null +++ b/core/java/android/annotation/RequiresPermission.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that the annotated element requires (or may require) one or more permissions. + * <p/> + * Example of requiring a single permission: + * <pre>{@code + * @RequiresPermission(Manifest.permission.SET_WALLPAPER) + * public abstract void setWallpaper(Bitmap bitmap) throws IOException; + * + * @RequiresPermission(ACCESS_COARSE_LOCATION) + * public abstract Location getLastKnownLocation(String provider); + * }</pre> + * Example of requiring at least one permission from a set: + * <pre>{@code + * @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) + * public abstract Location getLastKnownLocation(String provider); + * }</pre> + * Example of requiring multiple permissions: + * <pre>{@code + * @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) + * public abstract Location getLastKnownLocation(String provider); + * }</pre> + * Example of requiring separate read and write permissions for a content provider: + * <pre>{@code + * @RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS)) + * @RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS)) + * public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks"); + * }</pre> + * + * @hide + */ +@Retention(SOURCE) +@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD}) +public @interface RequiresPermission { + /** + * The name of the permission that is required, if precisely one permission + * is required. If more than one permission is required, specify either + * {@link #allOf()} or {@link #anyOf()} instead. + * <p> + * If specified, {@link #anyOf()} and {@link #allOf()} must both be null. + */ + String value() default ""; + + /** + * Specifies a list of permission names that are all required. + * <p> + * If specified, {@link #anyOf()} and {@link #value()} must both be null. + */ + String[] allOf() default {}; + + /** + * Specifies a list of permission names where at least one is required + * <p> + * If specified, {@link #allOf()} and {@link #value()} must both be null. + */ + String[] anyOf() default {}; + + /** + * If true, the permission may not be required in all cases (e.g. it may only be + * enforced on certain platforms, or for certain call parameters, etc. + */ + boolean conditional() default false; + + /** + * Specifies that the given permission is required for read operations + */ + @Target(FIELD) + @interface Read { + RequiresPermission value(); + } + + /** + * Specifies that the given permission is required for write operations + */ + @Target(FIELD) + @interface Write { + RequiresPermission value(); + } +} diff --git a/core/java/android/annotation/UiThread.java b/core/java/android/annotation/UiThread.java new file mode 100644 index 0000000..b814600 --- /dev/null +++ b/core/java/android/annotation/UiThread.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that the annotated method or constructor should only be called on the UI thread. + * If the annotated element is a class, then all methods in the class should be called + * on the UI thread. + * <p> + * Example: + * <pre>{@code + * @UiThread + * public abstract void setText(@NonNull String text) { ... } + * }</pre> + * + * {@hide} + */ +@Retention(SOURCE) +@Target({METHOD,CONSTRUCTOR,TYPE}) +public @interface UiThread { +}
\ No newline at end of file diff --git a/core/java/android/annotation/WorkerThread.java b/core/java/android/annotation/WorkerThread.java new file mode 100644 index 0000000..dd12e05 --- /dev/null +++ b/core/java/android/annotation/WorkerThread.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * Denotes that the annotated method should only be called on a worker thread. + * If the annotated element is a class, then all methods in the class should be called + * on a worker thread. + * <p> + * Example: + * <pre>{@code + * (@WorkerThread + * protected abstract FilterResults performFiltering(CharSequence constraint); + * }</pre> + * + * {@hide} + */ +@Retention(SOURCE) +@Target({METHOD,CONSTRUCTOR,TYPE}) +public @interface WorkerThread { +}
\ No newline at end of file diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 7f062d9..b11c509 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2513,6 +2513,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case UPDATE_DEVICE_OWNER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String packageName = data.readString(); + updateDeviceOwner(packageName); + reply.writeNoException(); + return true; + } + case GET_PACKAGE_PROCESS_STATE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String pkg = data.readString(); @@ -5801,6 +5809,18 @@ class ActivityManagerProxy implements IActivityManager } @Override + public void updateDeviceOwner(String packageName) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(packageName); + mRemote.transact(UPDATE_DEVICE_OWNER_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override public int getPackageProcessState(String packageName) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java index 1e159a3..9946d79 100644 --- a/core/java/android/app/AssistStructure.java +++ b/core/java/android/app/AssistStructure.java @@ -218,6 +218,7 @@ final public class AssistStructure implements Parcelable { static final int FLAGS_FOCUSED = 0x00000020; static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x04000000; static final int FLAGS_SELECTED = 0x00000040; + static final int FLAGS_ASSIST_BLOCKED = 0x00000080; static final int FLAGS_ACTIVATED = 0x40000000; static final int FLAGS_CHECKABLE = 0x00000100; static final int FLAGS_CHECKED = 0x00000200; @@ -356,6 +357,10 @@ final public class AssistStructure implements Parcelable { return mFlags&ViewNode.FLAGS_VISIBILITY_MASK; } + public boolean isAssistBlocked() { + return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) == 0; + } + public boolean isEnabled() { return (mFlags&ViewNode.FLAGS_DISABLED) == 0; } @@ -484,6 +489,12 @@ final public class AssistStructure implements Parcelable { } @Override + public void setAssistBlocked(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ASSIST_BLOCKED) + | (state ? 0 : ViewNode.FLAGS_ASSIST_BLOCKED); + } + + @Override public void setEnabled(boolean state) { mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_DISABLED) | (state ? 0 : ViewNode.FLAGS_DISABLED); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 7e03faa..00558fe 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -495,6 +495,7 @@ public interface IActivityManager extends IInterface { public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake) throws RemoteException; public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException; + public void updateDeviceOwner(String packageName) throws RemoteException; public int getPackageProcessState(String packageName) throws RemoteException; @@ -837,4 +838,5 @@ public interface IActivityManager extends IInterface { int NOTE_ALARM_FINISH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+292; int GET_PACKAGE_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+293; int SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+294; + int UPDATE_DEVICE_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+295; } diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index fe284ce..aea413d 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -264,6 +264,20 @@ public class DeviceAdminReceiver extends BroadcastReceiver { public static final String EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE = "android.app.extra.CHOOSE_PRIVATE_KEY_RESPONSE"; /** + * Broadcast action: notify device owner that there is a pending system update. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_NOTIFY_PENDING_SYSTEM_UPDATE = "android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE"; + + /** + * A long type extra for {@link #onSystemUpdatePending} recording the system time as given by + * {@link System#currentTimeMillis()} when the current pending system update is first available. + * @hide + */ + public static final String EXTRA_SYSTEM_UPDATE_RECEIVED_TIME = "android.app.extra.SYSTEM_UPDATE_RECEIVED_TIME"; + + /** * Name under which a DevicePolicy component publishes information * about itself. This meta-data must reference an XML resource containing * a device-admin tag. @@ -486,6 +500,22 @@ public class DeviceAdminReceiver extends BroadcastReceiver { } /** + * Allows the receiver to be notified when information about a pending system update is + * available from the system update service. The same pending system update can trigger multiple + * calls to this method, so it is necessary to examine the incoming parameters for details about + * the update. + * <p> + * This callback is only applicable to device owners. + * + * @param context The running context as per {@link #onReceive}. + * @param intent The received intent as per {@link #onReceive}. + * @param receivedTime The time as given by {@link System#currentTimeMillis()} indicating when + * the current pending update was first available. -1 if no pending update is available. + */ + public void onSystemUpdatePending(Context context, Intent intent, long receivedTime) { + } + + /** * Intercept standard device administrator broadcasts. Implementations * should not override this method; it is better to implement the * convenience callbacks for each action. @@ -530,6 +560,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver { onLockTaskModeExiting(context, intent); } else if (ACTION_READY_FOR_USER_INITIALIZATION.equals(action)) { onReadyForUserInitialization(context, intent); + } else if (ACTION_NOTIFY_PENDING_SYSTEM_UPDATE.equals(action)) { + long receivedTime = intent.getLongExtra(EXTRA_SYSTEM_UPDATE_RECEIVED_TIME, -1); + onSystemUpdatePending(context, intent, receivedTime); } } } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 9e2da61..a20aa66 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -4301,4 +4301,24 @@ public class DevicePolicyManager { Log.w(TAG, "Failed talking with device policy service", re); } } + + /** + * Callable by the system update service to notify device owners about pending updates. + * The caller must hold {@link android.Manifest.permission#NOTIFY_PENDING_SYSTEM_UPDATE} + * permission. + * + * @param updateReceivedTime The time as given by {@link System#currentTimeMillis()} indicating + * when the current pending update was first available. -1 if no update is available. + * @hide + */ + @SystemApi + public void notifyPendingSystemUpdate(long updateReceivedTime) { + if (mService != null) { + try { + mService.notifyPendingSystemUpdate(updateReceivedTime); + } catch (RemoteException re) { + Log.w(TAG, "Could not notify device owner about pending system update", re); + } + } + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 1f7498e..087fc88 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -225,4 +225,6 @@ interface IDevicePolicyManager { boolean setKeyguardEnabledState(in ComponentName admin, boolean enabled); void setStatusBarEnabledState(in ComponentName who, boolean enabled); boolean getDoNotAskCredentialsOnBoot(); + + void notifyPendingSystemUpdate(in long updateReceivedTime); } diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 393cf8e..fd65d56 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -26,6 +26,7 @@ import android.content.pm.ProviderInfo; import android.content.res.AssetFileDescriptor; import android.content.res.Configuration; import android.database.Cursor; +import android.database.MatrixCursor; import android.database.SQLException; import android.net.Uri; import android.os.AsyncTask; @@ -204,8 +205,13 @@ public abstract class ContentProvider implements ComponentCallbacks2 { validateIncomingUri(uri); uri = getUriWithoutUserId(uri); if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { - return rejectQuery(uri, projection, selection, selectionArgs, sortOrder, - CancellationSignal.fromTransport(cancellationSignal)); + // The caller has no access to the data, so return an empty cursor with + // the columns in the requested order. The caller may ask for an invalid + // column and we would not catch that but this is not a problem in practice. + // We do not call ContentProvider#query with a modified where clause since + // the implementation is not guaranteed to be backed by a SQL database, hence + // it may not handle properly the tautology where clause we would have created. + return new MatrixCursor(projection, 0); } final String original = setCallingPackage(callingPkg); try { @@ -817,31 +823,6 @@ public abstract class ContentProvider implements ComponentCallbacks2 { } /** - * @hide - * Implementation when a caller has performed a query on the content - * provider, but that call has been rejected for the operation given - * to {@link #setAppOps(int, int)}. The default implementation - * rewrites the <var>selection</var> argument to include a condition - * that is never true (so will always result in an empty cursor) - * and calls through to {@link #query(android.net.Uri, String[], String, String[], - * String, android.os.CancellationSignal)} with that. - */ - public Cursor rejectQuery(Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder, - CancellationSignal cancellationSignal) { - // The read is not allowed... to fake it out, we replace the given - // selection statement with a dummy one that will always be false. - // This way we will get a cursor back that has the correct structure - // but contains no rows. - if (selection == null || selection.isEmpty()) { - selection = "'A' = 'B'"; - } else { - selection = "'A' = 'B' AND (" + selection + ")"; - } - return query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); - } - - /** * Implement this to handle query requests from clients. * This method can be called from multiple threads, as described in * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 3bf3f85..5eacce3 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3098,7 +3098,6 @@ public abstract class Context { * {@link android.media.midi.MidiManager} for accessing the MIDI service. * * @see #getSystemService - * @hide */ public static final String MIDI_SERVICE = "midi"; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index a0cec50..e4108b1 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1574,6 +1574,21 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: This is a device dedicated to showing UI + * on a vehicle headunit. A headunit here is defined to be inside a + * vehicle that may or may not be moving. A headunit uses either a + * primary display in the center console and/or additional displays in + * the instrument cluster or elsewhere in the vehicle. Headunit display(s) + * have limited size and resolution. The user will likely be focused on + * driving so limiting driver distraction is a primary concern. User input + * can be a variety of hard buttons, touch, rotary controllers and even mouse- + * like interfaces. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: This is a device dedicated to showing UI * on a television. Television here is defined to be a typical living * room television experience: displayed on a big screen, where the user * is sitting far away from it, and the dominant form of input will be diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index a48b324..63f48cf 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -305,6 +305,9 @@ public class ConnectivityManager { * same network interface as {@link #TYPE_MOBILE} or it may use a different * one. This is used by applications needing to talk to the carrier's * Multimedia Messaging Service servers. + * + * @deprecated Applications should instead use {@link #requestNetwork} to request a network that + * provides the {@link NetworkCapabilities#NET_CAPABILITY_MMS} capability. */ public static final int TYPE_MOBILE_MMS = 2; /** @@ -312,6 +315,9 @@ public class ConnectivityManager { * same network interface as {@link #TYPE_MOBILE} or it may use a different * one. This is used by applications needing to talk to the carrier's * Secure User Plane Location servers for help locating the device. + * + * @deprecated Applications should instead use {@link #requestNetwork} to request a network that + * provides the {@link NetworkCapabilities#NET_CAPABILITY_SUPL} capability. */ public static final int TYPE_MOBILE_SUPL = 3; /** @@ -324,9 +330,10 @@ public class ConnectivityManager { /** * A High Priority Mobile data connection. This network type uses the * same network interface as {@link #TYPE_MOBILE} but the routing setup - * is different. Only requesting processes will have access to the - * Mobile DNS servers and only IP's explicitly requested via {@link #requestRouteToHost} - * will route over this interface if no default route exists. + * is different. + * + * @deprecated Applications should instead use {@link #requestNetwork} to request a network that + * uses the {@link NetworkCapabilities#TRANSPORT_CELLULAR} transport. */ public static final int TYPE_MOBILE_HIPRI = 5; /** @@ -386,7 +393,7 @@ public class ConnectivityManager { */ public static final int TYPE_MOBILE_IA = 14; -/** + /** * Emergency PDN connection for emergency calls * {@hide} */ @@ -736,7 +743,7 @@ public class ConnectivityManager { } /** - * Returns an array of of {@link NetworkCapabilities} objects, representing + * Returns an array of {@link android.net.NetworkCapabilities} objects, representing * the Networks that applications run by the given user will use by default. * @hide */ @@ -826,11 +833,11 @@ public class ConnectivityManager { } /** - * Get the {@link NetworkCapabilities} for the given {@link Network}. This + * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This * will return {@code null} if the network is unknown. * * @param network The {@link Network} object identifying the network in question. - * @return The {@link NetworkCapabilities} for the network, or {@code null}. + * @return The {@link android.net.NetworkCapabilities} for the network, or {@code null}. */ public NetworkCapabilities getNetworkCapabilities(Network network) { try { @@ -854,6 +861,7 @@ public class ConnectivityManager { * always indicates failure. * * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api. + * @removed */ public int startUsingNetworkFeature(int networkType, String feature) { NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature); @@ -901,6 +909,7 @@ public class ConnectivityManager { * always indicates failure. * * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api. + * @removed */ public int stopUsingNetworkFeature(int networkType, String feature) { NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature); @@ -1179,6 +1188,7 @@ public class ConnectivityManager { * * @deprecated Deprecated in favor of the {@link #requestNetwork}, * {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} api. + * @removed */ public boolean requestRouteToHost(int networkType, int hostAddress) { return requestRouteToHostAddress(networkType, NetworkUtils.intToInetAddress(hostAddress)); @@ -1197,6 +1207,7 @@ public class ConnectivityManager { * @hide * @deprecated Deprecated in favor of the {@link #requestNetwork} and * {@link #bindProcessToNetwork} api. + * @removed */ public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) { try { @@ -2057,7 +2068,7 @@ public class ConnectivityManager { * changes capabilities but still satisfies the stated need. * * @param network The {@link Network} whose capabilities have changed. - * @param networkCapabilities The new {@link NetworkCapabilities} for this network. + * @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this network. */ public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {} @@ -2299,7 +2310,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link NetworkCapabilities}. + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. * * This {@link NetworkRequest} will live until released via * {@link #unregisterNetworkCallback} or the calling application exits. @@ -2318,7 +2329,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link NetworkCapabilities}, limited + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited * by a timeout. * * This function behaves identically to the non-timedout version, but if a suitable @@ -2365,7 +2376,7 @@ public class ConnectivityManager { /** - * Request a network to satisfy a set of {@link NetworkCapabilities}. + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. * * This function behaves identically to the version that takes a NetworkCallback, but instead * of {@link NetworkCallback} a {@link PendingIntent} is used. This means diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a622a21..00c851b 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -189,6 +189,36 @@ public final class Settings { "android.settings.USAGE_ACCESS_SETTINGS"; /** + * Activity Category: Show application settings related to usage access. + * <p> + * An activity that provides a user interface for adjusting usage access related + * preferences for its containing application. Optional but recommended for apps that + * use {@link android.Manifest.permission#PACKAGE_USAGE_STATS}. + * <p> + * The activity may define meta-data to describe what usage access is + * used for within their app with {@link #METADATA_USAGE_ACCESS_REASON}, which + * will be displayed in Settings. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + */ + @SdkConstant(SdkConstantType.INTENT_CATEGORY) + public static final String INTENT_CATEGORY_USAGE_ACCESS_CONFIG = + "android.intent.category.USAGE_ACCESS_CONFIG"; + + /** + * Metadata key: Reason for needing usage access. + * <p> + * A key for metadata attached to an activity that receives action + * {@link #INTENT_CATEGORY_USAGE_ACCESS_CONFIG}, shown to the + * user as description of how the app uses usage access. + * <p> + */ + public static final String METADATA_USAGE_ACCESS_REASON = + "android.settings.metadata.USAGE_ACCESS_REASON"; + + /** * Activity Action: Show settings to allow configuration of security and * location privacy. * <p> @@ -5361,6 +5391,12 @@ public final class Settings { public static final String SMS_DEFAULT_APPLICATION = "sms_default_application"; /** + * Specifies the package name currently configured to be the default dialer application + * @hide + */ + public static final String DIALER_DEFAULT_APPLICATION = "dialer_default_application"; + + /** * Specifies the package name currently configured to be the emergency assistance application * * @see android.telephony.TelephonyManager#ACTION_EMERGENCY_ASSISTANCE diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9741239..5c6ce76 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -631,6 +631,7 @@ import java.util.concurrent.atomic.AtomicInteger; * </p> * * @attr ref android.R.styleable#View_alpha + * @attr ref android.R.styleable#View_assistBlocked * @attr ref android.R.styleable#View_background * @attr ref android.R.styleable#View_clickable * @attr ref android.R.styleable#View_contentDescription @@ -2324,6 +2325,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 1 PFLAG3_IS_LAID_OUT * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT * 1 PFLAG3_CALLED_SUPER + * 1 PFLAG3_APPLYING_INSETS + * 1 PFLAG3_FITTING_SYSTEM_WINDOWS + * 1 PFLAG3_NESTED_SCROLLING_ENABLED + * 1 PFLAG3_ASSIST_BLOCKED * |-------|-------|-------|-------| */ @@ -2381,6 +2386,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED; /** + * <p>Indicates that we are allowing {@link android.view.ViewAssistStructure} to traverse + * into this view.<p> + */ + static final int PFLAG3_ASSIST_BLOCKED = 0x100; + + /** * Always allow a user to over-scroll this view, provided it is a * view that can scroll. * @@ -3869,6 +3880,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, viewFlagMasks |= SAVE_DISABLED_MASK; } break; + case com.android.internal.R.styleable.View_assistBlocked: + if (a.getBoolean(attr, false)) { + mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED; + } + break; case com.android.internal.R.styleable.View_duplicateParentState: if (a.getBoolean(attr, false)) { viewFlagValues |= DUPLICATE_PARENT_STATE; @@ -5775,7 +5791,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { structure.setId(id, null, null, null); } - structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight-mLeft, mBottom-mTop); + structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop); structure.setVisibility(getVisibility()); structure.setEnabled(isEnabled()); if (isClickable()) { @@ -5890,8 +5906,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link #onProvideVirtualAssistStructure}. */ public void dispatchProvideAssistStructure(ViewAssistStructure structure) { - onProvideAssistStructure(structure); - onProvideVirtualAssistStructure(structure); + if (!isAssistBlocked()) { + onProvideAssistStructure(structure); + onProvideVirtualAssistStructure(structure); + } else { + structure.setClassName(getAccessibilityClassName().toString()); + structure.setAssistBlocked(true); + } } /** @@ -7458,6 +7479,42 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Indicates whether this view will participate in data collection through + * {@link android.view.ViewAssistStructure}. If true, it will not provide any data + * for itself or its children. If false, the normal data collection will be allowed. + * + * @return Returns false if assist data collection is not blocked, else true. + * + * @see #setAssistBlocked(boolean) + * @attr ref android.R.styleable#View_assistBlocked + */ + public boolean isAssistBlocked() { + return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0; + } + + /** + * Controls whether assist data collection from this view and its children is enabled + * (that is, whether {@link #onProvideAssistStructure} and + * {@link #onProvideVirtualAssistStructure} will be called). The default value is false, + * allowing normal assist collection. Setting this to false will disable assist collection. + * + * @param enabled Set to true to <em>disable</em> assist data collection, or false + * (the default) to allow it. + * + * @see #isAssistBlocked() + * @see #onProvideAssistStructure + * @see #onProvideVirtualAssistStructure + * @attr ref android.R.styleable#View_assistBlocked + */ + public void setAssistBlocked(boolean enabled) { + if (enabled) { + mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED; + } else { + mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED; + } + } + + /** * Indicates whether this view will save its state (that is, * whether its {@link #onSaveInstanceState} method will be called). * diff --git a/core/java/android/view/ViewAssistStructure.java b/core/java/android/view/ViewAssistStructure.java index 7d263c5..346b8ec 100644 --- a/core/java/android/view/ViewAssistStructure.java +++ b/core/java/android/view/ViewAssistStructure.java @@ -32,6 +32,8 @@ public abstract class ViewAssistStructure { public abstract void setVisibility(int visibility); + public abstract void setAssistBlocked(boolean state); + public abstract void setEnabled(boolean state); public abstract void setClickable(boolean state); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 8f2be99..4324e75 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2881,21 +2881,23 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ public void dispatchProvideAssistStructure(ViewAssistStructure structure) { super.dispatchProvideAssistStructure(structure); - if (structure.getChildCount() == 0) { - final int childrenCount = getChildCount(); - if (childrenCount > 0) { - structure.setChildCount(childrenCount); - final ArrayList<View> preorderedList = buildOrderedChildList(); - final boolean customOrder = preorderedList == null - && isChildrenDrawingOrderEnabled(); - final View[] children = mChildren; - for (int i=0; i<childrenCount; i++) { - final int childIndex = customOrder - ? getChildDrawingOrder(childrenCount, i) : i; - final View child = (preorderedList == null) - ? children[childIndex] : preorderedList.get(childIndex); - ViewAssistStructure cstructure = structure.newChild(i); - child.dispatchProvideAssistStructure(cstructure); + if (!isAssistBlocked()) { + if (structure.getChildCount() == 0) { + final int childrenCount = getChildCount(); + if (childrenCount > 0) { + structure.setChildCount(childrenCount); + final ArrayList<View> preorderedList = buildOrderedChildList(); + final boolean customOrder = preorderedList == null + && isChildrenDrawingOrderEnabled(); + final View[] children = mChildren; + for (int i=0; i<childrenCount; i++) { + final int childIndex = customOrder + ? getChildDrawingOrder(childrenCount, i) : i; + final View child = (preorderedList == null) + ? children[childIndex] : preorderedList.get(childIndex); + ViewAssistStructure cstructure = structure.newChild(i); + child.dispatchProvideAssistStructure(cstructure); + } } } } diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 943beb0..453e4f5 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -900,7 +900,9 @@ public abstract class WebSettings { * and therefore secure policy, this setting should be disabled. * Note that this setting affects only JavaScript access to file scheme * resources. Other access to such resources, for example, from image HTML - * elements, is unaffected. + * elements, is unaffected. To prevent possible violation of same domain policy + * on {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH} and earlier + * devices, you should explicitly set this value to {@code false}. * <p> * The default value is true for API level * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below, @@ -920,7 +922,9 @@ public abstract class WebSettings { * the value of {@link #getAllowUniversalAccessFromFileURLs} is true. * Note too, that this setting affects only JavaScript access to file scheme * resources. Other access to such resources, for example, from image HTML - * elements, is unaffected. + * elements, is unaffected. To prevent possible violation of same domain policy + * on {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH} and earlier + * devices, you should explicitly set this value to {@code false}. * <p> * The default value is true for API level * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below, diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 7d3a41e..b049e49 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -3079,6 +3079,12 @@ public class Editor { MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); } + if (mTextView.canShare()) { + menu.add(0, TextView.ID_SHARE, 0, com.android.internal.R.string.share). + setShowAsAction( + MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + } + menu.add(0, TextView.ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll). setAlphabeticShortcut('a'). setShowAsAction( @@ -4045,9 +4051,9 @@ public class Editor { positionCursor = true; } else if (offset + mTouchWordOffset < mPreviousOffset) { // User is shrinking the selection. - if (currLine > mPrevLine) { + if (currLine < mPrevLine) { // We're on a different line, so we'll snap to word boundaries. - offset = getWordStart(offset); + offset = start; } offset += mTouchWordOffset; positionCursor = true; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 726b89a..3e8df08 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8955,13 +8955,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener static final int ID_CUT = android.R.id.cut; static final int ID_COPY = android.R.id.copy; static final int ID_PASTE = android.R.id.paste; + static final int ID_SHARE = android.R.id.shareText; static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText; static final int ID_REPLACE = android.R.id.replaceText; /** * Called when a context menu option for the text view is selected. Currently * this will be one of {@link android.R.id#selectAll}, {@link android.R.id#cut}, - * {@link android.R.id#copy} or {@link android.R.id#paste}. + * {@link android.R.id#copy}, {@link android.R.id#paste} or {@link android.R.id#shareText}. * * @return true if the context menu item action was performed. */ @@ -9014,6 +9015,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max))); stopSelectionActionMode(); return true; + + case ID_SHARE: + shareSelectedText(); + return true; } return false; } @@ -9091,15 +9096,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * If provided, this ActionMode.Callback will be used to create the ActionMode when text * selection is initiated in this View. * - * The standard implementation populates the menu with a subset of Select All, Cut, Copy and - * Paste actions, depending on what this View supports. + * The standard implementation populates the menu with a subset of Select All, Cut, Copy, + * Paste and Share actions, depending on what this View supports. * * A custom implementation can add new entries in the default menu in its * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The * default actions can also be removed from the menu using * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll}, - * {@link android.R.id#cut}, {@link android.R.id#copy} or {@link android.R.id#paste} ids as - * parameters. + * {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste} or + * {@link android.R.id#shareText} ids as parameters. * * Returning false from * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent @@ -9168,6 +9173,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return false; } + boolean canShare() { + return canCopy(); + } + boolean canPaste() { return (mText instanceof Editable && mEditor != null && mEditor.mKeyListener != null && @@ -9241,6 +9250,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } + private void shareSelectedText() { + String selectedText = getSelectedText(); + if (selectedText != null && !selectedText.isEmpty()) { + Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); + sharingIntent.setType("text/plain"); + sharingIntent.removeExtra(android.content.Intent.EXTRA_TEXT); + sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, selectedText); + getContext().startActivity(Intent.createChooser(sharingIntent, null)); + stopSelectionActionMode(); + } + } + private void setPrimaryClip(ClipData clip) { ClipboardManager clipboard = (ClipboardManager) getContext(). getSystemService(Context.CLIPBOARD_SERVICE); diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index a14e98d..3a1e0ca 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -346,6 +346,17 @@ public final class FloatingToolbar { }; private final Region mTouchableRegion = new Region(); + private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = + new ViewTreeObserver.OnComputeInternalInsetsListener() { + public void onComputeInternalInsets( + ViewTreeObserver.InternalInsetsInfo info) { + info.contentInsets.setEmpty(); + info.visibleInsets.setEmpty(); + info.touchableRegion.set(mTouchableRegion); + info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo + .TOUCHABLE_INSETS_REGION); + } + }; private boolean mDismissed = true; // tracks whether this popup is dismissed or dismissing. private boolean mHidden; // tracks whether this popup is hidden or hiding. @@ -382,21 +393,6 @@ public final class FloatingToolbar { mPopupWindow.dismiss(); } }); - // Make the touchable area of this popup be the area specified by mTouchableRegion. - mPopupWindow.getContentView() - .getRootView() - .getViewTreeObserver() - .addOnComputeInternalInsetsListener( - new ViewTreeObserver.OnComputeInternalInsetsListener() { - public void onComputeInternalInsets( - ViewTreeObserver.InternalInsetsInfo info) { - info.contentInsets.setEmpty(); - info.visibleInsets.setEmpty(); - info.touchableRegion.set(mTouchableRegion); - info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo - .TOUCHABLE_INSETS_REGION); - } - }); mMarginHorizontal = parent.getResources() .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin); mMarginVertical = parent.getResources() @@ -437,16 +433,15 @@ public final class FloatingToolbar { mHidden = false; mDismissed = false; - cancelAllAnimations(); + cancelDismissAndHideAnimations(); + cancelOverflowAnimations(); // Make sure a panel is set as the content. if (mContentContainer.getChildCount() == 0) { setMainPanelAsContent(); } preparePopupContent(); - // If we're yet to show the popup, set the container visibility to zero. - // The "show" animation will make this visible. - mContentContainer.setAlpha(0); mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, x, y); + setTouchableSurfaceInsetsComputer(); runShowAnimation(); } @@ -454,12 +449,13 @@ public final class FloatingToolbar { * Gets rid of this popup. If the popup isn't currently showing, this will be a no-op. */ public void dismiss() { - if (!isShowing()) { + if (mDismissed) { return; } mHidden = false; mDismissed = true; + mHideAnimation.cancel(); runDismissAnimation(); setZeroTouchableSurface(); } @@ -502,7 +498,7 @@ public final class FloatingToolbar { return; } - cancelAllAnimations(); + cancelOverflowAnimations(); preparePopupContent(); mPopupWindow.update(x, y, getWidth(), getHeight()); } @@ -566,10 +562,12 @@ public final class FloatingToolbar { mHideAnimation.start(); } - private void cancelAllAnimations() { - mShowAnimation.cancel(); + private void cancelDismissAndHideAnimations() { mDismissAnimation.cancel(); mHideAnimation.cancel(); + } + + private void cancelOverflowAnimations() { mOpenOverflowAnimation.cancel(); mCloseOverflowAnimation.cancel(); } @@ -804,6 +802,19 @@ public final class FloatingToolbar { (int) mContentContainer.getX() + width, (int) mContentContainer.getY() + height); } + + /** + * Make the touchable area of this popup be the area specified by mTouchableRegion. + * This should be called after the popup window has been dismissed (dismiss/hide) + * and is probably being re-shown with a new content root view. + */ + private void setTouchableSurfaceInsetsComputer() { + ViewTreeObserver viewTreeObserver = mPopupWindow.getContentView() + .getRootView() + .getViewTreeObserver(); + viewTreeObserver.removeOnComputeInternalInsetsListener(mInsetsComputer); + viewTreeObserver.addOnComputeInternalInsetsListener(mInsetsComputer); + } } /** |
