summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManagerNative.java52
-rw-r--r--core/java/android/app/ActivityOptions.java4
-rw-r--r--core/java/android/app/ActivityThread.java3
-rw-r--r--core/java/android/app/ApplicationThreadNative.java7
-rw-r--r--core/java/android/app/ContextImpl.java33
-rw-r--r--core/java/android/app/IActivityManager.java24
-rw-r--r--core/java/android/app/IApplicationThread.java3
-rw-r--r--core/java/android/app/Notification.java4
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java45
-rw-r--r--core/java/android/app/task/TaskParams.java19
-rw-r--r--core/java/android/bluetooth/BluetoothTetheringDataTracker.java14
-rw-r--r--core/java/android/content/ClipData.java21
-rw-r--r--core/java/android/content/ContentProvider.java114
-rw-r--r--core/java/android/content/ContentProviderOperation.java27
-rw-r--r--core/java/android/content/ContentProviderResult.java10
-rw-r--r--core/java/android/content/ContentResolver.java11
-rw-r--r--core/java/android/content/Intent.java36
-rw-r--r--core/java/android/content/SharedPreferences.java2
-rw-r--r--core/java/android/content/Task.java48
-rw-r--r--core/java/android/hardware/Sensor.java26
-rw-r--r--core/java/android/net/BaseNetworkStateTracker.java8
-rw-r--r--core/java/android/net/DummyDataStateTracker.java7
-rw-r--r--core/java/android/net/EthernetDataTracker.java12
-rw-r--r--core/java/android/net/LinkCapabilities.java362
-rw-r--r--core/java/android/net/LinkSocket.java276
-rw-r--r--core/java/android/net/LinkSocketNotifier.java86
-rw-r--r--core/java/android/net/MobileDataStateTracker.java25
-rw-r--r--core/java/android/net/NetworkCapabilities.aidl (renamed from core/java/android/net/LinkCapabilities.aidl)4
-rw-r--r--core/java/android/net/NetworkCapabilities.java328
-rw-r--r--core/java/android/net/NetworkRequest.aidl20
-rw-r--r--core/java/android/net/NetworkRequest.java87
-rw-r--r--core/java/android/net/NetworkState.java14
-rw-r--r--core/java/android/net/NetworkStateTracker.java5
-rw-r--r--core/java/android/net/Proxy.java10
-rw-r--r--core/java/android/net/ProxyDataTracker.java2
-rw-r--r--core/java/android/net/ProxyInfo.java54
-rw-r--r--core/java/android/provider/Settings.java49
-rw-r--r--core/java/android/service/notification/INotificationListener.aidl10
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java82
-rw-r--r--core/java/android/service/notification/NotificationOrderUpdate.aidl19
-rw-r--r--core/java/android/service/notification/NotificationOrderUpdate.java62
-rw-r--r--core/java/android/speech/tts/TtsEngines.java18
-rw-r--r--core/java/android/tv/ITvInputClient.aidl5
-rw-r--r--core/java/android/tv/ITvInputManager.aidl8
-rw-r--r--core/java/android/tv/ITvInputServiceCallback.aidl2
-rw-r--r--core/java/android/tv/TvInputInfo.java15
-rw-r--r--core/java/android/tv/TvInputManager.java187
-rw-r--r--core/java/android/tv/TvInputService.java10
-rw-r--r--core/java/android/tv/TvView.java54
-rw-r--r--core/java/android/util/TimeUtils.java3
-rw-r--r--core/java/android/view/Choreographer.java10
-rw-r--r--core/java/android/view/RenderNodeAnimator.java53
-rw-r--r--core/java/android/view/ThreadedRenderer.java5
-rw-r--r--core/java/android/view/animation/AccelerateDecelerateInterpolator.java13
-rw-r--r--core/java/android/view/animation/AccelerateInterpolator.java13
-rw-r--r--core/java/android/view/animation/AnticipateInterpolator.java13
-rw-r--r--core/java/android/view/animation/AnticipateOvershootInterpolator.java14
-rw-r--r--core/java/android/view/animation/BounceInterpolator.java13
-rw-r--r--core/java/android/view/animation/CycleInterpolator.java13
-rw-r--r--core/java/android/view/animation/DecelerateInterpolator.java13
-rw-r--r--core/java/android/view/animation/LinearInterpolator.java13
-rw-r--r--core/java/android/view/animation/OvershootInterpolator.java13
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java26
-rw-r--r--core/java/android/widget/AbsListView.java2
64 files changed, 1414 insertions, 1127 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index ec2868a..296e9d3 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1114,7 +1114,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
int pid = data.readInt();
int uid = data.readInt();
int mode = data.readInt();
- int res = checkUriPermission(uri, pid, uid, mode);
+ int userId = data.readInt();
+ int res = checkUriPermission(uri, pid, uid, mode, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
@@ -1139,7 +1140,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
String targetPkg = data.readString();
Uri uri = Uri.CREATOR.createFromParcel(data);
int mode = data.readInt();
- grantUriPermission(app, targetPkg, uri, mode);
+ int userId = data.readInt();
+ grantUriPermission(app, targetPkg, uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1150,7 +1152,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Uri uri = Uri.CREATOR.createFromParcel(data);
int mode = data.readInt();
- revokeUriPermission(app, uri, mode);
+ int userId = data.readInt();
+ revokeUriPermission(app, uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1159,7 +1162,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
data.enforceInterface(IActivityManager.descriptor);
Uri uri = Uri.CREATOR.createFromParcel(data);
int mode = data.readInt();
- takePersistableUriPermission(uri, mode);
+ int userId = data.readInt();
+ takePersistableUriPermission(uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1168,7 +1172,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
data.enforceInterface(IActivityManager.descriptor);
Uri uri = Uri.CREATOR.createFromParcel(data);
int mode = data.readInt();
- releasePersistableUriPermission(uri, mode);
+ int userId = data.readInt();
+ releasePersistableUriPermission(uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1602,7 +1607,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
String targetPkg = data.readString();
Uri uri = Uri.CREATOR.createFromParcel(data);
int mode = data.readInt();
- grantUriPermissionFromOwner(owner, fromUid, targetPkg, uri, mode);
+ int userId = data.readInt();
+ grantUriPermissionFromOwner(owner, fromUid, targetPkg, uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1612,10 +1618,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
IBinder owner = data.readStrongBinder();
Uri uri = null;
if (data.readInt() != 0) {
- Uri.CREATOR.createFromParcel(data);
+ uri = Uri.CREATOR.createFromParcel(data);
}
int mode = data.readInt();
- revokeUriPermissionFromOwner(owner, uri, mode);
+ int userId = data.readInt();
+ revokeUriPermissionFromOwner(owner, uri, mode, userId);
reply.writeNoException();
return true;
}
@@ -1626,7 +1633,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
String targetPkg = data.readString();
Uri uri = Uri.CREATOR.createFromParcel(data);
int modeFlags = data.readInt();
- int res = checkGrantUriPermission(callingUid, targetPkg, uri, modeFlags);
+ int userId = data.readInt();
+ int res = checkGrantUriPermission(callingUid, targetPkg, uri, modeFlags, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
@@ -3540,7 +3548,7 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
return res;
}
- public int checkUriPermission(Uri uri, int pid, int uid, int mode)
+ public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -3549,6 +3557,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeInt(pid);
data.writeInt(uid);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(CHECK_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
@@ -3557,7 +3566,7 @@ class ActivityManagerProxy implements IActivityManager
return res;
}
public void grantUriPermission(IApplicationThread caller, String targetPkg,
- Uri uri, int mode) throws RemoteException {
+ Uri uri, int mode, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -3565,19 +3574,21 @@ class ActivityManagerProxy implements IActivityManager
data.writeString(targetPkg);
uri.writeToParcel(data, 0);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
public void revokeUriPermission(IApplicationThread caller, Uri uri,
- int mode) throws RemoteException {
+ int mode, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller.asBinder());
uri.writeToParcel(data, 0);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(REVOKE_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -3585,12 +3596,14 @@ class ActivityManagerProxy implements IActivityManager
}
@Override
- public void takePersistableUriPermission(Uri uri, int mode) throws RemoteException {
+ public void takePersistableUriPermission(Uri uri, int mode, int userId)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
uri.writeToParcel(data, 0);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(TAKE_PERSISTABLE_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -3598,12 +3611,14 @@ class ActivityManagerProxy implements IActivityManager
}
@Override
- public void releasePersistableUriPermission(Uri uri, int mode) throws RemoteException {
+ public void releasePersistableUriPermission(Uri uri, int mode, int userId)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
uri.writeToParcel(data, 0);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -4157,7 +4172,7 @@ class ActivityManagerProxy implements IActivityManager
}
public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
- Uri uri, int mode) throws RemoteException {
+ Uri uri, int mode, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -4166,6 +4181,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeString(targetPkg);
uri.writeToParcel(data, 0);
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -4173,7 +4189,7 @@ class ActivityManagerProxy implements IActivityManager
}
public void revokeUriPermissionFromOwner(IBinder owner, Uri uri,
- int mode) throws RemoteException {
+ int mode, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -4185,6 +4201,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeInt(0);
}
data.writeInt(mode);
+ data.writeInt(userId);
mRemote.transact(REVOKE_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -4192,7 +4209,7 @@ class ActivityManagerProxy implements IActivityManager
}
public int checkGrantUriPermission(int callingUid, String targetPkg,
- Uri uri, int modeFlags) throws RemoteException {
+ Uri uri, int modeFlags, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -4200,6 +4217,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeString(targetPkg);
uri.writeToParcel(data, 0);
data.writeInt(modeFlags);
+ data.writeInt(userId);
mRemote.transact(CHECK_GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index a49359f..692efd7 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -365,11 +365,15 @@ public class ActivityOptions {
* @param listener The listener to use to monitor activity transition events.
* @return Returns a new ActivityOptions object that you can use to
* supply these options as the options Bundle when starting an activity.
+ * Returns null if the Window does not have {@link Window#FEATURE_CONTENT_TRANSITIONS}.
* @see android.transition.Transition#setEpicenterCallback(
* android.transition.Transition.EpicenterCallback)
*/
public static ActivityOptions makeSceneTransitionAnimation(Window window,
ActivityTransitionListener listener) {
+ if (!window.hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
+ return null;
+ }
ActivityOptions opts = new ActivityOptions();
opts.mAnimationType = ANIM_SCENE_TRANSITION;
ExitTransitionCoordinator exit = new ExitTransitionCoordinator(window, listener);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 161cb76..4cf30ae 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -47,6 +47,7 @@ import android.hardware.display.DisplayManagerGlobal;
import android.net.IConnectivityManager;
import android.net.Proxy;
import android.net.ProxyInfo;
+import android.net.Uri;
import android.opengl.GLUtils;
import android.os.AsyncTask;
import android.os.Binder;
@@ -839,7 +840,7 @@ public final class ActivityThread {
InetAddress.clearDnsCache();
}
- public void setHttpProxy(String host, String port, String exclList, String pacFileUrl) {
+ public void setHttpProxy(String host, String port, String exclList, Uri pacFileUrl) {
Proxy.setHttpProxySystemProperty(host, port, exclList, pacFileUrl);
}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index e7902a9..0029efa 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -25,6 +25,7 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
@@ -339,7 +340,7 @@ public abstract class ApplicationThreadNative extends Binder
final String proxy = data.readString();
final String port = data.readString();
final String exclList = data.readString();
- final String pacFileUrl = data.readString();
+ final Uri pacFileUrl = Uri.CREATOR.createFromParcel(data);
setHttpProxy(proxy, port, exclList, pacFileUrl);
return true;
}
@@ -1008,13 +1009,13 @@ class ApplicationThreadProxy implements IApplicationThread {
}
public void setHttpProxy(String proxy, String port, String exclList,
- String pacFileUrl) throws RemoteException {
+ Uri pacFileUrl) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeString(proxy);
data.writeString(port);
data.writeString(exclList);
- data.writeString(pacFileUrl);
+ pacFileUrl.writeToParcel(data, 0);
mRemote.transact(SET_HTTP_PROXY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
data.recycle();
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 801182d..b4d8942 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -26,6 +26,7 @@ import com.android.internal.util.Preconditions;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
@@ -1818,8 +1819,8 @@ class ContextImpl extends Context {
public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
try {
ActivityManagerNative.getDefault().grantUriPermission(
- mMainThread.getApplicationThread(), toPackage, uri,
- modeFlags);
+ mMainThread.getApplicationThread(), toPackage,
+ ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
} catch (RemoteException e) {
}
}
@@ -1828,8 +1829,8 @@ class ContextImpl extends Context {
public void revokeUriPermission(Uri uri, int modeFlags) {
try {
ActivityManagerNative.getDefault().revokeUriPermission(
- mMainThread.getApplicationThread(), uri,
- modeFlags);
+ mMainThread.getApplicationThread(),
+ ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
} catch (RemoteException e) {
}
}
@@ -1838,12 +1839,17 @@ class ContextImpl extends Context {
public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
try {
return ActivityManagerNative.getDefault().checkUriPermission(
- uri, pid, uid, modeFlags);
+ ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags,
+ resolveUserId(uri));
} catch (RemoteException e) {
return PackageManager.PERMISSION_DENIED;
}
}
+ private int resolveUserId(Uri uri) {
+ return ContentProvider.getUserIdFromUri(uri, getUserId());
+ }
+
@Override
public int checkCallingUriPermission(Uri uri, int modeFlags) {
int pid = Binder.getCallingPid();
@@ -2280,12 +2286,16 @@ class ContextImpl extends Context {
@Override
protected IContentProvider acquireProvider(Context context, String auth) {
- return mMainThread.acquireProvider(context, auth, mUser.getIdentifier(), true);
+ return mMainThread.acquireProvider(context,
+ ContentProvider.getAuthorityWithoutUserId(auth),
+ resolveUserIdFromAuthority(auth), true);
}
@Override
protected IContentProvider acquireExistingProvider(Context context, String auth) {
- return mMainThread.acquireExistingProvider(context, auth, mUser.getIdentifier(), true);
+ return mMainThread.acquireExistingProvider(context,
+ ContentProvider.getAuthorityWithoutUserId(auth),
+ resolveUserIdFromAuthority(auth), true);
}
@Override
@@ -2295,7 +2305,9 @@ class ContextImpl extends Context {
@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
- return mMainThread.acquireProvider(c, auth, mUser.getIdentifier(), false);
+ return mMainThread.acquireProvider(c,
+ ContentProvider.getAuthorityWithoutUserId(auth),
+ resolveUserIdFromAuthority(auth), false);
}
@Override
@@ -2312,5 +2324,10 @@ class ContextImpl extends Context {
public void appNotRespondingViaProvider(IContentProvider icp) {
mMainThread.appNotRespondingViaProvider(icp.asBinder());
}
+
+ /** @hide */
+ protected int resolveUserIdFromAuthority(String auth) {
+ return ContentProvider.getUserIdFromAuthority(auth, mUser.getIdentifier());
+ }
}
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 074b427..a30a64a 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -210,14 +210,16 @@ public interface IActivityManager extends IInterface {
public int checkPermission(String permission, int pid, int uid)
throws RemoteException;
- public int checkUriPermission(Uri uri, int pid, int uid, int mode)
+ public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId)
+ throws RemoteException;
+ public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri,
+ int mode, int userId) throws RemoteException;
+ public void revokeUriPermission(IApplicationThread caller, Uri uri, int mode, int userId)
+ throws RemoteException;
+ public void takePersistableUriPermission(Uri uri, int modeFlags, int userId)
+ throws RemoteException;
+ public void releasePersistableUriPermission(Uri uri, int modeFlags, int userId)
throws RemoteException;
- public void grantUriPermission(IApplicationThread caller, String targetPkg,
- Uri uri, int mode) throws RemoteException;
- public void revokeUriPermission(IApplicationThread caller, Uri uri,
- int mode) throws RemoteException;
- public void takePersistableUriPermission(Uri uri, int modeFlags) throws RemoteException;
- public void releasePersistableUriPermission(Uri uri, int modeFlags) throws RemoteException;
public ParceledListSlice<UriPermission> getPersistedUriPermissions(
String packageName, boolean incoming) throws RemoteException;
@@ -323,12 +325,12 @@ public interface IActivityManager extends IInterface {
public IBinder newUriPermissionOwner(String name) throws RemoteException;
public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
- Uri uri, int mode) throws RemoteException;
+ Uri uri, int mode, int userId) throws RemoteException;
public void revokeUriPermissionFromOwner(IBinder owner, Uri uri,
- int mode) throws RemoteException;
+ int mode, int userId) throws RemoteException;
- public int checkGrantUriPermission(int callingUid, String targetPkg,
- Uri uri, int modeFlags) throws RemoteException;
+ public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri,
+ int modeFlags, int userId) throws RemoteException;
// Cause the specified process to dump the specified heap.
public boolean dumpHeap(String process, int userId, boolean managed, String path,
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index a832034..d5fbd0b 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -25,6 +25,7 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Debug;
import android.os.ParcelFileDescriptor;
@@ -106,7 +107,7 @@ public interface IApplicationThread extends IInterface {
void updateTimeZone() throws RemoteException;
void clearDnsCache() throws RemoteException;
void setHttpProxy(String proxy, String port, String exclList,
- String pacFileUrl) throws RemoteException;
+ Uri pacFileUrl) throws RemoteException;
void processInBackground() throws RemoteException;
void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)
throws RemoteException;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index bba6caf..76a6a8e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -659,8 +659,8 @@ public class Notification implements Parcelable
/**
* @hide
- * Extra added by NotificationManagerService to indicate whether a NotificationScorer
- * modified the Notifications's score.
+ * Extra added by NotificationManagerService to indicate whether
+ * the Notifications's score has been modified.
*/
public static final String EXTRA_SCORE_MODIFIED = "android.scoreModified";
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 58049fd..8884446 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2068,46 +2068,49 @@ public class DevicePolicyManager {
}
/**
- * Called by a profile owner to disable account management for a specific type of account.
- *
- * <p>The calling device admin must be a profile owner. If it is not, a
- * security exception will be thrown.
+ * Called by profile or device owner to re-enable system apps by intent that were disabled
+ * by default when the managed profile was created. This should only be called from a profile
+ * or device owner running within a managed profile.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param accountType For which account management is disabled or enabled.
- * @param disabled The boolean indicating that account management will be disabled (true) or
- * enabled (false).
+ * @param intent An intent matching the app(s) to be installed. All apps that resolve for this
+ * intent will be re-enabled in the current profile.
+ * @return int The number of activities that matched the intent and were installed.
*/
- public void setAccountManagementDisabled(ComponentName admin, String accountType,
- boolean disabled) {
+ public int enableSystemApp(ComponentName admin, Intent intent) {
if (mService != null) {
try {
- mService.setAccountManagementDisabled(admin, accountType, disabled);
+ return mService.enableSystemAppWithIntent(admin, intent);
} catch (RemoteException e) {
- Log.w(TAG, "Failed talking with device policy service", e);
+ Log.w(TAG, "Failed to install packages matching filter: " + intent);
}
}
+ return 0;
}
/**
- * Called by profile or device owner to re-enable system apps by intent that were disabled
- * by default when the managed profile was created. This should only be called from a profile
- * or device owner running within a managed profile.
+ * Called by a profile owner to disable account management for a specific type of account.
+ *
+ * <p>The calling device admin must be a profile owner. If it is not, a
+ * security exception will be thrown.
+ *
+ * <p>When account management is disabled for an account type, adding or removing an account
+ * of that type will not be possible.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param intent An intent matching the app(s) to be installed. All apps that resolve for this
- * intent will be re-enabled in the current profile.
- * @return int The number of activities that matched the intent and were installed.
+ * @param accountType For which account management is disabled or enabled.
+ * @param disabled The boolean indicating that account management will be disabled (true) or
+ * enabled (false).
*/
- public int enableSystemApp(ComponentName admin, Intent intent) {
+ public void setAccountManagementDisabled(ComponentName admin, String accountType,
+ boolean disabled) {
if (mService != null) {
try {
- return mService.enableSystemAppWithIntent(admin, intent);
+ mService.setAccountManagementDisabled(admin, accountType, disabled);
} catch (RemoteException e) {
- Log.w(TAG, "Failed to install packages matching filter: " + intent);
+ Log.w(TAG, "Failed talking with device policy service", e);
}
}
- return 0;
}
/**
diff --git a/core/java/android/app/task/TaskParams.java b/core/java/android/app/task/TaskParams.java
index e2eafd8..0351082 100644
--- a/core/java/android/app/task/TaskParams.java
+++ b/core/java/android/app/task/TaskParams.java
@@ -29,7 +29,14 @@ public class TaskParams implements Parcelable {
private final int taskId;
private final Bundle extras;
- private final IBinder mCallback;
+ private final IBinder callback;
+
+ /** @hide */
+ public TaskParams(int taskId, Bundle extras, IBinder callback) {
+ this.taskId = taskId;
+ this.extras = extras;
+ this.callback = callback;
+ }
/**
* @return The unique id of this task, specified at creation time.
@@ -47,17 +54,15 @@ public class TaskParams implements Parcelable {
return extras;
}
- /**
- * @hide
- */
+ /** @hide */
public ITaskCallback getCallback() {
- return ITaskCallback.Stub.asInterface(mCallback);
+ return ITaskCallback.Stub.asInterface(callback);
}
private TaskParams(Parcel in) {
taskId = in.readInt();
extras = in.readBundle();
- mCallback = in.readStrongBinder();
+ callback = in.readStrongBinder();
}
@Override
@@ -69,7 +74,7 @@ public class TaskParams implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(taskId);
dest.writeBundle(extras);
- dest.writeStrongBinder(mCallback);
+ dest.writeStrongBinder(callback);
}
public static final Creator<TaskParams> CREATOR = new Creator<TaskParams>() {
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index a0b603e..f0c8299 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -20,7 +20,7 @@ import android.net.BaseNetworkStateTracker;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DhcpResults;
-import android.net.LinkCapabilities;
+import android.net.NetworkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
@@ -75,7 +75,7 @@ public class BluetoothTetheringDataTracker extends BaseNetworkStateTracker {
private BluetoothTetheringDataTracker() {
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, "");
mLinkProperties = new LinkProperties();
- mLinkCapabilities = new LinkCapabilities();
+ mNetworkCapabilities = new NetworkCapabilities();
mNetworkInfo.setIsAvailable(false);
setTeardownRequested(false);
@@ -242,16 +242,6 @@ public class BluetoothTetheringDataTracker extends BaseNetworkStateTracker {
}
}
- /**
- * A capability is an Integer/String pair, the capabilities
- * are defined in the class LinkSocket#Key.
- *
- * @return a copy of this connections capabilities, may be empty but never null.
- */
- public LinkCapabilities getLinkCapabilities() {
- return new LinkCapabilities(mLinkCapabilities);
- }
-
/**
* Fetch default gateway address for the network
*/
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 50c4fed..b44abf9 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -16,6 +16,7 @@
package android.content;
+import static android.content.ContentProvider.maybeAddUserId;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -186,7 +187,7 @@ public class ClipData implements Parcelable {
final CharSequence mText;
final String mHtmlText;
final Intent mIntent;
- final Uri mUri;
+ Uri mUri;
/**
* Create an Item consisting of a single block of (possibly styled) text.
@@ -809,6 +810,24 @@ public class ClipData implements Parcelable {
}
}
+ /**
+ * Prepare this {@link ClipData} to leave an app process.
+ *
+ * @hide
+ */
+ public void prepareToLeaveUser(int userId) {
+ final int size = mItems.size();
+ for (int i = 0; i < size; i++) {
+ final Item item = mItems.get(i);
+ if (item.mIntent != null) {
+ item.mIntent.prepareToLeaveUser(userId);
+ }
+ if (item.mUri != null) {
+ item.mUri = maybeAddUserId(item.mUri, userId);
+ }
+ }
+ }
+
@Override
public String toString() {
StringBuilder b = new StringBuilder(128);
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 02c850b..be9782f 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -36,6 +36,7 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.UserHandle;
import android.util.Log;
+import android.text.TextUtils;
import java.io.File;
import java.io.FileDescriptor;
@@ -195,6 +196,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
return rejectQuery(uri, projection, selection, selectionArgs, sortOrder,
CancellationSignal.fromTransport(cancellationSignal));
}
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.query(
@@ -207,6 +209,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public String getType(Uri uri) {
+ uri = getUriWithoutUserId(uri);
return ContentProvider.this.getType(uri);
}
@@ -215,9 +218,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return rejectInsert(uri, initialValues);
}
+ int userId = getUserIdFromUri(uri);
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
- return ContentProvider.this.insert(uri, initialValues);
+ return maybeAddUserId(ContentProvider.this.insert(uri, initialValues), userId);
} finally {
setCallingPackage(original);
}
@@ -228,6 +233,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.bulkInsert(uri, initialValues);
@@ -240,24 +246,39 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public ContentProviderResult[] applyBatch(String callingPkg,
ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
- for (ContentProviderOperation operation : operations) {
+ int numOperations = operations.size();
+ final int[] userIds = new int[numOperations];
+ for (int i = 0; i < numOperations; i++) {
+ ContentProviderOperation operation = operations.get(i);
+ userIds[i] = getUserIdFromUri(operation.getUri());
if (operation.isReadOperation()) {
if (enforceReadPermission(callingPkg, operation.getUri())
!= AppOpsManager.MODE_ALLOWED) {
throw new OperationApplicationException("App op not allowed", 0);
}
}
-
if (operation.isWriteOperation()) {
if (enforceWritePermission(callingPkg, operation.getUri())
!= AppOpsManager.MODE_ALLOWED) {
throw new OperationApplicationException("App op not allowed", 0);
}
}
+ if (userIds[i] != UserHandle.USER_CURRENT) {
+ // Removing the user id from the uri.
+ operation = new ContentProviderOperation(operation, true);
+ }
+ operations.set(i, operation);
}
final String original = setCallingPackage(callingPkg);
try {
- return ContentProvider.this.applyBatch(operations);
+ ContentProviderResult[] results = ContentProvider.this.applyBatch(operations);
+ for (int i = 0; i < results.length ; i++) {
+ if (userIds[i] != UserHandle.USER_CURRENT) {
+ // Adding the userId to the uri.
+ results[i] = new ContentProviderResult(results[i], userIds[i]);
+ }
+ }
+ return results;
} finally {
setCallingPackage(original);
}
@@ -268,6 +289,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.delete(uri, selection, selectionArgs);
@@ -282,6 +304,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.update(uri, values, selection, selectionArgs);
@@ -295,6 +318,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
enforceFilePermission(callingPkg, uri, mode);
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openFile(
@@ -309,6 +333,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
enforceFilePermission(callingPkg, uri, mode);
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openAssetFile(
@@ -330,6 +355,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
+ uri = getUriWithoutUserId(uri);
return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
}
@@ -337,6 +363,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
enforceFilePermission(callingPkg, uri, "r");
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openTypedAssetFile(
@@ -356,9 +383,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return null;
}
+ int userId = getUserIdFromUri(uri);
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
- return ContentProvider.this.canonicalize(uri);
+ return maybeAddUserId(ContentProvider.this.canonicalize(uri), userId);
} finally {
setCallingPackage(original);
}
@@ -369,9 +398,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return null;
}
+ int userId = getUserIdFromUri(uri);
+ uri = getUriWithoutUserId(uri);
final String original = setCallingPackage(callingPkg);
try {
- return ContentProvider.this.uncanonicalize(uri);
+ return maybeAddUserId(ContentProvider.this.uncanonicalize(uri), userId);
} finally {
setCallingPackage(original);
}
@@ -1680,4 +1711,75 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
writer.println("nothing to dump");
}
+
+ /** @hide */
+ public static int getUserIdFromAuthority(String auth, int defaultUserId) {
+ if (auth == null) return defaultUserId;
+ int end = auth.indexOf('@');
+ if (end == -1) return defaultUserId;
+ String userIdString = auth.substring(0, end);
+ try {
+ return Integer.parseInt(userIdString);
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Error parsing userId.", e);
+ return UserHandle.USER_NULL;
+ }
+ }
+
+ /** @hide */
+ public static int getUserIdFromAuthority(String auth) {
+ return getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
+ }
+
+ /** @hide */
+ public static int getUserIdFromUri(Uri uri, int defaultUserId) {
+ if (uri == null) return defaultUserId;
+ return getUserIdFromAuthority(uri.getAuthority(), defaultUserId);
+ }
+
+ /** @hide */
+ public static int getUserIdFromUri(Uri uri) {
+ return getUserIdFromUri(uri, UserHandle.USER_CURRENT);
+ }
+
+ /**
+ * Removes userId part from authority string. Expects format:
+ * userId@some.authority
+ * If there is no userId in the authority, it symply returns the argument
+ * @hide
+ */
+ public static String getAuthorityWithoutUserId(String auth) {
+ if (auth == null) return null;
+ int end = auth.indexOf('@');
+ return auth.substring(end+1);
+ }
+
+ /** @hide */
+ public static Uri getUriWithoutUserId(Uri uri) {
+ if (uri == null) return null;
+ Uri.Builder builder = uri.buildUpon();
+ builder.authority(getAuthorityWithoutUserId(uri.getAuthority()));
+ return builder.build();
+ }
+
+ /** @hide */
+ public static boolean uriHasUserId(Uri uri) {
+ if (uri == null) return false;
+ return !TextUtils.isEmpty(uri.getUserInfo());
+ }
+
+ /** @hide */
+ public static Uri maybeAddUserId(Uri uri, int userId) {
+ if (uri == null) return null;
+ if (userId != UserHandle.USER_CURRENT
+ && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+ if (!uriHasUserId(uri)) {
+ //We don't add the user Id if there's already one
+ Uri.Builder builder = uri.buildUpon();
+ builder.encodedAuthority("" + userId + "@" + uri.getEncodedAuthority());
+ return builder.build();
+ }
+ }
+ return uri;
+ }
}
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 12e9bab..136e54d 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -16,6 +16,7 @@
package android.content;
+import android.content.ContentProvider;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
@@ -87,6 +88,31 @@ public class ContentProviderOperation implements Parcelable {
mYieldAllowed = source.readInt() != 0;
}
+ /** @hide */
+ public ContentProviderOperation(ContentProviderOperation cpo, boolean removeUserIdFromUri) {
+ mType = cpo.mType;
+ if (removeUserIdFromUri) {
+ mUri = ContentProvider.getUriWithoutUserId(cpo.mUri);
+ } else {
+ mUri = cpo.mUri;
+ }
+ mValues = cpo.mValues;
+ mSelection = cpo.mSelection;
+ mSelectionArgs = cpo.mSelectionArgs;
+ mExpectedCount = cpo.mExpectedCount;
+ mSelectionArgsBackReferences = cpo.mSelectionArgsBackReferences;
+ mValuesBackReferences = cpo.mValuesBackReferences;
+ mYieldAllowed = cpo.mYieldAllowed;
+ }
+
+ /** @hide */
+ public ContentProviderOperation getWithoutUserIdInUri() {
+ if (ContentProvider.uriHasUserId(mUri)) {
+ return new ContentProviderOperation(this, true);
+ }
+ return this;
+ }
+
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mType);
Uri.writeToParcel(dest, mUri);
@@ -387,7 +413,6 @@ public class ContentProviderOperation implements Parcelable {
}
};
-
/**
* Used to add parameters to a {@link ContentProviderOperation}. The {@link Builder} is
* first created by calling {@link ContentProviderOperation#newInsert(android.net.Uri)},
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
index 5d188ef..ec3d002 100644
--- a/core/java/android/content/ContentProviderResult.java
+++ b/core/java/android/content/ContentProviderResult.java
@@ -16,7 +16,9 @@
package android.content;
+import android.content.ContentProvider;
import android.net.Uri;
+import android.os.UserHandle;
import android.os.Parcelable;
import android.os.Parcel;
@@ -50,6 +52,12 @@ public class ContentProviderResult implements Parcelable {
}
}
+ /** @hide */
+ public ContentProviderResult(ContentProviderResult cpr, int userId) {
+ uri = ContentProvider.maybeAddUserId(cpr.uri, userId);
+ count = cpr.count;
+ }
+
public void writeToParcel(Parcel dest, int flags) {
if (uri == null) {
dest.writeInt(1);
@@ -81,4 +89,4 @@ public class ContentProviderResult implements Parcelable {
}
return "ContentProviderResult(count=" + count + ")";
}
-} \ No newline at end of file
+}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 5b41394..7642e13 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1643,7 +1643,8 @@ public abstract class ContentResolver {
*/
public void takePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
try {
- ActivityManagerNative.getDefault().takePersistableUriPermission(uri, modeFlags);
+ ActivityManagerNative.getDefault().takePersistableUriPermission(
+ ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
} catch (RemoteException e) {
}
}
@@ -1658,7 +1659,8 @@ public abstract class ContentResolver {
*/
public void releasePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
try {
- ActivityManagerNative.getDefault().releasePersistableUriPermission(uri, modeFlags);
+ ActivityManagerNative.getDefault().releasePersistableUriPermission(
+ ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
} catch (RemoteException e) {
}
}
@@ -2462,4 +2464,9 @@ public abstract class ContentResolver {
private final Context mContext;
final String mPackageName;
private static final String TAG = "ContentResolver";
+
+ /** @hide */
+ public int resolveUserId(Uri uri) {
+ return ContentProvider.getUserIdFromUri(uri, mContext.getUserId());
+ }
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3cfc56c..076f657 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -26,6 +26,7 @@ import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.pm.ActivityInfo;
+import static android.content.ContentProvider.maybeAddUserId;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
@@ -7433,6 +7434,41 @@ public class Intent implements Parcelable, Cloneable {
}
/**
+ * Prepare this {@link Intent} to be sent to another user
+ *
+ * @hide
+ */
+ public void prepareToLeaveUser(int userId) {
+ Uri data = getData();
+ if (data != null) {
+ mData = maybeAddUserId(data, userId);
+ }
+ if (mSelector != null) {
+ mSelector.prepareToLeaveUser(userId);
+ }
+ if (mClipData != null) {
+ mClipData.prepareToLeaveUser(userId);
+ }
+ String action = getAction();
+ if (ACTION_SEND.equals(action)) {
+ final Uri stream = getParcelableExtra(EXTRA_STREAM);
+ if (stream != null) {
+ putExtra(EXTRA_STREAM, maybeAddUserId(stream, userId));
+ }
+ }
+ if (ACTION_SEND_MULTIPLE.equals(action)) {
+ final ArrayList<Uri> streams = getParcelableArrayListExtra(EXTRA_STREAM);
+ if (streams != null) {
+ ArrayList<Uri> newStreams = new ArrayList<Uri>();
+ for (int i = 0; i < streams.size(); i++) {
+ newStreams.add(maybeAddUserId(streams.get(i), userId));
+ }
+ putParcelableArrayListExtra(EXTRA_STREAM, newStreams);
+ }
+ }
+ }
+
+ /**
* Migrate any {@link #EXTRA_STREAM} in {@link #ACTION_SEND} and
* {@link #ACTION_SEND_MULTIPLE} to {@link ClipData}. Also inspects nested
* intents in {@link #ACTION_CHOOSER}.
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index d4f7f06..6b4404d 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -82,7 +82,7 @@ public interface SharedPreferences {
/**
* Set a set of String values in the preferences editor, to be written
- * back once {@link #commit} is called.
+ * back once {@link #commit} or {@link #apply} is called.
*
* @param key The name of the preference to modify.
* @param values The set of new values for the preference. Passing {@code null}
diff --git a/core/java/android/content/Task.java b/core/java/android/content/Task.java
index ed5ed88..407880f 100644
--- a/core/java/android/content/Task.java
+++ b/core/java/android/content/Task.java
@@ -42,6 +42,20 @@ public class Task implements Parcelable {
public final int EXPONENTIAL = 1;
}
+ private final int taskId;
+ // TODO: Change this to use PersistableBundle when that lands in master.
+ private final Bundle extras;
+ private final ComponentName service;
+ private final boolean requireCharging;
+ private final boolean requireDeviceIdle;
+ private final int networkCapabilities;
+ private final long minLatencyMillis;
+ private final long maxExecutionDelayMillis;
+ private final boolean isPeriodic;
+ private final long intervalMillis;
+ private final long initialBackoffMillis;
+ private final int backoffPolicy;
+
/**
* Unique task id associated with this class. This is assigned to your task by the scheduler.
*/
@@ -59,8 +73,8 @@ public class Task implements Parcelable {
/**
* Name of the service endpoint that will be called back into by the TaskManager.
*/
- public String getServiceClassName() {
- return serviceClassName;
+ public ComponentName getService() {
+ return service;
}
/**
@@ -132,24 +146,10 @@ public class Task implements Parcelable {
return backoffPolicy;
}
- private final int taskId;
- // TODO: Change this to use PersistableBundle when that lands in master.
- private final Bundle extras;
- private final String serviceClassName;
- private final boolean requireCharging;
- private final boolean requireDeviceIdle;
- private final int networkCapabilities;
- private final long minLatencyMillis;
- private final long maxExecutionDelayMillis;
- private final boolean isPeriodic;
- private final long intervalMillis;
- private final long initialBackoffMillis;
- private final int backoffPolicy;
-
private Task(Parcel in) {
taskId = in.readInt();
extras = in.readBundle();
- serviceClassName = in.readString();
+ service = ComponentName.readFromParcel(in);
requireCharging = in.readInt() == 1;
requireDeviceIdle = in.readInt() == 1;
networkCapabilities = in.readInt();
@@ -164,7 +164,7 @@ public class Task implements Parcelable {
private Task(Task.Builder b) {
taskId = b.mTaskId;
extras = new Bundle(b.mExtras);
- serviceClassName = b.mTaskServiceClassName;
+ service = b.mTaskService;
requireCharging = b.mRequiresCharging;
requireDeviceIdle = b.mRequiresDeviceIdle;
networkCapabilities = b.mNetworkCapabilities;
@@ -185,7 +185,7 @@ public class Task implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeInt(taskId);
out.writeBundle(extras);
- out.writeString(serviceClassName);
+ ComponentName.writeToParcel(service, out);
out.writeInt(requireCharging ? 1 : 0);
out.writeInt(requireDeviceIdle ? 1 : 0);
out.writeInt(networkCapabilities);
@@ -215,7 +215,7 @@ public class Task implements Parcelable {
public final class Builder {
private int mTaskId;
private Bundle mExtras;
- private String mTaskServiceClassName;
+ private ComponentName mTaskService;
// Requirements.
private boolean mRequiresCharging;
private boolean mRequiresDeviceIdle;
@@ -236,11 +236,11 @@ public class Task implements Parcelable {
* @param taskId Application-provided id for this task. Subsequent calls to cancel, or
* tasks created with the same taskId, will update the pre-existing task with
* the same id.
- * @param cls The endpoint that you implement that will receive the callback from the
+ * @param taskService The endpoint that you implement that will receive the callback from the
* TaskManager.
*/
- public Builder(int taskId, Class<TaskService> cls) {
- mTaskServiceClassName = cls.getClass().getName();
+ public Builder(int taskId, ComponentName taskService) {
+ mTaskService = taskService;
mTaskId = taskId;
}
@@ -296,7 +296,7 @@ public class Task implements Parcelable {
* period. You have no control over when within this interval this task will be executed,
* only the guarantee that it will be executed at most once within this interval.
* A periodic task will be repeated until the phone is turned off, however it will only be
- * persisted if the client app has declared the
+ * persisted beyond boot if the client app has declared the
* {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission. You can schedule
* periodic tasks without this permission, they simply will cease to exist after the phone
* restarts.
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 4bea9ee..86208fc 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -397,6 +397,32 @@ public final class Sensor {
public static final String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
/**
+ * A constant describing a wake gesture sensor.
+ * <p>
+ * Wake gesture sensors enable waking up the device based on a device specific motion.
+ * <p>
+ * When this sensor triggers, the device behaves as if the power button was pressed, turning the
+ * screen on. This behavior (turning on the screen when this sensor triggers) might be
+ * deactivated by the user in the device settings. Changes in settings do not impact the
+ * behavior of the sensor: only whether the framework turns the screen on when it triggers.
+ * <p>
+ * The actual gesture to be detected is not specified, and can be chosen by the manufacturer of
+ * the device. This sensor must be low power, as it is likely to be activated 24/7.
+ * Values of events created by this sensors should not be used.
+ *
+ * @hide This sensor is expected to only be used by the power manager
+ */
+ public static final int TYPE_WAKE_GESTURE = 42;
+
+ /**
+ * A constant string describing a wake gesture sensor.
+ *
+ * @hide This sensor is expected to only be used by the power manager
+ * @see #TYPE_WAKE_GESTURE
+ */
+ public static final String STRING_TYPE_WAKE_GESTURE = "android.sensor.wake_gesture";
+
+ /**
* A constant describing all sensor types.
*/
public static final int TYPE_ALL = -1;
diff --git a/core/java/android/net/BaseNetworkStateTracker.java b/core/java/android/net/BaseNetworkStateTracker.java
index 862d59e..79db389 100644
--- a/core/java/android/net/BaseNetworkStateTracker.java
+++ b/core/java/android/net/BaseNetworkStateTracker.java
@@ -44,7 +44,7 @@ public abstract class BaseNetworkStateTracker implements NetworkStateTracker {
protected NetworkInfo mNetworkInfo;
protected LinkProperties mLinkProperties;
- protected LinkCapabilities mLinkCapabilities;
+ protected NetworkCapabilities mNetworkCapabilities;
protected Network mNetwork = new Network(ConnectivityManager.INVALID_NET_ID);
private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
@@ -55,7 +55,7 @@ public abstract class BaseNetworkStateTracker implements NetworkStateTracker {
mNetworkInfo = new NetworkInfo(
networkType, -1, ConnectivityManager.getNetworkTypeName(networkType), null);
mLinkProperties = new LinkProperties();
- mLinkCapabilities = new LinkCapabilities();
+ mNetworkCapabilities = new NetworkCapabilities();
}
protected BaseNetworkStateTracker() {
@@ -99,8 +99,8 @@ public abstract class BaseNetworkStateTracker implements NetworkStateTracker {
}
@Override
- public LinkCapabilities getLinkCapabilities() {
- return new LinkCapabilities(mLinkCapabilities);
+ public NetworkCapabilities getNetworkCapabilities() {
+ return new NetworkCapabilities(mNetworkCapabilities);
}
@Override
diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java
index a5d059e..eff9f9f 100644
--- a/core/java/android/net/DummyDataStateTracker.java
+++ b/core/java/android/net/DummyDataStateTracker.java
@@ -190,13 +190,6 @@ public class DummyDataStateTracker extends BaseNetworkStateTracker {
return new LinkProperties(mLinkProperties);
}
- /**
- * @see android.net.NetworkStateTracker#getLinkCapabilities()
- */
- public LinkCapabilities getLinkCapabilities() {
- return new LinkCapabilities(mLinkCapabilities);
- }
-
public void setDependencyMet(boolean met) {
// not supported on this network
}
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 10b5d0b..c1afc9b 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -103,7 +103,7 @@ public class EthernetDataTracker extends BaseNetworkStateTracker {
private EthernetDataTracker() {
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, "");
mLinkProperties = new LinkProperties();
- mLinkCapabilities = new LinkCapabilities();
+ mNetworkCapabilities = new NetworkCapabilities();
}
private void interfaceUpdated() {
@@ -372,16 +372,6 @@ public class EthernetDataTracker extends BaseNetworkStateTracker {
return new LinkProperties(mLinkProperties);
}
- /**
- * A capability is an Integer/String pair, the capabilities
- * are defined in the class LinkSocket#Key.
- *
- * @return a copy of this connections capabilities, may be empty but never null.
- */
- public LinkCapabilities getLinkCapabilities() {
- return new LinkCapabilities(mLinkCapabilities);
- }
-
/**
* Fetch default gateway address for the network
*/
diff --git a/core/java/android/net/LinkCapabilities.java b/core/java/android/net/LinkCapabilities.java
deleted file mode 100644
index fb444ea..0000000
--- a/core/java/android/net/LinkCapabilities.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-import android.util.Log;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-/**
- * A class representing the capabilities of a link
- *
- * @hide
- */
-public class LinkCapabilities implements Parcelable {
- private static final String TAG = "LinkCapabilities";
- private static final boolean DBG = false;
-
- /** The Map of Keys to Values */
- private HashMap<Integer, String> mCapabilities;
-
-
- /**
- * The set of keys defined for a links capabilities.
- *
- * Keys starting with RW are read + write, i.e. the application
- * can request for a certain requirement corresponding to that key.
- * Keys starting with RO are read only, i.e. the the application
- * can read the value of that key from the socket but cannot request
- * a corresponding requirement.
- *
- * TODO: Provide a documentation technique for concisely and precisely
- * define the syntax for each value string associated with a key.
- */
- public static final class Key {
- /** No constructor */
- private Key() {}
-
- /**
- * An integer representing the network type.
- * @see ConnectivityManager
- */
- public final static int RO_NETWORK_TYPE = 1;
-
- /**
- * Desired minimum forward link (download) bandwidth for the
- * in kilobits per second (kbps). Values should be strings such
- * "50", "100", "1500", etc.
- */
- public final static int RW_DESIRED_FWD_BW = 2;
-
- /**
- * Required minimum forward link (download) bandwidth, in
- * per second (kbps), below which the socket cannot function.
- * Values should be strings such as "50", "100", "1500", etc.
- */
- public final static int RW_REQUIRED_FWD_BW = 3;
-
- /**
- * Available forward link (download) bandwidth for the socket.
- * This value is in kilobits per second (kbps).
- * Values will be strings such as "50", "100", "1500", etc.
- */
- public final static int RO_AVAILABLE_FWD_BW = 4;
-
- /**
- * Desired minimum reverse link (upload) bandwidth for the socket
- * in kilobits per second (kbps).
- * Values should be strings such as "50", "100", "1500", etc.
- * <p>
- * This key is set via the needs map.
- */
- public final static int RW_DESIRED_REV_BW = 5;
-
- /**
- * Required minimum reverse link (upload) bandwidth, in kilobits
- * per second (kbps), below which the socket cannot function.
- * If a rate is not specified, the default rate of kbps will be
- * Values should be strings such as "50", "100", "1500", etc.
- */
- public final static int RW_REQUIRED_REV_BW = 6;
-
- /**
- * Available reverse link (upload) bandwidth for the socket.
- * This value is in kilobits per second (kbps).
- * Values will be strings such as "50", "100", "1500", etc.
- */
- public final static int RO_AVAILABLE_REV_BW = 7;
-
- /**
- * Maximum latency for the socket, in milliseconds, above which
- * socket cannot function.
- * Values should be strings such as "50", "300", "500", etc.
- */
- public final static int RW_MAX_ALLOWED_LATENCY = 8;
-
- /**
- * Interface that the socket is bound to. This can be a virtual
- * interface (e.g. VPN or Mobile IP) or a physical interface
- * (e.g. wlan0 or rmnet0).
- * Values will be strings such as "wlan0", "rmnet0"
- */
- public final static int RO_BOUND_INTERFACE = 9;
-
- /**
- * Physical interface that the socket is routed on.
- * This can be different from BOUND_INTERFACE in cases such as
- * VPN or Mobile IP. The physical interface may change over time
- * if seamless mobility is supported.
- * Values will be strings such as "wlan0", "rmnet0"
- */
- public final static int RO_PHYSICAL_INTERFACE = 10;
- }
-
- /**
- * Role informs the LinkSocket about the data usage patterns of your
- * application.
- * <P>
- * {@code Role.DEFAULT} is the default role, and is used whenever
- * a role isn't set.
- */
- public static final class Role {
- /** No constructor */
- private Role() {}
-
- // examples only, discuss which roles should be defined, and then
- // code these to match
-
- /** Default Role */
- public static final String DEFAULT = "default";
- /** Bulk down load */
- public static final String BULK_DOWNLOAD = "bulk.download";
- /** Bulk upload */
- public static final String BULK_UPLOAD = "bulk.upload";
-
- /** VoIP Application at 24kbps */
- public static final String VOIP_24KBPS = "voip.24k";
- /** VoIP Application at 32kbps */
- public static final String VOIP_32KBPS = "voip.32k";
-
- /** Video Streaming at 480p */
- public static final String VIDEO_STREAMING_480P = "video.streaming.480p";
- /** Video Streaming at 720p */
- public static final String VIDEO_STREAMING_720I = "video.streaming.720i";
-
- /** Video Chat Application at 360p */
- public static final String VIDEO_CHAT_360P = "video.chat.360p";
- /** Video Chat Application at 480p */
- public static final String VIDEO_CHAT_480P = "video.chat.480i";
- }
-
- /**
- * Constructor
- */
- public LinkCapabilities() {
- mCapabilities = new HashMap<Integer, String>();
- }
-
- /**
- * Copy constructor.
- *
- * @param source
- */
- public LinkCapabilities(LinkCapabilities source) {
- if (source != null) {
- mCapabilities = new HashMap<Integer, String>(source.mCapabilities);
- } else {
- mCapabilities = new HashMap<Integer, String>();
- }
- }
-
- /**
- * Create the {@code LinkCapabilities} with values depending on role type.
- * @param applicationRole a {@code LinkSocket.Role}
- * @return the {@code LinkCapabilities} associated with the applicationRole, empty if none
- */
- public static LinkCapabilities createNeedsMap(String applicationRole) {
- if (DBG) log("createNeededCapabilities(applicationRole) EX");
- return new LinkCapabilities();
- }
-
- /**
- * Remove all capabilities
- */
- public void clear() {
- mCapabilities.clear();
- }
-
- /**
- * Returns whether this map is empty.
- */
- public boolean isEmpty() {
- return mCapabilities.isEmpty();
- }
-
- /**
- * Returns the number of elements in this map.
- *
- * @return the number of elements in this map.
- */
- public int size() {
- return mCapabilities.size();
- }
-
- /**
- * Given the key return the capability string
- *
- * @param key
- * @return the capability string
- */
- public String get(int key) {
- return mCapabilities.get(key);
- }
-
- /**
- * Store the key/value capability pair
- *
- * @param key
- * @param value
- */
- public void put(int key, String value) {
- mCapabilities.put(key, value);
- }
-
- /**
- * Returns whether this map contains the specified key.
- *
- * @param key to search for.
- * @return {@code true} if this map contains the specified key,
- * {@code false} otherwise.
- */
- public boolean containsKey(int key) {
- return mCapabilities.containsKey(key);
- }
-
- /**
- * Returns whether this map contains the specified value.
- *
- * @param value to search for.
- * @return {@code true} if this map contains the specified value,
- * {@code false} otherwise.
- */
- public boolean containsValue(String value) {
- return mCapabilities.containsValue(value);
- }
-
- /**
- * Returns a set containing all of the mappings in this map. Each mapping is
- * an instance of {@link Map.Entry}. As the set is backed by this map,
- * changes in one will be reflected in the other.
- *
- * @return a set of the mappings.
- */
- public Set<Entry<Integer, String>> entrySet() {
- return mCapabilities.entrySet();
- }
-
- /**
- * @return the set of the keys.
- */
- public Set<Integer> keySet() {
- return mCapabilities.keySet();
- }
-
- /**
- * @return the set of values
- */
- public Collection<String> values() {
- return mCapabilities.values();
- }
-
- /**
- * Implement the Parcelable interface
- * @hide
- */
- public int describeContents() {
- return 0;
- }
-
- /**
- * Convert to string for debugging
- */
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("{");
- boolean firstTime = true;
- for (Entry<Integer, String> entry : mCapabilities.entrySet()) {
- if (firstTime) {
- firstTime = false;
- } else {
- sb.append(",");
- }
- sb.append(entry.getKey());
- sb.append(":\"");
- sb.append(entry.getValue());
- sb.append("\"");
- }
- sb.append("}");
- return sb.toString();
- }
-
- /**
- * Implement the Parcelable interface.
- * @hide
- */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mCapabilities.size());
- for (Entry<Integer, String> entry : mCapabilities.entrySet()) {
- dest.writeInt(entry.getKey().intValue());
- dest.writeString(entry.getValue());
- }
- }
-
- /**
- * Implement the Parcelable interface.
- * @hide
- */
- public static final Creator<LinkCapabilities> CREATOR =
- new Creator<LinkCapabilities>() {
- public LinkCapabilities createFromParcel(Parcel in) {
- LinkCapabilities capabilities = new LinkCapabilities();
- int size = in.readInt();
- while (size-- != 0) {
- int key = in.readInt();
- String value = in.readString();
- capabilities.mCapabilities.put(key, value);
- }
- return capabilities;
- }
-
- public LinkCapabilities[] newArray(int size) {
- return new LinkCapabilities[size];
- }
- };
-
- /**
- * Debug logging
- */
- protected static void log(String s) {
- Log.d(TAG, s);
- }
-}
diff --git a/core/java/android/net/LinkSocket.java b/core/java/android/net/LinkSocket.java
deleted file mode 100644
index 5aa6451..0000000
--- a/core/java/android/net/LinkSocket.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.net.LinkCapabilities;
-import android.net.LinkProperties;
-import android.net.LinkSocketNotifier;
-
-import android.util.Log;
-
-import java.io.IOException;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-import java.util.HashSet;
-import java.util.Set;
-
-/** @hide */
-public class LinkSocket extends Socket {
- private final static String TAG = "LinkSocket";
- private final static boolean DBG = true;
-
- /**
- * Default constructor
- */
- public LinkSocket() {
- if (DBG) log("LinkSocket() EX");
- }
-
- /**
- * Creates a new unconnected socket.
- * @param notifier a reference to a class that implements {@code LinkSocketNotifier}
- */
- public LinkSocket(LinkSocketNotifier notifier) {
- if (DBG) log("LinkSocket(notifier) EX");
- }
-
- /**
- * Creates a new unconnected socket usign the given proxy type.
- * @param notifier a reference to a class that implements {@code LinkSocketNotifier}
- * @param proxy the specified proxy for this socket
- * @throws IllegalArgumentException if the argument proxy is null or of an invalid type.
- * @throws SecurityException if a security manager exists and it denies the permission
- * to connect to the given proxy.
- */
- public LinkSocket(LinkSocketNotifier notifier, Proxy proxy) {
- if (DBG) log("LinkSocket(notifier, proxy) EX");
- }
-
- /**
- * @return the {@code LinkProperties} for the socket
- */
- public LinkProperties getLinkProperties() {
- if (DBG) log("LinkProperties() EX");
- return new LinkProperties();
- }
-
- /**
- * Set the {@code LinkCapabilies} needed for this socket. If the socket is already connected
- * or is a duplicate socket the request is ignored and {@code false} will
- * be returned. A needs map can be created via the {@code createNeedsMap} static
- * method.
- * @param needs the needs of the socket
- * @return {@code true} if needs are successfully set, {@code false} otherwise
- */
- public boolean setNeededCapabilities(LinkCapabilities needs) {
- if (DBG) log("setNeeds() EX");
- return false;
- }
-
- /**
- * @return the LinkCapabilites set by setNeededCapabilities, empty if none has been set
- */
- public LinkCapabilities getNeededCapabilities() {
- if (DBG) log("getNeeds() EX");
- return null;
- }
-
- /**
- * @return all of the {@code LinkCapabilities} of the link used by this socket
- */
- public LinkCapabilities getCapabilities() {
- if (DBG) log("getCapabilities() EX");
- return null;
- }
-
- /**
- * Returns this LinkSockets set of capabilities, filtered according to
- * the given {@code Set}. Capabilities in the Set but not available from
- * the link will not be reported in the results. Capabilities of the link
- * but not listed in the Set will also not be reported in the results.
- * @param capabilities {@code Set} of capabilities requested
- * @return the filtered {@code LinkCapabilities} of this LinkSocket, may be empty
- */
- public LinkCapabilities getCapabilities(Set<Integer> capabilities) {
- if (DBG) log("getCapabilities(capabilities) EX");
- return new LinkCapabilities();
- }
-
- /**
- * Provide the set of capabilities the application is interested in tracking
- * for this LinkSocket.
- * @param capabilities a {@code Set} of capabilities to track
- */
- public void setTrackedCapabilities(Set<Integer> capabilities) {
- if (DBG) log("setTrackedCapabilities(capabilities) EX");
- }
-
- /**
- * @return the {@code LinkCapabilities} that are tracked, empty if none has been set.
- */
- public Set<Integer> getTrackedCapabilities() {
- if (DBG) log("getTrackedCapabilities(capabilities) EX");
- return new HashSet<Integer>();
- }
-
- /**
- * Connects this socket to the given remote host address and port specified
- * by dstName and dstPort.
- * @param dstName the address of the remote host to connect to
- * @param dstPort the port to connect to on the remote host
- * @param timeout the timeout value in milliseconds or 0 for infinite timeout
- * @throws UnknownHostException if the given dstName is invalid
- * @throws IOException if the socket is already connected or an error occurs
- * while connecting
- * @throws SocketTimeoutException if the timeout fires
- */
- public void connect(String dstName, int dstPort, int timeout)
- throws UnknownHostException, IOException, SocketTimeoutException {
- if (DBG) log("connect(dstName, dstPort, timeout) EX");
- }
-
- /**
- * Connects this socket to the given remote host address and port specified
- * by dstName and dstPort.
- * @param dstName the address of the remote host to connect to
- * @param dstPort the port to connect to on the remote host
- * @throws UnknownHostException if the given dstName is invalid
- * @throws IOException if the socket is already connected or an error occurs
- * while connecting
- */
- public void connect(String dstName, int dstPort)
- throws UnknownHostException, IOException {
- if (DBG) log("connect(dstName, dstPort, timeout) EX");
- }
-
- /**
- * Connects this socket to the given remote host address and port specified
- * by the SocketAddress with the specified timeout.
- * @deprecated Use {@code connect(String dstName, int dstPort, int timeout)}
- * instead. Using this method may result in reduced functionality.
- * @param remoteAddr the address and port of the remote host to connect to
- * @throws IllegalArgumentException if the given SocketAddress is invalid
- * @throws IOException if the socket is already connected or an error occurs
- * while connecting
- * @throws SocketTimeoutException if the timeout expires
- */
- @Override
- @Deprecated
- public void connect(SocketAddress remoteAddr, int timeout)
- throws IOException, SocketTimeoutException {
- if (DBG) log("connect(remoteAddr, timeout) EX DEPRECATED");
- }
-
- /**
- * Connects this socket to the given remote host address and port specified
- * by the SocketAddress.
- * TODO add comment on all these that the network selection happens during connect
- * and may take 30 seconds
- * @deprecated Use {@code connect(String dstName, int dstPort)}
- * Using this method may result in reduced functionality.
- * @param remoteAddr the address and port of the remote host to connect to.
- * @throws IllegalArgumentException if the SocketAddress is invalid or not supported.
- * @throws IOException if the socket is already connected or an error occurs
- * while connecting
- */
- @Override
- @Deprecated
- public void connect(SocketAddress remoteAddr) throws IOException {
- if (DBG) log("connect(remoteAddr) EX DEPRECATED");
- }
-
- /**
- * Connect a duplicate socket socket to the same remote host address and port
- * as the original with a timeout parameter.
- * @param timeout the timeout value in milliseconds or 0 for infinite timeout
- * @throws IOException if the socket is already connected or an error occurs
- * while connecting
- */
- public void connect(int timeout) throws IOException {
- if (DBG) log("connect(timeout) EX");
- }
-
- /**
- * Connect a duplicate socket socket to the same remote host address and port
- * as the original.
- * @throws IOException if the socket is already connected or an error occurs
- * while connecting
- */
- public void connect() throws IOException {
- if (DBG) log("connect() EX");
- }
-
- /**
- * Closes the socket. It is not possible to reconnect or rebind to this
- * socket thereafter which means a new socket instance has to be created.
- * @throws IOException if an error occurs while closing the socket
- */
- @Override
- public synchronized void close() throws IOException {
- if (DBG) log("close() EX");
- }
-
- /**
- * Request that a new LinkSocket be created using a different radio
- * (such as WiFi or 3G) than the current LinkSocket. If a different
- * radio is available a call back will be made via {@code onBetterLinkAvail}.
- * If unable to find a better radio, application will be notified via
- * {@code onNewLinkUnavailable}
- * @see LinkSocketNotifier#onBetterLinkAvailable(LinkSocket, LinkSocket)
- * @param linkRequestReason reason for requesting a new link.
- */
- public void requestNewLink(LinkRequestReason linkRequestReason) {
- if (DBG) log("requestNewLink(linkRequestReason) EX");
- }
-
- /**
- * @deprecated LinkSocket will automatically pick the optimum interface
- * to bind to
- * @param localAddr the specific address and port on the local machine
- * to bind to
- * @throws IOException always as this method is deprecated for LinkSocket
- */
- @Override
- @Deprecated
- public void bind(SocketAddress localAddr) throws UnsupportedOperationException {
- if (DBG) log("bind(localAddr) EX throws IOException");
- throw new UnsupportedOperationException("bind is deprecated for LinkSocket");
- }
-
- /**
- * Reason codes an application can specify when requesting for a new link.
- * TODO: need better documentation
- */
- public static final class LinkRequestReason {
- /** No constructor */
- private LinkRequestReason() {}
-
- /** This link is working properly */
- public static final int LINK_PROBLEM_NONE = 0;
- /** This link has an unknown issue */
- public static final int LINK_PROBLEM_UNKNOWN = 1;
- }
-
- /**
- * Debug logging
- */
- protected static void log(String s) {
- Log.d(TAG, s);
- }
-}
diff --git a/core/java/android/net/LinkSocketNotifier.java b/core/java/android/net/LinkSocketNotifier.java
deleted file mode 100644
index e2429d8..0000000
--- a/core/java/android/net/LinkSocketNotifier.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-/**
- * Interface used to get feedback about a {@link android.net.LinkSocket}. Instance is optionally
- * passed when a LinkSocket is constructed. Multiple LinkSockets may use the same notifier.
- * @hide
- */
-public interface LinkSocketNotifier {
- /**
- * This callback function will be called if a better link
- * becomes available.
- * TODO - this shouldn't be checked for all cases - what's the conditional
- * flag?
- * If the duplicate socket is accepted, the original will be marked invalid
- * and additional use will throw exceptions.
- * @param original the original LinkSocket
- * @param duplicate the new LinkSocket that better meets the application
- * requirements
- * @return {@code true} if the application intends to use this link
- *
- * REM
- * TODO - how agressive should we be?
- * At a minimum CS tracks which LS have this turned on and tracks the requirements
- * When a new link becomes available, automatically check if any of the LinkSockets
- * will care.
- * If found, grab a refcount on the link so it doesn't go away and send notification
- * Optionally, periodically setup connection on available networks to check for better links
- * Maybe pass this info into the LinkFactories so condition changes can be acted on more quickly
- */
- public boolean onBetterLinkAvailable(LinkSocket original, LinkSocket duplicate);
-
- /**
- * This callback function will be called when a LinkSocket no longer has
- * an active link.
- * @param socket the LinkSocket that lost its link
- *
- * REM
- * NetworkStateTracker tells us it is disconnected
- * CS checks the table for LS on that link
- * CS calls each callback (need to work out p2p cross process callback)
- */
- public void onLinkLost(LinkSocket socket);
-
- /**
- * This callback function will be called when an application calls
- * requestNewLink on a LinkSocket but the LinkSocket is unable to find
- * a suitable new link.
- * @param socket the LinkSocket for which a new link was not found
- * TODO - why the diff between initial request (sync) and requestNewLink?
- *
- * REM
- * CS process of trying to find a new link must track the LS that started it
- * on failure, call callback
- */
- public void onNewLinkUnavailable(LinkSocket socket);
-
- /**
- * This callback function will be called when any of the notification-marked
- * capabilities of the LinkSocket (e.g. upstream bandwidth) have changed.
- * @param socket the linkSocet for which capabilities have changed
- * @param changedCapabilities the set of capabilities that the application
- * is interested in and have changed (with new values)
- *
- * REM
- * Maybe pass the interesting capabilities into the Links.
- * Get notified of every capability change
- * check for LinkSockets on that Link that are interested in that Capability - call them
- */
- public void onCapabilitiesChanged(LinkSocket socket, LinkCapabilities changedCapabilities);
-}
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 30b61c5..535bbe2 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -66,7 +66,6 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
private Handler mTarget;
private Context mContext;
private LinkProperties mLinkProperties;
- private LinkCapabilities mLinkCapabilities;
private boolean mPrivateDnsRouteSet = false;
private boolean mDefaultRouteSet = false;
@@ -200,11 +199,11 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
}
mLinkProperties.setMtu(mContext.getResources().getInteger(
com.android.internal.R.integer.config_mobile_mtu));
- mLinkCapabilities = intent.getParcelableExtra(
- PhoneConstants.DATA_LINK_CAPABILITIES_KEY);
- if (mLinkCapabilities == null) {
- loge("CONNECTED event did not supply link capabilities.");
- mLinkCapabilities = new LinkCapabilities();
+ mNetworkCapabilities = intent.getParcelableExtra(
+ PhoneConstants.DATA_NETWORK_CAPABILITIES_KEY);
+ if (mNetworkCapabilities == null) {
+ loge("CONNECTED event did not supply network capabilities.");
+ mNetworkCapabilities = new NetworkCapabilities();
}
}
@@ -316,10 +315,10 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
Slog.d(TAG, "LinkProperties = " );
}
- if (mLinkCapabilities != null) {
- Slog.d(TAG, "LinkCapabilities = " + mLinkCapabilities);
+ if (mNetworkCapabilities != null) {
+ Slog.d(TAG, mNetworkCapabilities.toString());
} else {
- Slog.d(TAG, "LinkCapabilities = " );
+ Slog.d(TAG, "NetworkCapabilities = " );
}
}
@@ -750,14 +749,6 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
return new LinkProperties(mLinkProperties);
}
- /**
- * @see android.net.NetworkStateTracker#getLinkCapabilities()
- */
- @Override
- public LinkCapabilities getLinkCapabilities() {
- return new LinkCapabilities(mLinkCapabilities);
- }
-
public void supplyMessenger(Messenger messenger) {
if (VDBG) log(mApnType + " got supplyMessenger");
AsyncChannel ac = new AsyncChannel();
diff --git a/core/java/android/net/LinkCapabilities.aidl b/core/java/android/net/NetworkCapabilities.aidl
index df72599..cd7d71c 100644
--- a/core/java/android/net/LinkCapabilities.aidl
+++ b/core/java/android/net/NetworkCapabilities.aidl
@@ -1,6 +1,6 @@
/*
**
-** Copyright (C) 2010 The Android Open Source Project
+** Copyright (C) 2014 The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -17,5 +17,5 @@
package android.net;
-parcelable LinkCapabilities;
+parcelable NetworkCapabilities;
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
new file mode 100644
index 0000000..b783046
--- /dev/null
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.lang.IllegalArgumentException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * A class representing the capabilities of a network
+ * @hide
+ */
+public final class NetworkCapabilities implements Parcelable {
+ private static final String TAG = "NetworkCapabilities";
+ private static final boolean DBG = false;
+
+
+ /**
+ * Represents the network's capabilities. If any are specified they will be satisfied
+ * by any Network that matches all of them.
+ */
+ private long mNetworkCapabilities = (1 << NET_CAPABILITY_NOT_RESTRICTED);
+
+ /**
+ * Values for NetworkCapabilities. Roughly matches/extends deprecated
+ * ConnectivityManager TYPE_*
+ */
+ public static final int NET_CAPABILITY_MMS = 0;
+ public static final int NET_CAPABILITY_SUPL = 1;
+ public static final int NET_CAPABILITY_DUN = 2;
+ public static final int NET_CAPABILITY_FOTA = 3;
+ public static final int NET_CAPABILITY_IMS = 4;
+ public static final int NET_CAPABILITY_CBS = 5;
+ public static final int NET_CAPABILITY_WIFI_P2P = 6;
+ public static final int NET_CAPABILITY_IA = 7;
+ public static final int NET_CAPABILITY_RCS = 8;
+ public static final int NET_CAPABILITY_XCAP = 9;
+ public static final int NET_CAPABILITY_EIMS = 10;
+ public static final int NET_CAPABILITY_NOT_METERED = 11;
+ public static final int NET_CAPABILITY_INTERNET = 12;
+ /** Set by default */
+ public static final int NET_CAPABILITY_NOT_RESTRICTED = 13;
+
+ private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
+ private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_RESTRICTED;
+
+ public void addNetworkCapability(int networkCapability) {
+ if (networkCapability < MIN_NET_CAPABILITY ||
+ networkCapability > MAX_NET_CAPABILITY) {
+ throw new IllegalArgumentException("NetworkCapability out of range");
+ }
+ mNetworkCapabilities |= 1 << networkCapability;
+ }
+ public void removeNetworkCapability(int networkCapability) {
+ if (networkCapability < MIN_NET_CAPABILITY ||
+ networkCapability > MAX_NET_CAPABILITY) {
+ throw new IllegalArgumentException("NetworkCapability out of range");
+ }
+ mNetworkCapabilities &= ~(1 << networkCapability);
+ }
+ public Collection<Integer> getNetworkCapabilities() {
+ return enumerateBits(mNetworkCapabilities);
+ }
+ public boolean hasCapability(int networkCapability) {
+ if (networkCapability < MIN_NET_CAPABILITY ||
+ networkCapability > MAX_NET_CAPABILITY) {
+ return false;
+ }
+ return ((mNetworkCapabilities & (1 << networkCapability)) != 0);
+ }
+
+ private Collection<Integer> enumerateBits(long val) {
+ ArrayList<Integer> result = new ArrayList<Integer>();
+ int resource = 0;
+ while (val > 0) {
+ if ((val & 1) == 1) result.add(resource);
+ val = val >> 1;
+ resource++;
+ }
+ return result;
+ }
+
+ private void combineNetCapabilities(NetworkCapabilities nc) {
+ this.mNetworkCapabilities |= nc.mNetworkCapabilities;
+ }
+
+ private boolean satisfiedByNetCapabilities(NetworkCapabilities nc) {
+ return ((nc.mNetworkCapabilities & this.mNetworkCapabilities) == this.mNetworkCapabilities);
+ }
+
+ private boolean equalsNetCapabilities(NetworkCapabilities nc) {
+ return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
+ }
+
+ /**
+ * Representing the transport type. Apps should generally not care about transport. A
+ * request for a fast internet connection could be satisfied by a number of different
+ * transports. If any are specified here it will be satisfied a Network that matches
+ * any of them. If a caller doesn't care about the transport it should not specify any.
+ */
+ private long mTransportTypes;
+
+ /**
+ * Values for TransportType
+ */
+ public static final int TRANSPORT_CELLULAR = 0;
+ public static final int TRANSPORT_WIFI = 1;
+ public static final int TRANSPORT_BLUETOOTH = 2;
+ public static final int TRANSPORT_ETHERNET = 3;
+
+ private static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
+ private static final int MAX_TRANSPORT = TRANSPORT_ETHERNET;
+
+ public void addTransportType(int transportType) {
+ if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
+ throw new IllegalArgumentException("TransportType out of range");
+ }
+ mTransportTypes |= 1 << transportType;
+ }
+ public void removeTransportType(int transportType) {
+ if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
+ throw new IllegalArgumentException("TransportType out of range");
+ }
+ mTransportTypes &= ~(1 << transportType);
+ }
+ public Collection<Integer> getTransportTypes() {
+ return enumerateBits(mTransportTypes);
+ }
+ public boolean hasTransport(int transportType) {
+ if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
+ return false;
+ }
+ return ((mTransportTypes & (1 << transportType)) != 0);
+ }
+
+ private void combineTransportTypes(NetworkCapabilities nc) {
+ this.mTransportTypes |= nc.mTransportTypes;
+ }
+ private boolean satisfiedByTransportTypes(NetworkCapabilities nc) {
+ return ((this.mTransportTypes == 0) ||
+ ((this.mTransportTypes & nc.mTransportTypes) != 0));
+ }
+ private boolean equalsTransportTypes(NetworkCapabilities nc) {
+ return (nc.mTransportTypes == this.mTransportTypes);
+ }
+
+ /**
+ * Passive link bandwidth. This is a rough guide of the expected peak bandwidth
+ * for the first hop on the given transport. It is not measured, but may take into account
+ * link parameters (Radio technology, allocated channels, etc).
+ */
+ private int mLinkUpBandwidthKbps;
+ private int mLinkDownBandwidthKbps;
+
+ public void setLinkUpstreamBandwidthKbps(int upKbps) {
+ mLinkUpBandwidthKbps = upKbps;
+ }
+ public int getLinkUpstreamBandwidthKbps() {
+ return mLinkUpBandwidthKbps;
+ }
+ public void setLinkDownstreamBandwidthKbps(int downKbps) {
+ mLinkDownBandwidthKbps = downKbps;
+ }
+ public int getLinkDownstreamBandwidthKbps() {
+ return mLinkDownBandwidthKbps;
+ }
+
+ private void combineLinkBandwidths(NetworkCapabilities nc) {
+ this.mLinkUpBandwidthKbps =
+ Math.max(this.mLinkUpBandwidthKbps, nc.mLinkUpBandwidthKbps);
+ this.mLinkDownBandwidthKbps =
+ Math.max(this.mLinkDownBandwidthKbps, nc.mLinkDownBandwidthKbps);
+ }
+ private boolean satisfiedByLinkBandwidths(NetworkCapabilities nc) {
+ return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps ||
+ this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps);
+ }
+ private boolean equalsLinkBandwidths(NetworkCapabilities nc) {
+ return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps &&
+ this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
+ }
+
+ /**
+ * Combine a set of Capabilities to this one. Useful for coming up with the complete set
+ * {@hide}
+ */
+ public void combineCapabilities(NetworkCapabilities nc) {
+ combineNetCapabilities(nc);
+ combineTransportTypes(nc);
+ combineLinkBandwidths(nc);
+ }
+
+ /**
+ * Check if our requirements are satisfied by the given Capabilities.
+ * {@hide}
+ */
+ public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) {
+ return (nc != null &&
+ satisfiedByNetCapabilities(nc) &&
+ satisfiedByTransportTypes(nc) &&
+ satisfiedByLinkBandwidths(nc));
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || (obj instanceof NetworkCapabilities == false)) return false;
+ NetworkCapabilities that = (NetworkCapabilities)obj;
+ return (equalsNetCapabilities(that) &&
+ equalsTransportTypes(that) &&
+ equalsLinkBandwidths(that));
+ }
+
+ @Override
+ public int hashCode() {
+ return ((int)(mNetworkCapabilities & 0xFFFFFFFF) +
+ ((int)(mNetworkCapabilities >> 32) * 3) +
+ ((int)(mTransportTypes & 0xFFFFFFFF) * 5) +
+ ((int)(mTransportTypes >> 32) * 7) +
+ (mLinkUpBandwidthKbps * 11) +
+ (mLinkDownBandwidthKbps * 13));
+ }
+
+ public NetworkCapabilities() {
+ }
+
+ public NetworkCapabilities(NetworkCapabilities nc) {
+ if (nc != null) {
+ mNetworkCapabilities = nc.mNetworkCapabilities;
+ mTransportTypes = nc.mTransportTypes;
+ mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
+ mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
+ }
+ }
+
+ // Parcelable
+ public int describeContents() {
+ return 0;
+ }
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mNetworkCapabilities);
+ dest.writeLong(mTransportTypes);
+ dest.writeInt(mLinkUpBandwidthKbps);
+ dest.writeInt(mLinkDownBandwidthKbps);
+ }
+ public static final Creator<NetworkCapabilities> CREATOR =
+ new Creator<NetworkCapabilities>() {
+ public NetworkCapabilities createFromParcel(Parcel in) {
+ NetworkCapabilities netCap = new NetworkCapabilities();
+
+ netCap.mNetworkCapabilities = in.readLong();
+ netCap.mTransportTypes = in.readLong();
+ netCap.mLinkUpBandwidthKbps = in.readInt();
+ netCap.mLinkDownBandwidthKbps = in.readInt();
+ return netCap;
+ }
+ public NetworkCapabilities[] newArray(int size) {
+ return new NetworkCapabilities[size];
+ }
+ };
+
+ public String toString() {
+ Collection<Integer> types = getTransportTypes();
+ String transports = (types.size() > 0 ? " Transports: " : "");
+ Iterator<Integer> i = types.iterator();
+ while (i.hasNext()) {
+ switch (i.next()) {
+ case TRANSPORT_CELLULAR: transports += "CELLULAR"; break;
+ case TRANSPORT_WIFI: transports += "WIFI"; break;
+ case TRANSPORT_BLUETOOTH: transports += "BLUETOOTH"; break;
+ case TRANSPORT_ETHERNET: transports += "ETHERNET"; break;
+ }
+ if (i.hasNext()) transports += "|";
+ }
+
+ types = getNetworkCapabilities();
+ String capabilities = (types.size() > 0 ? " Capabilities: " : "");
+ i = types.iterator();
+ while (i.hasNext()) {
+ switch (i.next().intValue()) {
+ case NET_CAPABILITY_MMS: capabilities += "MMS"; break;
+ case NET_CAPABILITY_SUPL: capabilities += "SUPL"; break;
+ case NET_CAPABILITY_DUN: capabilities += "DUN"; break;
+ case NET_CAPABILITY_FOTA: capabilities += "FOTA"; break;
+ case NET_CAPABILITY_IMS: capabilities += "IMS"; break;
+ case NET_CAPABILITY_CBS: capabilities += "CBS"; break;
+ case NET_CAPABILITY_WIFI_P2P: capabilities += "WIFI_P2P"; break;
+ case NET_CAPABILITY_IA: capabilities += "IA"; break;
+ case NET_CAPABILITY_RCS: capabilities += "RCS"; break;
+ case NET_CAPABILITY_XCAP: capabilities += "XCAP"; break;
+ case NET_CAPABILITY_EIMS: capabilities += "EIMS"; break;
+ case NET_CAPABILITY_NOT_METERED: capabilities += "NOT_METERED"; break;
+ case NET_CAPABILITY_INTERNET: capabilities += "INTERNET"; break;
+ case NET_CAPABILITY_NOT_RESTRICTED: capabilities += "NOT_RESTRICTED"; break;
+ }
+ if (i.hasNext()) capabilities += "&";
+ }
+
+ String upBand = ((mLinkUpBandwidthKbps > 0) ? " LinkUpBandwidth>=" +
+ mLinkUpBandwidthKbps + "Kbps" : "");
+ String dnBand = ((mLinkDownBandwidthKbps > 0) ? " LinkDnBandwidth>=" +
+ mLinkDownBandwidthKbps + "Kbps" : "");
+
+ return "NetworkCapabilities: [" + transports + capabilities + upBand + dnBand + "]";
+ }
+}
diff --git a/core/java/android/net/NetworkRequest.aidl b/core/java/android/net/NetworkRequest.aidl
new file mode 100644
index 0000000..508defc
--- /dev/null
+++ b/core/java/android/net/NetworkRequest.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+parcelable NetworkRequest;
+
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
new file mode 100644
index 0000000..7e3a06d
--- /dev/null
+++ b/core/java/android/net/NetworkRequest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @hide
+ */
+public class NetworkRequest implements Parcelable {
+ public final NetworkCapabilities networkCapabilities;
+ public final int requestId;
+ public final boolean legacy;
+ private static final AtomicInteger sRequestId = new AtomicInteger();
+
+ public NetworkRequest(NetworkCapabilities nc) {
+ this(nc, false, sRequestId.incrementAndGet());
+ }
+
+ public NetworkRequest(NetworkCapabilities nc, boolean legacy) {
+ this(nc, legacy, sRequestId.incrementAndGet());
+ }
+
+ private NetworkRequest(NetworkCapabilities nc, boolean legacy, int rId) {
+ requestId = rId;
+ networkCapabilities = nc;
+ this.legacy = legacy;
+ }
+
+ // implement the Parcelable interface
+ public int describeContents() {
+ return 0;
+ }
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(networkCapabilities, flags);
+ dest.writeInt(legacy ? 1 : 0);
+ dest.writeInt(requestId);
+ }
+ public static final Creator<NetworkRequest> CREATOR =
+ new Creator<NetworkRequest>() {
+ public NetworkRequest createFromParcel(Parcel in) {
+ NetworkCapabilities nc = (NetworkCapabilities)in.readParcelable(null);
+ boolean legacy = (in.readInt() == 1);
+ int requestId = in.readInt();
+ return new NetworkRequest(nc, legacy, requestId);
+ }
+ public NetworkRequest[] newArray(int size) {
+ return new NetworkRequest[size];
+ }
+ };
+
+ public String toString() {
+ return "NetworkRequest [ id=" + requestId + ", legacy=" + legacy + ", " +
+ networkCapabilities.toString() + " ]";
+ }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof NetworkRequest == false) return false;
+ NetworkRequest that = (NetworkRequest)obj;
+ return (that.legacy == this.legacy &&
+ that.requestId == this.requestId &&
+ ((that.networkCapabilities == null && this.networkCapabilities == null) ||
+ (that.networkCapabilities != null &&
+ that.networkCapabilities.equals(this.networkCapabilities))));
+ }
+
+ public int hashCode() {
+ return requestId + (legacy ? 1013 : 2026) + (networkCapabilities.hashCode() * 1051);
+ }
+}
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index fbe1f82..2e0e9e4 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -28,21 +28,21 @@ public class NetworkState implements Parcelable {
public final NetworkInfo networkInfo;
public final LinkProperties linkProperties;
- public final LinkCapabilities linkCapabilities;
+ public final NetworkCapabilities networkCapabilities;
/** Currently only used by testing. */
public final String subscriberId;
public final String networkId;
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
- LinkCapabilities linkCapabilities) {
- this(networkInfo, linkProperties, linkCapabilities, null, null);
+ NetworkCapabilities networkCapabilities) {
+ this(networkInfo, linkProperties, networkCapabilities, null, null);
}
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
- LinkCapabilities linkCapabilities, String subscriberId, String networkId) {
+ NetworkCapabilities networkCapabilities, String subscriberId, String networkId) {
this.networkInfo = networkInfo;
this.linkProperties = linkProperties;
- this.linkCapabilities = linkCapabilities;
+ this.networkCapabilities = networkCapabilities;
this.subscriberId = subscriberId;
this.networkId = networkId;
}
@@ -50,7 +50,7 @@ public class NetworkState implements Parcelable {
public NetworkState(Parcel in) {
networkInfo = in.readParcelable(null);
linkProperties = in.readParcelable(null);
- linkCapabilities = in.readParcelable(null);
+ networkCapabilities = in.readParcelable(null);
subscriberId = in.readString();
networkId = in.readString();
}
@@ -64,7 +64,7 @@ public class NetworkState implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeParcelable(networkInfo, flags);
out.writeParcelable(linkProperties, flags);
- out.writeParcelable(linkCapabilities, flags);
+ out.writeParcelable(networkCapabilities, flags);
out.writeString(subscriberId);
out.writeString(networkId);
}
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 29b57a5..35500cc 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -111,12 +111,9 @@ public interface NetworkStateTracker {
public LinkProperties getLinkProperties();
/**
- * A capability is an Integer/String pair, the capabilities
- * are defined in the class LinkSocket#Key.
- *
* @return a copy of this connections capabilities, may be empty but never null.
*/
- public LinkCapabilities getLinkCapabilities();
+ public NetworkCapabilities getNetworkCapabilities();
/**
* Get interesting information about this network link
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index daf0065..6a78c29 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -273,21 +273,19 @@ public final class Proxy {
String host = null;
String port = null;
String exclList = null;
- String pacFileUrl = null;
+ Uri pacFileUrl = Uri.EMPTY;
if (p != null) {
host = p.getHost();
port = Integer.toString(p.getPort());
exclList = p.getExclusionListAsString();
- if (p.getPacFileUrl() != null) {
- pacFileUrl = p.getPacFileUrl().toString();
- }
+ pacFileUrl = p.getPacFileUrl();
}
setHttpProxySystemProperty(host, port, exclList, pacFileUrl);
}
/** @hide */
public static final void setHttpProxySystemProperty(String host, String port, String exclList,
- String pacFileUrl) {
+ Uri pacFileUrl) {
if (exclList != null) exclList = exclList.replace(",", "|");
if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList);
if (host != null) {
@@ -311,7 +309,7 @@ public final class Proxy {
System.clearProperty("http.nonProxyHosts");
System.clearProperty("https.nonProxyHosts");
}
- if (!TextUtils.isEmpty(pacFileUrl)) {
+ if (!Uri.EMPTY.equals(pacFileUrl)) {
ProxySelector.setDefault(new PacProxySelector());
} else {
ProxySelector.setDefault(sDefaultProxySelector);
diff --git a/core/java/android/net/ProxyDataTracker.java b/core/java/android/net/ProxyDataTracker.java
index 461e8b8..4973b3d 100644
--- a/core/java/android/net/ProxyDataTracker.java
+++ b/core/java/android/net/ProxyDataTracker.java
@@ -104,7 +104,7 @@ public class ProxyDataTracker extends BaseNetworkStateTracker {
public ProxyDataTracker() {
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_PROXY, 0, NETWORK_TYPE, "");
mLinkProperties = new LinkProperties();
- mLinkCapabilities = new LinkCapabilities();
+ mNetworkCapabilities = new NetworkCapabilities();
mNetworkInfo.setIsAvailable(true);
try {
mLinkProperties.addDns(InetAddress.getByName(DNS1));
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index b40941f..991d9da 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -44,7 +44,7 @@ public class ProxyInfo implements Parcelable {
private String mExclusionList;
private String[] mParsedExclusionList;
- private String mPacFileUrl;
+ private Uri mPacFileUrl;
/**
*@hide
*/
@@ -85,7 +85,7 @@ public class ProxyInfo implements Parcelable {
* at the specified URL.
*/
public static ProxyInfo buildPacProxy(Uri pacUri) {
- return new ProxyInfo(pacUri.toString());
+ return new ProxyInfo(pacUri);
}
/**
@@ -96,27 +96,45 @@ public class ProxyInfo implements Parcelable {
mHost = host;
mPort = port;
setExclusionList(exclList);
+ mPacFileUrl = Uri.EMPTY;
}
/**
* Create a ProxyProperties that points at a PAC URL.
* @hide
*/
- public ProxyInfo(String pacFileUrl) {
+ public ProxyInfo(Uri pacFileUrl) {
mHost = LOCAL_HOST;
mPort = LOCAL_PORT;
setExclusionList(LOCAL_EXCL_LIST);
+ if (pacFileUrl == null) {
+ throw new NullPointerException();
+ }
mPacFileUrl = pacFileUrl;
}
/**
+ * Create a ProxyProperties that points at a PAC URL.
+ * @hide
+ */
+ public ProxyInfo(String pacFileUrl) {
+ mHost = LOCAL_HOST;
+ mPort = LOCAL_PORT;
+ setExclusionList(LOCAL_EXCL_LIST);
+ mPacFileUrl = Uri.parse(pacFileUrl);
+ }
+
+ /**
* Only used in PacManager after Local Proxy is bound.
* @hide
*/
- public ProxyInfo(String pacFileUrl, int localProxyPort) {
+ public ProxyInfo(Uri pacFileUrl, int localProxyPort) {
mHost = LOCAL_HOST;
mPort = localProxyPort;
setExclusionList(LOCAL_EXCL_LIST);
+ if (pacFileUrl == null) {
+ throw new NullPointerException();
+ }
mPacFileUrl = pacFileUrl;
}
@@ -125,7 +143,7 @@ public class ProxyInfo implements Parcelable {
mPort = port;
mExclusionList = exclList;
mParsedExclusionList = parsedExclList;
- mPacFileUrl = null;
+ mPacFileUrl = Uri.EMPTY;
}
// copy constructor instead of clone
@@ -137,6 +155,9 @@ public class ProxyInfo implements Parcelable {
mHost = source.getHost();
mPort = source.getPort();
mPacFileUrl = source.mPacFileUrl;
+ if (mPacFileUrl == null) {
+ mPacFileUrl = Uri.EMPTY;
+ }
mExclusionList = source.getExclusionListAsString();
mParsedExclusionList = source.mParsedExclusionList;
}
@@ -158,10 +179,7 @@ public class ProxyInfo implements Parcelable {
* no PAC script.
*/
public Uri getPacFileUrl() {
- if (TextUtils.isEmpty(mPacFileUrl)) {
- return null;
- }
- return Uri.parse(mPacFileUrl);
+ return mPacFileUrl;
}
/**
@@ -210,7 +228,7 @@ public class ProxyInfo implements Parcelable {
* @hide
*/
public boolean isValid() {
- if (!TextUtils.isEmpty(mPacFileUrl)) return true;
+ if (!Uri.EMPTY.equals(mPacFileUrl)) return true;
return Proxy.PROXY_VALID == Proxy.validate(mHost == null ? "" : mHost,
mPort == 0 ? "" : Integer.toString(mPort),
mExclusionList == null ? "" : mExclusionList);
@@ -234,7 +252,7 @@ public class ProxyInfo implements Parcelable {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- if (mPacFileUrl != null) {
+ if (!Uri.EMPTY.equals(mPacFileUrl)) {
sb.append("PAC Script: ");
sb.append(mPacFileUrl);
} else if (mHost != null) {
@@ -257,13 +275,15 @@ public class ProxyInfo implements Parcelable {
ProxyInfo p = (ProxyInfo)o;
// If PAC URL is present in either then they must be equal.
// Other parameters will only be for fall back.
- if (!TextUtils.isEmpty(mPacFileUrl)) {
+ if (!Uri.EMPTY.equals(mPacFileUrl)) {
return mPacFileUrl.equals(p.getPacFileUrl()) && mPort == p.mPort;
}
- if (!TextUtils.isEmpty(p.mPacFileUrl)) {
+ if (!Uri.EMPTY.equals(p.mPacFileUrl)) {
+ return false;
+ }
+ if (mExclusionList != null && !mExclusionList.equals(p.getExclusionListAsString())) {
return false;
}
- if (mExclusionList != null && !mExclusionList.equals(p.getExclusionListAsString())) return false;
if (mHost != null && p.getHost() != null && mHost.equals(p.getHost()) == false) {
return false;
}
@@ -296,9 +316,9 @@ public class ProxyInfo implements Parcelable {
* @hide
*/
public void writeToParcel(Parcel dest, int flags) {
- if (mPacFileUrl != null) {
+ if (!Uri.EMPTY.equals(mPacFileUrl)) {
dest.writeByte((byte)1);
- dest.writeString(mPacFileUrl);
+ mPacFileUrl.writeToParcel(dest, 0);
dest.writeInt(mPort);
return;
} else {
@@ -325,7 +345,7 @@ public class ProxyInfo implements Parcelable {
String host = null;
int port = 0;
if (in.readByte() != 0) {
- String url = in.readString();
+ Uri url = Uri.CREATOR.createFromParcel(in);
int localPort = in.readInt();
return new ProxyInfo(url, localPort);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1847b55..e1fd46e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3838,22 +3838,11 @@ public final class Settings {
/**
* Setting that specifies whether display color inversion is enabled.
- *
- * @hide
*/
public static final String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED =
"accessibility_display_inversion_enabled";
/**
- * Integer property that specifies the type of color inversion to
- * perform. Valid values are defined in AccessibilityManager.
- *
- * @hide
- */
- public static final String ACCESSIBILITY_DISPLAY_INVERSION =
- "accessibility_display_inversion";
-
- /**
* Setting that specifies whether the quick setting tile for display
* color space adjustment is enabled.
*
@@ -3881,44 +3870,6 @@ public final class Settings {
"accessibility_display_daltonizer";
/**
- * Setting that specifies whether the quick setting tile for display
- * contrast enhancement is enabled.
- *
- * @hide
- */
- public static final String ACCESSIBILITY_DISPLAY_CONTRAST_QUICK_SETTING_ENABLED =
- "accessibility_display_contrast_quick_setting_enabled";
-
- /**
- * Setting that specifies whether display contrast enhancement is
- * enabled.
- *
- * @hide
- */
- public static final String ACCESSIBILITY_DISPLAY_CONTRAST_ENABLED =
- "accessibility_display_contrast_enabled";
-
- /**
- * Floating point property that specifies display contrast adjustment.
- * Valid range is [0, ...] where 0 is gray, 1 is normal, and higher
- * values indicate enhanced contrast.
- *
- * @hide
- */
- public static final String ACCESSIBILITY_DISPLAY_CONTRAST =
- "accessibility_display_contrast";
-
- /**
- * Floating point property that specifies display brightness adjustment.
- * Valid range is [-1, 1] where -1 is black, 0 is default, and 1 is
- * white.
- *
- * @hide
- */
- public static final String ACCESSIBILITY_DISPLAY_BRIGHTNESS =
- "accessibility_display_brightness";
-
- /**
* The timout for considering a press to be a long press in milliseconds.
* @hide
*/
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index d4b29d8..d4919eb 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -17,11 +17,15 @@
package android.service.notification;
import android.service.notification.StatusBarNotification;
+import android.service.notification.NotificationOrderUpdate;
/** @hide */
oneway interface INotificationListener
{
- void onListenerConnected(in String[] notificationKeys);
- void onNotificationPosted(in StatusBarNotification notification);
- void onNotificationRemoved(in StatusBarNotification notification);
+ void onListenerConnected(in NotificationOrderUpdate update);
+ void onNotificationPosted(in StatusBarNotification notification,
+ in NotificationOrderUpdate update);
+ void onNotificationRemoved(in StatusBarNotification notification,
+ in NotificationOrderUpdate update);
+ void onNotificationOrderUpdate(in NotificationOrderUpdate update);
} \ No newline at end of file
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 3673f03..a94f45a 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -22,10 +22,13 @@ import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
+import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.UserHandle;
import android.util.Log;
+import java.util.Comparator;
+import java.util.HashMap;
+
/**
* A service that receives calls from the system when new notifications are posted or removed.
* <p>To extend this class, you must declare the service in your manifest file with
@@ -46,6 +49,7 @@ public abstract class NotificationListenerService extends Service {
+ "[" + getClass().getSimpleName() + "]";
private INotificationListenerWrapper mWrapper = null;
+ private String[] mNotificationKeys;
private INotificationManager mNoMan;
@@ -95,6 +99,15 @@ public abstract class NotificationListenerService extends Service {
// optional
}
+ /**
+ * Implement this method to be notified when the notification order cahnges.
+ *
+ * Call {@link #getOrderedNotificationKeys()} to retrieve the new order.
+ */
+ public void onNotificationOrderUpdate() {
+ // optional
+ }
+
private final INotificationManager getNotificationInterface() {
if (mNoMan == null) {
mNoMan = INotificationManager.Stub.asInterface(
@@ -202,7 +215,7 @@ public abstract class NotificationListenerService extends Service {
* Request the list of outstanding notifications (that is, those that are visible to the
* current user). Useful when you don't know what's already been posted.
*
- * @return An array of active notifications.
+ * @return An array of active notifications, sorted in natural order.
*/
public StatusBarNotification[] getActiveNotifications() {
return getActiveNotifications(null /*all*/);
@@ -213,7 +226,8 @@ public abstract class NotificationListenerService extends Service {
* current user). Useful when you don't know what's already been posted.
*
* @param keys A specific list of notification keys, or {@code null} for all.
- * @return An array of active notifications.
+ * @return An array of active notifications, sorted in natural order
+ * if {@code keys} is {@code null}.
*/
public StatusBarNotification[] getActiveNotifications(String[] keys) {
if (!isBound()) return null;
@@ -226,21 +240,15 @@ public abstract class NotificationListenerService extends Service {
}
/**
- * Request the list of outstanding notification keys(that is, those that are visible to the
- * current user). You can use the notification keys for subsequent retrieval via
+ * Request the list of notification keys in their current natural order.
+ * You can use the notification keys for subsequent retrieval via
* {@link #getActiveNotifications(String[]) or dismissal via
* {@link #cancelNotifications(String[]).
*
- * @return An array of active notification keys.
+ * @return An array of active notification keys, in their natural order.
*/
- public String[] getActiveNotificationKeys() {
- if (!isBound()) return null;
- try {
- return getNotificationInterface().getActiveNotificationKeysFromListener(mWrapper);
- } catch (android.os.RemoteException ex) {
- Log.v(TAG, "Unable to contact notification manager", ex);
- }
- return null;
+ public String[] getOrderedNotificationKeys() {
+ return mNotificationKeys;
}
@Override
@@ -261,28 +269,60 @@ public abstract class NotificationListenerService extends Service {
private class INotificationListenerWrapper extends INotificationListener.Stub {
@Override
- public void onNotificationPosted(StatusBarNotification sbn) {
+ public void onNotificationPosted(StatusBarNotification sbn,
+ NotificationOrderUpdate update) {
try {
- NotificationListenerService.this.onNotificationPosted(sbn);
+ // protect subclass from concurrent modifications of (@link mNotificationKeys}.
+ synchronized (mWrapper) {
+ updateNotificationKeys(update);
+ NotificationListenerService.this.onNotificationPosted(sbn);
+ }
} catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationPosted", t);
+ Log.w(TAG, "Error running onOrderedNotificationPosted", t);
}
}
@Override
- public void onNotificationRemoved(StatusBarNotification sbn) {
+ public void onNotificationRemoved(StatusBarNotification sbn,
+ NotificationOrderUpdate update) {
try {
- NotificationListenerService.this.onNotificationRemoved(sbn);
+ // protect subclass from concurrent modifications of (@link mNotificationKeys}.
+ synchronized (mWrapper) {
+ updateNotificationKeys(update);
+ NotificationListenerService.this.onNotificationRemoved(sbn);
+ }
} catch (Throwable t) {
Log.w(TAG, "Error running onNotificationRemoved", t);
}
}
@Override
- public void onListenerConnected(String[] notificationKeys) {
+ public void onListenerConnected(NotificationOrderUpdate update) {
try {
- NotificationListenerService.this.onListenerConnected(notificationKeys);
+ // protect subclass from concurrent modifications of (@link mNotificationKeys}.
+ synchronized (mWrapper) {
+ updateNotificationKeys(update);
+ NotificationListenerService.this.onListenerConnected(mNotificationKeys);
+ }
} catch (Throwable t) {
Log.w(TAG, "Error running onListenerConnected", t);
}
}
+ @Override
+ public void onNotificationOrderUpdate(NotificationOrderUpdate update)
+ throws RemoteException {
+ try {
+ // protect subclass from concurrent modifications of (@link mNotificationKeys}.
+ synchronized (mWrapper) {
+ updateNotificationKeys(update);
+ NotificationListenerService.this.onNotificationOrderUpdate();
+ }
+ } catch (Throwable t) {
+ Log.w(TAG, "Error running onNotificationOrderUpdate", t);
+ }
+ }
+ }
+
+ private void updateNotificationKeys(NotificationOrderUpdate update) {
+ // TODO: avoid garbage by comparing the lists
+ mNotificationKeys = update.getOrderedKeys();
}
}
diff --git a/core/java/android/service/notification/NotificationOrderUpdate.aidl b/core/java/android/service/notification/NotificationOrderUpdate.aidl
new file mode 100644
index 0000000..5d50641
--- /dev/null
+++ b/core/java/android/service/notification/NotificationOrderUpdate.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+parcelable NotificationOrderUpdate;
diff --git a/core/java/android/service/notification/NotificationOrderUpdate.java b/core/java/android/service/notification/NotificationOrderUpdate.java
new file mode 100644
index 0000000..20e19a3
--- /dev/null
+++ b/core/java/android/service/notification/NotificationOrderUpdate.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.notification;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class NotificationOrderUpdate implements Parcelable {
+ // TODO replace this with an update instead of the whole array
+ private final String[] mKeys;
+
+ /** @hide */
+ public NotificationOrderUpdate(String[] keys) {
+ this.mKeys = keys;
+ }
+
+ public NotificationOrderUpdate(Parcel in) {
+ this.mKeys = in.readStringArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeStringArray(this.mKeys);
+ }
+
+ public static final Parcelable.Creator<NotificationOrderUpdate> CREATOR
+ = new Parcelable.Creator<NotificationOrderUpdate>() {
+ public NotificationOrderUpdate createFromParcel(Parcel parcel) {
+ return new NotificationOrderUpdate(parcel);
+ }
+
+ public NotificationOrderUpdate[] newArray(int size) {
+ return new NotificationOrderUpdate[size];
+ }
+ };
+
+ /**
+ * @hide
+ * @return ordered list of keys
+ */
+ String[] getOrderedKeys() {
+ return mKeys;
+ }
+}
diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java
index 4f996cd..9b929a3 100644
--- a/core/java/android/speech/tts/TtsEngines.java
+++ b/core/java/android/speech/tts/TtsEngines.java
@@ -307,6 +307,24 @@ public class TtsEngines {
}
/**
+ * True if a given TTS engine uses the default phone locale as a default locale. Attempts to
+ * read the value from {@link Settings.Secure#TTS_DEFAULT_LOCALE}, failing which the
+ * old style value from {@link Settings.Secure#TTS_DEFAULT_LANG} is read. If
+ * both these values are empty, this methods returns true.
+ *
+ * @param engineName the engine to return the locale for.
+ */
+ public boolean isLocaleSetToDefaultForEngine(String engineName) {
+ return (TextUtils.isEmpty(parseEnginePrefFromList(
+ getString(mContext.getContentResolver(), Settings.Secure.TTS_DEFAULT_LOCALE),
+ engineName)) &&
+ TextUtils.isEmpty(
+ Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.TTS_DEFAULT_LANG)));
+ }
+
+
+ /**
* Parses a locale preference value delimited by {@link #LOCALE_DELIMITER}.
* Varies from {@link String#split} in that it will always return an array
* of length 3 with non null values.
diff --git a/core/java/android/tv/ITvInputClient.aidl b/core/java/android/tv/ITvInputClient.aidl
index 538f8a1..ac83356 100644
--- a/core/java/android/tv/ITvInputClient.aidl
+++ b/core/java/android/tv/ITvInputClient.aidl
@@ -26,6 +26,7 @@ import android.view.InputChannel;
* @hide
*/
oneway interface ITvInputClient {
- void onSessionCreated(in ComponentName name, IBinder token, in InputChannel channel, int seq);
- void onAvailabilityChanged(in ComponentName name, boolean isAvailable);
+ void onSessionCreated(in String inputId, IBinder token, in InputChannel channel, int seq);
+ void onAvailabilityChanged(in String inputId, boolean isAvailable);
+ void onSessionReleased(int seq);
}
diff --git a/core/java/android/tv/ITvInputManager.aidl b/core/java/android/tv/ITvInputManager.aidl
index a4c99e4..b756aba 100644
--- a/core/java/android/tv/ITvInputManager.aidl
+++ b/core/java/android/tv/ITvInputManager.aidl
@@ -30,12 +30,12 @@ import android.view.Surface;
interface ITvInputManager {
List<TvInputInfo> getTvInputList(int userId);
- boolean getAvailability(in ITvInputClient client, in ComponentName name, int userId);
+ boolean getAvailability(in ITvInputClient client, in String inputId, int userId);
- void registerCallback(in ITvInputClient client, in ComponentName name, int userId);
- void unregisterCallback(in ITvInputClient client, in ComponentName name, int userId);
+ void registerCallback(in ITvInputClient client, in String inputId, int userId);
+ void unregisterCallback(in ITvInputClient client, in String inputId, int userId);
- void createSession(in ITvInputClient client, in ComponentName name, int seq, int userId);
+ void createSession(in ITvInputClient client, in String inputId, int seq, int userId);
void releaseSession(in IBinder sessionToken, int userId);
void setSurface(in IBinder sessionToken, in Surface surface, int userId);
diff --git a/core/java/android/tv/ITvInputServiceCallback.aidl b/core/java/android/tv/ITvInputServiceCallback.aidl
index e535c81..71fc780 100644
--- a/core/java/android/tv/ITvInputServiceCallback.aidl
+++ b/core/java/android/tv/ITvInputServiceCallback.aidl
@@ -24,5 +24,5 @@ import android.content.ComponentName;
* @hide
*/
oneway interface ITvInputServiceCallback {
- void onAvailabilityChanged(in ComponentName name, boolean isAvailable);
+ void onAvailabilityChanged(in String inputId, boolean isAvailable);
}
diff --git a/core/java/android/tv/TvInputInfo.java b/core/java/android/tv/TvInputInfo.java
index 90e4177..50462cc 100644
--- a/core/java/android/tv/TvInputInfo.java
+++ b/core/java/android/tv/TvInputInfo.java
@@ -39,7 +39,7 @@ public final class TvInputInfo implements Parcelable {
public TvInputInfo(ResolveInfo service) {
mService = service;
ServiceInfo si = service.serviceInfo;
- mId = new ComponentName(si.packageName, si.name).flattenToShortString();
+ mId = generateInputIdForComponenetName(new ComponentName(si.packageName, si.name));
}
/**
@@ -75,7 +75,7 @@ public final class TvInputInfo implements Parcelable {
* Loads the user-displayed label for this TV input service.
*
* @param pm Supplies a PackageManager used to load the TV input's resources.
- * @return Returns a CharSequence containing the TV input's label. If the TV input does not have
+ * @return a CharSequence containing the TV input's label. If the TV input does not have
* a label, its name is returned.
*/
public CharSequence loadLabel(PackageManager pm) {
@@ -128,6 +128,17 @@ public final class TvInputInfo implements Parcelable {
}
/**
+ * Used to generate an input id from a ComponentName.
+ *
+ * @param name the component name for generating an input id.
+ * @return the generated input id for the given {@code name}.
+ * @hide
+ */
+ public static final String generateInputIdForComponenetName(ComponentName name) {
+ return name.flattenToShortString();
+ }
+
+ /**
* Used to make this class parcelable.
*
* @hide
diff --git a/core/java/android/tv/TvInputManager.java b/core/java/android/tv/TvInputManager.java
index 7b9b1fb..c5f179a 100644
--- a/core/java/android/tv/TvInputManager.java
+++ b/core/java/android/tv/TvInputManager.java
@@ -16,7 +16,6 @@
package android.tv;
-import android.content.ComponentName;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Handler;
@@ -50,15 +49,15 @@ public final class TvInputManager {
private final ITvInputManager mService;
// A mapping from an input to the list of its TvInputListenerRecords.
- private final Map<ComponentName, List<TvInputListenerRecord>> mTvInputListenerRecordsMap =
- new HashMap<ComponentName, List<TvInputListenerRecord>>();
+ private final Map<String, List<TvInputListenerRecord>> mTvInputListenerRecordsMap =
+ new HashMap<String, List<TvInputListenerRecord>>();
- // A mapping from the sequence number of a session to its SessionCreateCallbackRecord.
- private final SparseArray<SessionCreateCallbackRecord> mSessionCreateCallbackRecordMap =
- new SparseArray<SessionCreateCallbackRecord>();
+ // A mapping from the sequence number of a session to its SessionCallbackRecord.
+ private final SparseArray<SessionCallbackRecord> mSessionCallbackRecordMap =
+ new SparseArray<SessionCallbackRecord>();
// A sequence number for the next session to be created. Should be protected by a lock
- // {@code mSessionCreateCallbackRecordMap}.
+ // {@code mSessionCallbackRecordMap}.
private int mNextSeq;
private final ITvInputClient mClient;
@@ -68,31 +67,52 @@ public final class TvInputManager {
/**
* Interface used to receive the created session.
*/
- public interface SessionCreateCallback {
+ public abstract static class SessionCallback {
/**
* This is called after {@link TvInputManager#createSession} has been processed.
*
* @param session A {@link TvInputManager.Session} instance created. This can be
* {@code null} if the creation request failed.
*/
- void onSessionCreated(Session session);
+ public void onSessionCreated(Session session) {
+ }
+
+ /**
+ * This is called when {@link TvInputManager.Session} is released.
+ * This typically happens when the process hosting the session has crashed or been killed.
+ *
+ * @param session A {@link TvInputManager.Session} instance released.
+ */
+ public void onSessionReleased(Session session) {
+ }
}
- private static final class SessionCreateCallbackRecord {
- private final SessionCreateCallback mSessionCreateCallback;
+ private static final class SessionCallbackRecord {
+ private final SessionCallback mSessionCallback;
private final Handler mHandler;
+ private Session mSession;
- public SessionCreateCallbackRecord(SessionCreateCallback sessionCreateCallback,
+ public SessionCallbackRecord(SessionCallback sessionCallback,
Handler handler) {
- mSessionCreateCallback = sessionCreateCallback;
+ mSessionCallback = sessionCallback;
mHandler = handler;
}
public void postSessionCreated(final Session session) {
+ mSession = session;
mHandler.post(new Runnable() {
@Override
public void run() {
- mSessionCreateCallback.onSessionCreated(session);
+ mSessionCallback.onSessionCreated(session);
+ }
+ });
+ }
+
+ public void postSessionReleased() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mSessionCallback.onSessionReleased(mSession);
}
});
}
@@ -105,12 +125,11 @@ public final class TvInputManager {
/**
* This is called when the availability status of a given TV input is changed.
*
- * @param name {@link ComponentName} of {@link android.app.Service} that implements the
- * given TV input.
+ * @param inputId the id of the TV input.
* @param isAvailable {@code true} if the given TV input is available to show TV programs.
* {@code false} otherwise.
*/
- public void onAvailabilityChanged(ComponentName name, boolean isAvailable) {
+ public void onAvailabilityChanged(String inputId, boolean isAvailable) {
}
}
@@ -127,11 +146,11 @@ public final class TvInputManager {
return mListener;
}
- public void postAvailabilityChanged(final ComponentName name, final boolean isAvailable) {
+ public void postAvailabilityChanged(final String inputId, final boolean isAvailable) {
mHandler.post(new Runnable() {
@Override
public void run() {
- mListener.onAvailabilityChanged(name, isAvailable);
+ mListener.onAvailabilityChanged(inputId, isAvailable);
}
});
}
@@ -145,34 +164,48 @@ public final class TvInputManager {
mUserId = userId;
mClient = new ITvInputClient.Stub() {
@Override
- public void onSessionCreated(ComponentName name, IBinder token, InputChannel channel,
+ public void onSessionCreated(String inputId, IBinder token, InputChannel channel,
int seq) {
- synchronized (mSessionCreateCallbackRecordMap) {
- SessionCreateCallbackRecord record = mSessionCreateCallbackRecordMap.get(seq);
- mSessionCreateCallbackRecordMap.delete(seq);
+ synchronized (mSessionCallbackRecordMap) {
+ SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for " + token);
return;
}
Session session = null;
if (token != null) {
- session = new Session(token, channel, mService, mUserId);
+ session = new Session(token, channel, mService, mUserId, seq,
+ mSessionCallbackRecordMap);
}
record.postSessionCreated(session);
}
}
@Override
- public void onAvailabilityChanged(ComponentName name, boolean isAvailable) {
+ public void onSessionReleased(int seq) {
+ synchronized (mSessionCallbackRecordMap) {
+ SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+ mSessionCallbackRecordMap.delete(seq);
+ if (record == null) {
+ Log.e(TAG, "Callback not found for seq:" + seq);
+ return;
+ }
+ record.mSession.releaseInternal();
+ record.postSessionReleased();
+ }
+ }
+
+ @Override
+ public void onAvailabilityChanged(String inputId, boolean isAvailable) {
synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(name);
+ List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
if (records == null) {
// Silently ignore - no listener is registered yet.
return;
}
int recordsCount = records.size();
for (int i = 0; i < recordsCount; i++) {
- records.get(i).postAvailabilityChanged(name, isAvailable);
+ records.get(i).postAvailabilityChanged(inputId, isAvailable);
}
}
}
@@ -195,24 +228,23 @@ public final class TvInputManager {
/**
* Returns the availability of a given TV input.
*
- * @param name {@link ComponentName} of {@link android.app.Service} that implements the given TV
- * input.
+ * @param inputId the id of the TV input.
* @throws IllegalArgumentException if the argument is {@code null}.
* @throws IllegalStateException If there is no {@link TvInputListener} registered on the given
* TV input.
*/
- public boolean getAvailability(ComponentName name) {
- if (name == null) {
- throw new IllegalArgumentException("name cannot be null");
+ public boolean getAvailability(String inputId) {
+ if (inputId == null) {
+ throw new IllegalArgumentException("id cannot be null");
}
synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(name);
+ List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
if (records == null || records.size() == 0) {
throw new IllegalStateException("At least one listener should be registered.");
}
}
try {
- return mService.getAvailability(mClient, name, mUserId);
+ return mService.getAvailability(mClient, inputId, mUserId);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -221,15 +253,14 @@ public final class TvInputManager {
/**
* Registers a {@link TvInputListener} for a given TV input.
*
- * @param name {@link ComponentName} of {@link android.app.Service} that implements the given TV
- * input.
+ * @param inputId the id of the TV input.
* @param listener a listener used to monitor status of the given TV input.
* @param handler a {@link Handler} that the status change will be delivered to.
* @throws IllegalArgumentException if any of the arguments is {@code null}.
*/
- public void registerListener(ComponentName name, TvInputListener listener, Handler handler) {
- if (name == null) {
- throw new IllegalArgumentException("name cannot be null");
+ public void registerListener(String inputId, TvInputListener listener, Handler handler) {
+ if (inputId == null) {
+ throw new IllegalArgumentException("id cannot be null");
}
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
@@ -238,12 +269,12 @@ public final class TvInputManager {
throw new IllegalArgumentException("handler cannot be null");
}
synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(name);
+ List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
if (records == null) {
records = new ArrayList<TvInputListenerRecord>();
- mTvInputListenerRecordsMap.put(name, records);
+ mTvInputListenerRecordsMap.put(inputId, records);
try {
- mService.registerCallback(mClient, name, mUserId);
+ mService.registerCallback(mClient, inputId, mUserId);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -255,22 +286,21 @@ public final class TvInputManager {
/**
* Unregisters the existing {@link TvInputListener} for a given TV input.
*
- * @param name {@link ComponentName} of {@link android.app.Service} that implements the given TV
- * input.
+ * @param inputId the id of the TV input.
* @param listener the existing listener to remove for the given TV input.
* @throws IllegalArgumentException if any of the arguments is {@code null}.
*/
- public void unregisterListener(ComponentName name, final TvInputListener listener) {
- if (name == null) {
- throw new IllegalArgumentException("name cannot be null");
+ public void unregisterListener(String inputId, final TvInputListener listener) {
+ if (inputId == null) {
+ throw new IllegalArgumentException("id cannot be null");
}
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(name);
+ List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
if (records == null) {
- Log.e(TAG, "No listener found for " + name.getClassName());
+ Log.e(TAG, "No listener found for " + inputId);
return;
}
for (Iterator<TvInputListenerRecord> it = records.iterator(); it.hasNext();) {
@@ -281,11 +311,11 @@ public final class TvInputManager {
}
if (records.isEmpty()) {
try {
- mService.unregisterCallback(mClient, name, mUserId);
+ mService.unregisterCallback(mClient, inputId, mUserId);
} catch (RemoteException e) {
throw new RuntimeException(e);
} finally {
- mTvInputListenerRecordsMap.remove(name);
+ mTvInputListenerRecordsMap.remove(inputId);
}
}
}
@@ -298,16 +328,15 @@ public final class TvInputManager {
* the given TV input.
* </p>
*
- * @param name {@link ComponentName} of {@link android.app.Service} that implements the given TV
- * input.
+ * @param inputId the id of the TV input.
* @param callback a callback used to receive the created session.
* @param handler a {@link Handler} that the session creation will be delivered to.
* @throws IllegalArgumentException if any of the arguments is {@code null}.
*/
- public void createSession(ComponentName name, final SessionCreateCallback callback,
+ public void createSession(String inputId, final SessionCallback callback,
Handler handler) {
- if (name == null) {
- throw new IllegalArgumentException("name cannot be null");
+ if (inputId == null) {
+ throw new IllegalArgumentException("id cannot be null");
}
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
@@ -315,12 +344,12 @@ public final class TvInputManager {
if (handler == null) {
throw new IllegalArgumentException("handler cannot be null");
}
- SessionCreateCallbackRecord record = new SessionCreateCallbackRecord(callback, handler);
- synchronized (mSessionCreateCallbackRecordMap) {
+ SessionCallbackRecord record = new SessionCallbackRecord(callback, handler);
+ synchronized (mSessionCallbackRecordMap) {
int seq = mNextSeq++;
- mSessionCreateCallbackRecordMap.put(seq, record);
+ mSessionCallbackRecordMap.put(seq, record);
try {
- mService.createSession(mClient, name, seq, mUserId);
+ mService.createSession(mClient, inputId, seq, mUserId);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -337,6 +366,7 @@ public final class TvInputManager {
private final ITvInputManager mService;
private final int mUserId;
+ private final int mSeq;
// For scheduling input event handling on the main thread. This also serves as a lock to
// protect pending input events and the input channel.
@@ -344,17 +374,21 @@ public final class TvInputManager {
private final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20);
private final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20);
+ private final SparseArray<SessionCallbackRecord> mSessionCallbackRecordMap;
private IBinder mToken;
private TvInputEventSender mSender;
private InputChannel mChannel;
/** @hide */
- private Session(IBinder token, InputChannel channel, ITvInputManager service, int userId) {
+ private Session(IBinder token, InputChannel channel, ITvInputManager service, int userId,
+ int seq, SparseArray<SessionCallbackRecord> sessionCallbackRecordMap) {
mToken = token;
mChannel = channel;
mService = service;
mUserId = userId;
+ mSeq = seq;
+ mSessionCallbackRecordMap = sessionCallbackRecordMap;
}
/**
@@ -368,22 +402,11 @@ public final class TvInputManager {
}
try {
mService.releaseSession(mToken, mUserId);
- mToken = null;
} catch (RemoteException e) {
throw new RuntimeException(e);
}
- synchronized (mHandler) {
- if (mChannel != null) {
- if (mSender != null) {
- flushPendingEventsLocked();
- mSender.dispose();
- mSender = null;
- }
- mChannel.dispose();
- mChannel = null;
- }
- }
+ releaseInternal();
}
/**
@@ -675,6 +698,24 @@ public final class TvInputManager {
mPendingEventPool.release(p);
}
+ private void releaseInternal() {
+ mToken = null;
+ synchronized (mHandler) {
+ if (mChannel != null) {
+ if (mSender != null) {
+ flushPendingEventsLocked();
+ mSender.dispose();
+ mSender = null;
+ }
+ mChannel.dispose();
+ mChannel = null;
+ }
+ }
+ synchronized (mSessionCallbackRecordMap) {
+ mSessionCallbackRecordMap.remove(mSeq);
+ }
+ }
+
private final class InputEventHandler extends Handler {
public static final int MSG_SEND_INPUT_EVENT = 1;
public static final int MSG_TIMEOUT_INPUT_EVENT = 2;
diff --git a/core/java/android/tv/TvInputService.java b/core/java/android/tv/TvInputService.java
index 70e7f95..1d6298d 100644
--- a/core/java/android/tv/TvInputService.java
+++ b/core/java/android/tv/TvInputService.java
@@ -60,7 +60,7 @@ public abstract class TvInputService extends Service {
*/
public static final String SERVICE_INTERFACE = "android.tv.TvInputService";
- private ComponentName mComponentName;
+ private String mId;
private final Handler mHandler = new ServiceHandler();
private final RemoteCallbackList<ITvInputServiceCallback> mCallbacks =
new RemoteCallbackList<ITvInputServiceCallback>();
@@ -69,7 +69,8 @@ public abstract class TvInputService extends Service {
@Override
public void onCreate() {
super.onCreate();
- mComponentName = new ComponentName(getPackageName(), getClass().getName());
+ mId = TvInputInfo.generateInputIdForComponenetName(
+ new ComponentName(getPackageName(), getClass().getName()));
}
@Override
@@ -82,7 +83,7 @@ public abstract class TvInputService extends Service {
// The first time a callback is registered, the service needs to report its
// availability status so that the system can know its initial value.
try {
- cb.onAvailabilityChanged(mComponentName, mAvailable);
+ cb.onAvailabilityChanged(mId, mAvailable);
} catch (RemoteException e) {
Log.e(TAG, "error in onAvailabilityChanged", e);
}
@@ -531,8 +532,7 @@ public abstract class TvInputService extends Service {
int n = mCallbacks.beginBroadcast();
try {
for (int i = 0; i < n; i++) {
- mCallbacks.getBroadcastItem(i).onAvailabilityChanged(mComponentName,
- isAvailable);
+ mCallbacks.getBroadcastItem(i).onAvailabilityChanged(mId, isAvailable);
}
} catch (RemoteException e) {
Log.e(TAG, "Unexpected exception", e);
diff --git a/core/java/android/tv/TvView.java b/core/java/android/tv/TvView.java
index 289823b..80501e8 100644
--- a/core/java/android/tv/TvView.java
+++ b/core/java/android/tv/TvView.java
@@ -16,13 +16,13 @@
package android.tv;
-import android.content.ComponentName;
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
+import android.text.TextUtils;
import android.tv.TvInputManager.Session;
import android.tv.TvInputManager.Session.FinishedInputEventCallback;
-import android.tv.TvInputManager.SessionCreateCallback;
+import android.tv.TvInputManager.SessionCallback;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InputEvent;
@@ -46,7 +46,7 @@ public class TvView extends SurfaceView {
private boolean mOverlayViewCreated;
private Rect mOverlayViewFrame;
private final TvInputManager mTvInputManager;
- private SessionCreateCallback mSessionCreateCallback;
+ private SessionCallback mSessionCallback;
private OnUnhandledInputEventListener mOnUnhandledInputEventListener;
private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
@@ -108,19 +108,19 @@ public class TvView extends SurfaceView {
}
/**
- * Binds a TV input to this view. {@link SessionCreateCallback#onSessionCreated} will be
+ * Binds a TV input to this view. {@link SessionCallback#onSessionCreated} will be
* called to send the result of this binding with {@link TvInputManager.Session}.
* If a TV input is already bound, the input will be unbound from this view and its session
* will be released.
*
- * @param name TV input name will be bound to this view.
+ * @param inputId the id of TV input which will be bound to this view.
* @param callback called when TV input is bound. The callback sends
* {@link TvInputManager.Session}
* @throws IllegalArgumentException if any of the arguments is {@code null}.
*/
- public void bindTvInput(ComponentName name, SessionCreateCallback callback) {
- if (name == null) {
- throw new IllegalArgumentException("name cannot be null");
+ public void bindTvInput(String inputId, SessionCallback callback) {
+ if (TextUtils.isEmpty(inputId)) {
+ throw new IllegalArgumentException("inputId cannot be null or an empty string");
}
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
@@ -130,11 +130,11 @@ public class TvView extends SurfaceView {
}
// When bindTvInput is called multiple times before the callback is called,
// only the callback of the last bindTvInput call will be actually called back.
- // The previous callbacks will be ignored. For the logic, mSessionCreateCallback
+ // The previous callbacks will be ignored. For the logic, mSessionCallback
// is newly assigned for every bindTvInput call and compared with
// MySessionCreateCallback.this.
- mSessionCreateCallback = new MySessionCreateCallback(callback);
- mTvInputManager.createSession(name, mSessionCreateCallback, mHandler);
+ mSessionCallback = new MySessionCallback(callback);
+ mTvInputManager.createSession(inputId, mSessionCallback, mHandler);
}
/**
@@ -196,7 +196,9 @@ public class TvView extends SurfaceView {
if (mSession == null) {
return false;
}
- int ret = mSession.dispatchInputEvent(event, event, mFinishedInputEventCallback, mHandler);
+ InputEvent copiedEvent = event.copy();
+ int ret = mSession.dispatchInputEvent(copiedEvent, copiedEvent, mFinishedInputEventCallback,
+ mHandler);
return ret != Session.DISPATCH_NOT_HANDLED;
}
@@ -209,7 +211,9 @@ public class TvView extends SurfaceView {
if (mSession == null) {
return false;
}
- int ret = mSession.dispatchInputEvent(event, event, mFinishedInputEventCallback, mHandler);
+ InputEvent copiedEvent = event.copy();
+ int ret = mSession.dispatchInputEvent(copiedEvent, copiedEvent, mFinishedInputEventCallback,
+ mHandler);
return ret != Session.DISPATCH_NOT_HANDLED;
}
@@ -222,7 +226,9 @@ public class TvView extends SurfaceView {
if (mSession == null) {
return false;
}
- int ret = mSession.dispatchInputEvent(event, event, mFinishedInputEventCallback, mHandler);
+ InputEvent copiedEvent = event.copy();
+ int ret = mSession.dispatchInputEvent(copiedEvent, copiedEvent, mFinishedInputEventCallback,
+ mHandler);
return ret != Session.DISPATCH_NOT_HANDLED;
}
@@ -235,7 +241,9 @@ public class TvView extends SurfaceView {
if (mSession == null) {
return false;
}
- int ret = mSession.dispatchInputEvent(event, event, mFinishedInputEventCallback, mHandler);
+ InputEvent copiedEvent = event.copy();
+ int ret = mSession.dispatchInputEvent(copiedEvent, copiedEvent, mFinishedInputEventCallback,
+ mHandler);
return ret != Session.DISPATCH_NOT_HANDLED;
}
@@ -328,16 +336,16 @@ public class TvView extends SurfaceView {
boolean onUnhandledInputEvent(InputEvent event);
}
- private class MySessionCreateCallback implements SessionCreateCallback {
- final SessionCreateCallback mExternalCallback;
+ private class MySessionCallback extends SessionCallback {
+ final SessionCallback mExternalCallback;
- MySessionCreateCallback(SessionCreateCallback externalCallback) {
+ MySessionCallback(SessionCallback externalCallback) {
mExternalCallback = externalCallback;
}
@Override
public void onSessionCreated(Session session) {
- if (this != mSessionCreateCallback) {
+ if (this != mSessionCallback) {
// This callback is obsolete.
session.release();
return;
@@ -356,5 +364,13 @@ public class TvView extends SurfaceView {
mExternalCallback.onSessionCreated(session);
}
}
+
+ @Override
+ public void onSessionReleased(Session session) {
+ mSession = null;
+ if (mExternalCallback != null) {
+ mExternalCallback.onSessionReleased(session);
+ }
+ }
}
}
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 33964a0..8f4b710 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -245,6 +245,9 @@ public class TimeUtils {
private static final int SECONDS_PER_HOUR = 60 * 60;
private static final int SECONDS_PER_DAY = 24 * 60 * 60;
+ /** @hide */
+ public static final long NANOS_PER_MS = 1000000;
+
private static final Object sFormatSync = new Object();
private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+5];
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 0a76075..1066430 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -112,8 +112,6 @@ public final class Choreographer {
private static final int SKIPPED_FRAME_WARNING_LIMIT = SystemProperties.getInt(
"debug.choreographer.skipwarning", 30);
- private static final long NANOS_PER_MS = 1000000;
-
private static final int MSG_DO_FRAME = 0;
private static final int MSG_DO_SCHEDULE_VSYNC = 1;
private static final int MSG_DO_SCHEDULE_CALLBACK = 2;
@@ -263,7 +261,7 @@ public final class Choreographer {
* @return The refresh rate as the nanoseconds between frames
* @hide
*/
- long getFrameIntervalNanos() {
+ public long getFrameIntervalNanos() {
return mFrameIntervalNanos;
}
@@ -456,7 +454,7 @@ public final class Choreographer {
* @hide
*/
public long getFrameTime() {
- return getFrameTimeNanos() / NANOS_PER_MS;
+ return getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
}
/**
@@ -497,7 +495,7 @@ public final class Choreographer {
}
} else {
final long nextFrameTime = Math.max(
- mLastFrameTimeNanos / NANOS_PER_MS + sFrameDelay, now);
+ mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
if (DEBUG) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
@@ -746,7 +744,7 @@ public final class Choreographer {
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
- mHandler.sendMessageAtTime(msg, timestampNanos / NANOS_PER_MS);
+ mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index be3b6ce..ec4d560 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -16,12 +16,17 @@
package android.view;
+import android.animation.TimeInterpolator;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
import android.util.SparseIntArray;
+import android.util.TimeUtils;
import com.android.internal.util.VirtualRefBasePtr;
+import com.android.internal.view.animation.FallbackLUTInterpolator;
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
import java.lang.ref.WeakReference;
@@ -71,9 +76,12 @@ public final class RenderNodeAnimator {
public static final int DELTA_TYPE_ABSOLUTE = 0;
public static final int DELTA_TYPE_DELTA = 1;
- private RenderNode mTarget;
private VirtualRefBasePtr mNativePtr;
+ private RenderNode mTarget;
+ private TimeInterpolator mInterpolator;
+ private boolean mStarted = false;
+
public int mapViewPropertyToRenderProperty(int viewProperty) {
return sViewPropertyAnimatorMap.get(viewProperty);
}
@@ -100,9 +108,37 @@ public final class RenderNodeAnimator {
mNativePtr = new VirtualRefBasePtr(ptr);
}
- public void start(View target) {
- mTarget = target.mRenderNode;
+ private void checkMutable() {
+ if (mStarted) {
+ throw new IllegalStateException("Animator has already started, cannot change it now!");
+ }
+ }
+
+ private void applyInterpolator() {
+ if (mInterpolator == null) return;
+
+ long ni;
+ if (mInterpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class)) {
+ ni = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator();
+ } else {
+ int duration = nGetDuration(mNativePtr.get());
+ ni = FallbackLUTInterpolator.createNativeInterpolator(mInterpolator, duration);
+ }
+ nSetInterpolator(mNativePtr.get(), ni);
+ }
+
+ private void start(RenderNode node) {
+ if (mStarted) {
+ throw new IllegalStateException("Already started!");
+ }
+ mStarted = true;
+ applyInterpolator();
+ mTarget = node;
mTarget.addAnimator(this);
+ }
+
+ public void start(View target) {
+ start(target.mRenderNode);
// Kick off a frame to start the process
target.invalidateViewProperty(true, false);
}
@@ -112,8 +148,7 @@ public final class RenderNodeAnimator {
throw new IllegalArgumentException("Not a GLES20RecordingCanvas");
}
GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas;
- mTarget = recordingCanvas.mNode;
- mTarget.addAnimator(this);
+ start(recordingCanvas.mNode);
}
public void cancel() {
@@ -121,9 +156,15 @@ public final class RenderNodeAnimator {
}
public void setDuration(int duration) {
+ checkMutable();
nSetDuration(mNativePtr.get(), duration);
}
+ public void setInterpolator(TimeInterpolator interpolator) {
+ checkMutable();
+ mInterpolator = interpolator;
+ }
+
long getNativeAnimator() {
return mNativePtr.get();
}
@@ -147,4 +188,6 @@ public final class RenderNodeAnimator {
private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
long canvasProperty, int paintField, int deltaValueType, float deltaValue);
private static native void nSetDuration(long nativePtr, int duration);
+ private static native int nGetDuration(long nativePtr);
+ private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 2587ba1..5653066 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -20,6 +20,7 @@ import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.Trace;
+import android.util.TimeUtils;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
@@ -51,8 +52,6 @@ public class ThreadedRenderer extends HardwareRenderer {
private static final Rect NULL_RECT = new Rect();
- private static final long NANOS_PER_MS = 1000000;
-
// Keep in sync with DrawFrameTask.h SYNC_* flags
// Nothing interesting to report
private static final int SYNC_OK = 0x0;
@@ -203,7 +202,7 @@ public class ThreadedRenderer extends HardwareRenderer {
void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
attachInfo.mIgnoreDirtyState = true;
long frameTimeNanos = mChoreographer.getFrameTimeNanos();
- attachInfo.mDrawingTime = frameTimeNanos / NANOS_PER_MS;
+ attachInfo.mDrawingTime = frameTimeNanos / TimeUtils.NANOS_PER_MS;
updateRootDisplayList(view, callbacks);
diff --git a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
index 158c56e..ed6949a 100644
--- a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
+++ b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
@@ -19,12 +19,17 @@ package android.view.animation;
import android.content.Context;
import android.util.AttributeSet;
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
+
/**
* An interpolator where the rate of change starts and ends slowly but
* accelerates through the middle.
*
*/
-public class AccelerateDecelerateInterpolator implements Interpolator {
+@HasNativeInterpolator
+public class AccelerateDecelerateInterpolator implements Interpolator, NativeInterpolatorFactory {
public AccelerateDecelerateInterpolator() {
}
@@ -35,4 +40,10 @@ public class AccelerateDecelerateInterpolator implements Interpolator {
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
+
+ /** @hide */
+ @Override
+ public long createNativeInterpolator() {
+ return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator();
+ }
}
diff --git a/core/java/android/view/animation/AccelerateInterpolator.java b/core/java/android/view/animation/AccelerateInterpolator.java
index dcab743..c08f348 100644
--- a/core/java/android/view/animation/AccelerateInterpolator.java
+++ b/core/java/android/view/animation/AccelerateInterpolator.java
@@ -20,12 +20,17 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
+
/**
* An interpolator where the rate of change starts out slowly and
* and then accelerates.
*
*/
-public class AccelerateInterpolator implements Interpolator {
+@HasNativeInterpolator
+public class AccelerateInterpolator implements Interpolator, NativeInterpolatorFactory {
private final float mFactor;
private final double mDoubleFactor;
@@ -64,4 +69,10 @@ public class AccelerateInterpolator implements Interpolator {
return (float)Math.pow(input, mDoubleFactor);
}
}
+
+ /** @hide */
+ @Override
+ public long createNativeInterpolator() {
+ return NativeInterpolatorFactoryHelper.createAccelerateInterpolator(mFactor);
+ }
}
diff --git a/core/java/android/view/animation/AnticipateInterpolator.java b/core/java/android/view/animation/AnticipateInterpolator.java
index a6f110e..83a8007 100644
--- a/core/java/android/view/animation/AnticipateInterpolator.java
+++ b/core/java/android/view/animation/AnticipateInterpolator.java
@@ -20,10 +20,15 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
+
/**
* An interpolator where the change starts backward then flings forward.
*/
-public class AnticipateInterpolator implements Interpolator {
+@HasNativeInterpolator
+public class AnticipateInterpolator implements Interpolator, NativeInterpolatorFactory {
private final float mTension;
public AnticipateInterpolator() {
@@ -53,4 +58,10 @@ public class AnticipateInterpolator implements Interpolator {
// a(t) = t * t * ((tension + 1) * t - tension)
return t * t * ((mTension + 1) * t - mTension);
}
+
+ /** @hide */
+ @Override
+ public long createNativeInterpolator() {
+ return NativeInterpolatorFactoryHelper.createAnticipateInterpolator(mTension);
+ }
}
diff --git a/core/java/android/view/animation/AnticipateOvershootInterpolator.java b/core/java/android/view/animation/AnticipateOvershootInterpolator.java
index 3dc9722..1a8adfd 100644
--- a/core/java/android/view/animation/AnticipateOvershootInterpolator.java
+++ b/core/java/android/view/animation/AnticipateOvershootInterpolator.java
@@ -19,6 +19,11 @@ package android.view.animation;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
+
import static com.android.internal.R.styleable.AnticipateOvershootInterpolator_extraTension;
import static com.android.internal.R.styleable.AnticipateOvershootInterpolator_tension;
import static com.android.internal.R.styleable.AnticipateOvershootInterpolator;
@@ -27,7 +32,8 @@ import static com.android.internal.R.styleable.AnticipateOvershootInterpolator;
* An interpolator where the change starts backward then flings forward and overshoots
* the target value and finally goes back to the final value.
*/
-public class AnticipateOvershootInterpolator implements Interpolator {
+@HasNativeInterpolator
+public class AnticipateOvershootInterpolator implements Interpolator, NativeInterpolatorFactory {
private final float mTension;
public AnticipateOvershootInterpolator() {
@@ -80,4 +86,10 @@ public class AnticipateOvershootInterpolator implements Interpolator {
if (t < 0.5f) return 0.5f * a(t * 2.0f, mTension);
else return 0.5f * (o(t * 2.0f - 2.0f, mTension) + 2.0f);
}
+
+ /** @hide */
+ @Override
+ public long createNativeInterpolator() {
+ return NativeInterpolatorFactoryHelper.createAnticipateOvershootInterpolator(mTension);
+ }
}
diff --git a/core/java/android/view/animation/BounceInterpolator.java b/core/java/android/view/animation/BounceInterpolator.java
index ecf99a7..9d8ca90 100644
--- a/core/java/android/view/animation/BounceInterpolator.java
+++ b/core/java/android/view/animation/BounceInterpolator.java
@@ -19,10 +19,15 @@ package android.view.animation;
import android.content.Context;
import android.util.AttributeSet;
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
+
/**
* An interpolator where the change bounces at the end.
*/
-public class BounceInterpolator implements Interpolator {
+@HasNativeInterpolator
+public class BounceInterpolator implements Interpolator, NativeInterpolatorFactory {
public BounceInterpolator() {
}
@@ -47,4 +52,10 @@ public class BounceInterpolator implements Interpolator {
else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f;
else return bounce(t - 1.0435f) + 0.95f;
}
+
+ /** @hide */
+ @Override
+ public long createNativeInterpolator() {
+ return NativeInterpolatorFactoryHelper.createBounceInterpolator();
+ }
} \ No newline at end of file
diff --git a/core/java/android/view/animation/CycleInterpolator.java b/core/java/android/view/animation/CycleInterpolator.java
index d355c23..d1ebf05 100644
--- a/core/java/android/view/animation/CycleInterpolator.java
+++ b/core/java/android/view/animation/CycleInterpolator.java
@@ -20,12 +20,17 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
+
/**
* Repeats the animation for a specified number of cycles. The
* rate of change follows a sinusoidal pattern.
*
*/
-public class CycleInterpolator implements Interpolator {
+@HasNativeInterpolator
+public class CycleInterpolator implements Interpolator, NativeInterpolatorFactory {
public CycleInterpolator(float cycles) {
mCycles = cycles;
}
@@ -44,4 +49,10 @@ public class CycleInterpolator implements Interpolator {
}
private float mCycles;
+
+ /** @hide */
+ @Override
+ public long createNativeInterpolator() {
+ return NativeInterpolatorFactoryHelper.createCycleInterpolator(mCycles);
+ }
}
diff --git a/core/java/android/view/animation/DecelerateInterpolator.java b/core/java/android/view/animation/DecelerateInterpolator.java
index 20e079b..0789a0e 100644
--- a/core/java/android/view/animation/DecelerateInterpolator.java
+++ b/core/java/android/view/animation/DecelerateInterpolator.java
@@ -20,12 +20,17 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
+
/**
* An interpolator where the rate of change starts out quickly and
* and then decelerates.
*
*/
-public class DecelerateInterpolator implements Interpolator {
+@HasNativeInterpolator
+public class DecelerateInterpolator implements Interpolator, NativeInterpolatorFactory {
public DecelerateInterpolator() {
}
@@ -60,4 +65,10 @@ public class DecelerateInterpolator implements Interpolator {
}
private float mFactor = 1.0f;
+
+ /** @hide */
+ @Override
+ public long createNativeInterpolator() {
+ return NativeInterpolatorFactoryHelper.createDecelerateInterpolator(mFactor);
+ }
}
diff --git a/core/java/android/view/animation/LinearInterpolator.java b/core/java/android/view/animation/LinearInterpolator.java
index 96a039f..552c611 100644
--- a/core/java/android/view/animation/LinearInterpolator.java
+++ b/core/java/android/view/animation/LinearInterpolator.java
@@ -19,11 +19,16 @@ package android.view.animation;
import android.content.Context;
import android.util.AttributeSet;
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
+
/**
* An interpolator where the rate of change is constant
*
*/
-public class LinearInterpolator implements Interpolator {
+@HasNativeInterpolator
+public class LinearInterpolator implements Interpolator, NativeInterpolatorFactory {
public LinearInterpolator() {
}
@@ -34,4 +39,10 @@ public class LinearInterpolator implements Interpolator {
public float getInterpolation(float input) {
return input;
}
+
+ /** @hide */
+ @Override
+ public long createNativeInterpolator() {
+ return NativeInterpolatorFactoryHelper.createLinearInterpolator();
+ }
}
diff --git a/core/java/android/view/animation/OvershootInterpolator.java b/core/java/android/view/animation/OvershootInterpolator.java
index 494f8ab..a2466f1 100644
--- a/core/java/android/view/animation/OvershootInterpolator.java
+++ b/core/java/android/view/animation/OvershootInterpolator.java
@@ -20,11 +20,16 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
+
/**
* An interpolator where the change flings forward and overshoots the last value
* then comes back.
*/
-public class OvershootInterpolator implements Interpolator {
+@HasNativeInterpolator
+public class OvershootInterpolator implements Interpolator, NativeInterpolatorFactory {
private final float mTension;
public OvershootInterpolator() {
@@ -56,4 +61,10 @@ public class OvershootInterpolator implements Interpolator {
t -= 1.0f;
return t * t * ((mTension + 1) * t + mTension) + 1.0f;
}
+
+ /** @hide */
+ @Override
+ public long createNativeInterpolator() {
+ return NativeInterpolatorFactoryHelper.createOvershootInterpolator(mTension);
+ }
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index be0c27d..3fee0ac 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -24,6 +24,8 @@ import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputBindResult;
+import libcore.util.Objects;
+
import android.content.Context;
import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
@@ -317,10 +319,17 @@ public final class InputMethodManager {
int mCursorSelEnd;
int mCursorCandStart;
int mCursorCandEnd;
+
+ /**
+ * The instance that has previously been sent to the input method.
+ */
+ private CursorAnchorInfo mCursorAnchorInfo = null;
+
/**
* The buffer to retrieve the view location in screen coordinates in {@link #updateCursor}.
*/
private final int[] mViewTopLeft = new int[2];
+
// -----------------------------------------------------------
/**
@@ -489,6 +498,9 @@ public final class InputMethodManager {
case SET_CURSOR_ANCHOR_MONITOR_MODE: {
synchronized (mH) {
mCursorAnchorMonitorMode = msg.arg1;
+ // Clear the cache.
+ mCursorRect.setEmpty();
+ mCursorAnchorInfo = null;
}
return;
}
@@ -1173,6 +1185,7 @@ public final class InputMethodManager {
mCursorCandStart = -1;
mCursorCandEnd = -1;
mCursorRect.setEmpty();
+ mCursorAnchorInfo = null;
servedContext = new ControlledInputConnectionWrapper(vh.getLooper(), ic, this);
} else {
servedContext = null;
@@ -1535,10 +1548,9 @@ public final class InputMethodManager {
|| mCurrentTextBoxAttribute == null || mCurMethod == null) {
return;
}
+ if (DEBUG) Log.d(TAG, "updateCursor");
mTmpCursorRect.set(left, top, right, bottom);
- if (!mCursorRect.equals(mTmpCursorRect)) {
- if (DEBUG) Log.d(TAG, "updateCursor");
-
+ if (!Objects.equal(mCursorRect, mTmpCursorRect)) {
try {
if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
mCursorRect.set(mTmpCursorRect);
@@ -1569,10 +1581,14 @@ public final class InputMethodManager {
|| mCurrentTextBoxAttribute == null || mCurMethod == null) {
return;
}
- if (DEBUG) Log.d(TAG, "updateCursorAnchorInfo");
-
+ if (Objects.equal(mCursorAnchorInfo, cursorAnchorInfo)) {
+ Log.w(TAG, "Ignoring redundant updateCursorAnchorInfo: info=" + cursorAnchorInfo);
+ return;
+ }
+ if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo);
try {
mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
+ mCursorAnchorInfo = cursorAnchorInfo;
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 5fa63e5..d9a4f57 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3320,7 +3320,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
final int deltaY = rawDeltaY;
int incrementalDeltaY =
- mLastY != Integer.MIN_VALUE ? y - mLastY - scrollConsumedCorrection : deltaY;
+ mLastY != Integer.MIN_VALUE ? y - mLastY + scrollConsumedCorrection : deltaY;
int lastYCorrection = 0;
if (mTouchMode == TOUCH_MODE_SCROLL) {