diff options
Diffstat (limited to 'core/java')
62 files changed, 1011 insertions, 279 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index e79e20c..7260d10 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -21,6 +21,7 @@ import android.annotation.DrawableRes; import android.annotation.IdRes; import android.annotation.IntDef; import android.annotation.LayoutRes; +import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StyleRes; @@ -891,6 +892,7 @@ public class Activity extends ContextThemeWrapper * @see #onRestoreInstanceState * @see #onPostCreate */ + @MainThread @CallSuper protected void onCreate(@Nullable Bundle savedInstanceState) { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState); @@ -6496,6 +6498,11 @@ public class Activity extends ContextThemeWrapper return (w == null) ? 0 : w.getAttributes().windowAnimations; } + @Override + public void onAttachFragment(Fragment fragment) { + Activity.this.onAttachFragment(fragment); + } + @Nullable @Override public View onFindViewById(int id) { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 576a046..9bbb4be 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -16,8 +16,10 @@ package android.app; +import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.graphics.Canvas; import android.graphics.Matrix; @@ -26,6 +28,7 @@ import android.os.BatteryStats; import android.os.IBinder; import android.os.ParcelFileDescriptor; +import android.util.Log; import com.android.internal.app.ProcessStats; import com.android.internal.os.TransferPipe; import com.android.internal.util.FastPrintWriter; @@ -2396,7 +2399,24 @@ public class ActivityManager { } catch (RemoteException e) { } } - + + /** + * Kills the specified UID. + * @param uid The UID to kill. + * @param reason The reason for the kill. + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.KILL_UID) + public void killUid(int uid, String reason) { + try { + ActivityManagerNative.getDefault().killUid(uid, reason); + } catch (RemoteException e) { + Log.e(TAG, "Couldn't kill uid:" + uid, e); + } + } + /** * Have the system perform a force stop of everything associated with * the given application package. All processes that share its uid diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 6bbbf9e..5aa399b 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -941,7 +941,8 @@ public class AppOpsManager { * @hide */ public static int permissionToOpCode(String permission) { - return sPermToOp.get(permission); + Integer boxedOpCode = sPermToOp.get(permission); + return boxedOpCode != null ? boxedOpCode : OP_NONE; } /** diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 169952a..0f286fb 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -239,7 +239,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK)); } ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(mActivity, this, - mAllSharedElementNames, resultCode, data); + mSharedElementNames, resultCode, data); mActivity.convertToTranslucent(new Activity.TranslucentConversionListener() { @Override public void onTranslucentConversionComplete(boolean drawComplete) { diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 91d810e..40c5c64 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -1314,6 +1314,12 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene com.android.internal.R.styleable.Fragment_fragmentAllowReturnTransitionOverlap, true); } a.recycle(); + + final Activity hostActivity = mHost == null ? null : mHost.getActivity(); + if (hostActivity != null) { + mCalled = false; + onInflate(hostActivity, attrs, savedInstanceState); + } } /** diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java index dad2c79..3e753f0 100644 --- a/core/java/android/app/FragmentHostCallback.java +++ b/core/java/android/app/FragmentHostCallback.java @@ -23,7 +23,6 @@ import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.util.ArrayMap; -import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -140,6 +139,14 @@ public abstract class FragmentHostCallback<E> extends FragmentContainer { return mWindowAnimations; } + /** + * Called when a {@link Fragment} is being attached to this host, immediately + * after the call to its {@link Fragment#onAttach(Context)} method and before + * {@link Fragment#onCreate(Bundle)}. + */ + public void onAttachFragment(Fragment fragment) { + } + @Nullable @Override public View onFindViewById(int id) { @@ -187,14 +194,6 @@ public abstract class FragmentHostCallback<E> extends FragmentContainer { } } - void onFragmentInflate(Fragment fragment, AttributeSet attrs, Bundle savedInstanceState) { - fragment.onInflate(mContext, attrs, savedInstanceState); - } - - void onFragmentAttach(Fragment fragment) { - fragment.onAttach(mContext); - } - void doLoaderStart() { if (mLoadersStarted) { return; diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 62436e9..6b5239d 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -844,13 +844,13 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate f.mFragmentManager = mParent != null ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl(); f.mCalled = false; - mHost.onFragmentAttach(f); + f.onAttach(mHost.getContext()); if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onAttach()"); } if (f.mParentFragment == null) { - mHost.onFragmentAttach(f); + mHost.onAttachFragment(f); } if (!f.mRetaining) { @@ -2107,7 +2107,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate fragment.mTag = tag; fragment.mInLayout = true; fragment.mFragmentManager = this; - mHost.onFragmentInflate(fragment, attrs, fragment.mSavedFragmentState); + fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState); addFragment(fragment, true); } else if (fragment.mInLayout) { // A fragment already exists and it is not one we restored from @@ -2124,7 +2124,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate // from last saved state), then give it the attributes to // initialize itself. if (!fragment.mRetaining) { - mHost.onFragmentInflate(fragment, attrs, fragment.mSavedFragmentState); + fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState); } } diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java index 96767ae..3cda973 100644 --- a/core/java/android/app/IntentService.java +++ b/core/java/android/app/IntentService.java @@ -16,6 +16,7 @@ package android.app; +import android.annotation.WorkerThread; import android.content.Intent; import android.os.Handler; import android.os.HandlerThread; @@ -158,5 +159,6 @@ public abstract class IntentService extends Service { * @param intent The value passed to {@link * android.content.Context#startService(Intent)}. */ + @WorkerThread protected abstract void onHandleIntent(Intent intent); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index ff589f9..49b2549 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2095,6 +2095,7 @@ public class Notification implements Parcelable try { Constructor<? extends Style> constructor = styleClass.getConstructor(); + constructor.setAccessible(true); style = constructor.newInstance(); style.restoreFromExtras(extras); } catch (Throwable t) { diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index b1a5d21..fa11221 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -165,8 +165,6 @@ public class SearchDialog extends Dialog { setContentView(com.android.internal.R.layout.search_bar); // get the view elements for local access - SearchBar searchBar = (SearchBar) findViewById(com.android.internal.R.id.search_bar); - searchBar.setSearchDialog(this); mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view); mSearchView.setIconified(false); mSearchView.setOnCloseListener(mOnCloseListener); @@ -618,8 +616,6 @@ public class SearchDialog extends Dialog { */ public static class SearchBar extends LinearLayout { - private SearchDialog mSearchDialog; - public SearchBar(Context context, AttributeSet attrs) { super(context, attrs); } @@ -628,18 +624,6 @@ public class SearchDialog extends Dialog { super(context); } - public void setSearchDialog(SearchDialog searchDialog) { - mSearchDialog = searchDialog; - } - - /** - * Don't allow action modes in a SearchBar, it looks silly. - */ - @Override - public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) { - return null; - } - @Override public ActionMode startActionModeForChild( View child, ActionMode.Callback callback, int type) { diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index aea413d..470804d 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -231,7 +231,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * device owner app. * * <p>The broadcast will be limited to the {@link DeviceAdminReceiver} component specified in - * the (@link DevicePolicyManager#EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME) field + * the {@link DevicePolicyManager#EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME} field * of the original intent or NFC bump that started the provisioning process. You will generally * handle this in {@link DeviceAdminReceiver#onReadyForUserInitialization}. * @@ -450,9 +450,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * * <p>It is not assumed that the device initializer is finished when it returns from * this call, as it may do additional setup asynchronously. The device initializer must call - * {DevicePolicyManager#setUserEnabled(ComponentName admin)} when it has finished any additional - * setup (such as adding an account by using the {@link AccountManager}) in order for the user - * to be functional. + * {@link DevicePolicyManager#setUserEnabled(ComponentName admin)} when it has finished any + * additional setup (such as adding an account by using the {@link AccountManager}) in order for + * the user to be functional. * * @param context The running context as per {@link #onReceive}. * @param intent The received intent as per {@link #onReceive}. diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 9f71ea5..8009b6c 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -412,7 +412,7 @@ public class DevicePolicyManager { = "android.app.action.MANAGED_PROFILE_PROVISIONED"; /** - * A boolean extra indicating whether device encryption is required as part of Device Owner + * A boolean extra indicating whether device encryption can be skipped as part of Device Owner * provisioning. * * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner @@ -4294,14 +4294,14 @@ public class DevicePolicyManager { * being disabled. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param enabled New state of the keyguard. + * @param disabled {@code true} disables the keyguard, {@code false} reenables it. * * @return {@code false} if attempting to disable the keyguard while a lock password was in - * place. {@code true} otherwise." + * place. {@code true} otherwise. */ - public boolean setKeyguardEnabledState(ComponentName admin, boolean enabled) { + public boolean setKeyguardDisabled(ComponentName admin, boolean disabled) { try { - return mService.setKeyguardEnabledState(admin, enabled); + return mService.setKeyguardDisabled(admin, disabled); } catch (RemoteException re) { Log.w(TAG, "Failed talking with device policy service", re); return false; @@ -4309,18 +4309,22 @@ public class DevicePolicyManager { } /** - * Called by device owner to set the enabled state of the status bar. Disabling the status - * bar blocks notifications, quick settings and other screen overlays that allow escaping from + * Called by device owner to disable the status bar. Disabling the status bar blocks + * notifications, quick settings and other screen overlays that allow escaping from * a single use device. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param enabled New state of the status bar. + * @param disabled {@code true} disables the status bar, {@code false} reenables it. + * + * @return {@code false} if attempting to disable the status bar failed. + * {@code true} otherwise. */ - public void setStatusBarEnabledState(ComponentName admin, boolean enabled) { + public boolean setStatusBarDisabled(ComponentName admin, boolean disabled) { try { - mService.setStatusBarEnabledState(admin, enabled); + return mService.setStatusBarDisabled(admin, disabled); } catch (RemoteException re) { Log.w(TAG, "Failed talking with device policy service", re); + return false; } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 833bc00..e81e7c1 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -224,8 +224,8 @@ interface IDevicePolicyManager { void setSystemUpdatePolicy(in ComponentName who, in PersistableBundle policy); PersistableBundle getSystemUpdatePolicy(); - boolean setKeyguardEnabledState(in ComponentName admin, boolean enabled); - void setStatusBarEnabledState(in ComponentName who, boolean enabled); + boolean setKeyguardDisabled(in ComponentName admin, boolean disabled); + boolean setStatusBarDisabled(in ComponentName who, boolean disabled); boolean getDoNotAskCredentialsOnBoot(); void notifyPendingSystemUpdate(in long updateReceivedTime); diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl index 17cff5c..32951d9 100644 --- a/core/java/android/app/trust/ITrustManager.aidl +++ b/core/java/android/app/trust/ITrustManager.aidl @@ -32,4 +32,5 @@ interface ITrustManager { void reportKeyguardShowingChanged(); boolean isDeviceLocked(int userId); boolean isDeviceSecure(int userId); + boolean hasUserAuthenticatedSinceBoot(int userId); } diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java index b5c5317..8cab565 100644 --- a/core/java/android/app/trust/TrustManager.java +++ b/core/java/android/app/trust/TrustManager.java @@ -147,6 +147,23 @@ public class TrustManager { } } + /** + * Checks whether the specified user has been authenticated since the last boot. + * + * @param userId the user id of the user to check for + * @return true if the user has authenticated since boot, false otherwise + * + * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. + */ + public boolean hasUserAuthenticatedSinceBoot(int userId) { + try { + return mService.hasUserAuthenticatedSinceBoot(userId); + } catch (RemoteException e) { + onError(e); + return false; + } + } + private void onError(Exception e) { Log.e(TAG, "Error while calling TrustManagerService", e); } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 9b4dcc6..0a77868 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1692,7 +1692,8 @@ public final class BluetoothAdapter { * @param context Context of the application * @param listener The service Listener for connection callbacks. * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH}, - * {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}. + * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}. + * {@link BluetoothProfile#GATT} or {@link BluetoothProfile#GATT_SERVER}. * @return true on success, false on error */ public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, diff --git a/core/java/android/bluetooth/BluetoothHealthCallback.java b/core/java/android/bluetooth/BluetoothHealthCallback.java index baf2ade..128376f 100644 --- a/core/java/android/bluetooth/BluetoothHealthCallback.java +++ b/core/java/android/bluetooth/BluetoothHealthCallback.java @@ -17,6 +17,7 @@ package android.bluetooth; +import android.annotation.BinderThread; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -39,6 +40,7 @@ public abstract class BluetoothHealthCallback { * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_SUCCESS} or * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_FAILURE} */ + @BinderThread public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config, int status) { Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + "Status: " + status); @@ -58,6 +60,7 @@ public abstract class BluetoothHealthCallback { * @param channelId The id associated with the channel. This id will be used * in future calls like when disconnecting the channel. */ + @BinderThread public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config, BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd, int channelId) { diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java index 7b4c6f9..014cb22 100644 --- a/core/java/android/bluetooth/BluetoothSap.java +++ b/core/java/android/bluetooth/BluetoothSap.java @@ -28,13 +28,41 @@ import android.os.IBinder; import android.os.ServiceManager; import android.util.Log; - +/** + * This class provides the APIs to control the Bluetooth SIM + * Access Profile (SAP). + * + * <p>BluetoothSap is a proxy object for controlling the Bluetooth + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothSap proxy object. + * + * <p>Each method is protected with its appropriate permission. + * @hide + */ public final class BluetoothSap implements BluetoothProfile { private static final String TAG = "BluetoothSap"; private static final boolean DBG = true; private static final boolean VDBG = false; + /** + * Intent used to broadcast the change in connection state of the profile. + * + * <p>This intent will have 4 extras: + * <ul> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of + * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, + * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + * @hide + */ public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED"; @@ -43,12 +71,22 @@ public final class BluetoothSap implements BluetoothProfile { private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; - /** There was an error trying to obtain the state */ - public static final int STATE_ERROR = -1; + /** + * There was an error trying to obtain the state. + * @hide + */ + public static final int STATE_ERROR = -1; - public static final int RESULT_FAILURE = 0; + /** + * Connection state change succceeded. + * @hide + */ public static final int RESULT_SUCCESS = 1; - /** Connection canceled before completion. */ + + /** + * Connection canceled before completion. + * @hide + */ public static final int RESULT_CANCELED = 2; final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = @@ -124,6 +162,7 @@ public final class BluetoothSap implements BluetoothProfile { * Other public functions of BluetoothSap will return default error * results once close() has been called. Multiple invocations of close() * are ok. + * @hide */ public synchronized void close() { IBluetoothManager mgr = mAdapter.getBluetoothManager(); @@ -152,6 +191,7 @@ public final class BluetoothSap implements BluetoothProfile { * Get the current state of the BluetoothSap service. * @return One of the STATE_ return codes, or STATE_ERROR if this proxy * object is currently not connected to the Sap service. + * @hide */ public int getState() { if (VDBG) log("getState()"); @@ -171,6 +211,7 @@ public final class BluetoothSap implements BluetoothProfile { * @return The remote Bluetooth device, or null if not in connected or * connecting state, or if this proxy object is not connected to * the Sap service. + * @hide */ public BluetoothDevice getClient() { if (VDBG) log("getClient()"); @@ -189,6 +230,7 @@ public final class BluetoothSap implements BluetoothProfile { * Returns true if the specified Bluetooth device is connected. * Returns false if not connected, or if this proxy object is not * currently connected to the Sap service. + * @hide */ public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); @@ -206,6 +248,7 @@ public final class BluetoothSap implements BluetoothProfile { /** * Initiate connection. Initiation of outgoing connections is not * supported for SAP server. + * @hide */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")" + "not supported for SAPS"); @@ -218,6 +261,7 @@ public final class BluetoothSap implements BluetoothProfile { * @param device Remote Bluetooth Device * @return false on error, * true otherwise + * @hide */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); @@ -238,6 +282,7 @@ public final class BluetoothSap implements BluetoothProfile { * Get the list of connected devices. Currently at most one. * * @return list of connected devices + * @hide */ public List<BluetoothDevice> getConnectedDevices() { if (DBG) log("getConnectedDevices()"); @@ -257,6 +302,7 @@ public final class BluetoothSap implements BluetoothProfile { * Get the list of devices matching specified states. Currently at most one. * * @return list of matching devices + * @hide */ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); @@ -276,6 +322,7 @@ public final class BluetoothSap implements BluetoothProfile { * Get connection state of device * * @return device connection state + * @hide */ public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); @@ -300,6 +347,7 @@ public final class BluetoothSap implements BluetoothProfile { * @param device Paired bluetooth device * @param priority * @return true if priority is set, false on error + * @hide */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); @@ -325,6 +373,7 @@ public final class BluetoothSap implements BluetoothProfile { * * @param device Bluetooth device * @return priority of the device + * @hide */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index 5702d11..5cf2300 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -91,9 +91,13 @@ public final class BluetoothSocket implements Closeable { public static final int MAX_RFCOMM_CHANNEL = 30; /*package*/ static final int MAX_L2CAP_PACKAGE_SIZE = 0xFFFF; - /** Keep TYPE_ fields in sync with BluetoothSocket.cpp */ + /** RFCOMM socket */ public static final int TYPE_RFCOMM = 1; + + /** SCO socket */ public static final int TYPE_SCO = 2; + + /** L2CAP socket */ public static final int TYPE_L2CAP = 3; /*package*/ static final int EBADFD = 77; @@ -578,8 +582,8 @@ public final class BluetoothSocket implements Closeable { } /** - * Get the type of the underlying connection - * @return one of TYPE_ + * Get the type of the underlying connection. + * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP} */ public int getConnectionType() { return mType; diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java index 27b96bd..61b2e78 100644 --- a/core/java/android/bluetooth/le/ScanCallback.java +++ b/core/java/android/bluetooth/le/ScanCallback.java @@ -53,8 +53,10 @@ public abstract class ScanCallback { /** * Callback when a BLE advertisement has been found. * - * @param callbackType Determines how this callback was triggered. Could be of - * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES} + * @param callbackType Determines how this callback was triggered. Could be one of + * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}, + * {@link ScanSettings#CALLBACK_TYPE_FIRST_MATCH} or + * {@link ScanSettings#CALLBACK_TYPE_MATCH_LOST} * @param result A Bluetooth LE scan result. */ public void onScanResult(int callbackType, ScanResult result) { diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index dad486d..4eeb577 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -59,17 +59,13 @@ public final class ScanSettings implements Parcelable { /** * A result callback is only triggered for the first advertisement packet received that matches * the filter criteria. - * @hide */ - @SystemApi public static final int CALLBACK_TYPE_FIRST_MATCH = 2; /** * Receive a callback when advertisements are no longer received from a device that has been * previously reported by a first match callback. - * @hide */ - @SystemApi public static final int CALLBACK_TYPE_MATCH_LOST = 4; @@ -78,21 +74,18 @@ public final class ScanSettings implements Parcelable { */ /** * Match one advertisement per filter - * @hide */ public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; /** * Match few advertisement per filter, depends on current capability and availibility of * the resources in hw - * @hide */ public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; /** * Match as many advertisement per filter as hw could allow, depends on current * capability and availibility of the resources in hw - * @hide */ public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; @@ -100,14 +93,12 @@ public final class ScanSettings implements Parcelable { /** * In Aggressive mode, hw will determine a match sooner even with feeble signal strength * and few number of sightings/match in a duration. - * @hide */ public static final int MATCH_MODE_AGGRESSIVE = 1; /** * For sticky mode, higher threshold of signal strength and sightings is required * before reporting by hw - * @hide */ public static final int MATCH_MODE_STICKY = 2; @@ -324,7 +315,6 @@ public final class ScanSettings implements Parcelable { * {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or * {@link ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT} * @throws IllegalArgumentException If the {@code matchMode} is invalid. - * @hide */ public Builder setNumOfMatches(int numOfMatches) { if (numOfMatches < MATCH_NUM_ONE_ADVERTISEMENT @@ -342,7 +332,6 @@ public final class ScanSettings implements Parcelable { * {@link ScanSettings#MATCH_MODE_AGGRESSIVE} or * {@link ScanSettings#MATCH_MODE_STICKY} * @throws IllegalArgumentException If the {@code matchMode} is invalid. - * @hide */ public Builder setMatchMode(int matchMode) { if (matchMode < MATCH_MODE_AGGRESSIVE diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 16f6b1e..43cc63b 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -570,13 +570,16 @@ public class ActivityInfo extends ComponentInfo Configuration.NATIVE_CONFIG_DENSITY, // DENSITY Configuration.NATIVE_CONFIG_LAYOUTDIR, // LAYOUT DIRECTION }; - /** @hide + + /** * Convert Java change bits to native. + * + * @hide */ public static int activityInfoConfigToNative(int input) { int output = 0; - for (int i=0; i<CONFIG_NATIVE_BITS.length; i++) { - if ((input&(1<<i)) != 0) { + for (int i = 0; i < CONFIG_NATIVE_BITS.length; i++) { + if ((input & (1 << i)) != 0) { output |= CONFIG_NATIVE_BITS[i]; } } @@ -584,6 +587,21 @@ public class ActivityInfo extends ComponentInfo } /** + * Convert native change bits to Java. + * + * @hide + */ + public static int activityInfoConfigNativeToJava(int input) { + int output = 0; + for (int i = 0; i < CONFIG_NATIVE_BITS.length; i++) { + if ((input & CONFIG_NATIVE_BITS[i]) != 0) { + output |= (1 << i); + } + } + return output; + } + + /** * @hide * Unfortunately some developers (OpenFeint I am looking at you) have * compared the configChanges bit field against absolute values, so if we diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 0b24594..94b0223 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -96,9 +96,9 @@ interface IPackageManager { void removePermission(String name); - boolean grantPermission(String packageName, String permissionName, int userId); + void grantPermission(String packageName, String permissionName, int userId); - boolean revokePermission(String packageName, String permissionName, int userId); + void revokePermission(String packageName, String permissionName, int userId); boolean isProtectedBroadcast(String actionName); diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index a176593..525059f 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -789,6 +789,7 @@ public final class AssetManager implements AutoCloseable { TypedValue outValue, boolean resolve); /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix); + /*package*/ native static final int getThemeChangingConfigurations(long theme); private native final long openXmlAssetNative(int cookie, String fileName); diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 6e77e33..ae41b69 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1731,6 +1731,19 @@ public class Resources { } /** + * Returns a bit mask of configuration changes that will impact this + * theme (and thus require completely reloading it). + * + * @return a bit mask of configuration changes, as defined by + * {@link ActivityInfo} + * @see ActivityInfo + */ + public int getChangingConfigurations() { + final int nativeChangingConfig = AssetManager.getThemeChangingConfigurations(mTheme); + return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig); + } + + /** * Print contents of this theme out to the log. For debugging only. * * @param priority The log priority to use. diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 2d63e3f..d8c3361 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2571,10 +2571,8 @@ public class ConnectivityManager { * method assumes that the caller has previously called {@link #registerNetworkCallback} to * listen for network changes. * - * @param network{@link Network} specifying which network you're interested. + * @param network {@link Network} specifying which network you're interested. * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. - * - * @hide */ public boolean requestBandwidthUpdate(Network network) { try { diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index 47e8e69..243ddf7 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -16,6 +16,9 @@ package android.os; +import android.annotation.MainThread; +import android.annotation.WorkerThread; + import java.util.ArrayDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; @@ -350,6 +353,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * @see #onPostExecute * @see #publishProgress */ + @WorkerThread protected abstract Result doInBackground(Params... params); /** @@ -358,6 +362,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * @see #onPostExecute * @see #doInBackground */ + @MainThread protected void onPreExecute() { } @@ -374,6 +379,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * @see #onCancelled(Object) */ @SuppressWarnings({"UnusedDeclaration"}) + @MainThread protected void onPostExecute(Result result) { } @@ -387,6 +393,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * @see #doInBackground */ @SuppressWarnings({"UnusedDeclaration"}) + @MainThread protected void onProgressUpdate(Progress... values) { } @@ -405,6 +412,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * @see #isCancelled() */ @SuppressWarnings({"UnusedParameters"}) + @MainThread protected void onCancelled(Result result) { onCancelled(); } @@ -421,6 +429,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * @see #cancel(boolean) * @see #isCancelled() */ + @MainThread protected void onCancelled() { } @@ -535,6 +544,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * @see #executeOnExecutor(java.util.concurrent.Executor, Object[]) * @see #execute(Runnable) */ + @MainThread public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); } @@ -572,6 +582,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * * @see #execute(Object[]) */ + @MainThread public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { if (mStatus != Status.PENDING) { @@ -604,6 +615,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * @see #execute(Object[]) * @see #executeOnExecutor(java.util.concurrent.Executor, Object[]) */ + @MainThread public static void execute(Runnable runnable) { sDefaultExecutor.execute(runnable); } @@ -622,6 +634,7 @@ public abstract class AsyncTask<Params, Progress, Result> { * @see #onProgressUpdate * @see #doInBackground */ + @WorkerThread protected final void publishProgress(Progress... values) { if (!isCancelled()) { getHandler().obtainMessage(MESSAGE_POST_PROGRESS, diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index 5e9b8c1..74699fd 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -211,8 +211,9 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { } else if (obj instanceof Parcelable[]) { Parcelable[] array = (Parcelable[]) obj; for (int n = array.length - 1; n >= 0; n--) { - if ((array[n].describeContents() - & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) { + Parcelable p = array[n]; + if (p != null && ((p.describeContents() + & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) { fdFound = true; break; } @@ -221,7 +222,8 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { SparseArray<? extends Parcelable> array = (SparseArray<? extends Parcelable>) obj; for (int n = array.size() - 1; n >= 0; n--) { - if ((array.valueAt(n).describeContents() + Parcelable p = array.valueAt(n); + if (p != null && (p.describeContents() & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) { fdFound = true; break; diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 50e7d1c..3fdabee 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -584,7 +584,7 @@ public class StorageManager { // Nickname always takes precedence when defined if (!TextUtils.isEmpty(vol.fsUuid)) { final VolumeRecord rec = findRecordByUuid(vol.fsUuid); - if (!TextUtils.isEmpty(rec.nickname)) { + if (rec != null && !TextUtils.isEmpty(rec.nickname)) { return rec.nickname; } } diff --git a/core/java/android/preference/GenericInflater.java b/core/java/android/preference/GenericInflater.java index 918933b..3319e64 100644 --- a/core/java/android/preference/GenericInflater.java +++ b/core/java/android/preference/GenericInflater.java @@ -376,6 +376,7 @@ abstract class GenericInflater<T, P extends GenericInflater.Parent> { Class clazz = mContext.getClassLoader().loadClass( prefix != null ? (prefix + name) : name); constructor = clazz.getConstructor(mConstructorSignature); + constructor.setAccessible(true); sConstructorMap.put(name, constructor); } diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 396cf19..e07e846 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -9062,5 +9062,15 @@ public final class ContactsContract { */ public static final Uri CONTENT_URI = Uri.withAppendedPath(METADATA_AUTHORITY_URI, "metadata_sync"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of contact metadata + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata"; + + /** + * The MIME type of a {@link #CONTENT_URI} subdirectory of a single contact metadata. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata"; } } diff --git a/core/java/android/service/carrier/CarrierMessagingService.java b/core/java/android/service/carrier/CarrierMessagingService.java index 0592a84..d7bf10c 100644 --- a/core/java/android/service/carrier/CarrierMessagingService.java +++ b/core/java/android/service/carrier/CarrierMessagingService.java @@ -80,6 +80,11 @@ public abstract class CarrierMessagingService extends Service { */ public static final int DOWNLOAD_STATUS_ERROR = 2; + /** + * Flag to request SMS delivery status report. + */ + public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; + private final ICarrierMessagingWrapper mWrapper = new ICarrierMessagingWrapper(); /** @@ -103,12 +108,14 @@ public abstract class CarrierMessagingService extends Service { /** * Override this method to intercept text SMSs sent from the device. + * @deprecated Override {@link #onSendTextSms} below instead. * * @param text the text to send * @param subId SMS subscription ID of the SIM * @param destAddress phone number of the recipient of the message * @param callback result callback. Call with a {@link SendSmsResult}. */ + @Deprecated public void onSendTextSms( @NonNull String text, int subId, @NonNull String destAddress, @NonNull ResultCallback<SendSmsResult> callback) { @@ -120,7 +127,25 @@ public abstract class CarrierMessagingService extends Service { } /** + * Override this method to intercept text SMSs sent from the device. + * + * @param text the text to send + * @param subId SMS subscription ID of the SIM + * @param destAddress phone number of the recipient of the message + * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and + * {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}. + * @param callback result callback. Call with a {@link SendSmsResult}. + */ + public void onSendTextSms( + @NonNull String text, int subId, @NonNull String destAddress, + int sendSmsFlag, @NonNull ResultCallback<SendSmsResult> callback) { + // optional + onSendTextSms(text, subId, destAddress, callback); + } + + /** * Override this method to intercept binary SMSs sent from the device. + * @deprecated Override {@link #onSendDataSms} below instead. * * @param data the binary content * @param subId SMS subscription ID of the SIM @@ -128,6 +153,7 @@ public abstract class CarrierMessagingService extends Service { * @param destPort the destination port * @param callback result callback. Call with a {@link SendSmsResult}. */ + @Deprecated public void onSendDataSms(@NonNull byte[] data, int subId, @NonNull String destAddress, int destPort, @NonNull ResultCallback<SendSmsResult> callback) { @@ -139,13 +165,33 @@ public abstract class CarrierMessagingService extends Service { } /** + * Override this method to intercept binary SMSs sent from the device. + * + * @param data the binary content + * @param subId SMS subscription ID of the SIM + * @param destAddress phone number of the recipient of the message + * @param destPort the destination port + * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and + * {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}. + * @param callback result callback. Call with a {@link SendSmsResult}. + */ + public void onSendDataSms(@NonNull byte[] data, int subId, + @NonNull String destAddress, int destPort, int sendSmsFlag, + @NonNull ResultCallback<SendSmsResult> callback) { + // optional + onSendDataSms(data, subId, destAddress, destPort, callback); + } + + /** * Override this method to intercept long SMSs sent from the device. + * @deprecated Override {@link #onSendMultipartTextSms} below instead. * * @param parts a {@link List} of the message parts * @param subId SMS subscription ID of the SIM * @param destAddress phone number of the recipient of the message * @param callback result callback. Call with a {@link SendMultipartSmsResult}. */ + @Deprecated public void onSendMultipartTextSms(@NonNull List<String> parts, int subId, @NonNull String destAddress, @NonNull ResultCallback<SendMultipartSmsResult> callback) { @@ -158,6 +204,23 @@ public abstract class CarrierMessagingService extends Service { } /** + * Override this method to intercept long SMSs sent from the device. + * + * @param parts a {@link List} of the message parts + * @param subId SMS subscription ID of the SIM + * @param destAddress phone number of the recipient of the message + * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and + * {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}. + * @param callback result callback. Call with a {@link SendMultipartSmsResult}. + */ + public void onSendMultipartTextSms(@NonNull List<String> parts, + int subId, @NonNull String destAddress, int sendSmsFlag, + @NonNull ResultCallback<SendMultipartSmsResult> callback) { + // optional + onSendMultipartTextSms(parts, subId, destAddress, callback); + } + + /** * Override this method to intercept MMSs sent from the device. * * @param pduUri the content provider URI of the PDU to send @@ -355,8 +418,9 @@ public abstract class CarrierMessagingService extends Service { @Override public void sendTextSms(String text, int subId, String destAddress, - final ICarrierMessagingCallback callback) { - onSendTextSms(text, subId, destAddress, new ResultCallback<SendSmsResult>() { + int sendSmsFlag, final ICarrierMessagingCallback callback) { + onSendTextSms(text, subId, destAddress, sendSmsFlag, + new ResultCallback<SendSmsResult>() { @Override public void onReceiveResult(final SendSmsResult result) throws RemoteException { callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef()); @@ -366,8 +430,9 @@ public abstract class CarrierMessagingService extends Service { @Override public void sendDataSms(byte[] data, int subId, String destAddress, int destPort, - final ICarrierMessagingCallback callback) { - onSendDataSms(data, subId, destAddress, destPort, new ResultCallback<SendSmsResult>() { + int sendSmsFlag, final ICarrierMessagingCallback callback) { + onSendDataSms(data, subId, destAddress, destPort, sendSmsFlag, + new ResultCallback<SendSmsResult>() { @Override public void onReceiveResult(final SendSmsResult result) throws RemoteException { callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef()); @@ -377,8 +442,8 @@ public abstract class CarrierMessagingService extends Service { @Override public void sendMultipartTextSms(List<String> parts, int subId, String destAddress, - final ICarrierMessagingCallback callback) { - onSendMultipartTextSms(parts, subId, destAddress, + int sendSmsFlag, final ICarrierMessagingCallback callback) { + onSendMultipartTextSms(parts, subId, destAddress, sendSmsFlag, new ResultCallback<SendMultipartSmsResult>() { @Override public void onReceiveResult(final SendMultipartSmsResult result) diff --git a/core/java/android/service/carrier/ICarrierMessagingService.aidl b/core/java/android/service/carrier/ICarrierMessagingService.aidl index 40a9047..2d96c3d 100644 --- a/core/java/android/service/carrier/ICarrierMessagingService.aidl +++ b/core/java/android/service/carrier/ICarrierMessagingService.aidl @@ -48,9 +48,10 @@ oneway interface ICarrierMessagingService { * @param text the text to send * @param subId SMS subscription ID of the SIM * @param destAddress phone number of the recipient of the message + * @param sendSmsFlag flag for sending SMS * @param callback the callback to notify upon completion */ - void sendTextSms(String text, int subId, String destAddress, + void sendTextSms(String text, int subId, String destAddress, int sendSmsFlag, in ICarrierMessagingCallback callback); /** @@ -62,10 +63,11 @@ oneway interface ICarrierMessagingService { * @param subId SMS subscription ID of the SIM * @param destAddress phone number of the recipient of the message * @param destPort port number of the recipient of the message + * @param sendSmsFlag flag for sending SMS * @param callback the callback to notify upon completion */ void sendDataSms(in byte[] data, int subId, String destAddress, int destPort, - in ICarrierMessagingCallback callback); + int sendSmsFlag, in ICarrierMessagingCallback callback); /** * Request sending a new multi-part text SMS from the device. @@ -75,10 +77,11 @@ oneway interface ICarrierMessagingService { * @param parts the parts of the multi-part text SMS to send * @param subId SMS subscription ID of the SIM * @param destAddress phone number of the recipient of the message + * @param sendSmsFlag flag for sending SMS * @param callback the callback to notify upon completion */ void sendMultipartTextSms(in List<String> parts, int subId, String destAddress, - in ICarrierMessagingCallback callback); + int sendSmsFlag, in ICarrierMessagingCallback callback); /** * Request sending a new MMS PDU from the device. diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index f09f4d2..26bd10f 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -55,6 +55,7 @@ public class ZenModeConfig implements Parcelable { public static final int SOURCE_CONTACT = 1; public static final int SOURCE_STAR = 2; public static final int MAX_SOURCE = SOURCE_STAR; + private static final int DEFAULT_SOURCE = SOURCE_CONTACT; public static final int[] ALL_DAYS = { Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY, Calendar.SATURDAY }; @@ -67,6 +68,8 @@ public class ZenModeConfig implements Parcelable { private static final int MINUTES_MS = 60 * SECONDS_MS; private static final int ZERO_VALUE_MS = 10 * SECONDS_MS; + private static final boolean DEFAULT_ALLOW_CALLS = true; + private static final boolean DEFAULT_ALLOW_MESSAGES = false; private static final boolean DEFAULT_ALLOW_REMINDERS = true; private static final boolean DEFAULT_ALLOW_EVENTS = true; private static final boolean DEFAULT_ALLOW_REPEAT_CALLERS = false; @@ -79,6 +82,8 @@ public class ZenModeConfig implements Parcelable { private static final String ALLOW_ATT_REPEAT_CALLERS = "repeatCallers"; private static final String ALLOW_ATT_MESSAGES = "messages"; private static final String ALLOW_ATT_FROM = "from"; + private static final String ALLOW_ATT_CALLS_FROM = "callsFrom"; + private static final String ALLOW_ATT_MESSAGES_FROM = "messagesFrom"; private static final String ALLOW_ATT_REMINDERS = "reminders"; private static final String ALLOW_ATT_EVENTS = "events"; @@ -103,12 +108,13 @@ public class ZenModeConfig implements Parcelable { private static final String RULE_ATT_ZEN = "zen"; private static final String RULE_ATT_CONDITION_ID = "conditionId"; - public boolean allowCalls; + public boolean allowCalls = DEFAULT_ALLOW_CALLS; public boolean allowRepeatCallers = DEFAULT_ALLOW_REPEAT_CALLERS; - public boolean allowMessages; + public boolean allowMessages = DEFAULT_ALLOW_MESSAGES; public boolean allowReminders = DEFAULT_ALLOW_REMINDERS; public boolean allowEvents = DEFAULT_ALLOW_EVENTS; - public int allowFrom = SOURCE_ANYONE; + public int allowCallsFrom = DEFAULT_SOURCE; + public int allowMessagesFrom = DEFAULT_SOURCE; public ZenRule manualRule; public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>(); @@ -121,7 +127,8 @@ public class ZenModeConfig implements Parcelable { allowMessages = source.readInt() == 1; allowReminders = source.readInt() == 1; allowEvents = source.readInt() == 1; - allowFrom = source.readInt(); + allowCallsFrom = source.readInt(); + allowMessagesFrom = source.readInt(); manualRule = source.readParcelable(null); final int len = source.readInt(); if (len > 0) { @@ -142,7 +149,8 @@ public class ZenModeConfig implements Parcelable { dest.writeInt(allowMessages ? 1 : 0); dest.writeInt(allowReminders ? 1 : 0); dest.writeInt(allowEvents ? 1 : 0); - dest.writeInt(allowFrom); + dest.writeInt(allowCallsFrom); + dest.writeInt(allowMessagesFrom); dest.writeParcelable(manualRule, 0); if (!automaticRules.isEmpty()) { final int len = automaticRules.size(); @@ -166,7 +174,8 @@ public class ZenModeConfig implements Parcelable { .append("allowCalls=").append(allowCalls) .append(",allowRepeatCallers=").append(allowRepeatCallers) .append(",allowMessages=").append(allowMessages) - .append(",allowFrom=").append(sourceToString(allowFrom)) + .append(",allowCallsFrom=").append(sourceToString(allowCallsFrom)) + .append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom)) .append(",allowReminders=").append(allowReminders) .append(",allowEvents=").append(allowEvents) .append(",automaticRules=").append(automaticRules) @@ -234,7 +243,8 @@ public class ZenModeConfig implements Parcelable { return other.allowCalls == allowCalls && other.allowRepeatCallers == allowRepeatCallers && other.allowMessages == allowMessages - && other.allowFrom == allowFrom + && other.allowCallsFrom == allowCallsFrom + && other.allowMessagesFrom == allowMessagesFrom && other.allowReminders == allowReminders && other.allowEvents == allowEvents && Objects.equals(other.automaticRules, automaticRules) @@ -243,8 +253,8 @@ public class ZenModeConfig implements Parcelable { @Override public int hashCode() { - return Objects.hash(allowCalls, allowRepeatCallers, allowMessages, allowFrom, - allowReminders, allowEvents, automaticRules, manualRule); + return Objects.hash(allowCalls, allowRepeatCallers, allowMessages, allowCallsFrom, + allowMessagesFrom, allowReminders, allowEvents, automaticRules, manualRule); } private static String toDayList(int[] days) { @@ -314,9 +324,19 @@ public class ZenModeConfig implements Parcelable { rt.allowReminders = safeBoolean(parser, ALLOW_ATT_REMINDERS, DEFAULT_ALLOW_REMINDERS); rt.allowEvents = safeBoolean(parser, ALLOW_ATT_EVENTS, DEFAULT_ALLOW_EVENTS); - rt.allowFrom = safeInt(parser, ALLOW_ATT_FROM, SOURCE_ANYONE); - if (rt.allowFrom < SOURCE_ANYONE || rt.allowFrom > MAX_SOURCE) { - throw new IndexOutOfBoundsException("bad source in config:" + rt.allowFrom); + final int from = safeInt(parser, ALLOW_ATT_FROM, -1); + final int callsFrom = safeInt(parser, ALLOW_ATT_CALLS_FROM, -1); + final int messagesFrom = safeInt(parser, ALLOW_ATT_MESSAGES_FROM, -1); + if (isValidSource(callsFrom) && isValidSource(messagesFrom)) { + rt.allowCallsFrom = callsFrom; + rt.allowMessagesFrom = messagesFrom; + } else if (isValidSource(from)) { + Slog.i(TAG, "Migrating existing shared 'from': " + sourceToString(from)); + rt.allowCallsFrom = from; + rt.allowMessagesFrom = from; + } else { + rt.allowCallsFrom = DEFAULT_SOURCE; + rt.allowMessagesFrom = DEFAULT_SOURCE; } } else if (MANUAL_TAG.equals(tag)) { rt.manualRule = readRuleXml(parser, false /*conditionRequired*/); @@ -342,7 +362,8 @@ public class ZenModeConfig implements Parcelable { out.attribute(null, ALLOW_ATT_MESSAGES, Boolean.toString(allowMessages)); out.attribute(null, ALLOW_ATT_REMINDERS, Boolean.toString(allowReminders)); out.attribute(null, ALLOW_ATT_EVENTS, Boolean.toString(allowEvents)); - out.attribute(null, ALLOW_ATT_FROM, Integer.toString(allowFrom)); + out.attribute(null, ALLOW_ATT_CALLS_FROM, Integer.toString(allowCallsFrom)); + out.attribute(null, ALLOW_ATT_MESSAGES_FROM, Integer.toString(allowMessagesFrom)); out.endTag(null, ALLOW_TAG); if (manualRule != null) { @@ -432,6 +453,10 @@ public class ZenModeConfig implements Parcelable { return val >= 0 && val < 60; } + private static boolean isValidSource(int source) { + return source >= SOURCE_ANYONE && source <= MAX_SOURCE; + } + private static boolean safeBoolean(XmlPullParser parser, String att, boolean defValue) { final String val = parser.getAttributeValue(null, att); if (TextUtils.isEmpty(val)) return defValue; @@ -494,7 +519,8 @@ public class ZenModeConfig implements Parcelable { public Policy toNotificationPolicy() { int priorityCategories = 0; - int prioritySenders = Policy.PRIORITY_SENDERS_ANY; + int priorityCallSenders = Policy.PRIORITY_SENDERS_CONTACTS; + int priorityMessageSenders = Policy.PRIORITY_SENDERS_CONTACTS; if (allowCalls) { priorityCategories |= Policy.PRIORITY_CATEGORY_CALLS; } @@ -510,18 +536,27 @@ public class ZenModeConfig implements Parcelable { if (allowRepeatCallers) { priorityCategories |= Policy.PRIORITY_CATEGORY_REPEAT_CALLERS; } - switch (allowFrom) { - case SOURCE_ANYONE: - prioritySenders = Policy.PRIORITY_SENDERS_ANY; - break; - case SOURCE_CONTACT: - prioritySenders = Policy.PRIORITY_SENDERS_CONTACTS; - break; - case SOURCE_STAR: - prioritySenders = Policy.PRIORITY_SENDERS_STARRED; - break; + priorityCallSenders = sourceToPrioritySenders(allowCallsFrom, priorityCallSenders); + priorityMessageSenders = sourceToPrioritySenders(allowMessagesFrom, priorityMessageSenders); + return new Policy(priorityCategories, priorityCallSenders); + } + + private static int sourceToPrioritySenders(int source, int def) { + switch (source) { + case SOURCE_ANYONE: return Policy.PRIORITY_SENDERS_ANY; + case SOURCE_CONTACT: return Policy.PRIORITY_SENDERS_CONTACTS; + case SOURCE_STAR: return Policy.PRIORITY_SENDERS_STARRED; + default: return def; + } + } + + private static int prioritySendersToSource(int prioritySenders, int def) { + switch (prioritySenders) { + case Policy.PRIORITY_SENDERS_CONTACTS: return SOURCE_CONTACT; + case Policy.PRIORITY_SENDERS_STARRED: return SOURCE_STAR; + case Policy.PRIORITY_SENDERS_ANY: return SOURCE_ANYONE; + default: return def; } - return new Policy(priorityCategories, prioritySenders); } public void applyNotificationPolicy(Policy policy) { @@ -532,17 +567,7 @@ public class ZenModeConfig implements Parcelable { allowReminders = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_REMINDERS) != 0; allowRepeatCallers = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_REPEAT_CALLERS) != 0; - switch (policy.prioritySenders) { - case Policy.PRIORITY_SENDERS_CONTACTS: - allowFrom = SOURCE_CONTACT; - break; - case Policy.PRIORITY_SENDERS_STARRED: - allowFrom = SOURCE_STAR; - break; - default: - allowFrom = SOURCE_ANYONE; - break; - } + allowCallsFrom = prioritySendersToSource(policy.prioritySenders, allowCallsFrom); } public static Condition toTimeCondition(Context context, int minutesFromNow, int userHandle) { @@ -692,7 +717,6 @@ public class ZenModeConfig implements Parcelable { .authority(SYSTEM_AUTHORITY) .appendPath(EVENT_PATH) .appendQueryParameter("calendar", Long.toString(event.calendar)) - .appendQueryParameter("attendance", Integer.toString(event.attendance)) .appendQueryParameter("reply", Integer.toString(event.reply)) .build(); } @@ -710,22 +734,16 @@ public class ZenModeConfig implements Parcelable { if (!isEvent) return null; final EventInfo rt = new EventInfo(); rt.calendar = tryParseLong(conditionId.getQueryParameter("calendar"), 0L); - rt.attendance = tryParseInt(conditionId.getQueryParameter("attendance"), 0); rt.reply = tryParseInt(conditionId.getQueryParameter("reply"), 0); return rt; } public static class EventInfo { - public static final int ATTENDANCE_REQUIRED_OR_OPTIONAL = 0; - public static final int ATTENDANCE_REQUIRED = 1; - public static final int ATTENDANCE_OPTIONAL = 2; - - public static final int REPLY_ANY = 0; - public static final int REPLY_ANY_EXCEPT_NO = 1; + public static final int REPLY_ANY_EXCEPT_NO = 0; + public static final int REPLY_YES_OR_MAYBE = 1; public static final int REPLY_YES = 2; public long calendar; // CalendarContract.Calendars._ID, or 0 for any - public int attendance; public int reply; @Override @@ -738,14 +756,12 @@ public class ZenModeConfig implements Parcelable { if (!(o instanceof EventInfo)) return false; final EventInfo other = (EventInfo) o; return calendar == other.calendar - && attendance == other.attendance && reply == other.reply; } public EventInfo copy() { final EventInfo rt = new EventInfo(); rt.calendar = calendar; - rt.attendance = attendance; rt.reply = reply; return rt; } diff --git a/core/java/android/service/voice/IVoiceInteractionService.aidl b/core/java/android/service/voice/IVoiceInteractionService.aidl index e8265a2..e3d68a6 100644 --- a/core/java/android/service/voice/IVoiceInteractionService.aidl +++ b/core/java/android/service/voice/IVoiceInteractionService.aidl @@ -23,4 +23,5 @@ oneway interface IVoiceInteractionService { void ready(); void soundModelsChanged(); void shutdown(); + void launchVoiceAssistFromKeyguard(); } diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index fee0c75..8c89ddb 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -98,6 +98,10 @@ public class VoiceInteractionService extends Service { @Override public void soundModelsChanged() { mHandler.sendEmptyMessage(MSG_SOUND_MODELS_CHANGED); } + @Override + public void launchVoiceAssistFromKeyguard() throws RemoteException { + mHandler.sendEmptyMessage(MSG_LAUNCH_VOICE_ASSIST_FROM_KEYGUARD); + } }; MyHandler mHandler; @@ -113,6 +117,7 @@ public class VoiceInteractionService extends Service { static final int MSG_READY = 1; static final int MSG_SHUTDOWN = 2; static final int MSG_SOUND_MODELS_CHANGED = 3; + static final int MSG_LAUNCH_VOICE_ASSIST_FROM_KEYGUARD = 4; class MyHandler extends Handler { @Override @@ -127,6 +132,9 @@ public class VoiceInteractionService extends Service { case MSG_SOUND_MODELS_CHANGED: onSoundModelsChangedInternal(); break; + case MSG_LAUNCH_VOICE_ASSIST_FROM_KEYGUARD: + onLaunchVoiceAssistFromKeyguard(); + break; default: super.handleMessage(msg); } @@ -134,6 +142,19 @@ public class VoiceInteractionService extends Service { } /** + * Called when a user has activated an affordance to launch voice assist from the Keyguard. + * + * <p>This method will only be called if the VoiceInteractionService has set + * {@link android.R.attr#supportsLaunchVoiceAssistFromKeyguard} and the Keyguard is showing.</p> + * + * <p>A valid implementation must start a new activity that should use {@link + * android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} to display + * on top of the lock screen.</p> + */ + public void onLaunchVoiceAssistFromKeyguard() { + } + + /** * Check whether the given service component is the currently active * VoiceInteractionService. */ diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java index 997d586..463eb5b 100644 --- a/core/java/android/service/voice/VoiceInteractionServiceInfo.java +++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java @@ -44,6 +44,7 @@ public class VoiceInteractionServiceInfo { private String mRecognitionService; private String mSettingsActivity; private boolean mSupportsAssist; + private boolean mSupportsLaunchFromKeyguard; public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp) throws PackageManager.NameNotFoundException { @@ -98,6 +99,9 @@ public class VoiceInteractionServiceInfo { mSupportsAssist = array.getBoolean( com.android.internal.R.styleable.VoiceInteractionService_supportsAssist, false); + mSupportsLaunchFromKeyguard = array.getBoolean(com.android.internal. + R.styleable.VoiceInteractionService_supportsLaunchVoiceAssistFromKeyguard, + false); array.recycle(); if (mSessionService == null) { mParseError = "No sessionService specified"; @@ -148,4 +152,8 @@ public class VoiceInteractionServiceInfo { public boolean getSupportsAssist() { return mSupportsAssist; } + + public boolean getSupportsLaunchFromKeyguard() { + return mSupportsLaunchFromKeyguard; + } } diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java index 7bebbfb..a55a08c 100644 --- a/core/java/android/text/Html.java +++ b/core/java/android/text/Html.java @@ -278,7 +278,7 @@ public class Html { if (style[j] instanceof TypefaceSpan) { String s = ((TypefaceSpan) style[j]).getFamily(); - if (s.equals("monospace")) { + if ("monospace".equals(s)) { out.append("<tt>"); } } diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java index c942042..ebc2aac 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -792,6 +792,9 @@ public abstract class Transition implements Cloneable { * views are ignored and only the ids are used). */ boolean isValidTarget(View target) { + if (target == null) { + return false; + } int targetId = target.getId(); if (mTargetIdExcludes != null && mTargetIdExcludes.contains(targetId)) { return false; diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java index ca37d49..cbf76bc 100644 --- a/core/java/android/transition/TransitionInflater.java +++ b/core/java/android/transition/TransitionInflater.java @@ -211,10 +211,10 @@ public class TransitionInflater { .asSubclass(expectedType); if (c != null) { constructor = c.getConstructor(sConstructorSignature); + constructor.setAccessible(true); sConstructors.put(className, constructor); } } - constructor.setAccessible(true); return constructor.newInstance(mContext, attrs); } } catch (InstantiationException e) { diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index cd68fd1..ed7fd86 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -19,12 +19,17 @@ package android.transition; import com.android.internal.R; import android.animation.Animator; +import android.animation.Animator.AnimatorListener; +import android.animation.Animator.AnimatorPauseListener; import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.Animation.AnimationListener; + /** * This transition tracks changes to the visibility of target views in the * start and end scenes. Visibility is determined not just by the @@ -286,6 +291,12 @@ public abstract class Visibility extends Transition { return null; } } + final boolean isForcedVisibility = mForcedStartVisibility != -1 || + mForcedEndVisibility != -1; + if (isForcedVisibility) { + // Make sure that we reverse the effect of onDisappear's setTransitionAlpha(0) + endValues.view.setTransitionAlpha(1); + } return onAppear(sceneRoot, endValues.view, startValues, endValues); } @@ -418,9 +429,9 @@ public abstract class Visibility extends Transition { sceneRoot.getOverlay().remove(overlayView); } else { final View finalOverlayView = overlayView; - animator.addListener(new AnimatorListenerAdapter() { + addListener(new TransitionListenerAdapter() { @Override - public void onAnimationEnd(Animator animation) { + public void onTransitionEnd(Transition transition) { finalSceneRoot.getOverlay().remove(finalOverlayView); } }); @@ -438,40 +449,10 @@ public abstract class Visibility extends Transition { } Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues); if (animator != null) { - final View finalViewToKeep = viewToKeep; - animator.addListener(new AnimatorListenerAdapter() { - boolean mCanceled = false; - - @Override - public void onAnimationPause(Animator animation) { - if (!mCanceled && !isForcedVisibility) { - finalViewToKeep.setVisibility(finalVisibility); - } - } - - @Override - public void onAnimationResume(Animator animation) { - if (!mCanceled && !isForcedVisibility) { - finalViewToKeep.setVisibility(View.VISIBLE); - } - } - - @Override - public void onAnimationCancel(Animator animation) { - mCanceled = true; - } - - @Override - public void onAnimationEnd(Animator animation) { - if (!mCanceled) { - if (isForcedVisibility) { - finalViewToKeep.setTransitionAlpha(0); - } else { - finalViewToKeep.setVisibility(finalVisibility); - } - } - } - }); + DisappearListener disappearListener = new DisappearListener(viewToKeep, + finalVisibility, isForcedVisibility); + animator.addListener(disappearListener); + addListener(disappearListener); } else if (!isForcedVisibility) { viewToKeep.setVisibility(originalVisibility); } @@ -517,4 +498,68 @@ public abstract class Visibility extends Transition { TransitionValues endValues) { return null; } + + private static class DisappearListener + extends TransitionListenerAdapter implements AnimatorListener, AnimatorPauseListener { + private final boolean mIsForcedVisibility; + private final View mView; + private final int mFinalVisibility; + + boolean mCanceled = false; + + public DisappearListener(View view, int finalVisibility, boolean isForcedVisibility) { + this.mView = view; + this.mIsForcedVisibility = isForcedVisibility; + this.mFinalVisibility = finalVisibility; + } + + @Override + public void onAnimationPause(Animator animation) { + if (!mCanceled && !mIsForcedVisibility) { + mView.setVisibility(mFinalVisibility); + } + } + + @Override + public void onAnimationResume(Animator animation) { + if (!mCanceled && !mIsForcedVisibility) { + mView.setVisibility(View.VISIBLE); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + mCanceled = true; + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + hideViewWhenNotCanceled(); + } + + @Override + public void onTransitionEnd(Transition transition) { + hideViewWhenNotCanceled(); + } + + private void hideViewWhenNotCanceled() { + if (!mCanceled) { + if (mIsForcedVisibility) { + mView.setTransitionAlpha(0); + } else { + mView.setVisibility(mFinalVisibility); + } + } + } + } } diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java index 48167c8..bb761f0 100644 --- a/core/java/android/view/DisplayListCanvas.java +++ b/core/java/android/view/DisplayListCanvas.java @@ -93,12 +93,6 @@ public class DisplayListCanvas extends Canvas { private static native long nCreateDisplayListCanvas(); - public static void setProperty(String name, String value) { - nSetProperty(name, value); - } - - private static native void nSetProperty(String name, String value); - /////////////////////////////////////////////////////////////////////////// // Canvas management /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index 1503728..37312d0 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -590,6 +590,7 @@ public abstract class LayoutInflater { } } constructor = clazz.getConstructor(mConstructorSignature); + constructor.setAccessible(true); sConstructorMap.put(name, constructor); } else { // If we have a filter, apply it to cached constructor @@ -615,7 +616,6 @@ public abstract class LayoutInflater { Object[] args = mConstructorArgs; args[1] = attrs; - constructor.setAccessible(true); final View view = constructor.newInstance(args); if (view instanceof ViewStub) { // Use the same context when inflating ViewStub later. diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java index b49a59e..dc8cadf 100644 --- a/core/java/android/view/MenuInflater.java +++ b/core/java/android/view/MenuInflater.java @@ -544,6 +544,7 @@ public class MenuInflater { try { Class<?> clazz = mContext.getClassLoader().loadClass(className); Constructor<?> constructor = clazz.getConstructor(constructorSignature); + constructor.setAccessible(true); return (T) constructor.newInstance(arguments); } catch (Exception e) { Log.w(LOG_TAG, "Cannot instantiate class: " + className, e); diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 91e6d68..1fd7109 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -17,6 +17,7 @@ package android.view; import android.annotation.IntDef; +import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -412,6 +413,13 @@ public class ThreadedRenderer extends HardwareRenderer { nTrimMemory(level); } + public static void overrideProperty(@NonNull String name, @NonNull String value) { + if (name == null || value == null) { + throw new IllegalArgumentException("name and value must be non-null"); + } + nOverrideProperty(name, value); + } + public static void dumpProfileData(byte[] data, FileDescriptor fd) { nDumpProfileData(data, fd); } @@ -510,6 +518,7 @@ public class ThreadedRenderer extends HardwareRenderer { private static native void nDestroyHardwareResources(long nativeProxy); private static native void nTrimMemory(int level); + private static native void nOverrideProperty(String name, String value); private static native void nFence(long nativeProxy); private static native void nStopDrawing(long nativeProxy); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 963b7a6..f62e6a2 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -28,6 +28,7 @@ import android.annotation.LayoutRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; +import android.annotation.UiThread; import android.content.ClipData; import android.content.Context; import android.content.ContextWrapper; @@ -700,6 +701,7 @@ import java.util.concurrent.atomic.AtomicInteger; * * @see android.view.ViewGroup */ +@UiThread public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { private static final boolean DBG = false; @@ -2393,10 +2395,143 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80; + /** + * Flag indicating that the bottom scroll indicator should be displayed + * when this view can scroll up. + */ + static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100; + + /** + * Flag indicating that the bottom scroll indicator should be displayed + * when this view can scroll down. + */ + static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200; + + /** + * Flag indicating that the left scroll indicator should be displayed + * when this view can scroll left. + */ + static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400; + + /** + * Flag indicating that the right scroll indicator should be displayed + * when this view can scroll right. + */ + static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800; + + /** + * Flag indicating that the start scroll indicator should be displayed + * when this view can scroll in the start direction. + */ + static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000; + + /** + * Flag indicating that the end scroll indicator should be displayed + * when this view can scroll in the end direction. + */ + static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000; + /* End of masks for mPrivateFlags3 */ static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED; + static final int SCROLL_INDICATORS_NONE = 0x0000; + + /** + * Mask for use with setFlags indicating bits used for indicating which + * scroll indicators are enabled. + */ + static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP + | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT + | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START + | PFLAG3_SCROLL_INDICATOR_END; + + /** + * Left-shift required to translate between public scroll indicator flags + * and internal PFLAGS3 flags. When used as a right-shift, translates + * PFLAGS3 flags to public flags. + */ + static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, + value = { + SCROLL_INDICATOR_TOP, + SCROLL_INDICATOR_BOTTOM, + SCROLL_INDICATOR_LEFT, + SCROLL_INDICATOR_RIGHT, + SCROLL_INDICATOR_START, + SCROLL_INDICATOR_END, + }) + public @interface ScrollIndicators {} + + /** + * Scroll indicator direction for the top edge of the view. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_TOP = + PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + + /** + * Scroll indicator direction for the bottom edge of the view. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_BOTTOM = + PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + + /** + * Scroll indicator direction for the left edge of the view. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_LEFT = + PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + + /** + * Scroll indicator direction for the right edge of the view. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_RIGHT = + PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + + /** + * Scroll indicator direction for the starting edge of the view. + * <p> + * Resolved according to the view's layout direction, see + * {@link #getLayoutDirection()} for more information. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_START = + PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + + /** + * Scroll indicator direction for the ending edge of the view. + * <p> + * Resolved according to the view's layout direction, see + * {@link #getLayoutDirection()} for more information. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_END = + PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + /** * <p>Indicates that we are allowing {@link android.view.ViewAssistStructure} to traverse * into this view.<p> @@ -3215,6 +3350,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_") private ForegroundInfo mForegroundInfo; + private Drawable mScrollIndicatorDrawable; + /** * RenderNode used for backgrounds. * <p> @@ -3767,6 +3904,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; int overScrollMode = mOverScrollMode; boolean initializeScrollbars = false; + boolean initializeScrollIndicators = false; boolean startPaddingDefined = false; boolean endPaddingDefined = false; @@ -4133,6 +4271,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } mForegroundInfo.mInsidePadding = a.getBoolean(attr, mForegroundInfo.mInsidePadding); + case R.styleable.View_scrollIndicators: + final int scrollIndicators = + a.getInt(attr, SCROLL_INDICATORS_NONE) & SCROLL_INDICATORS_PFLAG3_MASK; + if (scrollIndicators != 0) { + viewFlagValues |= scrollIndicators; + viewFlagMasks |= SCROLL_INDICATORS_PFLAG3_MASK; + initializeScrollIndicators = true; + } break; } } @@ -4209,6 +4355,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, initializeScrollbarsInternal(a); } + if (initializeScrollIndicators) { + initializeScrollIndicatorsInternal(); + } + a.recycle(); // Needs to be called after mViewFlags is set @@ -4680,6 +4830,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, resolvePadding(); } + private void initializeScrollIndicatorsInternal() { + // Some day maybe we'll break this into top/left/start/etc. and let the + // client control it. Until then, you can have any scroll indicator you + // want as long as it's a 1dp foreground-colored rectangle. + if (mScrollIndicatorDrawable == null) { + mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material); + } + } + /** * <p> * Initalizes the scrollability cache if necessary. @@ -4719,6 +4878,118 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mVerticalScrollbarPosition; } + /** + * Sets the state of all scroll indicators. + * <p> + * See {@link #setScrollIndicators(int, int)} for usage information. + * + * @param indicators a bitmask of indicators that should be enabled, or + * {@code 0} to disable all indicators + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + * @attr ref android.R.styleable#View_scrollIndicators + */ + public void setScrollIndicators(@ScrollIndicators int indicators) { + setScrollIndicators(indicators, SCROLL_INDICATORS_PFLAG3_MASK); + } + + /** + * Sets the state of the scroll indicators specified by the mask. To change + * all scroll indicators at once, see {@link #setScrollIndicators(int)}. + * <p> + * When a scroll indicator is enabled, it will be displayed if the view + * can scroll in the direction of the indicator. + * <p> + * Multiple indicator types may be enabled or disabled by passing the + * logical OR of the desired types. If multiple types are specified, they + * will all be set to the same enabled state. + * <p> + * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators + * + * @param indicators the indicator direction, or the logical OR of multiple + * indicator directions. One or more of: + * <ul> + * <li>{@link #SCROLL_INDICATOR_TOP}</li> + * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li> + * <li>{@link #SCROLL_INDICATOR_LEFT}</li> + * <li>{@link #SCROLL_INDICATOR_RIGHT}</li> + * <li>{@link #SCROLL_INDICATOR_START}</li> + * <li>{@link #SCROLL_INDICATOR_END}</li> + * </ul> + * @see #setScrollIndicators(int) + * @see #getScrollIndicators() + * @attr ref android.R.styleable#View_scrollIndicators + */ + public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) { + // Shift and sanitize mask. + mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + mask &= SCROLL_INDICATORS_PFLAG3_MASK; + + // Shift and mask indicators. + indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + indicators &= mask; + + // Merge with non-masked flags. + final int updatedFlags = indicators | (mPrivateFlags3 & ~mask); + + if (mPrivateFlags3 != updatedFlags) { + mPrivateFlags3 = updatedFlags; + + if (indicators != 0) { + initializeScrollIndicatorsInternal(); + } + invalidate(); + } + } + + /** + * Returns a bitmask representing the enabled scroll indicators. + * <p> + * For example, if the top and left scroll indicators are enabled and all + * other indicators are disabled, the return value will be + * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}. + * <p> + * To check whether the bottom scroll indicator is enabled, use the value + * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}. + * + * @return a bitmask representing the enabled scroll indicators + */ + @ScrollIndicators + public int getScrollIndicators() { + return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) + >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + } + + /** + * Returns whether the specified scroll indicator is enabled. + * <p> + * Multiple indicator types may be queried by passing the logical OR of the + * desired types. If multiple types are specified, the return value + * represents whether they are all enabled. + * + * @param direction the indicator direction, or the logical OR of multiple + * indicator directions. One or more of: + * <ul> + * <li>{@link #SCROLL_INDICATOR_TOP}</li> + * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li> + * <li>{@link #SCROLL_INDICATOR_LEFT}</li> + * <li>{@link #SCROLL_INDICATOR_RIGHT}</li> + * <li>{@link #SCROLL_INDICATOR_START}</li> + * <li>{@link #SCROLL_INDICATOR_END}</li> + * </ul> + * @return {@code true} if the specified indicator(s) are enabled, + * {@code false} otherwise + * @attr ref android.R.styleable#View_scrollIndicators + */ + public boolean isScrollIndicatorEnabled(int direction) { + // Shift and sanitize input. + direction <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + direction &= SCROLL_INDICATORS_PFLAG3_MASK; + + // All of the flags must be set. + return (mPrivateFlags3 & direction) == direction; + } + ListenerInfo getListenerInfo() { if (mListenerInfo != null) { return mListenerInfo; @@ -8595,7 +8866,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public boolean performAccessibilityActionInternal(int action, Bundle arguments) { if (isNestedScrollingEnabled() && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD - || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) { + || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD + || action == R.id.accessibilityActionScrollUp + || action == R.id.accessibilityActionScrollLeft + || action == R.id.accessibilityActionScrollDown + || action == R.id.accessibilityActionScrollRight)) { if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) { return true; } @@ -13438,6 +13713,75 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } + void getScrollIndicatorBounds(@NonNull Rect out) { + out.left = mScrollX; + out.right = mScrollX + mRight - mLeft; + out.top = mScrollY; + out.bottom = mScrollY + mBottom - mTop; + } + + private void onDrawScrollIndicators(Canvas c) { + if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) { + // No scroll indicators enabled. + return; + } + + final Drawable dr = mScrollIndicatorDrawable; + if (dr == null) { + // Scroll indicators aren't supported here. + return; + } + + final int h = dr.getIntrinsicHeight(); + final int w = dr.getIntrinsicWidth(); + final Rect rect = mAttachInfo.mTmpInvalRect; + getScrollIndicatorBounds(rect); + + if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) { + final boolean canScrollUp = canScrollVertically(-1); + if (canScrollUp) { + dr.setBounds(rect.left, rect.top, rect.right, rect.top + h); + dr.draw(c); + } + } + + if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) { + final boolean canScrollDown = canScrollVertically(1); + if (canScrollDown) { + dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom); + dr.draw(c); + } + } + + final int leftRtl; + final int rightRtl; + if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) { + leftRtl = PFLAG3_SCROLL_INDICATOR_END; + rightRtl = PFLAG3_SCROLL_INDICATOR_START; + } else { + leftRtl = PFLAG3_SCROLL_INDICATOR_START; + rightRtl = PFLAG3_SCROLL_INDICATOR_END; + } + + final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl; + if ((mPrivateFlags3 & leftMask) != 0) { + final boolean canScrollLeft = canScrollHorizontally(-1); + if (canScrollLeft) { + dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom); + dr.draw(c); + } + } + + final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl; + if ((mPrivateFlags3 & rightMask) != 0) { + final boolean canScrollRight = canScrollHorizontally(1); + if (canScrollRight) { + dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom); + dr.draw(c); + } + } + } + /** * <p>Request the drawing of the horizontal and the vertical scrollbar. The * scrollbars are painted only if they have been awakened first.</p> @@ -17266,6 +17610,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param canvas canvas to draw into */ public void onDrawForeground(Canvas canvas) { + onDrawScrollIndicators(canvas); onDrawScrollBars(canvas); final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index ef57dc3..babb4e9 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -18,6 +18,8 @@ package android.view; import android.animation.LayoutTransition; import android.annotation.IdRes; +import android.annotation.NonNull; +import android.annotation.UiThread; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -105,6 +107,7 @@ import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; * @attr ref android.R.styleable#ViewGroup_splitMotionEvents * @attr ref android.R.styleable#ViewGroup_layoutMode */ +@UiThread public abstract class ViewGroup extends View implements ViewParent, ViewManager { private static final String TAG = "ViewGroup"; @@ -3545,6 +3548,21 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return child.draw(canvas, this, drawingTime); } + @Override + void getScrollIndicatorBounds(@NonNull Rect out) { + super.getScrollIndicatorBounds(out); + + // If we have padding and we're supposed to clip children to that + // padding, offset the scroll indicators to match our clip bounds. + final boolean clipToPadding = (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK; + if (clipToPadding) { + out.left += mPaddingLeft; + out.right -= mPaddingRight; + out.top += mPaddingTop; + out.bottom -= mPaddingBottom; + } + } + /** * Returns whether this group's children are clipped to their bounds before drawing. * The default value is true. diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index bf4b7ae..c785149 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -3500,6 +3500,30 @@ public class AccessibilityNodeInfo implements Parcelable { new AccessibilityAction(R.id.accessibilityActionScrollToPosition, null); /** + * Action to scroll the node content up. + */ + public static final AccessibilityAction ACTION_SCROLL_UP = + new AccessibilityAction(R.id.accessibilityActionScrollUp, null); + + /** + * Action to scroll the node content left. + */ + public static final AccessibilityAction ACTION_SCROLL_LEFT = + new AccessibilityAction(R.id.accessibilityActionScrollLeft, null); + + /** + * Action to scroll the node content down. + */ + public static final AccessibilityAction ACTION_SCROLL_DOWN = + new AccessibilityAction(R.id.accessibilityActionScrollDown, null); + + /** + * Action to scroll the node content right. + */ + public static final AccessibilityAction ACTION_SCROLL_RIGHT = + new AccessibilityAction(R.id.accessibilityActionScrollRight, null); + + /** * Action that stylus button presses the node. */ public static final AccessibilityAction ACTION_STYLUS_BUTTON_PRESS = @@ -3531,6 +3555,10 @@ public class AccessibilityNodeInfo implements Parcelable { sStandardActions.add(ACTION_SET_TEXT); sStandardActions.add(ACTION_SHOW_ON_SCREEN); sStandardActions.add(ACTION_SCROLL_TO_POSITION); + sStandardActions.add(ACTION_SCROLL_UP); + sStandardActions.add(ACTION_SCROLL_LEFT); + sStandardActions.add(ACTION_SCROLL_DOWN); + sStandardActions.add(ACTION_SCROLL_RIGHT); sStandardActions.add(ACTION_STYLUS_BUTTON_PRESS); } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 1df43d0..c57a53a 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -1506,10 +1506,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (isEnabled()) { if (canScrollUp()) { info.addAction(AccessibilityAction.ACTION_SCROLL_BACKWARD); + info.addAction(AccessibilityAction.ACTION_SCROLL_UP); info.setScrollable(true); } if (canScrollDown()) { info.addAction(AccessibilityAction.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityAction.ACTION_SCROLL_DOWN); info.setScrollable(true); } } @@ -1537,14 +1539,16 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te return true; } switch (action) { - case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { + case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: + case R.id.accessibilityActionScrollDown: { if (isEnabled() && getLastVisiblePosition() < getCount() - 1) { final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom; smoothScrollBy(viewportHeight, PositionScroller.SCROLL_DURATION); return true; } } return false; - case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { + case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: + case R.id.accessibilityActionScrollUp: { if (isEnabled() && mFirstPosition > 0) { final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom; smoothScrollBy(-viewportHeight, PositionScroller.SCROLL_DURATION); diff --git a/core/java/android/widget/CursorAdapter.java b/core/java/android/widget/CursorAdapter.java index 30c74c0..d8ce60c 100644 --- a/core/java/android/widget/CursorAdapter.java +++ b/core/java/android/widget/CursorAdapter.java @@ -16,6 +16,7 @@ package android.widget; +import android.annotation.WorkerThread; import android.content.Context; import android.content.res.Resources; import android.database.ContentObserver; @@ -425,6 +426,7 @@ public abstract class CursorAdapter extends BaseAdapter implements Filterable, * @see #getFilterQueryProvider() * @see #setFilterQueryProvider(android.widget.FilterQueryProvider) */ + @WorkerThread public Cursor runQueryOnBackgroundThread(CharSequence constraint) { if (mFilterQueryProvider != null) { return mFilterQueryProvider.runQuery(constraint); diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 9b36b84..712fdba 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -318,6 +318,7 @@ public class Editor { } getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true); + resumeBlink(); } void onDetachedFromWindow() { @@ -327,9 +328,7 @@ public class Editor { hideError(); } - if (mBlink != null) { - mBlink.removeCallbacks(mBlink); - } + suspendBlink(); if (mInsertionPointCursorController != null) { mInsertionPointCursorController.onDetached(); @@ -2422,7 +2421,8 @@ public class Editor { public PinnedPopupWindow() { createPopupWindow(); - mPopupWindow.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL); + mPopupWindow.setWindowLayoutType( + WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL); mPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); mPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 324c2aa..0879c5d 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -40,6 +40,8 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AnimationUtils; +import com.android.internal.R; + import java.util.List; /** @@ -768,7 +770,8 @@ public class HorizontalScrollView extends FrameLayout { return true; } switch (action) { - case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { + case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: + case R.id.accessibilityActionScrollRight: { if (!isEnabled()) { return false; } @@ -779,7 +782,8 @@ public class HorizontalScrollView extends FrameLayout { return true; } } return false; - case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { + case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: + case R.id.accessibilityActionScrollLeft: { if (!isEnabled()) { return false; } @@ -807,10 +811,12 @@ public class HorizontalScrollView extends FrameLayout { if (scrollRange > 0) { info.setScrollable(true); if (isEnabled() && mScrollX > 0) { - info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_LEFT); } if (isEnabled() && mScrollX < scrollRange) { - info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_RIGHT); } } } diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java index 310412f..05866f0 100644 --- a/core/java/android/widget/ListPopupWindow.java +++ b/core/java/android/widget/ListPopupWindow.java @@ -39,6 +39,7 @@ import android.view.View.OnTouchListener; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; +import android.view.WindowManager; import android.view.animation.AccelerateDecelerateInterpolator; import com.android.internal.R; @@ -77,6 +78,7 @@ public class ListPopupWindow { private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT; private int mDropDownHorizontalOffset; private int mDropDownVerticalOffset; + private int mDropDownWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; private boolean mDropDownVerticalOffsetSet; private int mDropDownGravity = Gravity.NO_GRAVITY; @@ -515,6 +517,19 @@ public class ListPopupWindow { } /** + * Set the layout type for this popup window. + * <p> + * See {@link WindowManager.LayoutParams#type} for possible values. + * + * @param layoutType Layout type for this window. + * + * @see WindowManager.LayoutParams#type + */ + public void setWindowLayoutType(int layoutType) { + mDropDownWindowLayoutType = layoutType; + } + + /** * Sets a listener to receive events when a list item is clicked. * * @param clickListener Listener to register @@ -567,8 +582,9 @@ public class ListPopupWindow { public void show() { int height = buildDropDown(); - boolean noInputMethod = isInputMethodNotNeeded(); + final boolean noInputMethod = isInputMethodNotNeeded(); mPopup.setAllowScrollingAnchorParent(!noInputMethod); + mPopup.setWindowLayoutType(mDropDownWindowLayoutType); if (mPopup.isShowing()) { final int widthSpec; diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index c3ac278..b4cbf35 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -829,9 +829,9 @@ public class PopupWindow { } /** - * Set the layout type for this window. This value will be passed through to - * {@link WindowManager.LayoutParams#type} therefore the value should match any value - * {@link WindowManager.LayoutParams#type} accepts. + * Set the layout type for this window. + * <p> + * See {@link WindowManager.LayoutParams#type} for possible values. * * @param layoutType Layout type for this window. * diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java index 10e4db3..5953a98 100644 --- a/core/java/android/widget/RemoteViewsAdapter.java +++ b/core/java/android/widget/RemoteViewsAdapter.java @@ -618,7 +618,15 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback // remove based on both its position as well as it's current memory usage, as well // as whether it was directly requested vs. whether it was preloaded by our caching // mechanism. - mIndexRemoteViews.remove(getFarthestPositionFrom(pruneFromPosition, visibleWindow)); + int trimIndex = getFarthestPositionFrom(pruneFromPosition, visibleWindow); + + // Need to check that this is a valid index, to cover the case where you have only + // a single view in the cache, but it's larger than the max memory limit + if (trimIndex < 0) { + break; + } + + mIndexRemoteViews.remove(trimIndex); } // Update the metadata cache diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 2026169..98d61d3 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -819,7 +819,8 @@ public class ScrollView extends FrameLayout { return false; } switch (action) { - case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { + case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: + case R.id.accessibilityActionScrollDown: { final int viewportHeight = getHeight() - mPaddingBottom - mPaddingTop; final int targetScrollY = Math.min(mScrollY + viewportHeight, getScrollRange()); if (targetScrollY != mScrollY) { @@ -827,7 +828,8 @@ public class ScrollView extends FrameLayout { return true; } } return false; - case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { + case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: + case R.id.accessibilityActionScrollUp: { final int viewportHeight = getHeight() - mPaddingBottom - mPaddingTop; final int targetScrollY = Math.max(mScrollY - viewportHeight, 0); if (targetScrollY != mScrollY) { @@ -853,10 +855,13 @@ public class ScrollView extends FrameLayout { if (scrollRange > 0) { info.setScrollable(true); if (mScrollY > 0) { - info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); + info.addAction( + AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP); } if (mScrollY < scrollRange) { - info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_DOWN); } } } diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index b8110e3..61ee00c 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -526,11 +526,15 @@ public class AlertController { mWindow.setCloseOnTouchOutsideIfNotSet(true); } - // Only display the divider if we have a title and a custom view or a - // message. if (hasTopPanel) { + // Only clip scrolling content to padding if we have a title. + if (mScrollView != null) { + mScrollView.setClipToPadding(true); + } + + // Only show the divider if we have a title. final View divider; - if (mMessage != null || hasCustomPanel || mListView != null) { + if (mMessage != null || mListView != null || hasCustomPanel) { divider = topPanel.findViewById(R.id.titleDivider); } else { divider = topPanel.findViewById(R.id.titleDividerTop); @@ -541,6 +545,17 @@ public class AlertController { } } + // Update scroll indicators as needed. + if (!hasCustomPanel) { + final View content = mListView != null ? mListView : mScrollView; + if (content != null) { + final int indicators = (hasTopPanel ? View.SCROLL_INDICATOR_TOP : 0) + | (hasButtonPanel ? View.SCROLL_INDICATOR_BOTTOM : 0); + content.setScrollIndicators(indicators, + View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM); + } + } + final TypedArray a = mContext.obtainStyledAttributes( null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0); setBackground(a, topPanel, contentPanel, customPanel, buttonPanel, @@ -654,59 +669,6 @@ public class AlertController { contentPanel.setVisibility(View.GONE); } } - - // Set up scroll indicators (if present). - final View indicatorUp = contentPanel.findViewById(R.id.scrollIndicatorUp); - final View indicatorDown = contentPanel.findViewById(R.id.scrollIndicatorDown); - if (indicatorUp != null || indicatorDown != null) { - if (mMessage != null) { - // We're just showing the ScrollView, set up listener. - mScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() { - @Override - public void onScrollChange(View v, int scrollX, int scrollY, - int oldScrollX, int oldScrollY) { - manageScrollIndicators(v, indicatorUp, indicatorDown); - } - }); - // Set up the indicators following layout. - mScrollView.post(new Runnable() { - @Override - public void run() { - manageScrollIndicators(mScrollView, indicatorUp, indicatorDown); - } - }); - - } else if (mListView != null) { - // We're just showing the AbsListView, set up listener. - mListView.setOnScrollListener(new AbsListView.OnScrollListener() { - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - // That's cool, I guess? - } - - @Override - public void onScroll(AbsListView v, int firstVisibleItem, - int visibleItemCount, int totalItemCount) { - manageScrollIndicators(v, indicatorUp, indicatorDown); - } - }); - // Set up the indicators following layout. - mListView.post(new Runnable() { - @Override - public void run() { - manageScrollIndicators(mListView, indicatorUp, indicatorDown); - } - }); - } else { - // We don't have any content to scroll, remove the indicators. - if (indicatorUp != null) { - contentPanel.removeView(indicatorUp); - } - if (indicatorDown != null) { - contentPanel.removeView(indicatorDown); - } - } - } } private static void manageScrollIndicators(View v, View upIndicator, View downIndicator) { diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl index 4c6db24..644adb6 100644 --- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl @@ -97,6 +97,12 @@ interface IVoiceInteractionManagerService { void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback); /** + * Notifies the active service that a launch was requested from the Keyguard. This will only + * be called if {@link #activeServiceSupportsLaunchFromKeyguard()} returns true. + */ + void launchVoiceAssistFromKeyguard(); + + /** * Indicates whether there is a voice session running (but not necessarily showing). */ boolean isSessionRunning(); @@ -106,4 +112,10 @@ interface IVoiceInteractionManagerService { * assist gesture. */ boolean activeServiceSupportsAssist(); + + /** + * Indicates whether the currently active voice interaction service is capable of being launched + * from the lockscreen. + */ + boolean activeServiceSupportsLaunchFromKeyguard(); } diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java index 240d9df..d77b998 100644 --- a/core/java/com/android/internal/os/BinderInternal.java +++ b/core/java/com/android/internal/os/BinderInternal.java @@ -20,6 +20,8 @@ import android.os.IBinder; import android.os.SystemClock; import android.util.EventLog; +import dalvik.system.VMRuntime; + import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -96,7 +98,7 @@ public class BinderInternal { public static void forceGc(String reason) { EventLog.writeEvent(2741, reason); - Runtime.getRuntime().gc(); + VMRuntime.getRuntime().requestConcurrentGC(); } static void forceBinderGc() { diff --git a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java index 9711c3b..8586d76 100644 --- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java +++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java @@ -52,7 +52,7 @@ public class MobileRadioPowerCalculator extends PowerCalculator { public MobileRadioPowerCalculator(PowerProfile profile, BatteryStats stats) { mPowerRadioOn = profile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE); for (int i = 0; i < mPowerBins.length; i++) { - mPowerBins[i] = profile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE, i); + mPowerBins[i] = profile.getAveragePower(PowerProfile.POWER_RADIO_ON, i); } mPowerScan = profile.getAveragePower(PowerProfile.POWER_RADIO_SCANNING); mStats = stats; @@ -128,7 +128,9 @@ public class MobileRadioPowerCalculator extends PowerCalculator { } if (power != 0) { - app.noCoveragePercent = noCoverageTimeMs * 100.0 / signalTimeMs; + if (signalTimeMs != 0) { + app.noCoveragePercent = noCoverageTimeMs * 100.0 / signalTimeMs; + } app.mobileActive = remainingActiveTimeMs; app.mobileActiveCount = stats.getMobileRadioActiveUnknownCount(statsType); app.mobileRadioPowerMah = power; diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java index 64e6c69..f58ab03 100644 --- a/core/java/com/android/internal/widget/ButtonBarLayout.java +++ b/core/java/com/android/internal/widget/ButtonBarLayout.java @@ -17,6 +17,7 @@ package com.android.internal.widget; import android.content.Context; +import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; @@ -29,37 +30,39 @@ import com.android.internal.R; * orientation when it can't fit its child views horizontally. */ public class ButtonBarLayout extends LinearLayout { - /** Spacer used in horizontal orientation. */ - private final View mSpacer; - /** Whether the current configuration allows stacking. */ - private final boolean mAllowStacked; + private final boolean mAllowStacking; /** Whether the layout is currently stacked. */ private boolean mStacked; + private int mLastWidthSize = -1; + public ButtonBarLayout(Context context, AttributeSet attrs) { super(context, attrs); - mAllowStacked = context.getResources().getBoolean(R.bool.allow_stacked_button_bar); - mSpacer = findViewById(R.id.spacer); + final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ButtonBarLayout); + mAllowStacking = ta.getBoolean(R.styleable.ButtonBarLayout_allowStacking, false); + ta.recycle(); + + mStacked = getOrientation() == VERTICAL; } @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (mAllowStacking) { + final int widthSize = MeasureSpec.getSize(widthMeasureSpec); + if (widthSize > mLastWidthSize && mStacked) { + // We're being measured wider this time, try un-stacking. + setStacked(false); + } - // Maybe we can fit the content now? - if (w > oldw && mStacked) { - setStacked(false); + mLastWidthSize = widthSize; } - } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (mAllowStacked && getOrientation() == LinearLayout.HORIZONTAL) { + if (mAllowStacking && !mStacked) { final int measuredWidth = getMeasuredWidthAndState(); final int measuredWidthState = measuredWidth & MEASURED_STATE_MASK; if (measuredWidthState == MEASURED_STATE_TOO_SMALL) { @@ -75,8 +78,9 @@ public class ButtonBarLayout extends LinearLayout { setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL); setGravity(stacked ? Gravity.RIGHT : Gravity.BOTTOM); - if (mSpacer != null) { - mSpacer.setVisibility(stacked ? View.GONE : View.INVISIBLE); + final View spacer = findViewById(R.id.spacer); + if (spacer != null) { + spacer.setVisibility(stacked ? View.GONE : View.INVISIBLE); } // Reverse the child order. This is specific to the Material button diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java index 441e640..e76302b 100644 --- a/core/java/com/android/internal/widget/ViewPager.java +++ b/core/java/com/android/internal/widget/ViewPager.java @@ -47,6 +47,8 @@ import android.view.animation.Interpolator; import android.widget.EdgeEffect; import android.widget.Scroller; +import com.android.internal.R; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -2720,10 +2722,12 @@ public class ViewPager extends ViewGroup { if (canScrollHorizontally(1)) { info.addAction(AccessibilityAction.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityAction.ACTION_SCROLL_RIGHT); } if (canScrollHorizontally(-1)) { info.addAction(AccessibilityAction.ACTION_SCROLL_BACKWARD); + info.addAction(AccessibilityAction.ACTION_SCROLL_LEFT); } } @@ -2735,12 +2739,14 @@ public class ViewPager extends ViewGroup { switch (action) { case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: + case R.id.accessibilityActionScrollRight: if (canScrollHorizontally(1)) { setCurrentItem(mCurItem + 1); return true; } return false; case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: + case R.id.accessibilityActionScrollLeft: if (canScrollHorizontally(-1)) { setCurrentItem(mCurItem - 1); return true; |