summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/AudioFlinger.cpp20
-rw-r--r--services/java/com/android/server/ConnectivityService.java19
-rw-r--r--services/java/com/android/server/MountService.java66
-rw-r--r--services/java/com/android/server/NetworkManagementService.java89
-rw-r--r--services/java/com/android/server/SystemServer.java13
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java62
-rwxr-xr-xservices/java/com/android/server/location/GpsLocationProvider.java4
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java197
-rw-r--r--services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java2
9 files changed, 287 insertions, 185 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a6ba1a0..8e86eda 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -87,40 +87,20 @@ static const int kDumpLockSleep = 20000;
static const nsecs_t kWarningThrottle = seconds(5);
-#define AUDIOFLINGER_SECURITY_ENABLED 1
-
// ----------------------------------------------------------------------------
static bool recordingAllowed() {
-#ifndef HAVE_ANDROID_OS
- return true;
-#endif
-#if AUDIOFLINGER_SECURITY_ENABLED
if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
return ok;
-#else
- if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
- LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
- return true;
-#endif
}
static bool settingsAllowed() {
-#ifndef HAVE_ANDROID_OS
- return true;
-#endif
-#if AUDIOFLINGER_SECURITY_ENABLED
if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
return ok;
-#else
- if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
- LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
- return true;
-#endif
}
// To collect the amplifier usage
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index ca2adb4..d2fd04b 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -543,11 +543,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
* active
*/
public NetworkInfo getActiveNetworkInfo() {
- enforceAccessPermission();
- if (mActiveDefaultNetwork != -1) {
- return mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
- }
- return null;
+ return getNetworkInfo(mActiveDefaultNetwork);
}
public NetworkInfo getNetworkInfo(int networkType) {
@@ -579,18 +575,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
* none is active
*/
public LinkProperties getActiveLinkProperties() {
- enforceAccessPermission();
- for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
- if (mNetConfigs[type] == null || !mNetConfigs[type].isDefault()) {
- continue;
- }
- NetworkStateTracker t = mNetTrackers[type];
- NetworkInfo info = t.getNetworkInfo();
- if (info.isConnected()) {
- return t.getLinkProperties();
- }
- }
- return null;
+ return getLinkProperties(mActiveDefaultNetwork);
}
public LinkProperties getLinkProperties(int networkType) {
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index ae04b7f..f78dca9 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -163,6 +163,7 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
private final ArrayList<StorageVolume> mVolumes = new ArrayList<StorageVolume>();
private StorageVolume mPrimaryVolume;
private final HashMap<String, String> mVolumeStates = new HashMap<String, String>();
+ private final HashMap<String, StorageVolume> mVolumeMap = new HashMap<String, StorageVolume>();
private String mExternalStoragePath;
private PackageManagerService mPms;
private boolean mUmsEnabling;
@@ -672,8 +673,6 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
* Callback from NativeDaemonConnector
*/
public boolean onEvent(int code, String raw, String[] cooked) {
- Intent in = null;
-
if (DEBUG_EVENTS) {
StringBuilder builder = new StringBuilder();
builder.append("onEvent::");
@@ -708,6 +707,7 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
// FMT: NNN Volume <label> <mountpoint> disk inserted (<major>:<minor>)
// FMT: NNN Volume <label> <mountpoint> disk removed (<major>:<minor>)
// FMT: NNN Volume <label> <mountpoint> bad removal (<major>:<minor>)
+ String action = null;
final String label = cooked[2];
final String path = cooked[3];
int major = -1;
@@ -746,32 +746,31 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
/* Send the media unmounted event first */
if (DEBUG_EVENTS) Slog.i(TAG, "Sending unmounted event first");
updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
- in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
- mContext.sendBroadcast(in);
+ sendStorageIntent(Environment.MEDIA_UNMOUNTED, path);
if (DEBUG_EVENTS) Slog.i(TAG, "Sending media removed");
updatePublicVolumeState(path, Environment.MEDIA_REMOVED);
- in = new Intent(Intent.ACTION_MEDIA_REMOVED, Uri.parse("file://" + path));
+ action = Intent.ACTION_MEDIA_REMOVED;
} else if (code == VoldResponseCode.VolumeBadRemoval) {
if (DEBUG_EVENTS) Slog.i(TAG, "Sending unmounted event first");
/* Send the media unmounted event first */
updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
- in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
- mContext.sendBroadcast(in);
+ action = Intent.ACTION_MEDIA_UNMOUNTED;
if (DEBUG_EVENTS) Slog.i(TAG, "Sending media bad removal");
updatePublicVolumeState(path, Environment.MEDIA_BAD_REMOVAL);
- in = new Intent(Intent.ACTION_MEDIA_BAD_REMOVAL, Uri.parse("file://" + path));
+ action = Intent.ACTION_MEDIA_BAD_REMOVAL;
} else {
Slog.e(TAG, String.format("Unknown code {%d}", code));
}
+
+ if (action != null) {
+ sendStorageIntent(action, path);
+ }
} else {
return false;
}
- if (in != null) {
- mContext.sendBroadcast(in);
- }
return true;
}
@@ -779,12 +778,11 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
String vs = getVolumeState(path);
if (DEBUG_EVENTS) Slog.i(TAG, "notifyVolumeStateChanged::" + vs);
- Intent in = null;
+ String action = null;
if (oldState == VolumeState.Shared && newState != oldState) {
if (LOCAL_LOGD) Slog.d(TAG, "Sending ACTION_MEDIA_UNSHARED intent");
- mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_UNSHARED,
- Uri.parse("file://" + path)));
+ sendStorageIntent(Intent.ACTION_MEDIA_UNSHARED, path);
}
if (newState == VolumeState.Init) {
@@ -801,31 +799,29 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
Environment.MEDIA_UNMOUNTABLE) && !getUmsEnabling()) {
if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state for media bad removal nofs and unmountable");
updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
- in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
+ action = Intent.ACTION_MEDIA_UNMOUNTED;
}
} else if (newState == VolumeState.Pending) {
} else if (newState == VolumeState.Checking) {
if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state checking");
updatePublicVolumeState(path, Environment.MEDIA_CHECKING);
- in = new Intent(Intent.ACTION_MEDIA_CHECKING, Uri.parse("file://" + path));
+ action = Intent.ACTION_MEDIA_CHECKING;
} else if (newState == VolumeState.Mounted) {
if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state mounted");
updatePublicVolumeState(path, Environment.MEDIA_MOUNTED);
- in = new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + path));
- in.putExtra("read-only", false);
+ action = Intent.ACTION_MEDIA_MOUNTED;
} else if (newState == VolumeState.Unmounting) {
- in = new Intent(Intent.ACTION_MEDIA_EJECT, Uri.parse("file://" + path));
+ action = Intent.ACTION_MEDIA_EJECT;
} else if (newState == VolumeState.Formatting) {
} else if (newState == VolumeState.Shared) {
if (DEBUG_EVENTS) Slog.i(TAG, "Updating volume state media mounted");
/* Send the media unmounted event first */
updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
- in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
- mContext.sendBroadcast(in);
+ sendStorageIntent(Intent.ACTION_MEDIA_UNMOUNTED, path);
if (DEBUG_EVENTS) Slog.i(TAG, "Updating media shared");
updatePublicVolumeState(path, Environment.MEDIA_SHARED);
- in = new Intent(Intent.ACTION_MEDIA_SHARED, Uri.parse("file://" + path));
+ action = Intent.ACTION_MEDIA_SHARED;
if (LOCAL_LOGD) Slog.d(TAG, "Sending ACTION_MEDIA_SHARED intent");
} else if (newState == VolumeState.SharedMnt) {
Slog.e(TAG, "Live shared mounts not supported yet!");
@@ -834,8 +830,8 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
Slog.e(TAG, "Unhandled VolumeState {" + newState + "}");
}
- if (in != null) {
- mContext.sendBroadcast(in);
+ if (action != null) {
+ sendStorageIntent(action, path);
}
}
@@ -885,7 +881,7 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
/*
* Mount failed for some reason
*/
- Intent in = null;
+ String action = null;
int code = e.getCode();
if (code == VoldResponseCode.OpFailedNoMedia) {
/*
@@ -898,7 +894,7 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
* Media is blank or does not contain a supported filesystem
*/
updatePublicVolumeState(path, Environment.MEDIA_NOFS);
- in = new Intent(Intent.ACTION_MEDIA_NOFS, Uri.parse("file://" + path));
+ action = Intent.ACTION_MEDIA_NOFS;
rc = StorageResultCode.OperationFailedMediaBlank;
} else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state media corrupt");
@@ -906,7 +902,7 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
* Volume consistency check failed
*/
updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTABLE);
- in = new Intent(Intent.ACTION_MEDIA_UNMOUNTABLE, Uri.parse("file://" + path));
+ action = Intent.ACTION_MEDIA_UNMOUNTABLE;
rc = StorageResultCode.OperationFailedMediaCorrupt;
} else {
rc = StorageResultCode.OperationFailedInternalError;
@@ -915,8 +911,8 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
/*
* Send broadcast intent (if required for the failure)
*/
- if (in != null) {
- mContext.sendBroadcast(in);
+ if (action != null) {
+ sendStorageIntent(action, path);
}
}
@@ -1073,6 +1069,14 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
}
}
+ private void sendStorageIntent(String action, String path) {
+ Intent intent = new Intent(action, Uri.parse("file://" + path));
+ // add StorageVolume extra
+ intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, mVolumeMap.get(path));
+ Slog.d(TAG, "sendStorageIntent " + intent);
+ mContext.sendBroadcast(intent);
+ }
+
private void sendUmsIntent(boolean c) {
mContext.sendBroadcast(
new Intent((c ? Intent.ACTION_UMS_CONNECTED : Intent.ACTION_UMS_DISCONNECTED)));
@@ -1124,7 +1128,8 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
if (path == null || description == null) {
Slog.e(TAG, "path or description is null in readStorageList");
} else {
- StorageVolume volume = new StorageVolume(path.toString(),
+ String pathString = path.toString();
+ StorageVolume volume = new StorageVolume(pathString,
description.toString(), removable, emulated, mtpReserve);
if (primary) {
if (mPrimaryVolume == null) {
@@ -1139,6 +1144,7 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
} else {
mVolumes.add(volume);
}
+ mVolumeMap.put(pathString, volume);
}
a.recycle();
}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 7c613c1..8f179f5 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -16,51 +16,34 @@
package com.android.server;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources;
import android.content.pm.PackageManager;
-import android.net.NetworkStats;
-import android.net.Uri;
-import android.net.InterfaceConfiguration;
import android.net.INetworkManagementEventObserver;
+import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
+import android.net.NetworkStats;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.os.Binder;
import android.os.INetworkManagementService;
-import android.os.Handler;
-import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
-import java.util.ArrayList;
-import java.util.NoSuchElementException;
-import java.util.StringTokenizer;
-import android.provider.Settings;
-import android.content.ContentResolver;
-import android.database.ContentObserver;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileReader;
import java.io.IOException;
-import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.RandomAccessFile;
-import java.io.Reader;
-import java.lang.IllegalStateException;
-import java.net.InetAddress;
import java.net.Inet4Address;
-import java.net.UnknownHostException;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
import java.util.concurrent.CountDownLatch;
import libcore.io.IoUtils;
@@ -69,14 +52,16 @@ import libcore.io.IoUtils;
* @hide
*/
class NetworkManagementService extends INetworkManagementService.Stub {
-
- private static final String TAG = "NetworkManagmentService";
+ private static final String TAG = "NetworkManagementService";
private static final boolean DBG = false;
private static final String NETD_TAG = "NetdConnector";
private static final int ADD = 1;
private static final int REMOVE = 2;
+ /** Base path to UID-granularity network statistics. */
+ private static final File PATH_PROC_UID_STAT = new File("/proc/uid_stat");
+
class NetdResponseCode {
public static final int InterfaceListResult = 110;
public static final int TetherInterfaceListResult = 111;
@@ -891,7 +876,7 @@ class NetworkManagementService extends INetworkManagementService.Stub {
return -1;
}
- /** {@inheritDoc} */
+ @Override
public NetworkStats getNetworkStatsSummary() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
@@ -909,31 +894,46 @@ class NetworkManagementService extends INetworkManagementService.Stub {
return stats.build();
}
- /** {@inheritDoc} */
+ @Override
public NetworkStats getNetworkStatsDetail() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
- final File procPath = new File("/proc/uid_stat");
- final String[] knownUids = procPath.list();
+ final String[] knownUids = PATH_PROC_UID_STAT.list();
final NetworkStats.Builder stats = new NetworkStats.Builder(
SystemClock.elapsedRealtime(), knownUids.length);
- // TODO: kernel module will provide interface-level stats in future
- // TODO: migrate these stats to come across netd in bulk, instead of all
- // these individual file reads.
for (String uid : knownUids) {
- final File uidPath = new File(procPath, uid);
- final int rx = readSingleIntFromFile(new File(uidPath, "tcp_rcv"));
- final int tx = readSingleIntFromFile(new File(uidPath, "tcp_snd"));
-
final int uidInt = Integer.parseInt(uid);
- stats.addEntry(NetworkStats.IFACE_ALL, uidInt, rx, tx);
+ collectNetworkStatsDetail(stats, uidInt);
}
return stats.build();
}
+ @Override
+ public NetworkStats getNetworkStatsUidDetail(int uid) {
+ if (Binder.getCallingUid() != uid) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
+ }
+
+ final NetworkStats.Builder stats = new NetworkStats.Builder(
+ SystemClock.elapsedRealtime(), 1);
+ collectNetworkStatsDetail(stats, uid);
+ return stats.build();
+ }
+
+ private void collectNetworkStatsDetail(NetworkStats.Builder stats, int uid) {
+ // TODO: kernel module will provide interface-level stats in future
+ // TODO: migrate these stats to come across netd in bulk, instead of all
+ // these individual file reads.
+ final File uidPath = new File(PATH_PROC_UID_STAT, Integer.toString(uid));
+ final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
+ final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
+ stats.addEntry(NetworkStats.IFACE_ALL, uid, rx, tx);
+ }
+
public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
@@ -994,22 +994,17 @@ class NetworkManagementService extends INetworkManagementService.Stub {
}
/**
- * Utility method to read a single plain-text {@link Integer} from the given
+ * Utility method to read a single plain-text {@link Long} from the given
* {@link File}, usually from a {@code /proc/} filesystem.
*/
- private static int readSingleIntFromFile(File file) {
- RandomAccessFile f = null;
+ private static long readSingleLongFromFile(File file) {
try {
- f = new RandomAccessFile(file, "r");
- byte[] buffer = new byte[(int) f.length()];
- f.readFully(buffer);
- return Integer.parseInt(new String(buffer).trim());
+ final byte[] buffer = IoUtils.readFileAsByteArray(file.toString());
+ return Long.parseLong(new String(buffer).trim());
} catch (NumberFormatException e) {
return -1;
} catch (IOException e) {
return -1;
- } finally {
- IoUtils.closeQuietly(f);
}
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index cd8915d..5355d44 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -18,6 +18,7 @@ package com.android.server;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.am.ActivityManagerService;
+import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.pm.PackageManagerService;
import com.android.server.usb.UsbService;
import com.android.server.wm.WindowManagerService;
@@ -119,6 +120,7 @@ class ServerThread extends Thread {
LightsService lights = null;
PowerManagerService power = null;
BatteryService battery = null;
+ NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
IPackageManager pm = null;
Context context = null;
@@ -282,6 +284,15 @@ class ServerThread extends Thread {
}
try {
+ Slog.i(TAG, "NetworkPolicy Service");
+ networkPolicy = new NetworkPolicyManagerService(
+ context, ActivityManagerService.self(), power);
+ ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failure starting Connectivity Service", e);
+ }
+
+ try {
Slog.i(TAG, "NetworkManagement Service");
ServiceManager.addService(
Context.NETWORKMANAGEMENT_SERVICE,
@@ -528,6 +539,7 @@ class ServerThread extends Thread {
// These are needed to propagate to the runnable below.
final Context contextF = context;
final BatteryService batteryF = battery;
+ final NetworkPolicyManagerService networkPolicyF = networkPolicy;
final ConnectivityService connectivityF = connectivity;
final DockObserver dockF = dock;
final UsbService usbF = usb;
@@ -553,6 +565,7 @@ class ServerThread extends Thread {
startSystemUi(contextF);
if (batteryF != null) batteryF.systemReady();
+ if (networkPolicyF != null) networkPolicyF.systemReady();
if (connectivityF != null) connectivityF.systemReady();
if (dockF != null) dockF.systemReady();
if (usbF != null) usbF.systemReady();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index fca2418..cf5592c 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -43,6 +43,7 @@ import android.app.IActivityWatcher;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
import android.app.INotificationManager;
+import android.app.IProcessObserver;
import android.app.IServiceConnection;
import android.app.IThumbnailReceiver;
import android.app.IThumbnailRetriever;
@@ -752,8 +753,6 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
final UsageStatsService mUsageStatsService;
- final NetworkPolicyManagerService mNetworkPolicyService;
-
/**
* Current configuration information. HistoryRecord objects are given
* a reference to this object to indicate which configuration they are
@@ -877,7 +876,10 @@ public final class ActivityManagerService extends ActivityManagerNative
final RemoteCallbackList<IActivityWatcher> mWatchers
= new RemoteCallbackList<IActivityWatcher>();
-
+
+ final RemoteCallbackList<IProcessObserver> mProcessObservers
+ = new RemoteCallbackList<IProcessObserver>();
+
/**
* Callback of last caller to {@link #requestPss}.
*/
@@ -1269,16 +1271,15 @@ public final class ActivityManagerService extends ActivityManagerNative
}
} break;
case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
- // Flag might have changed during dispatch, but it's always
- // consistent since we dispatch for every change.
final ProcessRecord app = (ProcessRecord) msg.obj;
- mNetworkPolicyService.onForegroundActivitiesChanged(
- app.info.uid, app.pid, app.foregroundActivities);
+ final boolean foregroundActivities = msg.arg1 != 0;
+ dispatchForegroundActivitiesChanged(
+ app.pid, app.info.uid, foregroundActivities);
break;
}
case DISPATCH_PROCESS_DIED: {
final ProcessRecord app = (ProcessRecord) msg.obj;
- mNetworkPolicyService.onProcessDied(app.info.uid, app.pid);
+ dispatchProcessDied(app.pid, app.info.uid);
break;
}
}
@@ -1350,7 +1351,6 @@ public final class ActivityManagerService extends ActivityManagerNative
m.mBatteryStatsService.publish(context);
m.mUsageStatsService.publish(context);
- m.mNetworkPolicyService.publish(context);
synchronized (thr) {
thr.mReady = true;
@@ -1463,8 +1463,6 @@ public final class ActivityManagerService extends ActivityManagerNative
mUsageStatsService = new UsageStatsService(new File(
systemDir, "usagestats").toString());
- mNetworkPolicyService = new NetworkPolicyManagerService();
-
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
@@ -2134,6 +2132,36 @@ public final class ActivityManagerService extends ActivityManagerNative
mWatchers.finishBroadcast();
}
+ private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
+ int i = mProcessObservers.beginBroadcast();
+ while (i > 0) {
+ i--;
+ final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
+ if (observer != null) {
+ try {
+ observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ mProcessObservers.finishBroadcast();
+ }
+
+ private void dispatchProcessDied(int pid, int uid) {
+ int i = mProcessObservers.beginBroadcast();
+ while (i > 0) {
+ i--;
+ final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
+ if (observer != null) {
+ try {
+ observer.onProcessDied(pid, uid);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ mProcessObservers.finishBroadcast();
+ }
+
final void doPendingActivityLaunchesLocked(boolean doResume) {
final int N = mPendingActivityLaunches.size();
if (N <= 0) {
@@ -6066,7 +6094,6 @@ public final class ActivityManagerService extends ActivityManagerNative
mUsageStatsService.shutdown();
mBatteryStatsService.shutdown();
- mNetworkPolicyService.shutdown();
return timedout;
}
@@ -6223,6 +6250,14 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ public void registerProcessObserver(IProcessObserver observer) {
+ mProcessObservers.register(observer);
+ }
+
+ public void unregisterProcessObserver(IProcessObserver observer) {
+ mProcessObservers.unregister(observer);
+ }
+
public void setImmersive(IBinder token, boolean immersive) {
synchronized(this) {
int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
@@ -12737,7 +12772,8 @@ public final class ActivityManagerService extends ActivityManagerNative
app.curSchedGroup = schedGroup;
if (hadForegroundActivities != app.foregroundActivities) {
- mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app).sendToTarget();
+ mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED,
+ app.foregroundActivities ? 1 : 0, 0, app).sendToTarget();
}
return adj;
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index b1ab05b..67e73f5 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -277,8 +277,8 @@ public class GpsLocationProvider implements LocationProviderInterface {
private final SparseIntArray mClientUids = new SparseIntArray();
// how often to request NTP time, in milliseconds
- // current setting 4 hours
- private static final long NTP_INTERVAL = 4*60*60*1000;
+ // current setting 24 hours
+ private static final long NTP_INTERVAL = 24*60*60*1000;
// how long to wait if we have a network error in NTP or XTRA downloading
// current setting - 5 minutes
private static final long RETRY_INTERVAL = 5*60*1000;
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index a7a4f07..d083d01 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -19,13 +19,20 @@ package com.android.server.net;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.net.NetworkPolicyManager.POLICY_NONE;
-import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID;
import static android.net.NetworkPolicyManager.POLICY_REJECT_BACKGROUND;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID;
+import android.app.IActivityManager;
+import android.app.IProcessObserver;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.net.INetworkPolicyManager;
-import android.os.ServiceManager;
+import android.os.IPowerManager;
+import android.os.RemoteException;
import android.util.Log;
+import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
@@ -38,92 +45,139 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final String TAG = "NetworkPolicy";
private static final boolean LOGD = true;
- private static final String SERVICE_NAME = "netpolicy";
-
private Context mContext;
+ private IActivityManager mActivityManager;
+ private IPowerManager mPowerManager;
+
+ private Object mRulesLock = new Object();
+
+ private boolean mScreenOn = false;
/** Current network policy for each UID. */
- private SparseIntArray mUidPolicy;
+ private SparseIntArray mUidPolicy = new SparseIntArray();
/** Foreground at both UID and PID granularity. */
- private SparseBooleanArray mUidForeground;
- private SparseArray<SparseBooleanArray> mUidPidForeground;
+ private SparseBooleanArray mUidForeground = new SparseBooleanArray();
+ private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
+ SparseBooleanArray>();
// TODO: periodically poll network stats and write to disk
// TODO: save/restore policy information from disk
- // TODO: watch screen on/off broadcasts to track foreground
+ public NetworkPolicyManagerService(
+ Context context, IActivityManager activityManager, IPowerManager powerManager) {
+ mContext = checkNotNull(context, "missing context");
+ mActivityManager = checkNotNull(activityManager, "missing activityManager");
+ mPowerManager = checkNotNull(powerManager, "missing powerManager");
+ }
- public void publish(Context context) {
- mContext = context;
- ServiceManager.addService(SERVICE_NAME, asBinder());
+ public void systemReady() {
+ // TODO: read current policy+stats from disk and generate NMS rules
- mUidPolicy = new SparseIntArray();
- mUidForeground = new SparseBooleanArray();
- mUidPidForeground = new SparseArray<SparseBooleanArray>();
+ updateScreenOn();
- // TODO: register for NetworkManagementService callbacks
- // TODO: read current policy+stats from disk and generate NMS rules
- }
+ try {
+ mActivityManager.registerProcessObserver(mProcessObserver);
+ } catch (RemoteException e) {
+ // ouch, no foregroundActivities updates means some processes may
+ // never get network access.
+ Slog.e(TAG, "unable to register IProcessObserver", e);
+ }
- public void shutdown() {
- // TODO: persist any pending stats during clean shutdown
+ // TODO: traverse existing processes to know foreground state, or have
+ // activitymanager dispatch current state when new observer attached.
- mUidPolicy = null;
- mUidForeground = null;
- mUidPidForeground = null;
- }
+ final IntentFilter screenFilter = new IntentFilter();
+ screenFilter.addAction(Intent.ACTION_SCREEN_ON);
+ screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
+ mContext.registerReceiver(mScreenReceiver, screenFilter);
- @Override
- public void onForegroundActivitiesChanged(int uid, int pid, boolean foreground) {
- // only someone like AMS should only be calling us
- mContext.enforceCallingOrSelfPermission(
- MANAGE_APP_TOKENS, "requires MANAGE_APP_TOKENS permission");
+ final IntentFilter shutdownFilter = new IntentFilter();
+ shutdownFilter.addAction(Intent.ACTION_SHUTDOWN);
+ mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
- // because a uid can have multiple pids running inside, we need to
- // remember all pid states and summarize foreground at uid level.
+ }
- // record foreground for this specific pid
- SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
- if (pidForeground == null) {
- pidForeground = new SparseBooleanArray(2);
- mUidPidForeground.put(uid, pidForeground);
+ private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
+ @Override
+ public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
+ // only someone like AMS should only be calling us
+ mContext.enforceCallingOrSelfPermission(
+ MANAGE_APP_TOKENS, "requires MANAGE_APP_TOKENS permission");
+
+ synchronized (mRulesLock) {
+ // because a uid can have multiple pids running inside, we need to
+ // remember all pid states and summarize foreground at uid level.
+
+ // record foreground for this specific pid
+ SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
+ if (pidForeground == null) {
+ pidForeground = new SparseBooleanArray(2);
+ mUidPidForeground.put(uid, pidForeground);
+ }
+ pidForeground.put(pid, foregroundActivities);
+ computeUidForegroundL(uid);
+ }
}
- pidForeground.put(pid, foreground);
- computeUidForeground(uid);
- }
- @Override
- public void onProcessDied(int uid, int pid) {
- // only someone like AMS should only be calling us
- mContext.enforceCallingOrSelfPermission(
- MANAGE_APP_TOKENS, "requires MANAGE_APP_TOKENS permission");
+ @Override
+ public void onProcessDied(int pid, int uid) {
+ // only someone like AMS should only be calling us
+ mContext.enforceCallingOrSelfPermission(
+ MANAGE_APP_TOKENS, "requires MANAGE_APP_TOKENS permission");
+
+ synchronized (mRulesLock) {
+ // clear records and recompute, when they exist
+ final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
+ if (pidForeground != null) {
+ pidForeground.delete(pid);
+ computeUidForegroundL(uid);
+ }
+ }
+ }
+ };
+
+ private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mRulesLock) {
+ // screen-related broadcasts are protected by system, no need
+ // for permissions check.
+ updateScreenOn();
+ }
+ }
+ };
- // clear records and recompute, when they exist
- final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
- if (pidForeground != null) {
- pidForeground.delete(pid);
- computeUidForeground(uid);
+ private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // TODO: persist any pending stats during clean shutdown
+ Log.d(TAG, "persisting stats");
}
- }
+ };
@Override
public void setUidPolicy(int uid, int policy) {
mContext.enforceCallingOrSelfPermission(
UPDATE_DEVICE_STATS, "requires UPDATE_DEVICE_STATS permission");
- mUidPolicy.put(uid, policy);
+
+ synchronized (mRulesLock) {
+ mUidPolicy.put(uid, policy);
+ }
}
@Override
public int getUidPolicy(int uid) {
- return mUidPolicy.get(uid, POLICY_NONE);
+ synchronized (mRulesLock) {
+ return mUidPolicy.get(uid, POLICY_NONE);
+ }
}
/**
* Foreground for PID changed; recompute foreground at UID level. If
- * changed, will trigger {@link #updateRulesForUid(int)}.
+ * changed, will trigger {@link #updateRulesForUidL(int)}.
*/
- private void computeUidForeground(int uid) {
+ private void computeUidForegroundL(int uid) {
final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
// current pid is dropping foreground; examine other pids
@@ -140,12 +194,37 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (oldUidForeground != uidForeground) {
// foreground changed, push updated rules
mUidForeground.put(uid, uidForeground);
- updateRulesForUid(uid);
+ updateRulesForUidL(uid);
+ }
+ }
+
+ private void updateScreenOn() {
+ synchronized (mRulesLock) {
+ try {
+ mScreenOn = mPowerManager.isScreenOn();
+ } catch (RemoteException e) {
+ }
+ updateRulesForScreenL();
+ }
+ }
+
+ /**
+ * Update rules that might be changed by {@link #mScreenOn} value.
+ */
+ private void updateRulesForScreenL() {
+ // only update rules for anyone with foreground activities
+ final int size = mUidForeground.size();
+ for (int i = 0; i < size; i++) {
+ if (mUidForeground.valueAt(i)) {
+ final int uid = mUidForeground.keyAt(i);
+ updateRulesForUidL(uid);
+ }
}
}
- private void updateRulesForUid(int uid) {
- final boolean uidForeground = mUidForeground.get(uid, false);
+ private void updateRulesForUidL(int uid) {
+ // only really in foreground when screen on
+ final boolean uidForeground = mUidForeground.get(uid, false) && mScreenOn;
final int uidPolicy = getUidPolicy(uid);
if (LOGD) {
@@ -162,4 +241,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ private static <T> T checkNotNull(T value, String message) {
+ if (value == null) {
+ throw new NullPointerException(message);
+ }
+ return value;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
index f20d5e5..ca33d32 100644
--- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
@@ -42,6 +42,7 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.Suppress;
import android.text.format.DateUtils;
import android.util.Log;
@@ -54,6 +55,7 @@ import java.util.concurrent.Future;
/**
* Tests for {@link ThrottleService}.
*/
+@LargeTest
public class ThrottleServiceTest extends AndroidTestCase {
private static final String TAG = "ThrottleServiceTest";