diff options
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/app/VoiceInteractor.java | 6 | ||||
-rw-r--r-- | core/java/android/app/backup/BackupTransport.java | 175 | ||||
-rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 7 | ||||
-rw-r--r-- | core/java/android/hardware/hdmi/HdmiCec.java | 4 | ||||
-rw-r--r-- | core/java/android/net/ConnectivityManager.java | 223 | ||||
-rw-r--r-- | core/java/android/net/ConnectivityServiceProtocol.java | 70 | ||||
-rw-r--r-- | core/java/android/net/IConnectivityManager.aidl | 4 | ||||
-rw-r--r-- | core/java/android/net/NetworkAgent.java | 337 | ||||
-rw-r--r-- | core/java/android/net/NetworkFactory.java | 275 | ||||
-rw-r--r-- | core/java/android/net/NetworkInfo.java | 14 | ||||
-rw-r--r-- | core/java/android/net/NetworkRequest.java | 22 | ||||
-rw-r--r-- | core/java/android/view/RenderNodeAnimator.java | 16 |
12 files changed, 728 insertions, 425 deletions
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java index f332c9d..85e970c 100644 --- a/core/java/android/app/VoiceInteractor.java +++ b/core/java/android/app/VoiceInteractor.java @@ -43,7 +43,7 @@ import java.util.ArrayList; * {@link Request} subclass describing the type of operation to perform -- currently the * possible requests are {@link ConfirmationRequest} and {@link CommandRequest}. * - * <p>Once a request is submitted, the voice system will process it and evetually deliver + * <p>Once a request is submitted, the voice system will process it and eventually deliver * the result to the request object. The application can cancel a pending request at any * time. * @@ -51,7 +51,7 @@ import java.util.ArrayList; * if an activity is being restarted with retained state, it will retain the current * VoiceInteractor and any outstanding requests. Because of this, you should always use * {@link Request#getActivity() Request.getActivity} to get back to the activity of a - * request, rather than holding on to the actvitity instance yourself, either explicitly + * request, rather than holding on to the activity instance yourself, either explicitly * or implicitly through a non-static inner class. */ public class VoiceInteractor { @@ -236,7 +236,7 @@ public class VoiceInteractor { * Reports that the current interaction can not be complete with voice, so the * application will need to switch to a traditional input UI. Applications should * only use this when they need to completely bail out of the voice interaction - * and switch to a traditional UI. When the resonsponse comes back, the voice + * and switch to a traditional UI. When the response comes back, the voice * system has handled the request and is ready to switch; at that point the application * can start a new non-voice activity. Be sure when starting the new activity * to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java index da5cb10..46f082e 100644 --- a/core/java/android/app/backup/BackupTransport.java +++ b/core/java/android/app/backup/BackupTransport.java @@ -22,7 +22,6 @@ import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; -import com.android.internal.backup.BackupConstants; import com.android.internal.backup.IBackupTransport; /** @@ -32,6 +31,13 @@ import com.android.internal.backup.IBackupTransport; * @hide */ public class BackupTransport { + public static final int TRANSPORT_OK = 0; + public static final int TRANSPORT_ERROR = 1; + public static final int TRANSPORT_NOT_INITIALIZED = 2; + public static final int TRANSPORT_PACKAGE_REJECTED = 3; + public static final int AGENT_ERROR = 4; + public static final int AGENT_UNKNOWN = 5; + IBackupTransport mBinderImpl = new TransportImpl(); /** @hide */ public IBinder getBinder() { @@ -99,10 +105,50 @@ public class BackupTransport { } // ------------------------------------------------------------------------------------ + // Device-level operations common to both key/value and full-data storage + + /** + * Initialize the server side storage for this device, erasing all stored data. + * The transport may send the request immediately, or may buffer it. After + * this is called, {@link #finishBackup} will be called to ensure the request + * is sent and received successfully. + * + * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far) or + * {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure). + */ + public int initializeDevice() { + return BackupTransport.TRANSPORT_ERROR; + } + + /** + * Erase the given application's data from the backup destination. This clears + * out the given package's data from the current backup set, making it as though + * the app had never yet been backed up. After this is called, {@link finishBackup} + * must be called to ensure that the operation is recorded successfully. + * + * @return the same error codes as {@link #performBackup}. + */ + public int clearBackupData(PackageInfo packageInfo) { + return BackupTransport.TRANSPORT_ERROR; + } + + /** + * Finish sending application data to the backup destination. This must be + * called after {@link #performBackup}, {@link #performFullBackup}, or {@link clearBackupData} + * to ensure that all data is sent and the operation properly finalized. Only when this + * method returns true can a backup be assumed to have succeeded. + * + * @return the same error codes as {@link #performBackup} or {@link #performFullBackup}. + */ + public int finishBackup() { + return BackupTransport.TRANSPORT_ERROR; + } + + // ------------------------------------------------------------------------------------ // Key/value incremental backup support interfaces /** - * Verify that this is a suitable time for a backup pass. This should return zero + * Verify that this is a suitable time for a key/value backup pass. This should return zero * if a backup is reasonable right now, some positive value otherwise. This method * will be called outside of the {@link #performBackup}/{@link #finishBackup} pair. * @@ -117,19 +163,6 @@ public class BackupTransport { } /** - * Initialize the server side storage for this device, erasing all stored data. - * The transport may send the request immediately, or may buffer it. After - * this is called, {@link #finishBackup} will be called to ensure the request - * is sent and received successfully. - * - * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far) or - * {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure). - */ - public int initializeDevice() { - return BackupConstants.TRANSPORT_ERROR; - } - - /** * Send one application's key/value data update to the backup destination. The * transport may send the data immediately, or may buffer it. After this is called, * {@link #finishBackup} will be called to ensure the data is sent and recorded successfully. @@ -143,37 +176,13 @@ public class BackupTransport { * must be erased prior to the storage of the data provided here. The purpose of this * is to provide a guarantee that no stale data exists in the restore set when the * device begins providing incremental backups. - * @return one of {@link BackupConstants#TRANSPORT_OK} (OK so far), - * {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure), or - * {@link BackupConstants#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has + * @return one of {@link BackupTransport#TRANSPORT_OK} (OK so far), + * {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure), or + * {@link BackupTransport#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has * become lost due to inactivity purge or some other reason and needs re-initializing) */ public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd) { - return BackupConstants.TRANSPORT_ERROR; - } - - /** - * Erase the give application's data from the backup destination. This clears - * out the given package's data from the current backup set, making it as though - * the app had never yet been backed up. After this is called, {@link finishBackup} - * must be called to ensure that the operation is recorded successfully. - * - * @return the same error codes as {@link #performBackup}. - */ - public int clearBackupData(PackageInfo packageInfo) { - return BackupConstants.TRANSPORT_ERROR; - } - - /** - * Finish sending application data to the backup destination. This must be - * called after {@link #performBackup} or {@link clearBackupData} to ensure that - * all data is sent. Only when this method returns true can a backup be assumed - * to have succeeded. - * - * @return the same error codes as {@link #performBackup}. - */ - public int finishBackup() { - return BackupConstants.TRANSPORT_ERROR; + return BackupTransport.TRANSPORT_ERROR; } // ------------------------------------------------------------------------------------ @@ -210,12 +219,12 @@ public class BackupTransport { * or {@link #getCurrentRestoreSet}. * @param packages List of applications to restore (if data is available). * Application data will be restored in the order given. - * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far, call - * {@link #nextRestorePackage}) or {@link BackupConstants#TRANSPORT_ERROR} + * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far, call + * {@link #nextRestorePackage}) or {@link BackupTransport#TRANSPORT_ERROR} * (an error occurred, the restore should be aborted and rescheduled). */ public int startRestore(long token, PackageInfo[] packages) { - return BackupConstants.TRANSPORT_ERROR; + return BackupTransport.TRANSPORT_ERROR; } /** @@ -235,7 +244,7 @@ public class BackupTransport { * @return the same error codes as {@link #startRestore}. */ public int getRestoreData(ParcelFileDescriptor outFd) { - return BackupConstants.TRANSPORT_ERROR; + return BackupTransport.TRANSPORT_ERROR; } /** @@ -247,6 +256,78 @@ public class BackupTransport { "Transport finishRestore() not implemented"); } + // ------------------------------------------------------------------------------------ + // Full backup interfaces + + /** + * Verify that this is a suitable time for a full-data backup pass. This should return zero + * if a backup is reasonable right now, some positive value otherwise. This method + * will be called outside of the {@link #performFullBackup}/{@link #finishBackup} pair. + * + * <p>If this is not a suitable time for a backup, the transport should return a + * backoff delay, in milliseconds, after which the Backup Manager should try again. + * + * @return Zero if this is a suitable time for a backup pass, or a positive time delay + * in milliseconds to suggest deferring the backup pass for a while. + * + * @see #requestBackupTime() + */ + public long requestFullBackupTime() { + return 0; + } + + /** + * Begin the process of sending an application's full-data archive to the backend. + * The description of the package whose data will be delivered is provided, as well as + * the socket file descriptor on which the transport will receive the data itself. + * + * <p>If the package is not eligible for backup, the transport should return + * {@link BackupTransport#TRANSPORT_PACKAGE_REJECTED}. In this case the system will + * simply proceed with the next candidate if any, or finish the full backup operation + * if all apps have been processed. + * + * <p>After the transport returns {@link BackupTransport#TRANSPORT_OK} from this + * method, the OS will proceed to call {@link #sendBackupData()} one or more times + * to deliver the application's data as a streamed tarball. The transport should not + * read() from the socket except as instructed to via the {@link #sendBackupData(int)} + * method. + * + * <p>After all data has been delivered to the transport, the system will call + * {@link #finishBackup()}. At this point the transport should commit the data to + * its datastore, if appropriate, and close the socket that had been provided in + * {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)}. + * + * @param targetPackage The package whose data is to follow. + * @param socket The socket file descriptor through which the data will be provided. + * If the transport returns {@link #TRANSPORT_PACKAGE_REJECTED} here, it must still + * close this file descriptor now; otherwise it should be cached for use during + * succeeding calls to {@link #sendBackupData(int)}, and closed in response to + * {@link #finishBackup()}. + * @return TRANSPORT_PACKAGE_REJECTED to indicate that the stated application is not + * to be backed up; TRANSPORT_OK to indicate that the OS may proceed with delivering + * backup data; TRANSPORT_ERROR to indicate a fatal error condition that precludes + * performing a backup at this time. + */ + public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) { + return BackupTransport.TRANSPORT_PACKAGE_REJECTED; + } + + /** + * Tells the transport to read {@code numBytes} bytes of data from the socket file + * descriptor provided in the {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)} + * call, and deliver those bytes to the datastore. + * + * @param numBytes The number of bytes of tarball data available to be read from the + * socket. + * @return TRANSPORT_OK on successful processing of the data; TRANSPORT_ERROR to + * indicate a fatal error situation. If an error is returned, the system will + * call finishBackup() and stop attempting backups until after a backoff and retry + * interval. + */ + public int sendBackupData(int numBytes) { + return BackupTransport.TRANSPORT_ERROR; + } + /** * Bridge between the actual IBackupTransport implementation and the stable API. If the * binder interface needs to change, we use this layer to translate so that we can diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 44a6a5d..70668e1 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -433,6 +433,13 @@ interface IPackageManager { in VerificationParams verificationParams, in ContainerEncryptionParams encryptionParams); + void installPackageWithVerificationEncryptionAndAbiOverrideEtc(in Uri packageURI, + in IPackageInstallObserver observer, in IPackageInstallObserver2 observer2, + int flags, in String installerPackageName, + in VerificationParams verificationParams, + in ContainerEncryptionParams encryptionParams, + in String packageAbiOverride); + int installExistingPackageAsUser(String packageName, int userId); void verifyPendingInstall(int id, int verificationCode); diff --git a/core/java/android/hardware/hdmi/HdmiCec.java b/core/java/android/hardware/hdmi/HdmiCec.java index a71a74d..723eda1 100644 --- a/core/java/android/hardware/hdmi/HdmiCec.java +++ b/core/java/android/hardware/hdmi/HdmiCec.java @@ -194,6 +194,8 @@ public final class HdmiCec { DEVICE_RECORDER, // ADDR_RECORDER_3 DEVICE_TUNER, // ADDR_TUNER_4 DEVICE_PLAYBACK, // ADDR_PLAYBACK_3 + DEVICE_RESERVED, + DEVICE_RESERVED, DEVICE_TV, // ADDR_SPECIFIC_USE }; @@ -210,6 +212,8 @@ public final class HdmiCec { "Recorder_3", "Tuner_4", "Playback_3", + "Reserved_1", + "Reserved_2", "Secondary_TV", }; diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 2f2aba3..a48a388 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -40,6 +40,7 @@ import android.util.ArrayMap; import android.util.Log; import com.android.internal.telephony.ITelephony; +import com.android.internal.telephony.PhoneConstants; import com.android.internal.util.Protocol; import java.net.InetAddress; @@ -807,11 +808,34 @@ public class ConnectivityManager { * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api. */ public int startUsingNetworkFeature(int networkType, String feature) { - try { - return mService.startUsingNetworkFeature(networkType, feature, - new Binder()); - } catch (RemoteException e) { - return -1; + NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature); + if (netCap == null) { + Log.d(TAG, "Can't satisfy startUsingNetworkFeature for " + networkType + ", " + + feature); + return PhoneConstants.APN_REQUEST_FAILED; + } + + NetworkRequest request = null; + synchronized (sLegacyRequests) { + LegacyRequest l = sLegacyRequests.get(netCap); + if (l != null) { + Log.d(TAG, "renewing startUsingNetworkFeature request " + l.networkRequest); + renewRequestLocked(l); + if (l.currentNetwork != null) { + return PhoneConstants.APN_ALREADY_ACTIVE; + } else { + return PhoneConstants.APN_REQUEST_STARTED; + } + } + + request = requestNetworkForFeatureLocked(netCap); + } + if (request != null) { + Log.d(TAG, "starting startUsingNeworkFeature for request " + request); + return PhoneConstants.APN_REQUEST_STARTED; + } else { + Log.d(TAG, " request Failed"); + return PhoneConstants.APN_REQUEST_FAILED; } } @@ -831,11 +855,172 @@ public class ConnectivityManager { * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api. */ public int stopUsingNetworkFeature(int networkType, String feature) { - try { - return mService.stopUsingNetworkFeature(networkType, feature); - } catch (RemoteException e) { + NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature); + if (netCap == null) { + Log.d(TAG, "Can't satisfy stopUsingNetworkFeature for " + networkType + ", " + + feature); return -1; } + + NetworkRequest request = removeRequestForFeature(netCap); + if (request != null) { + Log.d(TAG, "stopUsingNetworkFeature for " + networkType + ", " + feature); + releaseNetworkRequest(request); + } + return 1; + } + + private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) { + if (networkType == TYPE_MOBILE) { + int cap = -1; + if ("enableMMS".equals(feature)) { + cap = NetworkCapabilities.NET_CAPABILITY_MMS; + } else if ("enableSUPL".equals(feature)) { + cap = NetworkCapabilities.NET_CAPABILITY_SUPL; + } else if ("enableDUN".equals(feature) || "enableDUNAlways".equals(feature)) { + cap = NetworkCapabilities.NET_CAPABILITY_DUN; + } else if ("enableHIPRI".equals(feature)) { + cap = NetworkCapabilities.NET_CAPABILITY_INTERNET; + } else if ("enableFOTA".equals(feature)) { + cap = NetworkCapabilities.NET_CAPABILITY_FOTA; + } else if ("enableIMS".equals(feature)) { + cap = NetworkCapabilities.NET_CAPABILITY_IMS; + } else if ("enableCBS".equals(feature)) { + cap = NetworkCapabilities.NET_CAPABILITY_CBS; + } else { + return null; + } + NetworkCapabilities netCap = new NetworkCapabilities(); + netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); + netCap.addNetworkCapability(cap); + return netCap; + } else if (networkType == TYPE_WIFI) { + if ("p2p".equals(feature)) { + NetworkCapabilities netCap = new NetworkCapabilities(); + netCap.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); + netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P); + return netCap; + } + } + return null; + } + + private int legacyTypeForNetworkCapabilities(NetworkCapabilities netCap) { + if (netCap == null) return TYPE_NONE; + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) { + return TYPE_MOBILE_CBS; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) { + return TYPE_MOBILE_IMS; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) { + return TYPE_MOBILE_FOTA; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) { + return TYPE_MOBILE_DUN; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) { + return TYPE_MOBILE_SUPL; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { + return TYPE_MOBILE_MMS; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { + return TYPE_MOBILE_HIPRI; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P)) { + return TYPE_WIFI_P2P; + } + return TYPE_NONE; + } + + private static class LegacyRequest { + NetworkCapabilities networkCapabilities; + NetworkRequest networkRequest; + int expireSequenceNumber; + Network currentNetwork; + int delay = -1; + NetworkCallbackListener networkCallbackListener = new NetworkCallbackListener() { + @Override + public void onAvailable(NetworkRequest request, Network network) { + currentNetwork = network; + Log.d(TAG, "startUsingNetworkFeature got Network:" + network); + network.bindProcessForHostResolution(); + } + @Override + public void onLost(NetworkRequest request, Network network) { + if (network.equals(currentNetwork)) { + currentNetwork = null; + network.unbindProcessForHostResolution(); + } + Log.d(TAG, "startUsingNetworkFeature lost Network:" + network); + } + }; + } + + private HashMap<NetworkCapabilities, LegacyRequest> sLegacyRequests = + new HashMap<NetworkCapabilities, LegacyRequest>(); + + private NetworkRequest findRequestForFeature(NetworkCapabilities netCap) { + synchronized (sLegacyRequests) { + LegacyRequest l = sLegacyRequests.get(netCap); + if (l != null) return l.networkRequest; + } + return null; + } + + private void renewRequestLocked(LegacyRequest l) { + l.expireSequenceNumber++; + Log.d(TAG, "renewing request to seqNum " + l.expireSequenceNumber); + sendExpireMsgForFeature(l.networkCapabilities, l.expireSequenceNumber, l.delay); + } + + private void expireRequest(NetworkCapabilities netCap, int sequenceNum) { + int ourSeqNum = -1; + synchronized (sLegacyRequests) { + LegacyRequest l = sLegacyRequests.get(netCap); + if (l == null) return; + ourSeqNum = l.expireSequenceNumber; + if (l.expireSequenceNumber == sequenceNum) { + releaseNetworkRequest(l.networkRequest); + sLegacyRequests.remove(netCap); + } + } + Log.d(TAG, "expireRequest with " + ourSeqNum + ", " + sequenceNum); + } + + private NetworkRequest requestNetworkForFeatureLocked(NetworkCapabilities netCap) { + int delay = -1; + int type = legacyTypeForNetworkCapabilities(netCap); + try { + delay = mService.getRestoreDefaultNetworkDelay(type); + } catch (RemoteException e) {} + LegacyRequest l = new LegacyRequest(); + l.networkCapabilities = netCap; + l.delay = delay; + l.expireSequenceNumber = 0; + l.networkRequest = sendRequestForNetwork(netCap, l.networkCallbackListener, 0, + REQUEST, type); + if (l.networkRequest == null) return null; + sLegacyRequests.put(netCap, l); + sendExpireMsgForFeature(netCap, l.expireSequenceNumber, delay); + return l.networkRequest; + } + + private void sendExpireMsgForFeature(NetworkCapabilities netCap, int seqNum, int delay) { + if (delay >= 0) { + Log.d(TAG, "sending expire msg with seqNum " + seqNum + " and delay " + delay); + Message msg = sCallbackHandler.obtainMessage(EXPIRE_LEGACY_REQUEST, seqNum, 0, netCap); + sCallbackHandler.sendMessageDelayed(msg, delay); + } + } + + private NetworkRequest removeRequestForFeature(NetworkCapabilities netCap) { + synchronized (sLegacyRequests) { + LegacyRequest l = sLegacyRequests.remove(netCap); + if (l == null) return null; + return l.networkRequest; + } } /** @@ -1782,8 +1967,10 @@ public class ConnectivityManager { public static final int CALLBACK_RELEASED = BASE + 8; /** @hide */ public static final int CALLBACK_EXIT = BASE + 9; + /** @hide obj = NetworkCapabilities, arg1 = seq number */ + private static final int EXPIRE_LEGACY_REQUEST = BASE + 10; - private static class CallbackHandler extends Handler { + private class CallbackHandler extends Handler { private final HashMap<NetworkRequest, NetworkCallbackListener>mCallbackMap; private final AtomicInteger mRefCount; private static final String TAG = "ConnectivityManager.CallbackHandler"; @@ -1903,6 +2090,10 @@ public class ConnectivityManager { getLooper().quit(); break; } + case EXPIRE_LEGACY_REQUEST: { + expireRequest((NetworkCapabilities)message.obj, message.arg1); + break; + } } } @@ -1954,8 +2145,9 @@ public class ConnectivityManager { private final static int LISTEN = 1; private final static int REQUEST = 2; - private NetworkRequest somethingForNetwork(NetworkCapabilities need, - NetworkCallbackListener networkCallbackListener, int timeoutSec, int action) { + private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, + NetworkCallbackListener networkCallbackListener, int timeoutSec, int action, + int legacyType) { NetworkRequest networkRequest = null; if (networkCallbackListener == null) { throw new IllegalArgumentException("null NetworkCallbackListener"); @@ -1968,7 +2160,7 @@ public class ConnectivityManager { new Binder()); } else { networkRequest = mService.requestNetwork(need, new Messenger(sCallbackHandler), - timeoutSec, new Binder()); + timeoutSec, new Binder(), legacyType); } if (networkRequest != null) { synchronized(sNetworkCallbackListener) { @@ -1998,7 +2190,7 @@ public class ConnectivityManager { */ public NetworkRequest requestNetwork(NetworkCapabilities need, NetworkCallbackListener networkCallbackListener) { - return somethingForNetwork(need, networkCallbackListener, 0, REQUEST); + return sendRequestForNetwork(need, networkCallbackListener, 0, REQUEST, TYPE_NONE); } /** @@ -2021,7 +2213,8 @@ public class ConnectivityManager { */ public NetworkRequest requestNetwork(NetworkCapabilities need, NetworkCallbackListener networkCallbackListener, int timeoutSec) { - return somethingForNetwork(need, networkCallbackListener, timeoutSec, REQUEST); + return sendRequestForNetwork(need, networkCallbackListener, timeoutSec, REQUEST, + TYPE_NONE); } /** @@ -2099,7 +2292,7 @@ public class ConnectivityManager { */ public NetworkRequest listenForNetwork(NetworkCapabilities need, NetworkCallbackListener networkCallbackListener) { - return somethingForNetwork(need, networkCallbackListener, 0, LISTEN); + return sendRequestForNetwork(need, networkCallbackListener, 0, LISTEN, TYPE_NONE); } /** diff --git a/core/java/android/net/ConnectivityServiceProtocol.java b/core/java/android/net/ConnectivityServiceProtocol.java deleted file mode 100644 index 74096b4..0000000 --- a/core/java/android/net/ConnectivityServiceProtocol.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 static com.android.internal.util.Protocol.BASE_CONNECTIVITY_SERVICE; - -/** - * Describes the Internal protocols used to communicate with ConnectivityService. - * @hide - */ -public class ConnectivityServiceProtocol { - - private static final int BASE = BASE_CONNECTIVITY_SERVICE; - - private ConnectivityServiceProtocol() {} - - /** - * This is a contract between ConnectivityService and various bearers. - * A NetworkFactory is an abstract entity that creates NetworkAgent objects. - * The bearers register with ConnectivityService using - * ConnectivityManager.registerNetworkFactory, where they pass in a Messenger - * to be used to deliver the following Messages. - */ - public static class NetworkFactoryProtocol { - private NetworkFactoryProtocol() {} - /** - * Pass a network request to the bearer. If the bearer believes it can - * satisfy the request it should connect to the network and create a - * NetworkAgent. Once the NetworkAgent is fully functional it will - * register itself with ConnectivityService using registerNetworkAgent. - * If the bearer cannot immediately satisfy the request (no network, - * user disabled the radio, lower-scored network) it should remember - * any NetworkRequests it may be able to satisfy in the future. It may - * disregard any that it will never be able to service, for example - * those requiring a different bearer. - * msg.obj = NetworkRequest - * msg.arg1 = score - the score of the any network currently satisfying this - * request. If this bearer knows in advance it cannot - * exceed this score it should not try to connect, holding the request - * for the future. - * Note that subsequent events may give a different (lower - * or higher) score for this request, transmitted to each - * NetworkFactory through additional CMD_REQUEST_NETWORK msgs - * with the same NetworkRequest but an updated score. - * Also, network conditions may change for this bearer - * allowing for a better score in the future. - */ - public static final int CMD_REQUEST_NETWORK = BASE; - - /** - * Cancel a network request - * msg.obj = NetworkRequest - */ - public static final int CMD_CANCEL_REQUEST = BASE + 1; - } -} diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index baec36a..5f1ff3e 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -158,7 +158,7 @@ interface IConnectivityManager in NetworkCapabilities nc, int score); NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, - in Messenger messenger, int timeoutSec, in IBinder binder); + in Messenger messenger, int timeoutSec, in IBinder binder, int legacy); NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities, in PendingIntent operation); @@ -170,4 +170,6 @@ interface IConnectivityManager in PendingIntent operation); void releaseNetworkRequest(in NetworkRequest networkRequest); + + int getRestoreDefaultNetworkDelay(int networkType); } diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 1c18ba5..7e8b1f1 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -24,85 +24,39 @@ import android.os.Messenger; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; -import android.util.SparseArray; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; +import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; /** - * A Utility class for handling NetworkRequests. - * - * Created by bearer-specific code to handle tracking requests, scores, - * network data and handle communicating with ConnectivityService. Two - * abstract methods: connect and disconnect are used to act on the - * underlying bearer code. Connect is called when we have a NetworkRequest - * and our score is better than the current handling network's score, while - * disconnect is used when ConnectivityService requests a disconnect. + * A Utility class for handling for communicating between bearer-specific + * code and ConnectivityService. * * A bearer may have more than one NetworkAgent if it can simultaneously * support separate networks (IMS / Internet / MMS Apns on cellular, or - * perhaps connections with different SSID or P2P for Wi-Fi). The bearer - * code should pass its NetworkAgents the NetworkRequests each NetworkAgent - * can handle, demultiplexing for different network types. The bearer code - * can also filter out requests it can never handle. + * perhaps connections with different SSID or P2P for Wi-Fi). * - * Each NetworkAgent needs to be given a score and NetworkCapabilities for - * their potential network. While disconnected, the NetworkAgent will check - * each time its score changes or a NetworkRequest changes to see if - * the NetworkAgent can provide a higher scored network for a NetworkRequest - * that the NetworkAgent's NetworkCapabilties can satisfy. This condition will - * trigger a connect request via connect(). After connection, connection data - * should be given to the NetworkAgent by the bearer, including LinkProperties - * NetworkCapabilties and NetworkInfo. After that the NetworkAgent will register - * with ConnectivityService and forward the data on. * @hide */ public abstract class NetworkAgent extends Handler { - private final SparseArray<NetworkRequestAndScore> mNetworkRequests = new SparseArray<>(); - private boolean mConnectionRequested = false; - - private AsyncChannel mAsyncChannel; + private volatile AsyncChannel mAsyncChannel; private final String LOG_TAG; private static final boolean DBG = true; private static final boolean VDBG = true; - // TODO - this class shouldn't cache data or it runs the risk of getting out of sync - // Make the API require each of these when any is updated so we have the data we need, - // without caching. - private LinkProperties mLinkProperties; - private NetworkInfo mNetworkInfo; - private NetworkCapabilities mNetworkCapabilities; - private int mNetworkScore; - private boolean mRegistered = false; private final Context mContext; - private AtomicBoolean mHasRequests = new AtomicBoolean(false); - - // TODO - add a name member for logging purposes. - - protected final Object mLockObj = new Object(); - + private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>(); private static final int BASE = Protocol.BASE_NETWORK_AGENT; /** - * Sent by self to queue up a new/modified request. - * obj = NetworkRequestAndScore - */ - private static final int CMD_ADD_REQUEST = BASE + 1; - - /** - * Sent by self to queue up the removal of a request. - * obj = NetworkRequest - */ - private static final int CMD_REMOVE_REQUEST = BASE + 2; - - /** * Sent by ConnectivityService to the NetworkAgent to inform it of * suspected connectivity problems on its network. The NetworkAgent * should take steps to verify and correct connectivity. */ - public static final int CMD_SUSPECT_BAD = BASE + 3; + public static final int CMD_SUSPECT_BAD = BASE; /** * Sent by the NetworkAgent (note the EVENT vs CMD prefix) to @@ -110,84 +64,63 @@ public abstract class NetworkAgent extends Handler { * Sent when the NetworkInfo changes, mainly due to change of state. * obj = NetworkInfo */ - public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 4; + public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1; /** * Sent by the NetworkAgent to ConnectivityService to pass the current * NetworkCapabilties. * obj = NetworkCapabilities */ - public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 5; + public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2; /** * Sent by the NetworkAgent to ConnectivityService to pass the current * NetworkProperties. * obj = NetworkProperties */ - public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 6; + public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3; /** * Sent by the NetworkAgent to ConnectivityService to pass the current * network score. - * arg1 = network score int + * obj = network score Integer */ - public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 7; + public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4; - public NetworkAgent(Looper looper, Context context, String logTag) { + public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, + NetworkCapabilities nc, LinkProperties lp, int score) { super(looper); LOG_TAG = logTag; mContext = context; - } - - /** - * When conditions are right, register with ConnectivityService. - * Connditions include having a well defined network and a request - * that justifies it. The NetworkAgent will remain registered until - * disconnected. - * TODO - this should have all data passed in rather than caching - */ - private void registerSelf() { - synchronized(mLockObj) { - if (!mRegistered && mConnectionRequested && - mNetworkInfo != null && mNetworkInfo.isConnected() && - mNetworkCapabilities != null && - mLinkProperties != null && - mNetworkScore != 0) { - if (DBG) log("Registering NetworkAgent"); - mRegistered = true; - ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( - Context.CONNECTIVITY_SERVICE); - cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(mNetworkInfo), - new LinkProperties(mLinkProperties), - new NetworkCapabilities(mNetworkCapabilities), mNetworkScore); - } else if (DBG && !mRegistered) { - String err = "Not registering due to "; - if (mConnectionRequested == false) err += "no Connect requested "; - if (mNetworkInfo == null) err += "null NetworkInfo "; - if (mNetworkInfo != null && mNetworkInfo.isConnected() == false) { - err += "NetworkInfo disconnected "; - } - if (mLinkProperties == null) err += "null LinkProperties "; - if (mNetworkCapabilities == null) err += "null NetworkCapabilities "; - if (mNetworkScore == 0) err += "null NetworkScore"; - log(err); - } + if (ni == null || nc == null || lp == null) { + throw new IllegalArgumentException(); } + + if (DBG) log("Registering NetworkAgent"); + ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( + Context.CONNECTIVITY_SERVICE); + cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), + new LinkProperties(lp), new NetworkCapabilities(nc), score); } @Override public void handleMessage(Message msg) { switch (msg.what) { case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { - synchronized (mLockObj) { - if (mAsyncChannel != null) { - log("Received new connection while already connected!"); - } else { - if (DBG) log("NetworkAgent fully connected"); - mAsyncChannel = new AsyncChannel(); - mAsyncChannel.connected(null, this, msg.replyTo); - mAsyncChannel.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, - AsyncChannel.STATUS_SUCCESSFUL); + if (mAsyncChannel != null) { + log("Received new connection while already connected!"); + } else { + if (DBG) log("NetworkAgent fully connected"); + AsyncChannel ac = new AsyncChannel(); + ac.connected(null, this, msg.replyTo); + ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, + AsyncChannel.STATUS_SUCCESSFUL); + synchronized (mPreConnectedQueue) { + mAsyncChannel = ac; + for (Message m : mPreConnectedQueue) { + ac.sendMessage(m); + } + mPreConnectedQueue.clear(); } } break; @@ -199,213 +132,69 @@ public abstract class NetworkAgent extends Handler { } case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { if (DBG) log("NetworkAgent channel lost"); - disconnect(); - clear(); + // let the client know CS is done with us. + unwanted(); + synchronized (mPreConnectedQueue) { + mAsyncChannel = null; + } break; } case CMD_SUSPECT_BAD: { log("Unhandled Message " + msg); break; } - case CMD_ADD_REQUEST: { - handleAddRequest(msg); - break; - } - case CMD_REMOVE_REQUEST: { - handleRemoveRequest(msg); - break; - } - } - } - - private void clear() { - synchronized(mLockObj) { - mNetworkRequests.clear(); - mHasRequests.set(false); - mConnectionRequested = false; - mAsyncChannel = null; - mRegistered = false; - } - } - - private static class NetworkRequestAndScore { - NetworkRequest req; - int score; - - NetworkRequestAndScore(NetworkRequest networkRequest, int score) { - req = networkRequest; - this.score = score; } } - private void handleAddRequest(Message msg) { - NetworkRequestAndScore n = (NetworkRequestAndScore)msg.obj; - // replaces old request, updating score - mNetworkRequests.put(n.req.requestId, n); - mHasRequests.set(true); - evalScores(); - } - - private void handleRemoveRequest(Message msg) { - NetworkRequest networkRequest = (NetworkRequest)msg.obj; - - if (mNetworkRequests.get(networkRequest.requestId) != null) { - mNetworkRequests.remove(networkRequest.requestId); - if (mNetworkRequests.size() == 0) mHasRequests.set(false); - evalScores(); - } - } - - /** - * Called to go through our list of requests and see if we're - * good enough to try connecting, or if we have gotten worse and - * need to disconnect. - * - * Once we are registered, does nothing: we disconnect when requested via - * CMD_CHANNEL_DISCONNECTED, generated by either a loss of connection - * between modules (bearer or ConnectivityService dies) or more commonly - * when the NetworkInfo reports to ConnectivityService it is disconnected. - */ - private void evalScores() { - synchronized(mLockObj) { - if (mRegistered) { - if (VDBG) log("evalScores - already connected - size=" + mNetworkRequests.size()); - // already trying - return; - } - if (VDBG) log("evalScores!"); - for (int i=0; i < mNetworkRequests.size(); i++) { - int score = mNetworkRequests.valueAt(i).score; - if (VDBG) log(" checking request Min " + score + " vs my score " + mNetworkScore); - if (score < mNetworkScore) { - // have a request that has a lower scored network servicing it - // (or no network) than we could provide, so let's connect! - mConnectionRequested = true; - connect(); - return; - } - } - // Our score is not high enough to satisfy any current request. - // This can happen if our score goes down after a connection is - // requested but before we actually connect. In this case, disconnect - // rather than continue trying - there's no point connecting if we know - // we'll just be torn down as soon as we do. - if (mConnectionRequested) { - mConnectionRequested = false; - disconnect(); + private void queueOrSendMessage(int what, Object obj) { + synchronized (mPreConnectedQueue) { + if (mAsyncChannel != null) { + mAsyncChannel.sendMessage(what, obj); + } else { + Message msg = Message.obtain(); + msg.what = what; + msg.obj = obj; + mPreConnectedQueue.add(msg); } } } - public void addNetworkRequest(NetworkRequest networkRequest, int score) { - if (DBG) log("adding NetworkRequest " + networkRequest + " with score " + score); - sendMessage(obtainMessage(CMD_ADD_REQUEST, - new NetworkRequestAndScore(networkRequest, score))); - } - - public void removeNetworkRequest(NetworkRequest networkRequest) { - if (DBG) log("removing NetworkRequest " + networkRequest); - sendMessage(obtainMessage(CMD_REMOVE_REQUEST, networkRequest)); - } - /** * Called by the bearer code when it has new LinkProperties data. - * If we're a registered NetworkAgent, this new data will get forwarded on, - * otherwise we store a copy in anticipation of registering. This call - * may also prompt registration if it causes the NetworkAgent to meet - * the conditions (fully configured, connected, satisfys a request and - * has sufficient score). */ public void sendLinkProperties(LinkProperties linkProperties) { - linkProperties = new LinkProperties(linkProperties); - synchronized(mLockObj) { - mLinkProperties = linkProperties; - if (mAsyncChannel != null) { - mAsyncChannel.sendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, linkProperties); - } else { - registerSelf(); - } - } + queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties)); } /** * Called by the bearer code when it has new NetworkInfo data. - * If we're a registered NetworkAgent, this new data will get forwarded on, - * otherwise we store a copy in anticipation of registering. This call - * may also prompt registration if it causes the NetworkAgent to meet - * the conditions (fully configured, connected, satisfys a request and - * has sufficient score). */ public void sendNetworkInfo(NetworkInfo networkInfo) { - networkInfo = new NetworkInfo(networkInfo); - synchronized(mLockObj) { - mNetworkInfo = networkInfo; - if (mAsyncChannel != null) { - mAsyncChannel.sendMessage(EVENT_NETWORK_INFO_CHANGED, networkInfo); - } else { - registerSelf(); - } - } + queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo)); } /** * Called by the bearer code when it has new NetworkCapabilities data. - * If we're a registered NetworkAgent, this new data will get forwarded on, - * otherwise we store a copy in anticipation of registering. This call - * may also prompt registration if it causes the NetworkAgent to meet - * the conditions (fully configured, connected, satisfys a request and - * has sufficient score). - * Note that if these capabilities make the network non-useful, - * ConnectivityServce will tear this network down. */ public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) { - networkCapabilities = new NetworkCapabilities(networkCapabilities); - synchronized(mLockObj) { - mNetworkCapabilities = networkCapabilities; - if (mAsyncChannel != null) { - mAsyncChannel.sendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED, networkCapabilities); - } else { - registerSelf(); - } - } - } - - public NetworkCapabilities getNetworkCapabilities() { - synchronized(mLockObj) { - return new NetworkCapabilities(mNetworkCapabilities); - } + queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED, + new NetworkCapabilities(networkCapabilities)); } /** * Called by the bearer code when it has a new score for this network. - * If we're a registered NetworkAgent, this new data will get forwarded on, - * otherwise we store a copy. */ - public synchronized void sendNetworkScore(int score) { - synchronized(mLockObj) { - mNetworkScore = score; - evalScores(); - if (mAsyncChannel != null) { - mAsyncChannel.sendMessage(EVENT_NETWORK_SCORE_CHANGED, mNetworkScore); - } else { - registerSelf(); - } - } - } - - public boolean hasRequests() { - return mHasRequests.get(); + public void sendNetworkScore(int score) { + queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score)); } - public boolean isConnectionRequested() { - synchronized(mLockObj) { - return mConnectionRequested; - } - } - - - abstract protected void connect(); - abstract protected void disconnect(); + /** + * Called when ConnectivityService has indicated they no longer want this network. + * The parent factory should (previously) have received indication of the change + * as well, either canceling NetworkRequests or altering their score such that this + * network won't be immediately requested again. + */ + abstract protected void unwanted(); protected void log(String s) { Log.d(LOG_TAG, "NetworkAgent: " + s); diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java new file mode 100644 index 0000000..a20e8e7 --- /dev/null +++ b/core/java/android/net/NetworkFactory.java @@ -0,0 +1,275 @@ +/* + * 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.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; +import android.util.SparseArray; + +import com.android.internal.util.AsyncChannel; +import com.android.internal.util.Protocol; + +/** + * A NetworkFactory is an entity that creates NetworkAgent objects. + * The bearers register with ConnectivityService using {@link #register} and + * their factory will start receiving scored NetworkRequests. NetworkRequests + * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by + * overridden function. All of these can be dynamic - changing NetworkCapabilities + * or score forces re-evaluation of all current requests. + * + * If any requests pass the filter some overrideable functions will be called. + * If the bearer only cares about very simple start/stopNetwork callbacks, those + * functions can be overridden. If the bearer needs more interaction, it can + * override addNetworkRequest and removeNetworkRequest which will give it each + * request that passes their current filters. + * @hide + **/ +public class NetworkFactory extends Handler { + private static final boolean DBG = true; + + private static final int BASE = Protocol.BASE_NETWORK_FACTORY; + /** + * Pass a network request to the bearer. If the bearer believes it can + * satisfy the request it should connect to the network and create a + * NetworkAgent. Once the NetworkAgent is fully functional it will + * register itself with ConnectivityService using registerNetworkAgent. + * If the bearer cannot immediately satisfy the request (no network, + * user disabled the radio, lower-scored network) it should remember + * any NetworkRequests it may be able to satisfy in the future. It may + * disregard any that it will never be able to service, for example + * those requiring a different bearer. + * msg.obj = NetworkRequest + * msg.arg1 = score - the score of the any network currently satisfying this + * request. If this bearer knows in advance it cannot + * exceed this score it should not try to connect, holding the request + * for the future. + * Note that subsequent events may give a different (lower + * or higher) score for this request, transmitted to each + * NetworkFactory through additional CMD_REQUEST_NETWORK msgs + * with the same NetworkRequest but an updated score. + * Also, network conditions may change for this bearer + * allowing for a better score in the future. + */ + public static final int CMD_REQUEST_NETWORK = BASE; + + /** + * Cancel a network request + * msg.obj = NetworkRequest + */ + public static final int CMD_CANCEL_REQUEST = BASE + 1; + + /** + * Internally used to set our best-guess score. + * msg.arg1 = new score + */ + private static final int CMD_SET_SCORE = BASE + 2; + + /** + * Internally used to set our current filter for coarse bandwidth changes with + * technology changes. + * msg.obj = new filter + */ + private static final int CMD_SET_FILTER = BASE + 3; + + private final Context mContext; + private final String LOG_TAG; + + private final SparseArray<NetworkRequestInfo> mNetworkRequests = + new SparseArray<NetworkRequestInfo>(); + + private int mScore; + private NetworkCapabilities mCapabilityFilter; + + private int mRefCount = 0; + private Messenger mMessenger = null; + + public NetworkFactory(Looper looper, Context context, String logTag, + NetworkCapabilities filter) { + super(looper); + LOG_TAG = logTag; + mContext = context; + mCapabilityFilter = filter; + } + + public void register() { + if (DBG) log("Registering NetworkFactory"); + if (mMessenger == null) { + mMessenger = new Messenger(this); + ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG); + } + } + + public void unregister() { + if (DBG) log("Unregistering NetworkFactory"); + if (mMessenger != null) { + ConnectivityManager.from(mContext).unregisterNetworkFactory(mMessenger); + mMessenger = null; + } + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case CMD_REQUEST_NETWORK: { + handleAddRequest((NetworkRequest)msg.obj, msg.arg1); + break; + } + case CMD_CANCEL_REQUEST: { + handleRemoveRequest((NetworkRequest) msg.obj); + break; + } + case CMD_SET_SCORE: { + handleSetScore(msg.arg1); + break; + } + case CMD_SET_FILTER: { + handleSetFilter((NetworkCapabilities) msg.obj); + break; + } + } + } + + private class NetworkRequestInfo { + public final NetworkRequest request; + public int score; + public boolean requested; // do we have a request outstanding, limited by score + + public NetworkRequestInfo(NetworkRequest request, int score) { + this.request = request; + this.score = score; + this.requested = false; + } + } + + private void handleAddRequest(NetworkRequest request, int score) { + NetworkRequestInfo n = mNetworkRequests.get(request.requestId); + if (n == null) { + n = new NetworkRequestInfo(request, score); + mNetworkRequests.put(n.request.requestId, n); + } else { + n.score = score; + } + if (DBG) log("got request " + request + " with score " + score); + if (DBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter); + + evalRequest(n); + } + + private void handleRemoveRequest(NetworkRequest request) { + NetworkRequestInfo n = mNetworkRequests.get(request.requestId); + if (n != null && n.requested) { + mNetworkRequests.remove(request.requestId); + releaseNetworkFor(n.request); + } + } + + private void handleSetScore(int score) { + mScore = score; + evalRequests(); + } + + private void handleSetFilter(NetworkCapabilities netCap) { + mCapabilityFilter = netCap; + evalRequests(); + } + + /** + * Overridable function to provide complex filtering. + * Called for every request every time a new NetworkRequest is seen + * and whenever the filterScore or filterNetworkCapabilities change. + * + * acceptRequest can be overriden to provide complex filter behavior + * for the incoming requests + * + * For output, this class will call {@link #needNetworkFor} and + * {@link #releaseNetworkFor} for every request that passes the filters. + * If you don't need to see every request, you can leave the base + * implementations of those two functions and instead override + * {@link #startNetwork} and {@link #stopNetwork}. + * + * If you want to see every score fluctuation on every request, set + * your score filter to a very high number and watch {@link #needNetworkFor}. + * + * @return {@code true} to accept the request. + */ + public boolean acceptRequest(NetworkRequest request, int score) { + return true; + } + + private void evalRequest(NetworkRequestInfo n) { + if (n.requested == false && n.score < mScore && + n.request.networkCapabilities.satisfiedByNetworkCapabilities( + mCapabilityFilter) && acceptRequest(n.request, n.score)) { + needNetworkFor(n.request, n.score); + n.requested = true; + } else if (n.requested == true && + (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities( + mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) { + releaseNetworkFor(n.request); + n.requested = false; + } + } + + private void evalRequests() { + for (int i = 0; i < mNetworkRequests.size(); i++) { + NetworkRequestInfo n = mNetworkRequests.valueAt(i); + + evalRequest(n); + } + } + + // override to do simple mode (request independent) + protected void startNetwork() { } + protected void stopNetwork() { } + + // override to do fancier stuff + protected void needNetworkFor(NetworkRequest networkRequest, int score) { + if (++mRefCount == 1) startNetwork(); + } + + protected void releaseNetworkFor(NetworkRequest networkRequest) { + if (--mRefCount == 0) stopNetwork(); + } + + + public void addNetworkRequest(NetworkRequest networkRequest, int score) { + sendMessage(obtainMessage(CMD_REQUEST_NETWORK, + new NetworkRequestInfo(networkRequest, score))); + } + + public void removeNetworkRequest(NetworkRequest networkRequest) { + sendMessage(obtainMessage(CMD_CANCEL_REQUEST, networkRequest)); + } + + public void setScoreFilter(int score) { + sendMessage(obtainMessage(CMD_SET_SCORE, score, 0)); + } + + public void setCapabilityFilter(NetworkCapabilities netCap) { + sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap))); + } + + protected void log(String s) { + Log.d(LOG_TAG, s); + } +} diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java index 9e656ee..d279412 100644 --- a/core/java/android/net/NetworkInfo.java +++ b/core/java/android/net/NetworkInfo.java @@ -188,6 +188,15 @@ public class NetworkInfo implements Parcelable { } /** + * @hide + */ + public void setType(int type) { + synchronized (this) { + mNetworkType = type; + } + } + + /** * Return a network-type-specific integer describing the subtype * of the network. * @return the network subtype @@ -198,7 +207,10 @@ public class NetworkInfo implements Parcelable { } } - void setSubtype(int subtype, String subtypeName) { + /** + * @hide + */ + public void setSubtype(int subtype, String subtypeName) { synchronized (this) { mSubtype = subtype; mSubtypeName = subtypeName; diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 480cb05..47377e9 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -47,19 +47,19 @@ public class NetworkRequest implements Parcelable { public final int requestId; /** - * Set for legacy requests and the default. + * Set for legacy requests and the default. Set to TYPE_NONE for none. * Causes CONNECTIVITY_ACTION broadcasts to be sent. * @hide */ - public final boolean needsBroadcasts; + public final int legacyType; /** * @hide */ - public NetworkRequest(NetworkCapabilities nc, boolean needsBroadcasts, int rId) { + public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId) { requestId = rId; networkCapabilities = nc; - this.needsBroadcasts = needsBroadcasts; + this.legacyType = legacyType; } /** @@ -68,7 +68,7 @@ public class NetworkRequest implements Parcelable { public NetworkRequest(NetworkRequest that) { networkCapabilities = new NetworkCapabilities(that.networkCapabilities); requestId = that.requestId; - needsBroadcasts = that.needsBroadcasts; + this.legacyType = that.legacyType; } // implement the Parcelable interface @@ -77,16 +77,16 @@ public class NetworkRequest implements Parcelable { } public void writeToParcel(Parcel dest, int flags) { dest.writeParcelable(networkCapabilities, flags); - dest.writeInt(needsBroadcasts ? 1 : 0); + dest.writeInt(legacyType); dest.writeInt(requestId); } public static final Creator<NetworkRequest> CREATOR = new Creator<NetworkRequest>() { public NetworkRequest createFromParcel(Parcel in) { NetworkCapabilities nc = (NetworkCapabilities)in.readParcelable(null); - boolean needsBroadcasts = (in.readInt() == 1); + int legacyType = in.readInt(); int requestId = in.readInt(); - NetworkRequest result = new NetworkRequest(nc, needsBroadcasts, requestId); + NetworkRequest result = new NetworkRequest(nc, legacyType, requestId); return result; } public NetworkRequest[] newArray(int size) { @@ -95,14 +95,14 @@ public class NetworkRequest implements Parcelable { }; public String toString() { - return "NetworkRequest [ id=" + requestId + ", needsBroadcasts=" + needsBroadcasts + + return "NetworkRequest [ id=" + requestId + ", legacyType=" + legacyType + ", " + networkCapabilities.toString() + " ]"; } public boolean equals(Object obj) { if (obj instanceof NetworkRequest == false) return false; NetworkRequest that = (NetworkRequest)obj; - return (that.needsBroadcasts == this.needsBroadcasts && + return (that.legacyType == this.legacyType && that.requestId == this.requestId && ((that.networkCapabilities == null && this.networkCapabilities == null) || (that.networkCapabilities != null && @@ -110,7 +110,7 @@ public class NetworkRequest implements Parcelable { } public int hashCode() { - return requestId + (needsBroadcasts ? 1013 : 2026) + + return requestId + (legacyType * 1013) + (networkCapabilities.hashCode() * 1051); } } diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index e918119..4979059 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -219,6 +219,15 @@ public final class RenderNodeAnimator extends Animator { return mTarget; } + /** + * WARNING: May only be called once!!! + * TODO: Fix above -_- + */ + public void setStartValue(float startValue) { + checkMutable(); + nSetStartValue(mNativePtr.get(), startValue); + } + @Override public void setStartDelay(long startDelay) { checkMutable(); @@ -282,11 +291,12 @@ public final class RenderNodeAnimator extends Animator { } private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis, - int property, float deltaValue); + int property, float finalValue); private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis, - long canvasProperty, float deltaValue); + long canvasProperty, float finalValue); private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis, - long canvasProperty, int paintField, float deltaValue); + long canvasProperty, int paintField, float finalValue); + private static native void nSetStartValue(long nativePtr, float startValue); private static native void nSetDuration(long nativePtr, long duration); private static native long nGetDuration(long nativePtr); private static native void nSetStartDelay(long nativePtr, long startDelay); |