diff options
Diffstat (limited to 'services')
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"; |