Merge "API changes for DownloadManager and JobScheduler." into nyc-dev
This commit is contained in:
@@ -4359,6 +4359,8 @@ package android.app {
|
|||||||
method public android.app.DownloadManager.Request setDestinationUri(android.net.Uri);
|
method public android.app.DownloadManager.Request setDestinationUri(android.net.Uri);
|
||||||
method public android.app.DownloadManager.Request setMimeType(java.lang.String);
|
method public android.app.DownloadManager.Request setMimeType(java.lang.String);
|
||||||
method public android.app.DownloadManager.Request setNotificationVisibility(int);
|
method public android.app.DownloadManager.Request setNotificationVisibility(int);
|
||||||
|
method public android.app.DownloadManager.Request setRequiresCharging(boolean);
|
||||||
|
method public android.app.DownloadManager.Request setRequiresDeviceIdle(boolean);
|
||||||
method public deprecated android.app.DownloadManager.Request setShowRunningNotification(boolean);
|
method public deprecated android.app.DownloadManager.Request setShowRunningNotification(boolean);
|
||||||
method public android.app.DownloadManager.Request setTitle(java.lang.CharSequence);
|
method public android.app.DownloadManager.Request setTitle(java.lang.CharSequence);
|
||||||
method public android.app.DownloadManager.Request setVisibleInDownloadsUi(boolean);
|
method public android.app.DownloadManager.Request setVisibleInDownloadsUi(boolean);
|
||||||
@@ -6335,6 +6337,7 @@ package android.app.job {
|
|||||||
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
|
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
|
||||||
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
|
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
|
||||||
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
|
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
|
||||||
|
field public static final int NETWORK_TYPE_NOT_ROAMING = 3; // 0x3
|
||||||
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
|
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6382,6 +6385,7 @@ package android.app.job {
|
|||||||
method public abstract void cancel(int);
|
method public abstract void cancel(int);
|
||||||
method public abstract void cancelAll();
|
method public abstract void cancelAll();
|
||||||
method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
|
method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
|
||||||
|
method public abstract android.app.job.JobInfo getPendingJob(int);
|
||||||
method public abstract int schedule(android.app.job.JobInfo);
|
method public abstract int schedule(android.app.job.JobInfo);
|
||||||
field public static final int RESULT_FAILURE = 0; // 0x0
|
field public static final int RESULT_FAILURE = 0; // 0x0
|
||||||
field public static final int RESULT_SUCCESS = 1; // 0x1
|
field public static final int RESULT_SUCCESS = 1; // 0x1
|
||||||
@@ -23757,8 +23761,10 @@ package android.net {
|
|||||||
method public boolean isConnected();
|
method public boolean isConnected();
|
||||||
method public boolean isConnectedOrConnecting();
|
method public boolean isConnectedOrConnecting();
|
||||||
method public boolean isFailover();
|
method public boolean isFailover();
|
||||||
|
method public boolean isMetered();
|
||||||
method public boolean isRoaming();
|
method public boolean isRoaming();
|
||||||
method public void writeToParcel(android.os.Parcel, int);
|
method public void writeToParcel(android.os.Parcel, int);
|
||||||
|
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class NetworkInfo.DetailedState extends java.lang.Enum {
|
public static final class NetworkInfo.DetailedState extends java.lang.Enum {
|
||||||
|
|||||||
@@ -4502,6 +4502,8 @@ package android.app {
|
|||||||
method public android.app.DownloadManager.Request setDestinationUri(android.net.Uri);
|
method public android.app.DownloadManager.Request setDestinationUri(android.net.Uri);
|
||||||
method public android.app.DownloadManager.Request setMimeType(java.lang.String);
|
method public android.app.DownloadManager.Request setMimeType(java.lang.String);
|
||||||
method public android.app.DownloadManager.Request setNotificationVisibility(int);
|
method public android.app.DownloadManager.Request setNotificationVisibility(int);
|
||||||
|
method public android.app.DownloadManager.Request setRequiresCharging(boolean);
|
||||||
|
method public android.app.DownloadManager.Request setRequiresDeviceIdle(boolean);
|
||||||
method public deprecated android.app.DownloadManager.Request setShowRunningNotification(boolean);
|
method public deprecated android.app.DownloadManager.Request setShowRunningNotification(boolean);
|
||||||
method public android.app.DownloadManager.Request setTitle(java.lang.CharSequence);
|
method public android.app.DownloadManager.Request setTitle(java.lang.CharSequence);
|
||||||
method public android.app.DownloadManager.Request setVisibleInDownloadsUi(boolean);
|
method public android.app.DownloadManager.Request setVisibleInDownloadsUi(boolean);
|
||||||
@@ -6614,6 +6616,7 @@ package android.app.job {
|
|||||||
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
|
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
|
||||||
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
|
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
|
||||||
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
|
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
|
||||||
|
field public static final int NETWORK_TYPE_NOT_ROAMING = 3; // 0x3
|
||||||
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
|
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6661,6 +6664,7 @@ package android.app.job {
|
|||||||
method public abstract void cancel(int);
|
method public abstract void cancel(int);
|
||||||
method public abstract void cancelAll();
|
method public abstract void cancelAll();
|
||||||
method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
|
method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
|
||||||
|
method public abstract android.app.job.JobInfo getPendingJob(int);
|
||||||
method public abstract int schedule(android.app.job.JobInfo);
|
method public abstract int schedule(android.app.job.JobInfo);
|
||||||
field public static final int RESULT_FAILURE = 0; // 0x0
|
field public static final int RESULT_FAILURE = 0; // 0x0
|
||||||
field public static final int RESULT_SUCCESS = 1; // 0x1
|
field public static final int RESULT_SUCCESS = 1; // 0x1
|
||||||
@@ -25584,8 +25588,10 @@ package android.net {
|
|||||||
method public boolean isConnected();
|
method public boolean isConnected();
|
||||||
method public boolean isConnectedOrConnecting();
|
method public boolean isConnectedOrConnecting();
|
||||||
method public boolean isFailover();
|
method public boolean isFailover();
|
||||||
|
method public boolean isMetered();
|
||||||
method public boolean isRoaming();
|
method public boolean isRoaming();
|
||||||
method public void writeToParcel(android.os.Parcel, int);
|
method public void writeToParcel(android.os.Parcel, int);
|
||||||
|
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class NetworkInfo.DetailedState extends java.lang.Enum {
|
public static final class NetworkInfo.DetailedState extends java.lang.Enum {
|
||||||
|
|||||||
@@ -4359,6 +4359,8 @@ package android.app {
|
|||||||
method public android.app.DownloadManager.Request setDestinationUri(android.net.Uri);
|
method public android.app.DownloadManager.Request setDestinationUri(android.net.Uri);
|
||||||
method public android.app.DownloadManager.Request setMimeType(java.lang.String);
|
method public android.app.DownloadManager.Request setMimeType(java.lang.String);
|
||||||
method public android.app.DownloadManager.Request setNotificationVisibility(int);
|
method public android.app.DownloadManager.Request setNotificationVisibility(int);
|
||||||
|
method public android.app.DownloadManager.Request setRequiresCharging(boolean);
|
||||||
|
method public android.app.DownloadManager.Request setRequiresDeviceIdle(boolean);
|
||||||
method public deprecated android.app.DownloadManager.Request setShowRunningNotification(boolean);
|
method public deprecated android.app.DownloadManager.Request setShowRunningNotification(boolean);
|
||||||
method public android.app.DownloadManager.Request setTitle(java.lang.CharSequence);
|
method public android.app.DownloadManager.Request setTitle(java.lang.CharSequence);
|
||||||
method public android.app.DownloadManager.Request setVisibleInDownloadsUi(boolean);
|
method public android.app.DownloadManager.Request setVisibleInDownloadsUi(boolean);
|
||||||
@@ -6339,6 +6341,7 @@ package android.app.job {
|
|||||||
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
|
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
|
||||||
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
|
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
|
||||||
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
|
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
|
||||||
|
field public static final int NETWORK_TYPE_NOT_ROAMING = 3; // 0x3
|
||||||
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
|
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6386,6 +6389,7 @@ package android.app.job {
|
|||||||
method public abstract void cancel(int);
|
method public abstract void cancel(int);
|
||||||
method public abstract void cancelAll();
|
method public abstract void cancelAll();
|
||||||
method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
|
method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
|
||||||
|
method public abstract android.app.job.JobInfo getPendingJob(int);
|
||||||
method public abstract int schedule(android.app.job.JobInfo);
|
method public abstract int schedule(android.app.job.JobInfo);
|
||||||
field public static final int RESULT_FAILURE = 0; // 0x0
|
field public static final int RESULT_FAILURE = 0; // 0x0
|
||||||
field public static final int RESULT_SUCCESS = 1; // 0x1
|
field public static final int RESULT_SUCCESS = 1; // 0x1
|
||||||
@@ -23825,8 +23829,10 @@ package android.net {
|
|||||||
method public boolean isConnected();
|
method public boolean isConnected();
|
||||||
method public boolean isConnectedOrConnecting();
|
method public boolean isConnectedOrConnecting();
|
||||||
method public boolean isFailover();
|
method public boolean isFailover();
|
||||||
|
method public boolean isMetered();
|
||||||
method public boolean isRoaming();
|
method public boolean isRoaming();
|
||||||
method public void writeToParcel(android.os.Parcel, int);
|
method public void writeToParcel(android.os.Parcel, int);
|
||||||
|
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class NetworkInfo.DetailedState extends java.lang.Enum {
|
public static final class NetworkInfo.DetailedState extends java.lang.Enum {
|
||||||
|
|||||||
@@ -370,6 +370,7 @@ public class DownloadManager {
|
|||||||
* {@link ConnectivityManager#TYPE_BLUETOOTH}.
|
* {@link ConnectivityManager#TYPE_BLUETOOTH}.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static final int NETWORK_BLUETOOTH = 1 << 2;
|
public static final int NETWORK_BLUETOOTH = 1 << 2;
|
||||||
|
|
||||||
private Uri mUri;
|
private Uri mUri;
|
||||||
@@ -381,6 +382,7 @@ public class DownloadManager {
|
|||||||
private int mAllowedNetworkTypes = ~0; // default to all network types allowed
|
private int mAllowedNetworkTypes = ~0; // default to all network types allowed
|
||||||
private boolean mRoamingAllowed = true;
|
private boolean mRoamingAllowed = true;
|
||||||
private boolean mMeteredAllowed = true;
|
private boolean mMeteredAllowed = true;
|
||||||
|
private int mFlags = 0;
|
||||||
private boolean mIsVisibleInDownloadsUi = true;
|
private boolean mIsVisibleInDownloadsUi = true;
|
||||||
private boolean mScannable = false;
|
private boolean mScannable = false;
|
||||||
private boolean mUseSystemCache = false;
|
private boolean mUseSystemCache = false;
|
||||||
@@ -669,6 +671,10 @@ public class DownloadManager {
|
|||||||
* By default, all network types are allowed. Consider using
|
* By default, all network types are allowed. Consider using
|
||||||
* {@link #setAllowedOverMetered(boolean)} instead, since it's more
|
* {@link #setAllowedOverMetered(boolean)} instead, since it's more
|
||||||
* flexible.
|
* flexible.
|
||||||
|
* <p>
|
||||||
|
* As of {@link android.os.Build.VERSION_CODES#N}, setting only the
|
||||||
|
* {@link #NETWORK_WIFI} flag here is equivalent to calling
|
||||||
|
* {@link #setAllowedOverMetered(boolean)} with {@code false}.
|
||||||
*
|
*
|
||||||
* @param flags any combination of the NETWORK_* bit flags.
|
* @param flags any combination of the NETWORK_* bit flags.
|
||||||
* @return this object
|
* @return this object
|
||||||
@@ -700,6 +706,42 @@ public class DownloadManager {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify that to run this download, the device needs to be plugged in.
|
||||||
|
* This defaults to false.
|
||||||
|
*
|
||||||
|
* @param requiresCharging Whether or not the device is plugged in.
|
||||||
|
* @see android.app.job.JobInfo.Builder#setRequiresCharging(boolean)
|
||||||
|
*/
|
||||||
|
public Request setRequiresCharging(boolean requiresCharging) {
|
||||||
|
if (requiresCharging) {
|
||||||
|
mFlags |= Downloads.Impl.FLAG_REQUIRES_CHARGING;
|
||||||
|
} else {
|
||||||
|
mFlags &= ~Downloads.Impl.FLAG_REQUIRES_CHARGING;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify that to run, the download needs the device to be in idle
|
||||||
|
* mode. This defaults to false.
|
||||||
|
* <p>
|
||||||
|
* Idle mode is a loose definition provided by the system, which means
|
||||||
|
* that the device is not in use, and has not been in use for some time.
|
||||||
|
*
|
||||||
|
* @param requiresDeviceIdle Whether or not the device need be within an
|
||||||
|
* idle maintenance window.
|
||||||
|
* @see android.app.job.JobInfo.Builder#setRequiresDeviceIdle(boolean)
|
||||||
|
*/
|
||||||
|
public Request setRequiresDeviceIdle(boolean requiresDeviceIdle) {
|
||||||
|
if (requiresDeviceIdle) {
|
||||||
|
mFlags |= Downloads.Impl.FLAG_REQUIRES_DEVICE_IDLE;
|
||||||
|
} else {
|
||||||
|
mFlags &= ~Downloads.Impl.FLAG_REQUIRES_DEVICE_IDLE;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether this download should be displayed in the system's Downloads UI. True by
|
* Set whether this download should be displayed in the system's Downloads UI. True by
|
||||||
* default.
|
* default.
|
||||||
@@ -746,6 +788,7 @@ public class DownloadManager {
|
|||||||
values.put(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, mAllowedNetworkTypes);
|
values.put(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, mAllowedNetworkTypes);
|
||||||
values.put(Downloads.Impl.COLUMN_ALLOW_ROAMING, mRoamingAllowed);
|
values.put(Downloads.Impl.COLUMN_ALLOW_ROAMING, mRoamingAllowed);
|
||||||
values.put(Downloads.Impl.COLUMN_ALLOW_METERED, mMeteredAllowed);
|
values.put(Downloads.Impl.COLUMN_ALLOW_METERED, mMeteredAllowed);
|
||||||
|
values.put(Downloads.Impl.COLUMN_FLAGS, mFlags);
|
||||||
values.put(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI, mIsVisibleInDownloadsUi);
|
values.put(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI, mIsVisibleInDownloadsUi);
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
@@ -983,16 +1026,7 @@ public class DownloadManager {
|
|||||||
// called with nothing to remove!
|
// called with nothing to remove!
|
||||||
throw new IllegalArgumentException("input param 'ids' can't be null");
|
throw new IllegalArgumentException("input param 'ids' can't be null");
|
||||||
}
|
}
|
||||||
ContentValues values = new ContentValues();
|
return mResolver.delete(mBaseUri, getWhereClauseForIds(ids), getWhereArgsForIds(ids));
|
||||||
values.put(Downloads.Impl.COLUMN_DELETED, 1);
|
|
||||||
// if only one id is passed in, then include it in the uri itself.
|
|
||||||
// this will eliminate a full database scan in the download service.
|
|
||||||
if (ids.length == 1) {
|
|
||||||
return mResolver.update(ContentUris.withAppendedId(mBaseUri, ids[0]), values,
|
|
||||||
null, null);
|
|
||||||
}
|
|
||||||
return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids),
|
|
||||||
getWhereArgsForIds(ids));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1120,6 +1154,20 @@ public class DownloadManager {
|
|||||||
mResolver.update(mBaseUri, values, getWhereClauseForIds(ids), getWhereArgsForIds(ids));
|
mResolver.update(mBaseUri, values, getWhereClauseForIds(ids), getWhereArgsForIds(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force the given downloads to proceed even if their size is larger than
|
||||||
|
* {@link #getMaxBytesOverMobile(Context)}.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void forceDownload(long... ids) {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PENDING);
|
||||||
|
values.put(Downloads.Impl.COLUMN_CONTROL, Downloads.Impl.CONTROL_RUN);
|
||||||
|
values.put(Downloads.Impl.COLUMN_BYPASS_RECOMMENDED_SIZE_LIMIT, 1);
|
||||||
|
mResolver.update(mBaseUri, values, getWhereClauseForIds(ids), getWhereArgsForIds(ids));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns maximum size, in bytes, of downloads that may go over a mobile connection; or null if
|
* Returns maximum size, in bytes, of downloads that may go over a mobile connection; or null if
|
||||||
* there's no limit
|
* there's no limit
|
||||||
|
|||||||
@@ -78,4 +78,13 @@ public class JobSchedulerImpl extends JobScheduler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JobInfo getPendingJob(int jobId) {
|
||||||
|
try {
|
||||||
|
return mBinder.getPendingJob(jobId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,4 +28,5 @@ interface IJobScheduler {
|
|||||||
void cancel(int jobId);
|
void cancel(int jobId);
|
||||||
void cancelAll();
|
void cancelAll();
|
||||||
List<JobInfo> getAllPendingJobs();
|
List<JobInfo> getAllPendingJobs();
|
||||||
|
JobInfo getPendingJob(int jobId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ public class JobInfo implements Parcelable {
|
|||||||
public static final int NETWORK_TYPE_ANY = 1;
|
public static final int NETWORK_TYPE_ANY = 1;
|
||||||
/** This job requires network connectivity that is unmetered. */
|
/** This job requires network connectivity that is unmetered. */
|
||||||
public static final int NETWORK_TYPE_UNMETERED = 2;
|
public static final int NETWORK_TYPE_UNMETERED = 2;
|
||||||
|
/** This job requires network connectivity that is not roaming. */
|
||||||
|
public static final int NETWORK_TYPE_NOT_ROAMING = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Amount of backoff a job has initially by default, in milliseconds.
|
* Amount of backoff a job has initially by default, in milliseconds.
|
||||||
@@ -240,8 +242,9 @@ public class JobInfo implements Parcelable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY},
|
* One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY},
|
||||||
* {@link android.app.job.JobInfo#NETWORK_TYPE_NONE}, or
|
* {@link android.app.job.JobInfo#NETWORK_TYPE_NONE},
|
||||||
* {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED}.
|
* {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED}, or
|
||||||
|
* {@link android.app.job.JobInfo#NETWORK_TYPE_NOT_ROAMING}.
|
||||||
*/
|
*/
|
||||||
public int getNetworkType() {
|
public int getNetworkType() {
|
||||||
return networkType;
|
return networkType;
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package android.app.job;
|
package android.app.job;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,7 +81,6 @@ public abstract class JobScheduler {
|
|||||||
* Cancel a job that is pending in the JobScheduler.
|
* Cancel a job that is pending in the JobScheduler.
|
||||||
* @param jobId unique identifier for this job. Obtain this value from the jobs returned by
|
* @param jobId unique identifier for this job. Obtain this value from the jobs returned by
|
||||||
* {@link #getAllPendingJobs()}.
|
* {@link #getAllPendingJobs()}.
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public abstract void cancel(int jobId);
|
public abstract void cancel(int jobId);
|
||||||
|
|
||||||
@@ -88,8 +90,18 @@ public abstract class JobScheduler {
|
|||||||
public abstract void cancelAll();
|
public abstract void cancelAll();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a list of all the jobs registered by this package that have not yet been executed.
|
* Retrieve all jobs for this package that are pending in the JobScheduler.
|
||||||
|
*
|
||||||
|
* @return a list of all the jobs registered by this package that have not
|
||||||
|
* yet been executed.
|
||||||
*/
|
*/
|
||||||
public abstract List<JobInfo> getAllPendingJobs();
|
public abstract @NonNull List<JobInfo> getAllPendingJobs();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a specific job for this package that is pending in the
|
||||||
|
* JobScheduler.
|
||||||
|
*
|
||||||
|
* @return job registered by this package that has not yet been executed.
|
||||||
|
*/
|
||||||
|
public abstract @Nullable JobInfo getPendingJob(int jobId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,12 +119,9 @@ public class NetworkInfo implements Parcelable {
|
|||||||
private String mReason;
|
private String mReason;
|
||||||
private String mExtraInfo;
|
private String mExtraInfo;
|
||||||
private boolean mIsFailover;
|
private boolean mIsFailover;
|
||||||
private boolean mIsRoaming;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether network connectivity is possible:
|
|
||||||
*/
|
|
||||||
private boolean mIsAvailable;
|
private boolean mIsAvailable;
|
||||||
|
private boolean mIsRoaming;
|
||||||
|
private boolean mIsMetered;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
@@ -139,8 +136,6 @@ public class NetworkInfo implements Parcelable {
|
|||||||
mSubtypeName = subtypeName;
|
mSubtypeName = subtypeName;
|
||||||
setDetailedState(DetailedState.IDLE, null, null);
|
setDetailedState(DetailedState.IDLE, null, null);
|
||||||
mState = State.UNKNOWN;
|
mState = State.UNKNOWN;
|
||||||
mIsAvailable = false; // until we're told otherwise, assume unavailable
|
|
||||||
mIsRoaming = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@hide} */
|
/** {@hide} */
|
||||||
@@ -156,8 +151,9 @@ public class NetworkInfo implements Parcelable {
|
|||||||
mReason = source.mReason;
|
mReason = source.mReason;
|
||||||
mExtraInfo = source.mExtraInfo;
|
mExtraInfo = source.mExtraInfo;
|
||||||
mIsFailover = source.mIsFailover;
|
mIsFailover = source.mIsFailover;
|
||||||
mIsRoaming = source.mIsRoaming;
|
|
||||||
mIsAvailable = source.mIsAvailable;
|
mIsAvailable = source.mIsAvailable;
|
||||||
|
mIsRoaming = source.mIsRoaming;
|
||||||
|
mIsMetered = source.mIsMetered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,6 +325,30 @@ public class NetworkInfo implements Parcelable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if this network is metered. A network is classified as metered
|
||||||
|
* when the user is sensitive to heavy data usage on that connection due to
|
||||||
|
* monetary costs, data limitations or battery/performance issues. You
|
||||||
|
* should check this before doing large data transfers, and warn the user or
|
||||||
|
* delay the operation until another network is available.
|
||||||
|
*
|
||||||
|
* @return {@code true} if large transfers should be avoided, otherwise
|
||||||
|
* {@code false}.
|
||||||
|
*/
|
||||||
|
public boolean isMetered() {
|
||||||
|
synchronized (this) {
|
||||||
|
return mIsMetered;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@hide} */
|
||||||
|
@VisibleForTesting
|
||||||
|
public void setMetered(boolean isMetered) {
|
||||||
|
synchronized (this) {
|
||||||
|
mIsMetered = isMetered;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports the current coarse-grained state of the network.
|
* Reports the current coarse-grained state of the network.
|
||||||
* @return the coarse-grained state
|
* @return the coarse-grained state
|
||||||
@@ -409,26 +429,21 @@ public class NetworkInfo implements Parcelable {
|
|||||||
append("], state: ").append(mState).append("/").append(mDetailedState).
|
append("], state: ").append(mState).append("/").append(mDetailedState).
|
||||||
append(", reason: ").append(mReason == null ? "(unspecified)" : mReason).
|
append(", reason: ").append(mReason == null ? "(unspecified)" : mReason).
|
||||||
append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo).
|
append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo).
|
||||||
append(", roaming: ").append(mIsRoaming).
|
|
||||||
append(", failover: ").append(mIsFailover).
|
append(", failover: ").append(mIsFailover).
|
||||||
append(", isAvailable: ").append(mIsAvailable).
|
append(", available: ").append(mIsAvailable).
|
||||||
|
append(", roaming: ").append(mIsRoaming).
|
||||||
|
append(", metered: ").append(mIsMetered).
|
||||||
append("]");
|
append("]");
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Implement the Parcelable interface
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Implement the Parcelable interface.
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
dest.writeInt(mNetworkType);
|
dest.writeInt(mNetworkType);
|
||||||
@@ -440,17 +455,14 @@ public class NetworkInfo implements Parcelable {
|
|||||||
dest.writeInt(mIsFailover ? 1 : 0);
|
dest.writeInt(mIsFailover ? 1 : 0);
|
||||||
dest.writeInt(mIsAvailable ? 1 : 0);
|
dest.writeInt(mIsAvailable ? 1 : 0);
|
||||||
dest.writeInt(mIsRoaming ? 1 : 0);
|
dest.writeInt(mIsRoaming ? 1 : 0);
|
||||||
|
dest.writeInt(mIsMetered ? 1 : 0);
|
||||||
dest.writeString(mReason);
|
dest.writeString(mReason);
|
||||||
dest.writeString(mExtraInfo);
|
dest.writeString(mExtraInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static final Creator<NetworkInfo> CREATOR = new Creator<NetworkInfo>() {
|
||||||
* Implement the Parcelable interface.
|
@Override
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static final Creator<NetworkInfo> CREATOR =
|
|
||||||
new Creator<NetworkInfo>() {
|
|
||||||
public NetworkInfo createFromParcel(Parcel in) {
|
public NetworkInfo createFromParcel(Parcel in) {
|
||||||
int netType = in.readInt();
|
int netType = in.readInt();
|
||||||
int subtype = in.readInt();
|
int subtype = in.readInt();
|
||||||
@@ -462,11 +474,13 @@ public class NetworkInfo implements Parcelable {
|
|||||||
netInfo.mIsFailover = in.readInt() != 0;
|
netInfo.mIsFailover = in.readInt() != 0;
|
||||||
netInfo.mIsAvailable = in.readInt() != 0;
|
netInfo.mIsAvailable = in.readInt() != 0;
|
||||||
netInfo.mIsRoaming = in.readInt() != 0;
|
netInfo.mIsRoaming = in.readInt() != 0;
|
||||||
|
netInfo.mIsMetered = in.readInt() != 0;
|
||||||
netInfo.mReason = in.readString();
|
netInfo.mReason = in.readString();
|
||||||
netInfo.mExtraInfo = in.readString();
|
netInfo.mExtraInfo = in.readString();
|
||||||
return netInfo;
|
return netInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public NetworkInfo[] newArray(int size) {
|
public NetworkInfo[] newArray(int size) {
|
||||||
return new NetworkInfo[size];
|
return new NetworkInfo[size];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.os.Parcelable;
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class NetworkState implements Parcelable {
|
public class NetworkState implements Parcelable {
|
||||||
|
public static final NetworkState EMPTY = new NetworkState(null, null, null, null, null, null);
|
||||||
|
|
||||||
public final NetworkInfo networkInfo;
|
public final NetworkInfo networkInfo;
|
||||||
public final LinkProperties linkProperties;
|
public final LinkProperties linkProperties;
|
||||||
|
|||||||
@@ -412,6 +412,11 @@ public final class Downloads {
|
|||||||
|
|
||||||
public static final String COLUMN_ALLOW_WRITE = "allow_write";
|
public static final String COLUMN_ALLOW_WRITE = "allow_write";
|
||||||
|
|
||||||
|
public static final int FLAG_REQUIRES_CHARGING = 1 << 0;
|
||||||
|
public static final int FLAG_REQUIRES_DEVICE_IDLE = 1 << 1;
|
||||||
|
|
||||||
|
public static final String COLUMN_FLAGS = "flags";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* default value for {@link #COLUMN_LAST_UPDATESRC}.
|
* default value for {@link #COLUMN_LAST_UPDATESRC}.
|
||||||
* This value is used when this column's value is not relevant.
|
* This value is used when this column's value is not relevant.
|
||||||
|
|||||||
@@ -821,37 +821,25 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
private NetworkState getFilteredNetworkState(int networkType, int uid) {
|
private NetworkState getFilteredNetworkState(int networkType, int uid) {
|
||||||
NetworkInfo info = null;
|
|
||||||
LinkProperties lp = null;
|
|
||||||
NetworkCapabilities nc = null;
|
|
||||||
Network network = null;
|
|
||||||
String subscriberId = null;
|
|
||||||
|
|
||||||
if (mLegacyTypeTracker.isTypeSupported(networkType)) {
|
if (mLegacyTypeTracker.isTypeSupported(networkType)) {
|
||||||
NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
|
final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
|
||||||
|
final NetworkState state;
|
||||||
if (nai != null) {
|
if (nai != null) {
|
||||||
synchronized (nai) {
|
state = nai.getNetworkState();
|
||||||
info = new NetworkInfo(nai.networkInfo);
|
state.networkInfo.setType(networkType);
|
||||||
lp = new LinkProperties(nai.linkProperties);
|
|
||||||
nc = new NetworkCapabilities(nai.networkCapabilities);
|
|
||||||
// Network objects are outwardly immutable so there is no point to duplicating.
|
|
||||||
// Duplicating also precludes sharing socket factories and connection pools.
|
|
||||||
network = nai.network;
|
|
||||||
subscriberId = (nai.networkMisc != null) ? nai.networkMisc.subscriberId : null;
|
|
||||||
}
|
|
||||||
info.setType(networkType);
|
|
||||||
} else {
|
} else {
|
||||||
info = new NetworkInfo(networkType, 0, getNetworkTypeName(networkType), "");
|
final NetworkInfo info = new NetworkInfo(networkType, 0,
|
||||||
|
getNetworkTypeName(networkType), "");
|
||||||
info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
|
info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
|
||||||
info.setIsAvailable(true);
|
info.setIsAvailable(true);
|
||||||
lp = new LinkProperties();
|
state = new NetworkState(info, new LinkProperties(), new NetworkCapabilities(),
|
||||||
nc = new NetworkCapabilities();
|
null, null, null);
|
||||||
network = null;
|
|
||||||
}
|
}
|
||||||
info = getFilteredNetworkInfo(info, lp, uid);
|
filterNetworkStateForUid(state, uid);
|
||||||
|
return state;
|
||||||
|
} else {
|
||||||
|
return NetworkState.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NetworkState(info, lp, nc, network, subscriberId, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
|
private NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
|
||||||
@@ -861,7 +849,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
synchronized (mNetworkForNetId) {
|
synchronized (mNetworkForNetId) {
|
||||||
return mNetworkForNetId.get(network.netId);
|
return mNetworkForNetId.get(network.netId);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
private Network[] getVpnUnderlyingNetworks(int uid) {
|
private Network[] getVpnUnderlyingNetworks(int uid) {
|
||||||
if (!mLockdownEnabled) {
|
if (!mLockdownEnabled) {
|
||||||
@@ -877,12 +865,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
private NetworkState getUnfilteredActiveNetworkState(int uid) {
|
private NetworkState getUnfilteredActiveNetworkState(int uid) {
|
||||||
NetworkInfo info = null;
|
|
||||||
LinkProperties lp = null;
|
|
||||||
NetworkCapabilities nc = null;
|
|
||||||
Network network = null;
|
|
||||||
String subscriberId = null;
|
|
||||||
|
|
||||||
NetworkAgentInfo nai = getDefaultNetwork();
|
NetworkAgentInfo nai = getDefaultNetwork();
|
||||||
|
|
||||||
final Network[] networks = getVpnUnderlyingNetworks(uid);
|
final Network[] networks = getVpnUnderlyingNetworks(uid);
|
||||||
@@ -900,20 +882,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nai != null) {
|
if (nai != null) {
|
||||||
synchronized (nai) {
|
return nai.getNetworkState();
|
||||||
info = new NetworkInfo(nai.networkInfo);
|
} else {
|
||||||
lp = new LinkProperties(nai.linkProperties);
|
return NetworkState.EMPTY;
|
||||||
nc = new NetworkCapabilities(nai.networkCapabilities);
|
|
||||||
// Network objects are outwardly immutable so there is no point to duplicating.
|
|
||||||
// Duplicating also precludes sharing socket factories and connection pools.
|
|
||||||
network = nai.network;
|
|
||||||
subscriberId = (nai.networkMisc != null) ? nai.networkMisc.subscriberId : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NetworkState(info, lp, nc, network, subscriberId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if UID should be blocked from using the network with the given LinkProperties.
|
* Check if UID should be blocked from using the network with the given LinkProperties.
|
||||||
*/
|
*/
|
||||||
@@ -952,21 +926,29 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a filtered {@link NetworkInfo}, potentially marked
|
* Apply any relevant filters to {@link NetworkState} for the given UID. For
|
||||||
* {@link DetailedState#BLOCKED} based on
|
* example, this may mark the network as {@link DetailedState#BLOCKED} based
|
||||||
* {@link #isNetworkWithLinkPropertiesBlocked}.
|
* on {@link #isNetworkWithLinkPropertiesBlocked}, or
|
||||||
|
* {@link NetworkInfo#isMetered()} based on network policies.
|
||||||
*/
|
*/
|
||||||
private NetworkInfo getFilteredNetworkInfo(NetworkInfo info, LinkProperties lp, int uid) {
|
private void filterNetworkStateForUid(NetworkState state, int uid) {
|
||||||
if (info != null && isNetworkWithLinkPropertiesBlocked(lp, uid)) {
|
if (state == null || state.networkInfo == null || state.linkProperties == null) return;
|
||||||
// network is blocked; clone and override state
|
|
||||||
info = new NetworkInfo(info);
|
if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid)) {
|
||||||
info.setDetailedState(DetailedState.BLOCKED, null, null);
|
state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null);
|
||||||
}
|
}
|
||||||
if (info != null && mLockdownTracker != null) {
|
if (mLockdownTracker != null) {
|
||||||
info = mLockdownTracker.augmentNetworkInfo(info);
|
mLockdownTracker.augmentNetworkInfo(state.networkInfo);
|
||||||
if (VDBG) log("returning Locked NetworkInfo");
|
}
|
||||||
|
|
||||||
|
// TODO: apply metered state closer to NetworkAgentInfo
|
||||||
|
final long token = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
state.networkInfo.setMetered(mPolicyManager.isNetworkMetered(state));
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(token);
|
||||||
}
|
}
|
||||||
return info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -980,10 +962,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
public NetworkInfo getActiveNetworkInfo() {
|
public NetworkInfo getActiveNetworkInfo() {
|
||||||
enforceAccessPermission();
|
enforceAccessPermission();
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
NetworkState state = getUnfilteredActiveNetworkState(uid);
|
final NetworkState state = getUnfilteredActiveNetworkState(uid);
|
||||||
NetworkInfo ni = getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid);
|
filterNetworkStateForUid(state, uid);
|
||||||
maybeLogBlockedNetworkInfo(ni, uid);
|
maybeLogBlockedNetworkInfo(state.networkInfo, uid);
|
||||||
return ni;
|
return state.networkInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1027,8 +1009,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public NetworkInfo getActiveNetworkInfoForUid(int uid) {
|
public NetworkInfo getActiveNetworkInfoForUid(int uid) {
|
||||||
enforceConnectivityInternalPermission();
|
enforceConnectivityInternalPermission();
|
||||||
NetworkState state = getUnfilteredActiveNetworkState(uid);
|
final NetworkState state = getUnfilteredActiveNetworkState(uid);
|
||||||
return getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid);
|
filterNetworkStateForUid(state, uid);
|
||||||
|
return state.networkInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1039,12 +1022,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
// A VPN is active, so we may need to return one of its underlying networks. This
|
// A VPN is active, so we may need to return one of its underlying networks. This
|
||||||
// information is not available in LegacyTypeTracker, so we have to get it from
|
// information is not available in LegacyTypeTracker, so we have to get it from
|
||||||
// getUnfilteredActiveNetworkState.
|
// getUnfilteredActiveNetworkState.
|
||||||
NetworkState state = getUnfilteredActiveNetworkState(uid);
|
final NetworkState state = getUnfilteredActiveNetworkState(uid);
|
||||||
if (state.networkInfo != null && state.networkInfo.getType() == networkType) {
|
if (state.networkInfo != null && state.networkInfo.getType() == networkType) {
|
||||||
return getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid);
|
filterNetworkStateForUid(state, uid);
|
||||||
|
return state.networkInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NetworkState state = getFilteredNetworkState(networkType, uid);
|
final NetworkState state = getFilteredNetworkState(networkType, uid);
|
||||||
return state.networkInfo;
|
return state.networkInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1052,16 +1036,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
public NetworkInfo getNetworkInfoForNetwork(Network network) {
|
public NetworkInfo getNetworkInfoForNetwork(Network network) {
|
||||||
enforceAccessPermission();
|
enforceAccessPermission();
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
NetworkInfo info = null;
|
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
|
||||||
NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
|
|
||||||
if (nai != null) {
|
if (nai != null) {
|
||||||
synchronized (nai) {
|
final NetworkState state = nai.getNetworkState();
|
||||||
info = new NetworkInfo(nai.networkInfo);
|
filterNetworkStateForUid(state, uid);
|
||||||
info = getFilteredNetworkInfo(info, nai.linkProperties, uid);
|
return state.networkInfo;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NetworkInfo[] getAllNetworkInfo() {
|
public NetworkInfo[] getAllNetworkInfo() {
|
||||||
@@ -1222,12 +1205,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
for (Network network : getAllNetworks()) {
|
for (Network network : getAllNetworks()) {
|
||||||
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
|
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
|
||||||
if (nai != null) {
|
if (nai != null) {
|
||||||
synchronized (nai) {
|
result.add(nai.getNetworkState());
|
||||||
final String subscriberId = (nai.networkMisc != null)
|
|
||||||
? nai.networkMisc.subscriberId : null;
|
|
||||||
result.add(new NetworkState(nai.networkInfo, nai.linkProperties,
|
|
||||||
nai.networkCapabilities, network, subscriberId, null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.toArray(new NetworkState[result.size()]);
|
return result.toArray(new NetworkState[result.size()]);
|
||||||
@@ -1255,24 +1233,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public boolean isActiveNetworkMetered() {
|
public boolean isActiveNetworkMetered() {
|
||||||
enforceAccessPermission();
|
enforceAccessPermission();
|
||||||
final int uid = Binder.getCallingUid();
|
|
||||||
final long token = Binder.clearCallingIdentity();
|
|
||||||
try {
|
|
||||||
return isActiveNetworkMeteredUnchecked(uid);
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isActiveNetworkMeteredUnchecked(int uid) {
|
final NetworkInfo info = getActiveNetworkInfo();
|
||||||
final NetworkState state = getUnfilteredActiveNetworkState(uid);
|
return (info != null) ? info.isMetered() : false;
|
||||||
if (state.networkInfo != null) {
|
|
||||||
try {
|
|
||||||
return mPolicyManager.isNetworkMetered(state);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
|
private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
|
||||||
@@ -1490,7 +1453,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
|
|
||||||
private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
|
private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
|
||||||
if (mLockdownTracker != null) {
|
if (mLockdownTracker != null) {
|
||||||
info = mLockdownTracker.augmentNetworkInfo(info);
|
info = new NetworkInfo(info);
|
||||||
|
mLockdownTracker.augmentNetworkInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent intent = new Intent(bcastType);
|
Intent intent = new Intent(bcastType);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.net.NetworkCapabilities;
|
|||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.net.NetworkMisc;
|
import android.net.NetworkMisc;
|
||||||
import android.net.NetworkRequest;
|
import android.net.NetworkRequest;
|
||||||
|
import android.net.NetworkState;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
@@ -247,6 +248,17 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
|||||||
currentScore = newScore;
|
currentScore = newScore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NetworkState getNetworkState() {
|
||||||
|
synchronized (this) {
|
||||||
|
// Network objects are outwardly immutable so there is no point to duplicating.
|
||||||
|
// Duplicating also precludes sharing socket factories and connection pools.
|
||||||
|
final String subscriberId = (networkMisc != null) ? networkMisc.subscriberId : null;
|
||||||
|
return new NetworkState(new NetworkInfo(networkInfo),
|
||||||
|
new LinkProperties(linkProperties),
|
||||||
|
new NetworkCapabilities(networkCapabilities), network, subscriberId, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "NetworkAgentInfo{ ni{" + networkInfo + "} " +
|
return "NetworkAgentInfo{ ni{" + networkInfo + "} " +
|
||||||
"network{" + network + "} nethandle{" + network.getNetworkHandle() + "} " +
|
"network{" + network + "} nethandle{" + network.getNetworkHandle() + "} " +
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import android.content.IntentFilter;
|
|||||||
import android.content.pm.IPackageManager;
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.os.BatteryStats;
|
import android.os.BatteryStats;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -336,6 +337,19 @@ public final class JobSchedulerService extends com.android.server.SystemService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JobInfo getPendingJob(int uid, int jobId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
List<JobStatus> jobs = mJobs.getJobsByUid(uid);
|
||||||
|
for (int i = jobs.size() - 1; i >= 0; i--) {
|
||||||
|
JobStatus job = jobs.get(i);
|
||||||
|
if (job.getJobId() == jobId) {
|
||||||
|
return job.getJob();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cancelJobsForUser(int userHandle) {
|
void cancelJobsForUser(int userHandle) {
|
||||||
List<JobStatus> jobsForUser;
|
List<JobStatus> jobsForUser;
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
@@ -912,7 +926,8 @@ public final class JobSchedulerService extends com.android.server.SystemService
|
|||||||
if (job.hasIdleConstraint()) {
|
if (job.hasIdleConstraint()) {
|
||||||
idleCount++;
|
idleCount++;
|
||||||
}
|
}
|
||||||
if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()) {
|
if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()
|
||||||
|
|| job.hasNotRoamingConstraint()) {
|
||||||
connectivityCount++;
|
connectivityCount++;
|
||||||
}
|
}
|
||||||
if (job.hasChargingConstraint()) {
|
if (job.hasChargingConstraint()) {
|
||||||
@@ -1345,6 +1360,18 @@ public final class JobSchedulerService extends com.android.server.SystemService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JobInfo getPendingJob(int jobId) throws RemoteException {
|
||||||
|
final int uid = Binder.getCallingUid();
|
||||||
|
|
||||||
|
long ident = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
return JobSchedulerService.this.getPendingJob(uid, jobId);
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancelAll() throws RemoteException {
|
public void cancelAll() throws RemoteException {
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
@@ -1378,7 +1405,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
|
|||||||
|
|
||||||
long identityToken = Binder.clearCallingIdentity();
|
long identityToken = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
JobSchedulerService.this.dumpInternal(pw);
|
JobSchedulerService.this.dumpInternal(pw, args);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(identityToken);
|
Binder.restoreCallingIdentity(identityToken);
|
||||||
}
|
}
|
||||||
@@ -1450,7 +1477,17 @@ public final class JobSchedulerService extends com.android.server.SystemService
|
|||||||
return s.toString();
|
return s.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpInternal(final PrintWriter pw) {
|
void dumpInternal(final PrintWriter pw, String[] args) {
|
||||||
|
int filterUid = -1;
|
||||||
|
if (!ArrayUtils.isEmpty(args)) {
|
||||||
|
try {
|
||||||
|
filterUid = getContext().getPackageManager().getPackageUid(args[0],
|
||||||
|
PackageManager.MATCH_UNINSTALLED_PACKAGES);
|
||||||
|
} catch (NameNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final int filterUidFinal = filterUid;
|
||||||
final long now = SystemClock.elapsedRealtime();
|
final long now = SystemClock.elapsedRealtime();
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
pw.println("Started users: " + Arrays.toString(mStartedUsers));
|
pw.println("Started users: " + Arrays.toString(mStartedUsers));
|
||||||
@@ -1463,6 +1500,13 @@ public final class JobSchedulerService extends com.android.server.SystemService
|
|||||||
public void process(JobStatus job) {
|
public void process(JobStatus job) {
|
||||||
pw.print(" Job #"); pw.print(index++); pw.print(": ");
|
pw.print(" Job #"); pw.print(index++); pw.print(": ");
|
||||||
pw.println(job.toShortString());
|
pw.println(job.toShortString());
|
||||||
|
|
||||||
|
// Skip printing details if the caller requested a filter
|
||||||
|
if (filterUidFinal != -1 && job.getUid() != filterUidFinal
|
||||||
|
&& job.getSourceUid() != filterUidFinal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
job.dump(pw, " ", true);
|
job.dump(pw, " ", true);
|
||||||
pw.print(" Ready: ");
|
pw.print(" Ready: ");
|
||||||
pw.print(mHandler.isReadyToBeExecutedLocked(job));
|
pw.print(mHandler.isReadyToBeExecutedLocked(job));
|
||||||
|
|||||||
@@ -365,11 +365,14 @@ public class JobStore {
|
|||||||
*/
|
*/
|
||||||
private void writeConstraintsToXml(XmlSerializer out, JobStatus jobStatus) throws IOException {
|
private void writeConstraintsToXml(XmlSerializer out, JobStatus jobStatus) throws IOException {
|
||||||
out.startTag(null, XML_TAG_PARAMS_CONSTRAINTS);
|
out.startTag(null, XML_TAG_PARAMS_CONSTRAINTS);
|
||||||
|
if (jobStatus.hasConnectivityConstraint()) {
|
||||||
|
out.attribute(null, "connectivity", Boolean.toString(true));
|
||||||
|
}
|
||||||
if (jobStatus.hasUnmeteredConstraint()) {
|
if (jobStatus.hasUnmeteredConstraint()) {
|
||||||
out.attribute(null, "unmetered", Boolean.toString(true));
|
out.attribute(null, "unmetered", Boolean.toString(true));
|
||||||
}
|
}
|
||||||
if (jobStatus.hasConnectivityConstraint()) {
|
if (jobStatus.hasNotRoamingConstraint()) {
|
||||||
out.attribute(null, "connectivity", Boolean.toString(true));
|
out.attribute(null, "not-roaming", Boolean.toString(true));
|
||||||
}
|
}
|
||||||
if (jobStatus.hasIdleConstraint()) {
|
if (jobStatus.hasIdleConstraint()) {
|
||||||
out.attribute(null, "idle", Boolean.toString(true));
|
out.attribute(null, "idle", Boolean.toString(true));
|
||||||
@@ -693,13 +696,17 @@ public class JobStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) {
|
private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) {
|
||||||
String val = parser.getAttributeValue(null, "unmetered");
|
String val = parser.getAttributeValue(null, "connectivity");
|
||||||
|
if (val != null) {
|
||||||
|
jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
|
||||||
|
}
|
||||||
|
val = parser.getAttributeValue(null, "unmetered");
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
|
jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
|
||||||
}
|
}
|
||||||
val = parser.getAttributeValue(null, "connectivity");
|
val = parser.getAttributeValue(null, "not-roaming");
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
|
jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NOT_ROAMING);
|
||||||
}
|
}
|
||||||
val = parser.getAttributeValue(null, "idle");
|
val = parser.getAttributeValue(null, "idle");
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
|
|||||||
@@ -16,44 +16,44 @@
|
|||||||
|
|
||||||
package com.android.server.job.controllers;
|
package com.android.server.job.controllers;
|
||||||
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.INetworkPolicyListener;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.os.ServiceManager;
|
import android.net.NetworkPolicyManager;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import com.android.server.ConnectivityService;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.server.job.JobSchedulerService;
|
import com.android.server.job.JobSchedulerService;
|
||||||
import com.android.server.job.StateChangedListener;
|
import com.android.server.job.StateChangedListener;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.LinkedList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles changes in connectivity.
|
* Handles changes in connectivity.
|
||||||
* We are only interested in metered vs. unmetered networks, and we're interested in them on a
|
* <p>
|
||||||
* per-user basis.
|
* Each app can have a different default networks or different connectivity
|
||||||
|
* status due to user-requested network policies, so we need to check
|
||||||
|
* constraints on a per-UID basis.
|
||||||
*/
|
*/
|
||||||
public class ConnectivityController extends StateController implements
|
public class ConnectivityController extends StateController implements
|
||||||
ConnectivityManager.OnNetworkActiveListener {
|
ConnectivityManager.OnNetworkActiveListener {
|
||||||
private static final String TAG = "JobScheduler.Conn";
|
private static final String TAG = "JobScheduler.Conn";
|
||||||
|
|
||||||
private final List<JobStatus> mTrackedJobs = new LinkedList<JobStatus>();
|
private final ConnectivityManager mConnManager;
|
||||||
private final BroadcastReceiver mConnectivityChangedReceiver =
|
private final NetworkPolicyManager mNetPolicyManager;
|
||||||
new ConnectivityChangedReceiver();
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private final ArrayList<JobStatus> mTrackedJobs = new ArrayList<JobStatus>();
|
||||||
|
|
||||||
/** Singleton. */
|
/** Singleton. */
|
||||||
private static ConnectivityController mSingleton;
|
private static ConnectivityController mSingleton;
|
||||||
private static Object sCreationLock = new Object();
|
private static Object sCreationLock = new Object();
|
||||||
/** Track whether the latest active network is metered. */
|
|
||||||
private boolean mNetworkUnmetered;
|
|
||||||
/** Track whether the latest active network is connected. */
|
|
||||||
private boolean mNetworkConnected;
|
|
||||||
|
|
||||||
public static ConnectivityController get(JobSchedulerService jms) {
|
public static ConnectivityController get(JobSchedulerService jms) {
|
||||||
synchronized (sCreationLock) {
|
synchronized (sCreationLock) {
|
||||||
@@ -67,51 +67,62 @@ public class ConnectivityController extends StateController implements
|
|||||||
private ConnectivityController(StateChangedListener stateChangedListener, Context context,
|
private ConnectivityController(StateChangedListener stateChangedListener, Context context,
|
||||||
Object lock) {
|
Object lock) {
|
||||||
super(stateChangedListener, context, lock);
|
super(stateChangedListener, context, lock);
|
||||||
// Register connectivity changed BR.
|
|
||||||
IntentFilter intentFilter = new IntentFilter();
|
mConnManager = mContext.getSystemService(ConnectivityManager.class);
|
||||||
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
|
||||||
|
|
||||||
|
final IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||||
mContext.registerReceiverAsUser(
|
mContext.registerReceiverAsUser(
|
||||||
mConnectivityChangedReceiver, UserHandle.ALL, intentFilter, null, null);
|
mConnectivityReceiver, UserHandle.SYSTEM, intentFilter, null, null);
|
||||||
ConnectivityService cs =
|
|
||||||
(ConnectivityService)ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
|
mNetPolicyManager.registerListener(mNetPolicyListener);
|
||||||
if (cs != null) {
|
|
||||||
if (cs.getActiveNetworkInfo() != null) {
|
|
||||||
mNetworkConnected = cs.getActiveNetworkInfo().isConnected();
|
|
||||||
mNetworkUnmetered = mNetworkConnected && !cs.isActiveNetworkMetered();
|
|
||||||
} else {
|
|
||||||
mNetworkConnected = mNetworkUnmetered = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
|
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
|
||||||
if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
|
if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()
|
||||||
jobStatus.setConnectivityConstraintSatisfied(mNetworkConnected);
|
|| jobStatus.hasNotRoamingConstraint()) {
|
||||||
jobStatus.setUnmeteredConstraintSatisfied(mNetworkUnmetered);
|
updateConstraintsSatisfied(jobStatus);
|
||||||
mTrackedJobs.add(jobStatus);
|
mTrackedJobs.add(jobStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
|
public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
|
||||||
if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
|
boolean forUpdate) {
|
||||||
|
if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()
|
||||||
|
|| jobStatus.hasNotRoamingConstraint()) {
|
||||||
mTrackedJobs.remove(jobStatus);
|
mTrackedJobs.remove(jobStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
|
||||||
|
final NetworkInfo info = mConnManager.getActiveNetworkInfoForUid(jobStatus.getSourceUid());
|
||||||
|
final boolean connected = (info != null) && info.isConnected();
|
||||||
|
final boolean unmetered = connected && !info.isMetered();
|
||||||
|
final boolean notRoaming = connected && !info.isRoaming();
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
changed |= jobStatus.setConnectivityConstraintSatisfied(connected);
|
||||||
|
changed |= jobStatus.setUnmeteredConstraintSatisfied(unmetered);
|
||||||
|
changed |= jobStatus.setNotRoamingConstraintSatisfied(notRoaming);
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param userId Id of the user for whom we are updating the connectivity state.
|
* Update all jobs tracked by this controller.
|
||||||
|
*
|
||||||
|
* @param uid only update jobs belonging to this UID, or {@code -1} to
|
||||||
|
* update all tracked jobs.
|
||||||
*/
|
*/
|
||||||
private void updateTrackedJobs(int userId) {
|
private void updateTrackedJobs(int uid) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for (JobStatus js : mTrackedJobs) {
|
for (int i = 0; i < mTrackedJobs.size(); i++) {
|
||||||
if (js.getUserId() != userId) {
|
final JobStatus js = mTrackedJobs.get(i);
|
||||||
continue;
|
if (uid == -1 || uid == js.getSourceUid()) {
|
||||||
|
changed |= updateConstraintsSatisfied(js);
|
||||||
}
|
}
|
||||||
changed |= js.setConnectivityConstraintSatisfied(mNetworkConnected);
|
|
||||||
changed |= js.setUnmeteredConstraintSatisfied(mNetworkUnmetered);
|
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
mStateChangedListener.onControllerStateChanged();
|
mStateChangedListener.onControllerStateChanged();
|
||||||
@@ -122,9 +133,11 @@ public class ConnectivityController extends StateController implements
|
|||||||
/**
|
/**
|
||||||
* We know the network has just come up. We want to run any jobs that are ready.
|
* We know the network has just come up. We want to run any jobs that are ready.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public synchronized void onNetworkActive() {
|
public synchronized void onNetworkActive() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
for (JobStatus js : mTrackedJobs) {
|
for (int i = 0; i < mTrackedJobs.size(); i++) {
|
||||||
|
final JobStatus js = mTrackedJobs.get(i);
|
||||||
if (js.isReady()) {
|
if (js.isReady()) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "Running " + js + " due to network activity.");
|
Slog.d(TAG, "Running " + js + " due to network activity.");
|
||||||
@@ -135,61 +148,44 @@ public class ConnectivityController extends StateController implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConnectivityChangedReceiver extends BroadcastReceiver {
|
private BroadcastReceiver mConnectivityReceiver = new BroadcastReceiver() {
|
||||||
/**
|
|
||||||
* We'll receive connectivity changes for each user here, which we process independently.
|
|
||||||
* We are only interested in the active network here. We're only interested in the active
|
|
||||||
* network, b/c the end result of this will be for apps to try to hit the network.
|
|
||||||
* @param context The Context in which the receiver is running.
|
|
||||||
* @param intent The Intent being received.
|
|
||||||
*/
|
|
||||||
// TODO: Test whether this will be called twice for each user.
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (DEBUG) {
|
updateTrackedJobs(-1);
|
||||||
Slog.d(TAG, "Received connectivity event: " + intent.getAction() + " u"
|
|
||||||
+ context.getUserId());
|
|
||||||
}
|
}
|
||||||
final String action = intent.getAction();
|
};
|
||||||
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
|
|
||||||
final int networkType =
|
private INetworkPolicyListener mNetPolicyListener = new INetworkPolicyListener.Stub() {
|
||||||
intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
|
@Override
|
||||||
ConnectivityManager.TYPE_NONE);
|
public void onUidRulesChanged(int uid, int uidRules) {
|
||||||
// Connectivity manager for THIS context - important!
|
updateTrackedJobs(uid);
|
||||||
final ConnectivityManager connManager = (ConnectivityManager)
|
|
||||||
context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
||||||
final NetworkInfo activeNetwork = connManager.getActiveNetworkInfo();
|
|
||||||
final int userid = context.getUserId();
|
|
||||||
// This broadcast gets sent a lot, only update if the active network has changed.
|
|
||||||
if (activeNetwork == null) {
|
|
||||||
mNetworkUnmetered = false;
|
|
||||||
mNetworkConnected = false;
|
|
||||||
updateTrackedJobs(userid);
|
|
||||||
} else if (activeNetwork.getType() == networkType) {
|
|
||||||
mNetworkUnmetered = false;
|
|
||||||
mNetworkConnected = !intent.getBooleanExtra(
|
|
||||||
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
|
|
||||||
if (mNetworkConnected) { // No point making the call if we know there's no conn.
|
|
||||||
mNetworkUnmetered = !connManager.isActiveNetworkMetered();
|
|
||||||
}
|
}
|
||||||
updateTrackedJobs(userid);
|
|
||||||
}
|
@Override
|
||||||
} else {
|
public void onMeteredIfacesChanged(String[] meteredIfaces) {
|
||||||
if (DEBUG) {
|
updateTrackedJobs(-1);
|
||||||
Slog.d(TAG, "Unrecognised action in intent: " + action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRestrictBackgroundChanged(boolean restrictBackground) {
|
||||||
|
updateTrackedJobs(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
|
||||||
|
updateTrackedJobs(uid);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dumpControllerStateLocked(PrintWriter pw) {
|
public void dumpControllerStateLocked(PrintWriter pw) {
|
||||||
pw.println("Conn.");
|
pw.println("Conn.");
|
||||||
pw.println("connected: " + mNetworkConnected + " unmetered: " + mNetworkUnmetered);
|
for (int i = 0; i < mTrackedJobs.size(); i++) {
|
||||||
for (JobStatus js: mTrackedJobs) {
|
final JobStatus js = mTrackedJobs.get(i);
|
||||||
pw.println(String.valueOf(js.getJobId() + "," + js.getUid())
|
pw.println(String.valueOf(js.getJobId() + "," + js.getUid())
|
||||||
+ ": C=" + js.hasConnectivityConstraint()
|
+ ": C=" + js.hasConnectivityConstraint()
|
||||||
+ ", UM=" + js.hasUnmeteredConstraint());
|
+ ", UM=" + js.hasUnmeteredConstraint()
|
||||||
|
+ ", NR=" + js.hasNotRoamingConstraint());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import android.util.ArraySet;
|
|||||||
import android.util.TimeUtils;
|
import android.util.TimeUtils;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uniquely identifies a job internally.
|
* Uniquely identifies a job internally.
|
||||||
@@ -55,6 +54,7 @@ public final class JobStatus {
|
|||||||
static final int CONSTRAINT_APP_NOT_IDLE = 1<<6;
|
static final int CONSTRAINT_APP_NOT_IDLE = 1<<6;
|
||||||
static final int CONSTRAINT_CONTENT_TRIGGER = 1<<7;
|
static final int CONSTRAINT_CONTENT_TRIGGER = 1<<7;
|
||||||
static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<8;
|
static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<8;
|
||||||
|
static final int CONSTRAINT_NOT_ROAMING = 1<<9;
|
||||||
|
|
||||||
// Soft override: ignore constraints like time that don't affect API availability
|
// Soft override: ignore constraints like time that don't affect API availability
|
||||||
public static final int OVERRIDE_SOFT = 1;
|
public static final int OVERRIDE_SOFT = 1;
|
||||||
@@ -176,6 +176,9 @@ public final class JobStatus {
|
|||||||
if (job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED) {
|
if (job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED) {
|
||||||
requiredConstraints |= CONSTRAINT_UNMETERED;
|
requiredConstraints |= CONSTRAINT_UNMETERED;
|
||||||
}
|
}
|
||||||
|
if (job.getNetworkType() == JobInfo.NETWORK_TYPE_NOT_ROAMING) {
|
||||||
|
requiredConstraints |= CONSTRAINT_NOT_ROAMING;
|
||||||
|
}
|
||||||
if (job.isRequireCharging()) {
|
if (job.isRequireCharging()) {
|
||||||
requiredConstraints |= CONSTRAINT_CHARGING;
|
requiredConstraints |= CONSTRAINT_CHARGING;
|
||||||
}
|
}
|
||||||
@@ -312,6 +315,10 @@ public final class JobStatus {
|
|||||||
return (requiredConstraints&CONSTRAINT_UNMETERED) != 0;
|
return (requiredConstraints&CONSTRAINT_UNMETERED) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasNotRoamingConstraint() {
|
||||||
|
return (requiredConstraints&CONSTRAINT_NOT_ROAMING) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasChargingConstraint() {
|
public boolean hasChargingConstraint() {
|
||||||
return (requiredConstraints&CONSTRAINT_CHARGING) != 0;
|
return (requiredConstraints&CONSTRAINT_CHARGING) != 0;
|
||||||
}
|
}
|
||||||
@@ -376,12 +383,16 @@ public final class JobStatus {
|
|||||||
return setConstraintSatisfied(CONSTRAINT_IDLE, state);
|
return setConstraintSatisfied(CONSTRAINT_IDLE, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean setConnectivityConstraintSatisfied(boolean state) {
|
||||||
|
return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state);
|
||||||
|
}
|
||||||
|
|
||||||
boolean setUnmeteredConstraintSatisfied(boolean state) {
|
boolean setUnmeteredConstraintSatisfied(boolean state) {
|
||||||
return setConstraintSatisfied(CONSTRAINT_UNMETERED, state);
|
return setConstraintSatisfied(CONSTRAINT_UNMETERED, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean setConnectivityConstraintSatisfied(boolean state) {
|
boolean setNotRoamingConstraintSatisfied(boolean state) {
|
||||||
return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state);
|
return setConstraintSatisfied(CONSTRAINT_NOT_ROAMING, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean setAppNotIdleConstraintSatisfied(boolean state) {
|
boolean setAppNotIdleConstraintSatisfied(boolean state) {
|
||||||
@@ -425,7 +436,7 @@ public final class JobStatus {
|
|||||||
|
|
||||||
static final int CONSTRAINTS_OF_INTEREST =
|
static final int CONSTRAINTS_OF_INTEREST =
|
||||||
CONSTRAINT_CHARGING | CONSTRAINT_TIMING_DELAY |
|
CONSTRAINT_CHARGING | CONSTRAINT_TIMING_DELAY |
|
||||||
CONSTRAINT_CONNECTIVITY | CONSTRAINT_UNMETERED |
|
CONSTRAINT_CONNECTIVITY | CONSTRAINT_UNMETERED | CONSTRAINT_NOT_ROAMING |
|
||||||
CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER;
|
CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER;
|
||||||
|
|
||||||
// Soft override covers all non-"functional" constraints
|
// Soft override covers all non-"functional" constraints
|
||||||
@@ -517,11 +528,14 @@ public final class JobStatus {
|
|||||||
if ((constraints&CONSTRAINT_IDLE) != 0) {
|
if ((constraints&CONSTRAINT_IDLE) != 0) {
|
||||||
pw.print(" IDLE");
|
pw.print(" IDLE");
|
||||||
}
|
}
|
||||||
|
if ((constraints&CONSTRAINT_CONNECTIVITY) != 0) {
|
||||||
|
pw.print(" CONNECTIVITY");
|
||||||
|
}
|
||||||
if ((constraints&CONSTRAINT_UNMETERED) != 0) {
|
if ((constraints&CONSTRAINT_UNMETERED) != 0) {
|
||||||
pw.print(" UNMETERED");
|
pw.print(" UNMETERED");
|
||||||
}
|
}
|
||||||
if ((constraints&CONSTRAINT_CONNECTIVITY) != 0) {
|
if ((constraints&CONSTRAINT_NOT_ROAMING) != 0) {
|
||||||
pw.print(" CONNECTIVITY");
|
pw.print(" NOT_ROAMING");
|
||||||
}
|
}
|
||||||
if ((constraints&CONSTRAINT_APP_NOT_IDLE) != 0) {
|
if ((constraints&CONSTRAINT_APP_NOT_IDLE) != 0) {
|
||||||
pw.print(" APP_NOT_IDLE");
|
pw.print(" APP_NOT_IDLE");
|
||||||
|
|||||||
@@ -209,7 +209,9 @@ public class LockdownVpnTracker {
|
|||||||
throw new RuntimeException("Problem setting firewall rules", e);
|
throw new RuntimeException("Problem setting firewall rules", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
mConnService.sendConnectedBroadcast(augmentNetworkInfo(egressInfo));
|
final NetworkInfo clone = new NetworkInfo(egressInfo);
|
||||||
|
augmentNetworkInfo(clone);
|
||||||
|
mConnService.sendConnectedBroadcast(clone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,13 +322,11 @@ public class LockdownVpnTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetworkInfo augmentNetworkInfo(NetworkInfo info) {
|
public void augmentNetworkInfo(NetworkInfo info) {
|
||||||
if (info.isConnected()) {
|
if (info.isConnected()) {
|
||||||
final NetworkInfo vpnInfo = mVpn.getNetworkInfo();
|
final NetworkInfo vpnInfo = mVpn.getNetworkInfo();
|
||||||
info = new NetworkInfo(info);
|
|
||||||
info.setDetailedState(vpnInfo.getDetailedState(), vpnInfo.getReason(), null);
|
info.setDetailedState(vpnInfo.getDetailedState(), vpnInfo.getReason(), null);
|
||||||
}
|
}
|
||||||
return info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showNotification(int titleRes, int iconRes) {
|
private void showNotification(int titleRes, int iconRes) {
|
||||||
|
|||||||
@@ -2148,6 +2148,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isNetworkMetered(NetworkState state) {
|
public boolean isNetworkMetered(NetworkState state) {
|
||||||
|
if (state.networkInfo == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
|
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
|
||||||
|
|
||||||
// roaming networks are always considered metered
|
// roaming networks are always considered metered
|
||||||
@@ -2163,10 +2167,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
|||||||
if (policy != null) {
|
if (policy != null) {
|
||||||
return policy.metered;
|
return policy.metered;
|
||||||
} else {
|
} else {
|
||||||
if (state.networkInfo == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int type = state.networkInfo.getType();
|
final int type = state.networkInfo.getType();
|
||||||
if (isNetworkTypeMobile(type) || type == TYPE_WIMAX) {
|
if (isNetworkTypeMobile(type) || type == TYPE_WIMAX) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user