diff options
Diffstat (limited to 'services/java')
17 files changed, 1383 insertions, 594 deletions
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java index 87de79a..83ce3e3 100644 --- a/services/java/com/android/server/AccessibilityManagerService.java +++ b/services/java/com/android/server/AccessibilityManagerService.java @@ -269,14 +269,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub }); } - public void addClient(IAccessibilityManagerClient client) { + public boolean addClient(IAccessibilityManagerClient client) { synchronized (mLock) { - try { - client.setEnabled(mIsEnabled); - mClients.add(client); - } catch (RemoteException re) { - Slog.w(LOG_TAG, "Dead AccessibilityManagerClient: " + client, re); - } + mClients.add(client); + return mIsEnabled; } } diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index 3ed6c12..3059732 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -425,6 +425,23 @@ class AppWidgetService extends IAppWidgetService.Stub } } + public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, RemoteViews views, int viewId) { + if (appWidgetIds == null) { + return; + } + if (appWidgetIds.length == 0) { + return; + } + final int N = appWidgetIds.length; + + synchronized (mAppWidgetIds) { + for (int i=0; i<N; i++) { + AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]); + notifyAppWidgetViewDataChangedInstanceLocked(id, views, viewId); + } + } + } + public void updateAppWidgetProvider(ComponentName provider, RemoteViews views) { synchronized (mAppWidgetIds) { Provider p = lookupProviderLocked(provider); @@ -462,6 +479,27 @@ class AppWidgetService extends IAppWidgetService.Stub } } + void notifyAppWidgetViewDataChangedInstanceLocked(AppWidgetId id, RemoteViews views, int viewId) { + // allow for stale appWidgetIds and other badness + // lookup also checks that the calling process can access the appWidgetId + // drop unbound appWidgetIds (shouldn't be possible under normal circumstances) + if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) { + id.views = views; + + // is anyone listening? + if (id.host.callbacks != null) { + try { + // the lock is held, but this is a oneway call + id.host.callbacks.viewDataChanged(id.appWidgetId, views, viewId); + } catch (RemoteException e) { + // It failed; remove the callback. No need to prune because + // we know that this host is still referenced by this instance. + id.host.callbacks = null; + } + } + } + } + public int[] startListening(IAppWidgetHost callbacks, String packageName, int hostId, List<RemoteViews> updatedViews) { int callingUid = enforceCallingUid(packageName); @@ -741,6 +779,9 @@ class AppWidgetService extends IAppWidgetService.Stub } info.label = activityInfo.loadLabel(mPackageManager).toString(); info.icon = ri.getIconResource(); + info.previewImage = sa.getResourceId( + com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0); + sa.recycle(); } catch (Exception e) { // Ok to catch Exception here, because anything going wrong because diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 81b8d40..9c504fe 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -26,13 +26,16 @@ import android.net.ConnectivityManager; import android.net.IConnectivityManager; import android.net.MobileDataStateTracker; import android.net.NetworkInfo; +import android.net.NetworkProperties; import android.net.NetworkStateTracker; import android.net.wifi.WifiStateTracker; +import android.net.NetworkUtils; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; @@ -46,8 +49,13 @@ import com.android.internal.telephony.Phone; import com.android.server.connectivity.Tethering; import java.io.FileDescriptor; +import java.io.FileWriter; +import java.io.IOException; import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -64,7 +72,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { private static final String NETWORK_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore"; - private Tethering mTethering; private boolean mTetheringConfigValid = false; @@ -104,6 +111,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { private boolean mSystemReady; private Intent mInitialBroadcast; + private PowerManager.WakeLock mNetTransitionWakeLock; + private String mNetTransitionWakeLockCausedBy = ""; + private int mNetTransitionWakeLockSerialNumber; + private int mNetTransitionWakeLockTimeout; + private static class NetworkAttributes { /** * Class for holding settings read from resources. @@ -194,6 +206,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { } mContext = context; + + PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); + mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); + mNetTransitionWakeLockTimeout = mContext.getResources().getInteger( + com.android.internal.R.integer.config_networkTransitionTimeout); + mNetTrackers = new NetworkStateTracker[ ConnectivityManager.MAX_NETWORK_TYPE+1]; mHandler = new MyHandler(); @@ -597,15 +615,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { network.reconnect(); return Phone.APN_REQUEST_STARTED; } else { - synchronized(this) { - mFeatureUsers.add(f); - } - mHandler.sendMessageDelayed(mHandler.obtainMessage( - NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK, - f), getRestoreDefaultNetworkDelay()); - - return network.startUsingNetworkFeature(feature, - getCallingPid(), getCallingUid()); + return -1; } } return Phone.APN_TYPE_NOT_AVAILABLE; @@ -724,8 +734,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { tracker.teardown(); return 1; } else { - // do it the old fashioned way - return tracker.stopUsingNetworkFeature(feature, pid, uid); + return -1; } } @@ -736,6 +745,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { * specified host is to be routed * @param hostAddress the IP address of the host to which the route is * desired + * todo - deprecate (only v4!) * @return {@code true} on success, {@code false} on failure */ public boolean requestRouteToHost(int networkType, int hostAddress) { @@ -752,7 +762,39 @@ public class ConnectivityService extends IConnectivityManager.Stub { } return false; } - return tracker.requestRouteToHost(hostAddress); + try { + InetAddress addr = InetAddress.getByAddress(NetworkUtils.v4IntToArray(hostAddress)); + return addHostRoute(tracker, addr); + } catch (UnknownHostException e) {} + return false; + } + + /** + * Ensure that a network route exists to deliver traffic to the specified + * host via the mobile data network. + * @param hostAddress the IP address of the host to which the route is desired, + * in network byte order. + * TODO - deprecate + * @return {@code true} on success, {@code false} on failure + */ + private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress) { + if (nt.getNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) { + return false; + } + + NetworkProperties p = nt.getNetworkProperties(); + if (p == null) return false; + String interfaceName = p.getInterfaceName(); + + if (DBG) { + Slog.d(TAG, "Requested host route to " + hostAddress + "(" + interfaceName + ")"); + } + if (interfaceName != null) { + return NetworkUtils.addHostRoute(interfaceName, hostAddress) == 0; + } else { + if (DBG) Slog.e(TAG, "addHostRoute failed due to null interface name"); + return false; + } } /** @@ -859,6 +901,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { "ConnectivityService"); } + private void enforceConnectivityInternalPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CONNECTIVITY_INTERNAL, + "ConnectivityService"); + } + /** * Handle a {@code DISCONNECTED} event. If this pertains to the non-active * network, we ignore it. If it is for the active network, we send out a @@ -1134,15 +1182,23 @@ public class ConnectivityService extends IConnectivityManager.Stub { Slog.e(TAG, "Network declined teardown request"); return; } - if (isFailover) { - otherNet.releaseWakeLock(); - } + } + } + synchronized (ConnectivityService.this) { + // have a new default network, release the transition wakelock in a second + // if it's held. The second pause is to allow apps to reconnect over the + // new network + if (mNetTransitionWakeLock.isHeld()) { + mHandler.sendMessageDelayed(mHandler.obtainMessage( + NetworkStateTracker.EVENT_CLEAR_NET_TRANSITION_WAKELOCK, + mNetTransitionWakeLockSerialNumber, 0), + 1000); } } mActiveDefaultNetwork = type; } thisNet.setTeardownRequested(false); - thisNet.updateNetworkSettings(); + updateNetworkSettings(thisNet); handleConnectivityChange(); sendConnectedBroadcast(info); } @@ -1192,20 +1248,167 @@ public class ConnectivityService extends IConnectivityManager.Stub { for (int netType : mPriorityList) { if (mNetTrackers[netType].getNetworkInfo().isConnected()) { if (mNetAttributes[netType].isDefault()) { - mNetTrackers[netType].addDefaultRoute(); + addDefaultRoute(mNetTrackers[netType]); } else { - mNetTrackers[netType].addPrivateDnsRoutes(); + addPrivateDnsRoutes(mNetTrackers[netType]); } } else { if (mNetAttributes[netType].isDefault()) { - mNetTrackers[netType].removeDefaultRoute(); + removeDefaultRoute(mNetTrackers[netType]); } else { - mNetTrackers[netType].removePrivateDnsRoutes(); + removePrivateDnsRoutes(mNetTrackers[netType]); } } } } + private void addPrivateDnsRoutes(NetworkStateTracker nt) { + boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet(); + NetworkProperties p = nt.getNetworkProperties(); + if (p == null) return; + String interfaceName = p.getInterfaceName(); + + if (DBG) { + Slog.d(TAG, "addPrivateDnsRoutes for " + nt + + "(" + interfaceName + ") - mPrivateDnsRouteSet = " + privateDnsRouteSet); + } + if (interfaceName != null && !privateDnsRouteSet) { + Collection<InetAddress> dnsList = p.getDnses(); + for (InetAddress dns : dnsList) { + if (DBG) Slog.d(TAG, " adding " + dns); + NetworkUtils.addHostRoute(interfaceName, dns); + } + nt.privateDnsRouteSet(true); + } + } + + private void removePrivateDnsRoutes(NetworkStateTracker nt) { + // TODO - we should do this explicitly but the NetUtils api doesnt + // support this yet - must remove all. No worse than before + NetworkProperties p = nt.getNetworkProperties(); + if (p == null) return; + String interfaceName = p.getInterfaceName(); + boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet(); + if (interfaceName != null && privateDnsRouteSet) { + if (DBG) { + Slog.d(TAG, "removePrivateDnsRoutes for " + nt.getNetworkInfo().getTypeName() + + " (" + interfaceName + ")"); + } + NetworkUtils.removeHostRoutes(interfaceName); + nt.privateDnsRouteSet(false); + } + } + + + private void addDefaultRoute(NetworkStateTracker nt) { + NetworkProperties p = nt.getNetworkProperties(); + if (p == null) return; + String interfaceName = p.getInterfaceName(); + InetAddress defaultGatewayAddr = p.getGateway(); + boolean defaultRouteSet = nt.isDefaultRouteSet(); + + if ((interfaceName != null) && (defaultGatewayAddr != null ) && + (defaultRouteSet == false)) { + boolean error = (NetworkUtils.setDefaultRoute(interfaceName, defaultGatewayAddr) < 0); + + if (DBG && !error) { + NetworkInfo networkInfo = nt.getNetworkInfo(); + Slog.d(TAG, "addDefaultRoute for " + networkInfo.getTypeName() + + " (" + interfaceName + "), GatewayAddr=" + defaultGatewayAddr); + } + nt.defaultRouteSet(!error); + } + } + + + public void removeDefaultRoute(NetworkStateTracker nt) { + NetworkProperties p = nt.getNetworkProperties(); + if (p == null) return; + String interfaceName = p.getInterfaceName(); + boolean defaultRouteSet = nt.isDefaultRouteSet(); + + if (interfaceName != null && defaultRouteSet == true) { + boolean error = (NetworkUtils.removeDefaultRoute(interfaceName) < 0); + if (DBG && !error) { + NetworkInfo networkInfo = nt.getNetworkInfo(); + Slog.d(TAG, "removeDefaultRoute for " + networkInfo.getTypeName() + " (" + + interfaceName + ")"); + } + nt.defaultRouteSet(error); + } + } + + /** + * Reads the network specific TCP buffer sizes from SystemProperties + * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system + * wide use + */ + public void updateNetworkSettings(NetworkStateTracker nt) { + String key = nt.getTcpBufferSizesPropName(); + String bufferSizes = SystemProperties.get(key); + + if (bufferSizes.length() == 0) { + Slog.e(TAG, key + " not found in system properties. Using defaults"); + + // Setting to default values so we won't be stuck to previous values + key = "net.tcp.buffersize.default"; + bufferSizes = SystemProperties.get(key); + } + + // Set values in kernel + if (bufferSizes.length() != 0) { + if (DBG) { + Slog.v(TAG, "Setting TCP values: [" + bufferSizes + + "] which comes from [" + key + "]"); + } + setBufferSize(bufferSizes); + } + } + + /** + * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max] + * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem + * + * @param bufferSizes in the format of "readMin, readInitial, readMax, + * writeMin, writeInitial, writeMax" + */ + private void setBufferSize(String bufferSizes) { + try { + String[] values = bufferSizes.split(","); + + if (values.length == 6) { + final String prefix = "/sys/kernel/ipv4/tcp_"; + stringToFile(prefix + "rmem_min", values[0]); + stringToFile(prefix + "rmem_def", values[1]); + stringToFile(prefix + "rmem_max", values[2]); + stringToFile(prefix + "wmem_min", values[3]); + stringToFile(prefix + "wmem_def", values[4]); + stringToFile(prefix + "wmem_max", values[5]); + } else { + Slog.e(TAG, "Invalid buffersize string: " + bufferSizes); + } + } catch (IOException e) { + Slog.e(TAG, "Can't set tcp buffer sizes:" + e); + } + } + + /** + * Writes string to file. Basically same as "echo -n $string > $filename" + * + * @param filename + * @param string + * @throws IOException + */ + private void stringToFile(String filename, String string) throws IOException { + FileWriter out = new FileWriter(filename); + try { + out.write(string); + } finally { + out.close(); + } + } + + /** * Adjust the per-process dns entries (net.dns<x>.<pid>) based * on the highest priority active net which this process requested. @@ -1221,12 +1424,14 @@ public class ConnectivityService extends IConnectivityManager.Stub { NetworkStateTracker nt = mNetTrackers[i]; if (nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) { + NetworkProperties p = nt.getNetworkProperties(); + if (p == null) continue; List pids = mNetRequestersPids[i]; for (int j=0; j<pids.size(); j++) { Integer pid = (Integer)pids.get(j); if (pid.intValue() == myPid) { - String[] dnsList = nt.getNameServers(); - writePidDns(dnsList, myPid); + Collection<InetAddress> dnses = p.getDnses(); + writePidDns(dnses, myPid); if (doBump) { bumpDns(); } @@ -1248,12 +1453,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } - private void writePidDns(String[] dnsList, int pid) { + private void writePidDns(Collection <InetAddress> dnses, int pid) { int j = 1; - for (String dns : dnsList) { - if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) { - SystemProperties.set("net.dns" + j++ + "." + pid, dns); - } + for (InetAddress dns : dnses) { + SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress()); } } @@ -1279,17 +1482,17 @@ public class ConnectivityService extends IConnectivityManager.Stub { NetworkStateTracker nt = mNetTrackers[netType]; if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) { - String[] dnsList = nt.getNameServers(); + NetworkProperties p = nt.getNetworkProperties(); + if (p == null) continue; + Collection<InetAddress> dnses = p.getDnses(); if (mNetAttributes[netType].isDefault()) { int j = 1; - for (String dns : dnsList) { - if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) { - if (DBG) { - Slog.d(TAG, "adding dns " + dns + " for " + - nt.getNetworkInfo().getTypeName()); - } - SystemProperties.set("net.dns" + j++, dns); + for (InetAddress dns : dnses) { + if (DBG) { + Slog.d(TAG, "adding dns " + dns + " for " + + nt.getNetworkInfo().getTypeName()); } + SystemProperties.set("net.dns" + j++, dns.getHostAddress()); } for (int k=j ; k<mNumDnsEntries; k++) { if (DBG) Slog.d(TAG, "erasing net.dns" + k); @@ -1301,7 +1504,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { List pids = mNetRequestersPids[netType]; for (int y=0; y< pids.size(); y++) { Integer pid = (Integer)pids.get(y); - writePidDns(dnsList, pid.intValue()); + writePidDns(dnses, pid.intValue()); } } } @@ -1362,6 +1565,13 @@ public class ConnectivityService extends IConnectivityManager.Stub { } pw.println(); + synchronized (this) { + pw.println("NetworkTranstionWakeLock is currently " + + (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held."); + pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy); + } + pw.println(); + mTethering.dump(fd, pw, args); } @@ -1453,6 +1663,20 @@ public class ConnectivityService extends IConnectivityManager.Stub { FeatureUser u = (FeatureUser)msg.obj; u.expire(); break; + case NetworkStateTracker.EVENT_CLEAR_NET_TRANSITION_WAKELOCK: + String causedBy = null; + synchronized (ConnectivityService.this) { + if (msg.arg1 == mNetTransitionWakeLockSerialNumber && + mNetTransitionWakeLock.isHeld()) { + mNetTransitionWakeLock.release(); + causedBy = mNetTransitionWakeLockCausedBy; + } + } + if (causedBy != null) { + Slog.d(TAG, "NetTransition Wakelock for " + + causedBy + " released by timeout"); + } + break; } } } @@ -1536,4 +1760,23 @@ public class ConnectivityService extends IConnectivityManager.Stub { Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0); return tetherEnabledInSettings && mTetheringConfigValid; } + + // An API NetworkStateTrackers can call when they lose their network. + // This will automatically be cleared after X seconds or a network becomes CONNECTED, + // whichever happens first. The timer is started by the first caller and not + // restarted by subsequent callers. + public void requestNetworkTransitionWakelock(String forWhom) { + enforceConnectivityInternalPermission(); + synchronized (this) { + if (mNetTransitionWakeLock.isHeld()) return; + mNetTransitionWakeLockSerialNumber++; + mNetTransitionWakeLock.acquire(); + mNetTransitionWakeLockCausedBy = forWhom; + } + mHandler.sendMessageDelayed(mHandler.obtainMessage( + NetworkStateTracker.EVENT_CLEAR_NET_TRANSITION_WAKELOCK, + mNetTransitionWakeLockSerialNumber, 0), + mNetTransitionWakeLockTimeout); + return; + } } diff --git a/services/java/com/android/server/DemoDataSet.java b/services/java/com/android/server/DemoDataSet.java deleted file mode 100644 index 277985f..0000000 --- a/services/java/com/android/server/DemoDataSet.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.content.res.AssetManager; -import android.net.Uri; -import android.os.Environment; -import android.provider.Contacts; -import android.provider.Settings; -import android.provider.MediaStore.Images; -import android.util.Config; -import android.util.Slog; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.OutputStream; - -public class DemoDataSet -{ - private final static String LOG_TAG = "DemoDataSet"; - - private ContentResolver mContentResolver; - - public final void add(Context context) - { - mContentResolver = context.getContentResolver(); - - // Remove all the old data - mContentResolver.delete(Contacts.People.CONTENT_URI, null, null); - - // Add the new data - addDefaultData(); - - // Add images from /android/images - addDefaultImages(); - } - - private final void addDefaultImages() - { - File rootDirectory = Environment.getRootDirectory(); - String [] files - = new File(rootDirectory, "images").list(); - int count = files.length; - - if (count == 0) { - Slog.i(LOG_TAG, "addDefaultImages: no images found!"); - return; - } - - for (int i = 0; i < count; i++) - { - String name = files[i]; - String path = rootDirectory + "/" + name; - - try { - Images.Media.insertImage(mContentResolver, path, name, null); - } catch (FileNotFoundException e) { - Slog.e(LOG_TAG, "Failed to import image " + path, e); - } - } - } - - private final void addDefaultData() - { - Slog.i(LOG_TAG, "Adding default data..."); - -// addImage("Violet", "images/violet.png"); -// addImage("Corky", "images/corky.png"); - - // PENDING: should this be done here?!?! - Intent intent = new Intent( - Intent.ACTION_CALL, Uri.fromParts("voicemail", "", null)); - addShortcut("1", intent); - } - - private final Uri addImage(String name, Uri file) - { - ContentValues imagev = new ContentValues(); - imagev.put("name", name); - - Uri url = null; - - AssetManager ass = AssetManager.getSystem(); - InputStream in = null; - OutputStream out = null; - - try - { - in = ass.open(file.toString()); - - url = mContentResolver.insert(Images.Media.INTERNAL_CONTENT_URI, imagev); - out = mContentResolver.openOutputStream(url); - - final int size = 8 * 1024; - byte[] buf = new byte[size]; - - int count = 0; - do - { - count = in.read(buf, 0, size); - if (count > 0) { - out.write(buf, 0, count); - } - } while (count > 0); - } - catch (Exception e) - { - Slog.e(LOG_TAG, "Failed to insert image '" + file + "'", e); - url = null; - } - - return url; - } - - private final Uri addShortcut(String shortcut, Intent intent) - { - if (Config.LOGV) Slog.v(LOG_TAG, "addShortcut: shortcut=" + shortcut + ", intent=" + intent); - return Settings.Bookmarks.add(mContentResolver, intent, null, null, - shortcut != null ? shortcut.charAt(0) : 0, 0); - } -} diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 19d146d..c0ea68d 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -67,37 +67,50 @@ import java.util.List; */ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { static final String TAG = "DevicePolicyManagerService"; - + final Context mContext; final MyPackageMonitor mMonitor; IPowerManager mIPowerManager; - + int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; int mActivePasswordLength = 0; + int mActivePasswordUpperCase = 0; + int mActivePasswordLowerCase = 0; + int mActivePasswordLetters = 0; + int mActivePasswordNumeric = 0; + int mActivePasswordSymbols = 0; + int mActivePasswordNonLetter = 0; int mFailedPasswordAttempts = 0; - + int mPasswordOwner = -1; - + final HashMap<ComponentName, ActiveAdmin> mAdminMap = new HashMap<ComponentName, ActiveAdmin>(); final ArrayList<ActiveAdmin> mAdminList = new ArrayList<ActiveAdmin>(); - + static class ActiveAdmin { final DeviceAdminInfo info; - + int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; int minimumPasswordLength = 0; + int passwordHistoryLength = 0; + int minimumPasswordUpperCase = 0; + int minimumPasswordLowerCase = 0; + int minimumPasswordLetters = 1; + int minimumPasswordNumeric = 1; + int minimumPasswordSymbols = 1; + int minimumPasswordNonLetter = 0; long maximumTimeToUnlock = 0; int maximumFailedPasswordsForWipe = 0; - + ActiveAdmin(DeviceAdminInfo _info) { info = _info; } - + int getUid() { return info.getActivityInfo().applicationInfo.uid; } - + void writeToXml(XmlSerializer out) throws IllegalArgumentException, IllegalStateException, IOException { out.startTag(null, "policies"); @@ -110,7 +123,42 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (minimumPasswordLength > 0) { out.startTag(null, "min-password-length"); out.attribute(null, "value", Integer.toString(minimumPasswordLength)); - out.endTag(null, "mn-password-length"); + out.endTag(null, "min-password-length"); + } + if(passwordHistoryLength > 0) { + out.startTag(null, "password-history-length"); + out.attribute(null, "value", Integer.toString(passwordHistoryLength)); + out.endTag(null, "password-history-length"); + } + if (minimumPasswordUpperCase > 0) { + out.startTag(null, "min-password-uppercase"); + out.attribute(null, "value", Integer.toString(minimumPasswordUpperCase)); + out.endTag(null, "min-password-uppercase"); + } + if (minimumPasswordLowerCase > 0) { + out.startTag(null, "min-password-lowercase"); + out.attribute(null, "value", Integer.toString(minimumPasswordLowerCase)); + out.endTag(null, "min-password-lowercase"); + } + if (minimumPasswordLetters > 0) { + out.startTag(null, "min-password-letters"); + out.attribute(null, "value", Integer.toString(minimumPasswordLetters)); + out.endTag(null, "min-password-letters"); + } + if (minimumPasswordNumeric > 0) { + out.startTag(null, "min-password-numeric"); + out.attribute(null, "value", Integer.toString(minimumPasswordNumeric)); + out.endTag(null, "min-password-numeric"); + } + if (minimumPasswordSymbols > 0) { + out.startTag(null, "min-password-symbols"); + out.attribute(null, "value", Integer.toString(minimumPasswordSymbols)); + out.endTag(null, "min-password-symbols"); + } + if (minimumPasswordNonLetter > 0) { + out.startTag(null, "min-password-nonletter"); + out.attribute(null, "value", Integer.toString(minimumPasswordNonLetter)); + out.endTag(null, "min-password-nonletter"); } } if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { @@ -124,7 +172,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.endTag(null, "max-failed-password-wipe"); } } - + void readFromXml(XmlPullParser parser) throws XmlPullParserException, IOException { int outerDepth = parser.getDepth(); @@ -143,6 +191,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else if ("min-password-length".equals(tag)) { minimumPasswordLength = Integer.parseInt( parser.getAttributeValue(null, "value")); + } else if ("password-history-length".equals(tag)) { + passwordHistoryLength = Integer.parseInt( + parser.getAttributeValue(null, "value")); + } else if ("min-password-uppercase".equals(tag)) { + minimumPasswordUpperCase = Integer.parseInt( + parser.getAttributeValue(null, "value")); + } else if ("min-password-lowercase".equals(tag)) { + minimumPasswordLowerCase = Integer.parseInt( + parser.getAttributeValue(null, "value")); + } else if ("min-password-letters".equals(tag)) { + minimumPasswordLetters = Integer.parseInt( + parser.getAttributeValue(null, "value")); + } else if ("min-password-numeric".equals(tag)) { + minimumPasswordNumeric = Integer.parseInt( + parser.getAttributeValue(null, "value")); + } else if ("min-password-symbols".equals(tag)) { + minimumPasswordSymbols = Integer.parseInt( + parser.getAttributeValue(null, "value")); + } else if ("min-password-nonletter".equals(tag)) { + minimumPasswordNonLetter = Integer.parseInt( + parser.getAttributeValue(null, "value")); } else if ("max-time-to-unlock".equals(tag)) { maximumTimeToUnlock = Long.parseLong( parser.getAttributeValue(null, "value")); @@ -155,7 +224,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { XmlUtils.skipCurrentTag(parser); } } - + void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("uid="); pw.println(getUid()); pw.print(prefix); pw.println("policies:"); @@ -166,23 +235,37 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } pw.print(prefix); pw.print("passwordQuality=0x"); - pw.print(Integer.toHexString(passwordQuality)); - pw.print(" minimumPasswordLength="); + pw.println(Integer.toHexString(passwordQuality)); + pw.print(prefix); pw.print("minimumPasswordLength="); pw.println(minimumPasswordLength); + pw.print(prefix); pw.print("passwordHistoryLength="); + pw.println(passwordHistoryLength); + pw.print(prefix); pw.print("minimumPasswordUpperCase="); + pw.println(minimumPasswordUpperCase); + pw.print(prefix); pw.print("minimumPasswordLowerCase="); + pw.println(minimumPasswordLowerCase); + pw.print(prefix); pw.print("minimumPasswordLetters="); + pw.println(minimumPasswordLetters); + pw.print(prefix); pw.print("minimumPasswordNumeric="); + pw.println(minimumPasswordNumeric); + pw.print(prefix); pw.print("minimumPasswordSymbols="); + pw.println(minimumPasswordSymbols); + pw.print(prefix); pw.print("minimumPasswordNonLetter="); + pw.println(minimumPasswordNonLetter); pw.print(prefix); pw.print("maximumTimeToUnlock="); pw.println(maximumTimeToUnlock); pw.print(prefix); pw.print("maximumFailedPasswordsForWipe="); pw.println(maximumFailedPasswordsForWipe); } } - + class MyPackageMonitor extends PackageMonitor { public void onSomePackagesChanged() { synchronized (DevicePolicyManagerService.this) { boolean removed = false; for (int i=mAdminList.size()-1; i>=0; i--) { ActiveAdmin aa = mAdminList.get(i); - int change = isPackageDisappearing(aa.info.getPackageName()); + int change = isPackageDisappearing(aa.info.getPackageName()); if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) { Slog.w(TAG, "Admin unexpectedly uninstalled: " @@ -207,7 +290,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + /** * Instantiates the service. */ @@ -224,7 +307,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } return mIPowerManager; } - + ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) { ActiveAdmin admin = mAdminMap.get(who); if (admin != null @@ -234,7 +317,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } return null; } - + ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy) throws SecurityException { final int callingUid = Binder.getCallingUid(); @@ -265,13 +348,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + Binder.getCallingUid() + " for policy #" + reqPolicy); } } - + void sendAdminCommandLocked(ActiveAdmin admin, String action) { Intent intent = new Intent(action); intent.setComponent(admin.info.getComponent()); mContext.sendBroadcast(intent); } - + void sendAdminCommandLocked(String action, int reqPolicy) { final int N = mAdminList.size(); if (N > 0) { @@ -283,7 +366,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + void removeActiveAdminLocked(ComponentName adminReceiver) { ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver); if (admin != null) { @@ -295,7 +378,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { validatePasswordOwnerLocked(); } } - + public DeviceAdminInfo findAdmin(ComponentName adminName) { Intent resolveIntent = new Intent(); resolveIntent.setComponent(adminName); @@ -304,7 +387,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (infos == null || infos.size() <= 0) { throw new IllegalArgumentException("Unknown admin: " + adminName); } - + try { return new DeviceAdminInfo(mContext, infos.get(0)); } catch (XmlPullParserException e) { @@ -315,7 +398,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return null; } } - + private static JournaledFile makeJournaledFile() { final String base = "/data/system/device_policies.xml"; return new JournaledFile(new File(base), new File(base + ".tmp")); @@ -331,7 +414,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.startDocument(null, true); out.startTag(null, "policies"); - + final int N = mAdminList.size(); for (int i=0; i<N; i++) { ActiveAdmin ap = mAdminList.get(i); @@ -342,26 +425,36 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.endTag(null, "admin"); } } - + if (mPasswordOwner >= 0) { out.startTag(null, "password-owner"); out.attribute(null, "value", Integer.toString(mPasswordOwner)); out.endTag(null, "password-owner"); } - + if (mFailedPasswordAttempts != 0) { out.startTag(null, "failed-password-attempts"); out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts)); out.endTag(null, "failed-password-attempts"); } - - if (mActivePasswordQuality != 0 || mActivePasswordLength != 0) { + + if (mActivePasswordQuality != 0 || mActivePasswordLength != 0 + || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0 + || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0 + || mActivePasswordSymbols != 0 || mActivePasswordNonLetter != 0) { out.startTag(null, "active-password"); out.attribute(null, "quality", Integer.toString(mActivePasswordQuality)); out.attribute(null, "length", Integer.toString(mActivePasswordLength)); + out.attribute(null, "uppercase", Integer.toString(mActivePasswordUpperCase)); + out.attribute(null, "lowercase", Integer.toString(mActivePasswordLowerCase)); + out.attribute(null, "letters", Integer.toString(mActivePasswordLetters)); + out.attribute(null, "numeric", Integer + .toString(mActivePasswordNumeric)); + out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols)); + out.attribute(null, "nonletter", Integer.toString(mActivePasswordNonLetter)); out.endTag(null, "active-password"); } - + out.endTag(null, "policies"); out.endDocument(); @@ -439,6 +532,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { parser.getAttributeValue(null, "quality")); mActivePasswordLength = Integer.parseInt( parser.getAttributeValue(null, "length")); + mActivePasswordUpperCase = Integer.parseInt( + parser.getAttributeValue(null, "uppercase")); + mActivePasswordLowerCase = Integer.parseInt( + parser.getAttributeValue(null, "lowercase")); + mActivePasswordLetters = Integer.parseInt( + parser.getAttributeValue(null, "letters")); + mActivePasswordNumeric = Integer.parseInt( + parser.getAttributeValue(null, "numeric")); + mActivePasswordSymbols = Integer.parseInt( + parser.getAttributeValue(null, "symbols")); + mActivePasswordNonLetter = Integer.parseInt( + parser.getAttributeValue(null, "nonletter")); XmlUtils.skipCurrentTag(parser); } else { Slog.w(TAG, "Unknown tag: " + tag); @@ -476,10 +581,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + Integer.toHexString(utils.getActivePasswordQuality())); mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; mActivePasswordLength = 0; + mActivePasswordUpperCase = 0; + mActivePasswordLowerCase = 0; + mActivePasswordLetters = 0; + mActivePasswordNumeric = 0; + mActivePasswordSymbols = 0; + mActivePasswordNonLetter = 0; } - + validatePasswordOwnerLocked(); - + long timeMs = getMaximumTimeToLock(null); if (timeMs <= 0) { timeMs = Integer.MAX_VALUE; @@ -498,12 +609,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: return; } throw new IllegalArgumentException("Invalid quality constant: 0x" + Integer.toHexString(quality)); } - + void validatePasswordOwnerLocked() { if (mPasswordOwner >= 0) { boolean haveOwner = false; @@ -520,17 +632,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + public void systemReady() { synchronized (this) { loadSettingsLocked(); } } - + public void setActiveAdmin(ComponentName adminReceiver) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); - + DeviceAdminInfo info = findAdmin(adminReceiver); if (info == null) { throw new IllegalArgumentException("Bad admin: " + adminReceiver); @@ -552,13 +664,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + public boolean isAdminActive(ComponentName adminReceiver) { synchronized (this) { return getActiveAdminUncheckedLocked(adminReceiver) != null; } } - + public List<ComponentName> getActiveAdmins() { synchronized (this) { final int N = mAdminList.size(); @@ -572,7 +684,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return res; } } - + public boolean packageHasActiveAdmins(String packageName) { synchronized (this) { final int N = mAdminList.size(); @@ -584,7 +696,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return false; } } - + public void removeActiveAdmin(ComponentName adminReceiver) { synchronized (this) { ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver); @@ -603,10 +715,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + public void setPasswordQuality(ComponentName who, int quality) { validateQualityConstant(quality); - + synchronized (this) { if (who == null) { throw new NullPointerException("ComponentName is null"); @@ -619,16 +731,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + public int getPasswordQuality(ComponentName who) { synchronized (this) { int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; - + if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who); return admin != null ? admin.passwordQuality : mode; } - + final int N = mAdminList.size(); for (int i=0; i<N; i++) { ActiveAdmin admin = mAdminList.get(i); @@ -639,7 +751,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return mode; } } - + public void setPasswordMinimumLength(ComponentName who, int length) { synchronized (this) { if (who == null) { @@ -653,16 +765,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + public int getPasswordMinimumLength(ComponentName who) { synchronized (this) { int length = 0; - + if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who); return admin != null ? admin.minimumPasswordLength : length; } - + final int N = mAdminList.size(); for (int i=0; i<N; i++) { ActiveAdmin admin = mAdminList.get(i); @@ -673,18 +785,267 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return length; } } - + + public void setPasswordHistoryLength(ComponentName who, int length) { + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + ActiveAdmin ap = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); + if (ap.passwordHistoryLength != length) { + ap.passwordHistoryLength = length; + saveSettingsLocked(); + } + } + } + + public int getPasswordHistoryLength(ComponentName who) { + synchronized (this) { + int length = 0; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.passwordHistoryLength : length; + } + + final int N = mAdminList.size(); + for (int i = 0; i < N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (length < admin.passwordHistoryLength) { + length = admin.passwordHistoryLength; + } + } + return length; + } + } + + public void setPasswordMinimumUpperCase(ComponentName who, int length) { + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + ActiveAdmin ap = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); + if (ap.minimumPasswordUpperCase != length) { + ap.minimumPasswordUpperCase = length; + saveSettingsLocked(); + } + } + } + + public int getPasswordMinimumUpperCase(ComponentName who) { + synchronized (this) { + int length = 0; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.minimumPasswordUpperCase : length; + } + + final int N = mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (length < admin.minimumPasswordUpperCase) { + length = admin.minimumPasswordUpperCase; + } + } + return length; + } + } + + public void setPasswordMinimumLowerCase(ComponentName who, int length) { + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + ActiveAdmin ap = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); + if (ap.minimumPasswordLowerCase != length) { + ap.minimumPasswordLowerCase = length; + saveSettingsLocked(); + } + } + } + + public int getPasswordMinimumLowerCase(ComponentName who) { + synchronized (this) { + int length = 0; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.minimumPasswordLowerCase : length; + } + + final int N = mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (length < admin.minimumPasswordLowerCase) { + length = admin.minimumPasswordLowerCase; + } + } + return length; + } + } + + public void setPasswordMinimumLetters(ComponentName who, int length) { + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + ActiveAdmin ap = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); + if (ap.minimumPasswordLetters != length) { + ap.minimumPasswordLetters = length; + saveSettingsLocked(); + } + } + } + + public int getPasswordMinimumLetters(ComponentName who) { + synchronized (this) { + int length = 0; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.minimumPasswordLetters : length; + } + + final int N = mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (length < admin.minimumPasswordLetters) { + length = admin.minimumPasswordLetters; + } + } + return length; + } + } + + public void setPasswordMinimumNumeric(ComponentName who, int length) { + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + ActiveAdmin ap = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); + if (ap.minimumPasswordNumeric != length) { + ap.minimumPasswordNumeric = length; + saveSettingsLocked(); + } + } + } + + public int getPasswordMinimumNumeric(ComponentName who) { + synchronized (this) { + int length = 0; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.minimumPasswordNumeric : length; + } + + final int N = mAdminList.size(); + for (int i = 0; i < N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (length < admin.minimumPasswordNumeric) { + length = admin.minimumPasswordNumeric; + } + } + return length; + } + } + + public void setPasswordMinimumSymbols(ComponentName who, int length) { + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + ActiveAdmin ap = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); + if (ap.minimumPasswordSymbols != length) { + ap.minimumPasswordSymbols = length; + saveSettingsLocked(); + } + } + } + + public int getPasswordMinimumSymbols(ComponentName who) { + synchronized (this) { + int length = 0; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.minimumPasswordSymbols : length; + } + + final int N = mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (length < admin.minimumPasswordSymbols) { + length = admin.minimumPasswordSymbols; + } + } + return length; + } + } + + public void setPasswordMinimumNonLetter(ComponentName who, int length) { + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + ActiveAdmin ap = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); + if (ap.minimumPasswordNonLetter != length) { + ap.minimumPasswordNonLetter = length; + saveSettingsLocked(); + } + } + } + + public int getPasswordMinimumNonLetter(ComponentName who) { + synchronized (this) { + int length = 0; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.minimumPasswordNonLetter : length; + } + + final int N = mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (length < admin.minimumPasswordNonLetter) { + length = admin.minimumPasswordNonLetter; + } + } + return length; + } + } + public boolean isActivePasswordSufficient() { synchronized (this) { // This API can only be called by an active device admin, // so try to retrieve it to check that the caller is one. getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); - return mActivePasswordQuality >= getPasswordQuality(null) - && mActivePasswordLength >= getPasswordMinimumLength(null); + if (mActivePasswordQuality < getPasswordQuality(null) + || mActivePasswordLength < getPasswordMinimumLength(null)) { + return false; + } + if(mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { + return true; + } + return mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null) + && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null) + && mActivePasswordLetters >= getPasswordMinimumLetters(null) + && mActivePasswordNumeric >= getPasswordMinimumNumeric(null) + && mActivePasswordSymbols >= getPasswordMinimumSymbols(null) + && mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null); } } - + public int getCurrentFailedPasswordAttempts() { synchronized (this) { // This API can only be called by an active device admin, @@ -694,7 +1055,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return mFailedPasswordAttempts; } } - + public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) { synchronized (this) { // This API can only be called by an active device admin, @@ -709,16 +1070,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + public int getMaximumFailedPasswordsForWipe(ComponentName who) { synchronized (this) { int count = 0; - + if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who); return admin != null ? admin.maximumFailedPasswordsForWipe : count; } - + final int N = mAdminList.size(); for (int i=0; i<N; i++) { ActiveAdmin admin = mAdminList.get(i); @@ -732,7 +1093,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return count; } } - + public boolean resetPassword(String password, int flags) { int quality; synchronized (this) { @@ -743,14 +1104,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { quality = getPasswordQuality(null); if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { int realQuality = LockPatternUtils.computePasswordQuality(password); - if (realQuality < quality) { + if (realQuality < quality + && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { Slog.w(TAG, "resetPassword: password quality 0x" + Integer.toHexString(quality) + " does not meet required quality 0x" + Integer.toHexString(quality)); return false; } - quality = realQuality; + quality = Math.max(realQuality, quality); } int length = getPasswordMinimumLength(null); if (password.length() < length) { @@ -758,14 +1120,86 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + " does not meet required length " + length); return false; } + if (quality == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { + int letters = 0; + int uppercase = 0; + int lowercase = 0; + int numbers = 0; + int symbols = 0; + int nonletter = 0; + for (int i = 0; i < password.length(); i++) { + char c = password.charAt(i); + if (c >= 'A' && c <= 'Z') { + letters++; + uppercase++; + } else if (c >= 'a' && c <= 'z') { + letters++; + lowercase++; + } else if (c >= '0' && c <= '9') { + numbers++; + nonletter++; + } else { + symbols++; + nonletter++; + } + } + int neededLetters = getPasswordMinimumLetters(null); + if(letters < neededLetters) { + Slog.w(TAG, "resetPassword: number of letters " + letters + + " does not meet required number of letters " + neededLetters); + return false; + } + int neededNumbers = getPasswordMinimumNumeric(null); + if (numbers < neededNumbers) { + Slog + .w(TAG, "resetPassword: number of numerical digits " + numbers + + " does not meet required number of numerical digits " + + neededNumbers); + return false; + } + int neededLowerCase = getPasswordMinimumLowerCase(null); + if (lowercase < neededLowerCase) { + Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase + + " does not meet required number of lowercase letters " + + neededLowerCase); + return false; + } + int neededUpperCase = getPasswordMinimumUpperCase(null); + if (uppercase < neededUpperCase) { + Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase + + " does not meet required number of uppercase letters " + + neededUpperCase); + return false; + } + int neededSymbols = getPasswordMinimumSymbols(null); + if (symbols < neededSymbols) { + Slog.w(TAG, "resetPassword: number of special symbols " + symbols + + " does not meet required number of special symbols " + neededSymbols); + return false; + } + int neededNonLetter = getPasswordMinimumNonLetter(null); + if (nonletter < neededNonLetter) { + Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter + + " does not meet required number of non-letter characters " + + neededNonLetter); + return false; + } + } + + LockPatternUtils utils = new LockPatternUtils(mContext); + if(utils.checkPasswordHistory(password)) { + Slog.w(TAG, "resetPassword: password is the same as one of the last " + + getPasswordHistoryLength(null) + " passwords"); + return false; + } } - + int callingUid = Binder.getCallingUid(); if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) { Slog.w(TAG, "resetPassword: already set by another uid and not entered by user"); return false; } - + // Don't do this with the lock held, because it is going to call // back in to the service. long ident = Binder.clearCallingIdentity(); @@ -783,10 +1217,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } finally { Binder.restoreCallingIdentity(ident); } - + return true; } - + public void setMaximumTimeToLock(ComponentName who, long timeMs) { synchronized (this) { if (who == null) { @@ -796,16 +1230,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DeviceAdminInfo.USES_POLICY_FORCE_LOCK); if (ap.maximumTimeToUnlock != timeMs) { ap.maximumTimeToUnlock = timeMs; - + long ident = Binder.clearCallingIdentity(); try { saveSettingsLocked(); - + timeMs = getMaximumTimeToLock(null); if (timeMs <= 0) { timeMs = Integer.MAX_VALUE; } - + try { getIPowerManager().setMaximumScreenOffTimeount((int)timeMs); } catch (RemoteException e) { @@ -817,16 +1251,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + public long getMaximumTimeToLock(ComponentName who) { synchronized (this) { long time = 0; - + if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who); return admin != null ? admin.maximumTimeToUnlock : time; } - + final int N = mAdminList.size(); for (int i=0; i<N; i++) { ActiveAdmin admin = mAdminList.get(i); @@ -840,7 +1274,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return time; } } - + public void lockNow() { synchronized (this) { // This API can only be called by an active device admin, @@ -857,7 +1291,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + void wipeDataLocked(int flags) { try { RecoverySystem.rebootWipeUserData(mContext); @@ -865,7 +1299,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Slog.w(TAG, "Failed requesting data wipe", e); } } - + public void wipeData(int flags) { synchronized (this) { // This API can only be called by an active device admin, @@ -880,11 +1314,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + public void getRemoveWarning(ComponentName comp, final RemoteCallback result) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); - + synchronized (this) { ActiveAdmin admin = getActiveAdminUncheckedLocked(comp); if (admin == null) { @@ -907,20 +1341,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { }, null, Activity.RESULT_OK, null, null); } } - - public void setActivePasswordState(int quality, int length) { + + public void setActivePasswordState(int quality, int length, int letters, int uppercase, + int lowercase, int numbers, int symbols, int nonletter) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); - + validateQualityConstant(quality); - + synchronized (this) { if (mActivePasswordQuality != quality || mActivePasswordLength != length - || mFailedPasswordAttempts != 0) { + || mFailedPasswordAttempts != 0 || mActivePasswordLetters != letters + || mActivePasswordUpperCase != uppercase + || mActivePasswordLowerCase != lowercase || mActivePasswordNumeric != numbers + || mActivePasswordSymbols != symbols || mActivePasswordNonLetter != nonletter) { long ident = Binder.clearCallingIdentity(); try { mActivePasswordQuality = quality; mActivePasswordLength = length; + mActivePasswordLetters = letters; + mActivePasswordLowerCase = lowercase; + mActivePasswordUpperCase = uppercase; + mActivePasswordNumeric = numbers; + mActivePasswordSymbols = symbols; + mActivePasswordNonLetter = nonletter; mFailedPasswordAttempts = 0; saveSettingsLocked(); sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED, @@ -931,11 +1375,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + public void reportFailedPasswordAttempt() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); - + synchronized (this) { long ident = Binder.clearCallingIdentity(); try { @@ -952,11 +1396,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + public void reportSuccessfulPasswordAttempt() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); - + synchronized (this) { if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) { long ident = Binder.clearCallingIdentity(); @@ -972,7 +1416,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) @@ -983,12 +1427,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + ", uid=" + Binder.getCallingUid()); return; } - + final Printer p = new PrintWriterPrinter(pw); - + synchronized (this) { p.println("Current Device Policy Manager state:"); - + p.println(" Enabled Device Admins:"); final int N = mAdminList.size(); for (int i=0; i<N; i++) { @@ -999,11 +1443,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ap.dump(" ", pw); } } - + pw.println(" "); pw.print(" mActivePasswordQuality=0x"); pw.println(Integer.toHexString(mActivePasswordQuality)); pw.print(" mActivePasswordLength="); pw.println(mActivePasswordLength); + pw.print(" mActivePasswordUpperCase="); pw.println(mActivePasswordUpperCase); + pw.print(" mActivePasswordLowerCase="); pw.println(mActivePasswordLowerCase); + pw.print(" mActivePasswordLetters="); pw.println(mActivePasswordLetters); + pw.print(" mActivePasswordNumeric="); pw.println(mActivePasswordNumeric); + pw.print(" mActivePasswordSymbols="); pw.println(mActivePasswordSymbols); + pw.print(" mActivePasswordNonLetter="); pw.println(mActivePasswordNonLetter); pw.print(" mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts); pw.print(" mPasswordOwner="); pw.println(mPasswordOwner); } diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 4d35bec..36b3a5e 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -469,8 +469,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mContext.getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS); Slog.i(TAG, "Enabled input methods: " + enabledStr); - if (enabledStr == null) { - Slog.i(TAG, "Enabled input methods has not been set, enabling all"); + final String defaultIme = Settings.Secure.getString(mContext + .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); + if (enabledStr == null || TextUtils.isEmpty(defaultIme)) { + Slog.i(TAG, "Enabled input methods or default IME has not been set, enabling all"); InputMethodInfo defIm = null; StringBuilder sb = new StringBuilder(256); final int N = mMethodList.size(); @@ -978,7 +980,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub void setInputMethodLocked(String id) { InputMethodInfo info = mMethodMap.get(id); if (info == null) { - throw new IllegalArgumentException("Unknown id: " + mCurMethodId); + throw new IllegalArgumentException("Unknown id: " + id); } if (id.equals(mCurMethodId)) { @@ -1476,7 +1478,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub String defaultIme = Settings.Secure.getString(mContext .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); - if (!map.containsKey(defaultIme)) { + if (!TextUtils.isEmpty(defaultIme) && !map.containsKey(defaultIme)) { if (chooseNewDefaultIMELocked()) { updateFromSettingsLocked(); } diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index 3bcf427..5697181 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -465,10 +465,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run mEnabledProviders.add(passiveProvider.getName()); // initialize external network location and geocoder services + PackageManager pm = mContext. getPackageManager(); Resources resources = mContext.getResources(); String serviceName = resources.getString( com.android.internal.R.string.config_networkLocationProvider); - if (serviceName != null) { + if (serviceName != null && pm.resolveService(new Intent(serviceName), 0) != null) { mNetworkLocationProvider = new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER, serviceName, mLocationHandler); @@ -476,7 +477,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } serviceName = resources.getString(com.android.internal.R.string.config_geocodeProvider); - if (serviceName != null) { + if (serviceName != null && pm.resolveService(new Intent(serviceName), 0) != null) { mGeocodeProvider = new GeocoderProxy(mContext, serviceName); } diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index d7b92ec..ef5e9cc 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -127,6 +127,8 @@ class MountService extends IMountService.Stub private boolean mBooted = false; private boolean mReady = false; private boolean mSendUmsConnectedOnBoot = false; + // true if we should fake MEDIA_MOUNTED state for external storage + private boolean mEmulateExternalStorage = false; /** * Private hash of currently mounted secure containers. @@ -319,7 +321,9 @@ class MountService extends IMountService.Stub String path = Environment.getExternalStorageDirectory().getPath(); String state = getVolumeState(path); - if (state.equals(Environment.MEDIA_UNMOUNTED)) { + if (mEmulateExternalStorage) { + notifyVolumeStateChange(null, path, VolumeState.NoMedia, VolumeState.Mounted); + } else if (state.equals(Environment.MEDIA_UNMOUNTED)) { int rc = doMountVolume(path); if (rc != StorageResultCode.OperationSucceeded) { Slog.e(TAG, String.format("Boot-time mount failed (%d)", rc)); @@ -390,11 +394,13 @@ class MountService extends IMountService.Stub Slog.w(TAG, String.format("Duplicate state transition (%s -> %s)", mLegacyState, state)); return; } - // Update state on PackageManager - if (Environment.MEDIA_UNMOUNTED.equals(state)) { - mPms.updateExternalMediaStatus(false, false); - } else if (Environment.MEDIA_MOUNTED.equals(state)) { - mPms.updateExternalMediaStatus(true, false); + // Update state on PackageManager, but only of real events + if (!mEmulateExternalStorage) { + if (Environment.MEDIA_UNMOUNTED.equals(state)) { + mPms.updateExternalMediaStatus(false, false); + } else if (Environment.MEDIA_MOUNTED.equals(state)) { + mPms.updateExternalMediaStatus(true, false); + } } String oldState = mLegacyState; mLegacyState = state; @@ -894,6 +900,13 @@ class MountService extends IMountService.Stub public MountService(Context context) { mContext = context; + mEmulateExternalStorage = context.getResources().getBoolean( + com.android.internal.R.bool.config_emulateExternalStorage); + if (mEmulateExternalStorage) { + Slog.d(TAG, "using emulated external storage"); + mLegacyState = Environment.MEDIA_MOUNTED; + } + // XXX: This will go away soon in favor of IMountServiceObserver mPms = (PackageManagerService) ServiceManager.getService("package"); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 11d0b7a..af2145e 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -9584,7 +9584,8 @@ class PackageManagerService extends IPackageManager.Stub { * Update media status on PackageManager. */ public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) { - if (Binder.getCallingUid() != Process.SYSTEM_UID) { + int callingUid = Binder.getCallingUid(); + if (callingUid != 0 && callingUid != Process.SYSTEM_UID) { throw new SecurityException("Media status can only be updated by the system"); } synchronized (mPackages) { diff --git a/services/java/com/android/server/SamplingProfilerService.java b/services/java/com/android/server/SamplingProfilerService.java new file mode 100644 index 0000000..26af7f7 --- /dev/null +++ b/services/java/com/android/server/SamplingProfilerService.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.content.ContentResolver; +import android.os.DropBoxManager; +import android.os.FileObserver; +import android.os.Binder; + +import android.util.Slog; +import android.content.Context; +import android.database.ContentObserver; +import android.os.SystemProperties; +import android.provider.Settings; +import com.android.internal.os.SamplingProfilerIntegration; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.PrintWriter; + +public class SamplingProfilerService extends Binder { + + private static final String TAG = "SamplingProfilerService"; + private static final boolean LOCAL_LOGV = false; + public static final String SNAPSHOT_DIR = SamplingProfilerIntegration.SNAPSHOT_DIR; + + private FileObserver snapshotObserver; + + public SamplingProfilerService(Context context) { + registerSettingObserver(context); + startWorking(context); + } + + private void startWorking(Context context) { + if (LOCAL_LOGV) Slog.v(TAG, "starting SamplingProfilerService!"); + + final DropBoxManager dropbox = + (DropBoxManager) context.getSystemService(Context.DROPBOX_SERVICE); + + // before FileObserver is ready, there could have already been some snapshots + // in the directory, we don't want to miss them + File[] snapshotFiles = new File(SNAPSHOT_DIR).listFiles(); + for (int i = 0; snapshotFiles != null && i < snapshotFiles.length; i++) { + handleSnapshotFile(snapshotFiles[i], dropbox); + } + + // detect new snapshot and put it in dropbox + // delete it afterwards no matter what happened before + // Note: needs listening at event ATTRIB rather than CLOSE_WRITE, because we set the + // readability of snapshot files after writing them! + snapshotObserver = new FileObserver(SNAPSHOT_DIR, FileObserver.ATTRIB) { + @Override + public void onEvent(int event, String path) { + handleSnapshotFile(new File(SNAPSHOT_DIR, path), dropbox); + } + }; + snapshotObserver.startWatching(); + + if (LOCAL_LOGV) Slog.v(TAG, "SamplingProfilerService activated"); + } + + private void handleSnapshotFile(File file, DropBoxManager dropbox) { + try { + dropbox.addFile(TAG, file, 0); + if (LOCAL_LOGV) Slog.v(TAG, file.getPath() + " added to dropbox"); + } catch (IOException e) { + Slog.e(TAG, "Can't add " + file.getPath() + " to dropbox", e); + } finally { + file.delete(); + } + } + + private void registerSettingObserver(Context context) { + ContentResolver contentResolver = context.getContentResolver(); + contentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.SAMPLING_PROFILER_HZ), + false, new SamplingProfilerSettingsObserver(contentResolver)); + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("SamplingProfilerService:"); + pw.println("Watching directory: " + SNAPSHOT_DIR); + } + + private class SamplingProfilerSettingsObserver extends ContentObserver { + private ContentResolver mContentResolver; + public SamplingProfilerSettingsObserver(ContentResolver contentResolver) { + super(null); + mContentResolver = contentResolver; + onChange(false); + } + @Override + public void onChange(boolean selfChange) { + Integer samplingProfilerHz = Settings.Secure.getInt( + mContentResolver, Settings.Secure.SAMPLING_PROFILER_HZ, 0); + // setting this secure property will start or stop sampling profiler, + // as well as adjust the frequency of taking snapshots. + SystemProperties.set("persist.sys.profiler_hz", samplingProfilerHz.toString()); + } + } +} + diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index ab869bb..3586d21 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -23,26 +23,26 @@ import com.android.internal.os.SamplingProfilerIntegration; import dalvik.system.VMRuntime; import dalvik.system.Zygote; +import android.accounts.AccountManagerService; import android.app.ActivityManagerNative; import android.bluetooth.BluetoothAdapter; -import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentService; import android.content.Context; -import android.content.Intent; import android.content.pm.IPackageManager; import android.database.ContentObserver; -import android.database.Cursor; import android.media.AudioService; -import android.os.*; -import android.provider.Contacts.People; +import android.os.Looper; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.os.SystemProperties; import android.provider.Settings; import android.server.BluetoothA2dpService; import android.server.BluetoothService; import android.server.search.SearchManagerService; import android.util.EventLog; import android.util.Slog; -import android.accounts.AccountManagerService; import java.io.File; import java.util.Timer; @@ -50,11 +50,8 @@ import java.util.TimerTask; class ServerThread extends Thread { private static final String TAG = "SystemServer"; - private final static boolean INCLUDE_DEMO = false; - - private static final int LOG_BOOT_PROGRESS_SYSTEM_RUN = 3010; - private ContentResolver mContentResolver; + ContentResolver mContentResolver; private class AdbSettingsObserver extends ContentObserver { public AdbSettingsObserver() { @@ -326,11 +323,6 @@ class ServerThread extends Thread { Slog.e(TAG, "Failure starting Search Service", e); } - if (INCLUDE_DEMO) { - Slog.i(TAG, "Installing demo data..."); - (new DemoThread(context)).start(); - } - try { Slog.i(TAG, "DropBox Service"); ServiceManager.addService(Context.DROPBOX_SERVICE, @@ -415,6 +407,18 @@ class ServerThread extends Thread { } catch (Throwable e) { Slog.e(TAG, "Failure starting DiskStats Service", e); } + + try { + // need to add this service even if SamplingProfilerIntegration.isEnabled() + // is false, because it is this service that detects system property change and + // turns on SamplingProfilerIntegration. Plus, when sampling profiler doesn't work, + // there is little overhead for running this service. + Slog.i(TAG, "SamplingProfiler Service"); + ServiceManager.addService("samplingprofiler", + new SamplingProfilerService(context)); + } catch (Throwable e) { + Slog.e(TAG, "Failure starting SamplingProfiler Service", e); + } } // make sure the ADB_ENABLED setting value matches the secure property value @@ -511,37 +515,7 @@ class ServerThread extends Thread { } } -class DemoThread extends Thread -{ - DemoThread(Context context) - { - mContext = context; - } - - @Override - public void run() - { - try { - Cursor c = mContext.getContentResolver().query(People.CONTENT_URI, null, null, null, null); - boolean hasData = c != null && c.moveToFirst(); - if (c != null) { - c.deactivate(); - } - if (!hasData) { - DemoDataSet dataset = new DemoDataSet(); - dataset.add(mContext); - } - } catch (Throwable e) { - Slog.e("SystemServer", "Failure installing demo data", e); - } - - } - - Context mContext; -} - -public class SystemServer -{ +public class SystemServer { private static final String TAG = "SystemServer"; public static final int FACTORY_TEST_OFF = 0; @@ -565,7 +539,7 @@ public class SystemServer timer.schedule(new TimerTask() { @Override public void run() { - SamplingProfilerIntegration.writeSnapshot("system_server"); + SamplingProfilerIntegration.writeSnapshot("system_server", null); } }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); } @@ -573,7 +547,7 @@ public class SystemServer // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); - + System.loadLibrary("android_servers"); init1(args); } diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java index 664dfa5..73234df 100644 --- a/services/java/com/android/server/TelephonyRegistry.java +++ b/services/java/com/android/server/TelephonyRegistry.java @@ -19,6 +19,7 @@ package com.android.server; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.net.NetworkProperties; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -34,6 +35,7 @@ import android.util.Slog; import java.util.ArrayList; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.net.NetworkInterface; import com.android.internal.app.IBatteryStats; import com.android.internal.telephony.ITelephonyRegistry; @@ -88,9 +90,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private String mDataConnectionApn = ""; - private String[] mDataConnectionApnTypes = null; + private ArrayList<String> mConnectedApns; - private String mDataConnectionInterfaceName = ""; + private NetworkProperties mDataConnectionProperties; private Bundle mCellLocation = new Bundle(); @@ -120,6 +122,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } mContext = context; mBatteryStats = BatteryStatsService.getService(); + mConnectedApns = new ArrayList<String>(); } public void listen(String pkgForDebug, IPhoneStateListener callback, int events, @@ -232,19 +235,20 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!checkNotifyPermission("notifyCallState()")) { return; } + ArrayList<IBinder> removeList = new ArrayList<IBinder>(); synchronized (mRecords) { mCallState = state; mCallIncomingNumber = incomingNumber; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { try { r.callback.onCallStateChanged(state, incomingNumber); } catch (RemoteException ex) { - remove(r.binder); + removeList.add(r.binder); } } } + for (IBinder b : removeList) remove(b); } broadcastCallStateChanged(state, incomingNumber); } @@ -255,8 +259,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } synchronized (mRecords) { mServiceState = state; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { sendServiceState(r, state); } @@ -269,10 +272,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!checkNotifyPermission("notifySignalStrength()")) { return; } + ArrayList<IBinder> removeList = new ArrayList<IBinder>(); synchronized (mRecords) { mSignalStrength = signalStrength; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { sendSignalStrength(r, signalStrength); } @@ -282,10 +285,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 : gsmSignalStrength)); } catch (RemoteException ex) { - remove(r.binder); + removeList.add(r.binder); } } } + for (IBinder b : removeList) remove(b); } broadcastSignalStrengthChanged(signalStrength); } @@ -294,18 +298,19 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!checkNotifyPermission("notifyMessageWaitingChanged()")) { return; } + ArrayList<IBinder> removeList = new ArrayList<IBinder>(); synchronized (mRecords) { mMessageWaiting = mwi; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { try { r.callback.onMessageWaitingIndicatorChanged(mwi); } catch (RemoteException ex) { - remove(r.binder); + removeList.add(r.binder); } } } + for (IBinder b : removeList) remove(b); } } @@ -313,18 +318,19 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!checkNotifyPermission("notifyCallForwardingChanged()")) { return; } + ArrayList<IBinder> removeList = new ArrayList<IBinder>(); synchronized (mRecords) { mCallForwarding = cfi; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { try { r.callback.onCallForwardingIndicatorChanged(cfi); } catch (RemoteException ex) { - remove(r.binder); + removeList.add(r.binder); } } } + for (IBinder b : removeList) remove(b); } } @@ -332,56 +338,81 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!checkNotifyPermission("notifyDataActivity()" )) { return; } + ArrayList<IBinder> removeList = new ArrayList<IBinder>(); synchronized (mRecords) { mDataActivity = state; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { try { r.callback.onDataActivity(state); } catch (RemoteException ex) { - remove(r.binder); + removeList.add(r.binder); } } } + for (IBinder b : removeList) remove(b); } } public void notifyDataConnection(int state, boolean isDataConnectivityPossible, - String reason, String apn, String[] apnTypes, String interfaceName, int networkType) { + String reason, String apn, String apnType, NetworkProperties networkProperties, + int networkType) { if (!checkNotifyPermission("notifyDataConnection()" )) { return; } synchronized (mRecords) { - mDataConnectionState = state; + boolean modified = false; + if (state == TelephonyManager.DATA_CONNECTED) { + if (!mConnectedApns.contains(apnType)) { + mConnectedApns.add(apnType); + if (mDataConnectionState != state) { + mDataConnectionState = state; + modified = true; + } + } + } else { + mConnectedApns.remove(apnType); + if (mConnectedApns.isEmpty()) { + mDataConnectionState = state; + modified = true; + } else { + // leave mDataConnectionState as is and + // send out the new status for the APN in question. + } + } mDataConnectionPossible = isDataConnectivityPossible; mDataConnectionReason = reason; mDataConnectionApn = apn; - mDataConnectionApnTypes = apnTypes; - mDataConnectionInterfaceName = interfaceName; - mDataConnectionNetworkType = networkType; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); - if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { - try { - r.callback.onDataConnectionStateChanged(state, networkType); - } catch (RemoteException ex) { - remove(r.binder); + mDataConnectionProperties = networkProperties; + if (mDataConnectionNetworkType != networkType) { + mDataConnectionNetworkType = networkType; + modified = true; + } + if (modified) { + ArrayList<IBinder> removeList = new ArrayList<IBinder>(); + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { + try { + r.callback.onDataConnectionStateChanged(state, networkType); + } catch (RemoteException ex) { + removeList.add(r.binder); + } } } + for (IBinder b : removeList) remove(b); } } broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn, - apnTypes, interfaceName); + apnType, networkProperties); } - public void notifyDataConnectionFailed(String reason) { + public void notifyDataConnectionFailed(String reason, String apnType) { if (!checkNotifyPermission("notifyDataConnectionFailed()")) { return; } /* - * This is commented out because there is on onDataConnectionFailed callback - * on PhoneStateListener. There should be + * This is commented out because there is no onDataConnectionFailed callback + * in PhoneStateListener. There should be. synchronized (mRecords) { mDataConnectionFailedReason = reason; final int N = mRecords.size(); @@ -393,7 +424,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } */ - broadcastDataConnectionFailed(reason); + broadcastDataConnectionFailed(reason, apnType); } public void notifyCellLocation(Bundle cellLocation) { @@ -402,8 +433,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } synchronized (mRecords) { mCellLocation = cellLocation; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) { sendCellLocation(r, cellLocation); } @@ -414,7 +444,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { /** * Copy the service state object so they can't mess it up in the local calls */ - public void sendServiceState(Record r, ServiceState state) { + private void sendServiceState(Record r, ServiceState state) { try { r.callback.onServiceStateChanged(new ServiceState(state)); } catch (RemoteException ex) { @@ -460,11 +490,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println(" mDataConnectionPossible=" + mDataConnectionPossible); pw.println(" mDataConnectionReason=" + mDataConnectionReason); pw.println(" mDataConnectionApn=" + mDataConnectionApn); - pw.println(" mDataConnectionInterfaceName=" + mDataConnectionInterfaceName); + pw.println(" mDataConnectionProperties=" + mDataConnectionProperties); pw.println(" mCellLocation=" + mCellLocation); pw.println("registrations: count=" + recordCount); - for (int i = 0; i < recordCount; i++) { - Record r = mRecords.get(i); + for (Record r : mRecords) { pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events)); } } @@ -535,7 +564,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private void broadcastDataConnectionStateChanged(int state, boolean isDataConnectivityPossible, - String reason, String apn, String[] apnTypes, String interfaceName) { + String reason, String apn, String apnType, NetworkProperties networkProperties) { // Note: not reporting to the battery stats service here, because the // status bar takes care of that after taking into account all of the // required info. @@ -548,23 +577,23 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (reason != null) { intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason); } - intent.putExtra(Phone.DATA_APN_KEY, apn); - String types = new String(""); - if (apnTypes.length > 0) { - types = apnTypes[0]; - for (int i = 1; i < apnTypes.length; i++) { - types = types+","+apnTypes[i]; + if (networkProperties != null) { + intent.putExtra(Phone.DATA_NETWORK_PROPERTIES_KEY, networkProperties); + NetworkInterface iface = networkProperties.getInterface(); + if (iface != null) { + intent.putExtra(Phone.DATA_IFACE_NAME_KEY, iface.getName()); } } - intent.putExtra(Phone.DATA_APN_TYPES_KEY, types); - intent.putExtra(Phone.DATA_IFACE_NAME_KEY, interfaceName); + intent.putExtra(Phone.DATA_APN_KEY, apn); + intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType); mContext.sendStickyBroadcast(intent); } - private void broadcastDataConnectionFailed(String reason) { + private void broadcastDataConnectionFailed(String reason, String apnType) { Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(Phone.FAILURE_REASON_KEY, reason); + intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType); mContext.sendStickyBroadcast(intent); } diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java index a93a6ee..d841cb3 100644 --- a/services/java/com/android/server/ThrottleService.java +++ b/services/java/com/android/server/ThrottleService.java @@ -60,6 +60,8 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Calendar; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import java.util.GregorianCalendar; import java.util.Properties; import java.util.Random; @@ -83,8 +85,8 @@ public class ThrottleService extends IThrottleManager.Stub { private static final long TESTING_THRESHOLD = 1 * 1024 * 1024; private int mPolicyPollPeriodSec; - private long mPolicyThreshold; - private int mPolicyThrottleValue; + private AtomicLong mPolicyThreshold; + private AtomicInteger mPolicyThrottleValue; private int mPolicyResetDay; // 1-28 private int mPolicyNotificationsAllowedMask; @@ -114,7 +116,7 @@ public class ThrottleService extends IThrottleManager.Stub { private InterfaceObserver mInterfaceObserver; private SettingsObserver mSettingsObserver; - private int mThrottleIndex; // 0 for none, 1 for first throttle val, 2 for next, etc + private AtomicInteger mThrottleIndex; // 0 for none, 1 for first throttle val, 2 for next, etc private static final int THROTTLE_INDEX_UNINITIALIZED = -1; private static final int THROTTLE_INDEX_UNTHROTTLED = 0; @@ -126,6 +128,10 @@ public class ThrottleService extends IThrottleManager.Stub { if (VDBG) Slog.v(TAG, "Starting ThrottleService"); mContext = context; + mPolicyThreshold = new AtomicLong(); + mPolicyThrottleValue = new AtomicInteger(); + mThrottleIndex = new AtomicInteger(); + mNtpActive = false; mIface = mContext.getResources().getString(R.string.config_datause_iface); @@ -214,7 +220,7 @@ public class ThrottleService extends IThrottleManager.Stub { } private long ntpToWallTime(long ntpTime) { - long bestNow = getBestTime(); + long bestNow = getBestTime(true); // do it quickly long localNow = System.currentTimeMillis(); return localNow + (ntpTime - bestNow); } @@ -222,40 +228,42 @@ public class ThrottleService extends IThrottleManager.Stub { // TODO - fetch for the iface // return time in the local, system wall time, correcting for the use of ntp - public synchronized long getResetTime(String iface) { + public long getResetTime(String iface) { enforceAccessPermission(); long resetTime = 0; if (mRecorder != null) { - resetTime = ntpToWallTime(mRecorder.getPeriodEnd()); + resetTime = mRecorder.getPeriodEnd(); } + resetTime = ntpToWallTime(resetTime); return resetTime; } // TODO - fetch for the iface // return time in the local, system wall time, correcting for the use of ntp - public synchronized long getPeriodStartTime(String iface) { - enforceAccessPermission(); + public long getPeriodStartTime(String iface) { long startTime = 0; + enforceAccessPermission(); if (mRecorder != null) { - startTime = ntpToWallTime(mRecorder.getPeriodStart()); + startTime = mRecorder.getPeriodStart(); } + startTime = ntpToWallTime(startTime); return startTime; } //TODO - a better name? getCliffByteCountThreshold? // TODO - fetch for the iface - public synchronized long getCliffThreshold(String iface, int cliff) { + public long getCliffThreshold(String iface, int cliff) { enforceAccessPermission(); if (cliff == 1) { - return mPolicyThreshold; + return mPolicyThreshold.get(); } return 0; } // TODO - a better name? getThrottleRate? // TODO - fetch for the iface - public synchronized int getCliffLevel(String iface, int cliff) { + public int getCliffLevel(String iface, int cliff) { enforceAccessPermission(); if (cliff == 1) { - return mPolicyThrottleValue; + return mPolicyThrottleValue.get(); } return 0; } @@ -267,10 +275,9 @@ public class ThrottleService extends IThrottleManager.Stub { } // TODO - fetch for the iface - public synchronized long getByteCount(String iface, int dir, int period, int ago) { + public long getByteCount(String iface, int dir, int period, int ago) { enforceAccessPermission(); - if ((period == ThrottleManager.PERIOD_CYCLE) && - (mRecorder != null)) { + if ((period == ThrottleManager.PERIOD_CYCLE) && (mRecorder != null)) { if (dir == ThrottleManager.DIRECTION_TX) return mRecorder.getPeriodTx(ago); if (dir == ThrottleManager.DIRECTION_RX) return mRecorder.getPeriodRx(ago); } @@ -279,10 +286,10 @@ public class ThrottleService extends IThrottleManager.Stub { // TODO - a better name - getCurrentThrottleRate? // TODO - fetch for the iface - public synchronized int getThrottle(String iface) { + public int getThrottle(String iface) { enforceAccessPermission(); - if (mThrottleIndex == 1) { - return mPolicyThrottleValue; + if (mThrottleIndex.get() == 1) { + return mPolicyThrottleValue.get(); } return 0; } @@ -305,22 +312,6 @@ public class ThrottleService extends IThrottleManager.Stub { } }, new IntentFilter(ACTION_RESET)); - // use a new thread as we don't want to stall the system for file writes - mThread = new HandlerThread(TAG); - mThread.start(); - mHandler = new MyHandler(mThread.getLooper()); - mHandler.obtainMessage(EVENT_REBOOT_RECOVERY).sendToTarget(); - - mInterfaceObserver = new InterfaceObserver(mHandler, EVENT_IFACE_UP, mIface); - try { - mNMService.registerObserver(mInterfaceObserver); - } catch (RemoteException e) { - Slog.e(TAG, "Could not register InterfaceObserver " + e); - } - - mSettingsObserver = new SettingsObserver(mHandler, EVENT_POLICY_CHANGED); - mSettingsObserver.observe(mContext); - FileInputStream stream = null; try { Properties properties = new Properties(); @@ -337,6 +328,22 @@ public class ThrottleService extends IThrottleManager.Stub { } catch (Exception e) {} } } + + // use a new thread as we don't want to stall the system for file writes + mThread = new HandlerThread(TAG); + mThread.start(); + mHandler = new MyHandler(mThread.getLooper()); + mHandler.obtainMessage(EVENT_REBOOT_RECOVERY).sendToTarget(); + + mInterfaceObserver = new InterfaceObserver(mHandler, EVENT_IFACE_UP, mIface); + try { + mNMService.registerObserver(mInterfaceObserver); + } catch (RemoteException e) { + Slog.e(TAG, "Could not register InterfaceObserver " + e); + } + + mSettingsObserver = new SettingsObserver(mHandler, EVENT_POLICY_CHANGED); + mSettingsObserver.observe(mContext); } @@ -375,7 +382,7 @@ public class ThrottleService extends IThrottleManager.Stub { // check for sim change TODO // reregister for notification of policy change - mThrottleIndex = THROTTLE_INDEX_UNINITIALIZED; + mThrottleIndex.set(THROTTLE_INDEX_UNINITIALIZED); mRecorder = new DataRecorder(mContext, ThrottleService.this); @@ -403,15 +410,16 @@ public class ThrottleService extends IThrottleManager.Stub { R.integer.config_datause_threshold_bytes); int defaultValue = mContext.getResources().getInteger( R.integer.config_datause_throttle_kbitsps); - synchronized (ThrottleService.this) { - mPolicyThreshold = Settings.Secure.getLong(mContext.getContentResolver(), - Settings.Secure.THROTTLE_THRESHOLD_BYTES, defaultThreshold); - mPolicyThrottleValue = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.THROTTLE_VALUE_KBITSPS, defaultValue); - if (testing) { - mPolicyPollPeriodSec = TESTING_POLLING_PERIOD_SEC; - mPolicyThreshold = TESTING_THRESHOLD; - } + long threshold = Settings.Secure.getLong(mContext.getContentResolver(), + Settings.Secure.THROTTLE_THRESHOLD_BYTES, defaultThreshold); + int value = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.THROTTLE_VALUE_KBITSPS, defaultValue); + + mPolicyThreshold.set(threshold); + mPolicyThrottleValue.set(value); + if (testing) { + mPolicyPollPeriodSec = TESTING_POLLING_PERIOD_SEC; + mPolicyThreshold.set(TESTING_THRESHOLD); } mPolicyResetDay = Settings.Secure.getInt(mContext.getContentResolver(), @@ -423,10 +431,8 @@ public class ThrottleService extends IThrottleManager.Stub { Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.THROTTLE_RESET_DAY, mPolicyResetDay); } - synchronized (ThrottleService.this) { - if (mIface == null) { - mPolicyThreshold = 0; - } + if (mIface == null) { + mPolicyThreshold.set(0); } int defaultNotificationType = mContext.getResources().getInteger( @@ -437,15 +443,16 @@ public class ThrottleService extends IThrottleManager.Stub { mMaxNtpCacheAgeSec = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC, MAX_NTP_CACHE_AGE_SEC); - if (VDBG || (mPolicyThreshold != 0)) { + if (VDBG || (mPolicyThreshold.get() != 0)) { Slog.d(TAG, "onPolicyChanged testing=" + testing +", period=" + - mPolicyPollPeriodSec + ", threshold=" + mPolicyThreshold + ", value=" + - mPolicyThrottleValue + ", resetDay=" + mPolicyResetDay + ", noteType=" + - mPolicyNotificationsAllowedMask + ", maxNtpCacheAge=" + mMaxNtpCacheAgeSec); + mPolicyPollPeriodSec + ", threshold=" + mPolicyThreshold.get() + + ", value=" + mPolicyThrottleValue.get() + ", resetDay=" + mPolicyResetDay + + ", noteType=" + mPolicyNotificationsAllowedMask + ", maxNtpCacheAge=" + + mMaxNtpCacheAgeSec); } // force updates - mThrottleIndex = THROTTLE_INDEX_UNINITIALIZED; + mThrottleIndex.set(THROTTLE_INDEX_UNINITIALIZED); onResetAlarm(); @@ -487,7 +494,7 @@ public class ThrottleService extends IThrottleManager.Stub { long periodRx = mRecorder.getPeriodRx(0); long periodTx = mRecorder.getPeriodTx(0); long total = periodRx + periodTx; - if (VDBG || (mPolicyThreshold != 0)) { + if (VDBG || (mPolicyThreshold.get() != 0)) { Slog.d(TAG, "onPollAlarm - roaming =" + roaming + ", read =" + incRead + ", written =" + incWrite + ", new total =" + total); } @@ -510,11 +517,11 @@ public class ThrottleService extends IThrottleManager.Stub { private void onIfaceUp() { // if we were throttled before, be sure and set it again - the iface went down // (and may have disappeared all together) and these settings were lost - if (mThrottleIndex == 1) { + if (mThrottleIndex.get() == 1) { try { mNMService.setInterfaceThrottle(mIface, -1, -1); mNMService.setInterfaceThrottle(mIface, - mPolicyThrottleValue, mPolicyThrottleValue); + mPolicyThrottleValue.get(), mPolicyThrottleValue.get()); } catch (Exception e) { Slog.e(TAG, "error setting Throttle: " + e); } @@ -523,7 +530,8 @@ public class ThrottleService extends IThrottleManager.Stub { private void checkThrottleAndPostNotification(long currentTotal) { // is throttling enabled? - if (mPolicyThreshold == 0) { + long threshold = mPolicyThreshold.get(); + if (threshold == 0) { clearThrottleAndNotification(); return; } @@ -535,15 +543,13 @@ public class ThrottleService extends IThrottleManager.Stub { } // check if we need to throttle - if (currentTotal > mPolicyThreshold) { - if (mThrottleIndex != 1) { - synchronized (ThrottleService.this) { - mThrottleIndex = 1; - } - if (DBG) Slog.d(TAG, "Threshold " + mPolicyThreshold + " exceeded!"); + if (currentTotal > threshold) { + if (mThrottleIndex.get() != 1) { + mThrottleIndex.set(1); + if (DBG) Slog.d(TAG, "Threshold " + threshold + " exceeded!"); try { mNMService.setInterfaceThrottle(mIface, - mPolicyThrottleValue, mPolicyThrottleValue); + mPolicyThrottleValue.get(), mPolicyThrottleValue.get()); } catch (Exception e) { Slog.e(TAG, "error setting Throttle: " + e); } @@ -556,7 +562,8 @@ public class ThrottleService extends IThrottleManager.Stub { Notification.FLAG_ONGOING_EVENT); Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION); - broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, mPolicyThrottleValue); + broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, + mPolicyThrottleValue.get()); mContext.sendStickyBroadcast(broadcast); } // else already up! @@ -579,8 +586,8 @@ public class ThrottleService extends IThrottleManager.Stub { long periodLength = end - start; long now = System.currentTimeMillis(); long timeUsed = now - start; - long warningThreshold = 2*mPolicyThreshold*timeUsed/(timeUsed+periodLength); - if ((currentTotal > warningThreshold) && (currentTotal > mPolicyThreshold/4)) { + long warningThreshold = 2*threshold*timeUsed/(timeUsed+periodLength); + if ((currentTotal > warningThreshold) && (currentTotal > threshold/4)) { if (mWarningNotificationSent == false) { mWarningNotificationSent = true; mNotificationManager.cancel(R.drawable.stat_sys_throttled); @@ -625,11 +632,9 @@ public class ThrottleService extends IThrottleManager.Stub { } - private synchronized void clearThrottleAndNotification() { - if (mThrottleIndex != THROTTLE_INDEX_UNTHROTTLED) { - synchronized (ThrottleService.this) { - mThrottleIndex = THROTTLE_INDEX_UNTHROTTLED; - } + private void clearThrottleAndNotification() { + if (mThrottleIndex.get() != THROTTLE_INDEX_UNTHROTTLED) { + mThrottleIndex.set(THROTTLE_INDEX_UNTHROTTLED); try { mNMService.setInterfaceThrottle(mIface, -1, -1); } catch (Exception e) { @@ -687,12 +692,12 @@ public class ThrottleService extends IThrottleManager.Stub { } private void onResetAlarm() { - if (VDBG || (mPolicyThreshold != 0)) { + if (VDBG || (mPolicyThreshold.get() != 0)) { Slog.d(TAG, "onResetAlarm - last period had " + mRecorder.getPeriodRx(0) + " bytes read and " + mRecorder.getPeriodTx(0) + " written"); } - long now = getBestTime(); + long now = getBestTime(false); if (mNtpActive || (mNtpServer == null)) { Calendar end = calculatePeriodEnd(now); @@ -719,20 +724,23 @@ public class ThrottleService extends IThrottleManager.Stub { // will try to get the ntp time and switch to it if found. // will also cache the time so we don't fetch it repeatedly. - getBestTime(); + getBestTime(false); } private static final int MAX_NTP_CACHE_AGE_SEC = 60 * 60 * 24; // 1 day - private static final int MAX_NTP_FETCH_WAIT = 10 * 1000; + private static final int MAX_NTP_FETCH_WAIT = 20 * 1000; private int mMaxNtpCacheAgeSec = MAX_NTP_CACHE_AGE_SEC; private long cachedNtp; private long cachedNtpTimestamp; - private long getBestTime() { + // if the request is tied to UI and ANR's are a danger, request a fast result + // the regular polling should have updated the cached time recently using the + // slower method (!fast) + private long getBestTime(boolean fast) { if (mNtpServer != null) { if (mNtpActive) { long ntpAge = SystemClock.elapsedRealtime() - cachedNtpTimestamp; - if (ntpAge < mMaxNtpCacheAgeSec * 1000) { + if (ntpAge < mMaxNtpCacheAgeSec * 1000 || fast) { if (VDBG) Slog.v(TAG, "using cached time"); return cachedNtp + ntpAge; } @@ -1025,39 +1033,57 @@ public class ThrottleService extends IThrottleManager.Stub { if (DBG) Slog.d(TAG, "data file empty"); return; } - synchronized (mParent) { - String[] parsed = data.split(":"); - int parsedUsed = 0; - if (parsed.length < 6) { - Slog.e(TAG, "reading data file with insufficient length - ignoring"); - return; - } + String[] parsed = data.split(":"); + int parsedUsed = 0; + if (parsed.length < 6) { + Slog.e(TAG, "reading data file with insufficient length - ignoring"); + return; + } + int periodCount; + long[] periodRxData; + long[] periodTxData; + int currentPeriod; + Calendar periodStart; + Calendar periodEnd; + try { if (Integer.parseInt(parsed[parsedUsed++]) != DATA_FILE_VERSION) { Slog.e(TAG, "reading data file with bad version - ignoring"); return; } - mPeriodCount = Integer.parseInt(parsed[parsedUsed++]); - if (parsed.length != 5 + (2 * mPeriodCount)) { + periodCount = Integer.parseInt(parsed[parsedUsed++]); + if (parsed.length != 5 + (2 * periodCount)) { Slog.e(TAG, "reading data file with bad length (" + parsed.length + - " != " + (5+(2*mPeriodCount)) + ") - ignoring"); + " != " + (5 + (2 * periodCount)) + ") - ignoring"); return; } - - mPeriodRxData = new long[mPeriodCount]; - for(int i = 0; i < mPeriodCount; i++) { - mPeriodRxData[i] = Long.parseLong(parsed[parsedUsed++]); + periodRxData = new long[periodCount]; + for (int i = 0; i < periodCount; i++) { + periodRxData[i] = Long.parseLong(parsed[parsedUsed++]); } - mPeriodTxData = new long[mPeriodCount]; - for(int i = 0; i < mPeriodCount; i++) { - mPeriodTxData[i] = Long.parseLong(parsed[parsedUsed++]); + periodTxData = new long[periodCount]; + for (int i = 0; i < periodCount; i++) { + periodTxData[i] = Long.parseLong(parsed[parsedUsed++]); } - mCurrentPeriod = Integer.parseInt(parsed[parsedUsed++]); - mPeriodStart = new GregorianCalendar(); - mPeriodStart.setTimeInMillis(Long.parseLong(parsed[parsedUsed++])); - mPeriodEnd = new GregorianCalendar(); - mPeriodEnd.setTimeInMillis(Long.parseLong(parsed[parsedUsed++])); + + currentPeriod = Integer.parseInt(parsed[parsedUsed++]); + + periodStart = new GregorianCalendar(); + periodStart.setTimeInMillis(Long.parseLong(parsed[parsedUsed++])); + periodEnd = new GregorianCalendar(); + periodEnd.setTimeInMillis(Long.parseLong(parsed[parsedUsed++])); + } catch (Exception e) { + Slog.e(TAG, "Error parsing data file - ignoring"); + return; + } + synchronized (mParent) { + mPeriodCount = periodCount; + mPeriodRxData = periodRxData; + mPeriodTxData = periodTxData; + mCurrentPeriod = currentPeriod; + mPeriodStart = periodStart; + mPeriodEnd = periodEnd; } } @@ -1091,15 +1117,15 @@ public class ThrottleService extends IThrottleManager.Stub { } pw.println(); - pw.println("The threshold is " + mPolicyThreshold + + pw.println("The threshold is " + mPolicyThreshold.get() + ", after which you experince throttling to " + - mPolicyThrottleValue + "kbps"); + mPolicyThrottleValue.get() + "kbps"); pw.println("Current period is " + (mRecorder.getPeriodEnd() - mRecorder.getPeriodStart())/1000 + " seconds long " + "and ends in " + (getResetTime(mIface) - System.currentTimeMillis()) / 1000 + " seconds."); pw.println("Polling every " + mPolicyPollPeriodSec + " seconds"); - pw.println("Current Throttle Index is " + mThrottleIndex); + pw.println("Current Throttle Index is " + mThrottleIndex.get()); pw.println("Max NTP Cache Age is " + mMaxNtpCacheAgeSec); for (int i = 0; i < mRecorder.getPeriodCount(); i++) { diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 509c789..35baaa7 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -144,19 +144,6 @@ public class WifiService extends IWifiManager.Stub { private static final String WAKELOCK_TAG = "WifiService"; - /** - * The maximum amount of time to hold the wake lock after a disconnect - * caused by stopping the driver. Establishing an EDGE connection has been - * observed to take about 5 seconds under normal circumstances. This - * provides a bit of extra margin. - * <p> - * See {@link android.provider.Settings.Secure#WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS}. - * This is the default value if a Settings.Secure value is not present. - */ - private static final int DEFAULT_WAKELOCK_TIMEOUT = 8000; - - // Wake lock used by driver-stop operation - private static PowerManager.WakeLock sDriverStopWakeLock; // Wake lock used by other operations private static PowerManager.WakeLock sWakeLock; @@ -164,7 +151,6 @@ public class WifiService extends IWifiManager.Stub { private static final int MESSAGE_DISABLE_WIFI = 1; private static final int MESSAGE_STOP_WIFI = 2; private static final int MESSAGE_START_WIFI = 3; - private static final int MESSAGE_RELEASE_WAKELOCK = 4; private static final int MESSAGE_UPDATE_STATE = 5; private static final int MESSAGE_START_ACCESS_POINT = 6; private static final int MESSAGE_STOP_ACCESS_POINT = 7; @@ -238,7 +224,6 @@ public class WifiService extends IWifiManager.Stub { PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); sWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG); - sDriverStopWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG); mContext.registerReceiver( new BroadcastReceiver() { @@ -293,7 +278,10 @@ public class WifiService extends IWifiManager.Stub { IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); - mCm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + if (mCm == null) { + mCm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + } + mWifiRegexs = mCm.getTetherableWifiRegexs(); for (String intf : available) { @@ -1829,19 +1817,12 @@ public class WifiService extends IWifiManager.Stub { sWakeLock.acquire(); sendStartMessage(strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY); } else if (!mWifiStateTracker.isDriverStopped()) { - int wakeLockTimeout = - Settings.Secure.getInt( - mContext.getContentResolver(), - Settings.Secure.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS, - DEFAULT_WAKELOCK_TIMEOUT); - /* - * We are assuming that ConnectivityService can make - * a transition to cellular data within wakeLockTimeout time. - * The wakelock is released by the delayed message. - */ - sDriverStopWakeLock.acquire(); + if (mCm == null) { + mCm = (ConnectivityManager)mContext. + getSystemService(Context.CONNECTIVITY_SERVICE); + } + mCm.requestNetworkTransitionWakelock(TAG); mWifiHandler.sendEmptyMessage(MESSAGE_STOP_WIFI); - mWifiHandler.sendEmptyMessageDelayed(MESSAGE_RELEASE_WAKELOCK, wakeLockTimeout); } } else { sWakeLock.acquire(); @@ -1927,10 +1908,6 @@ public class WifiService extends IWifiManager.Stub { // don't release wakelock break; - case MESSAGE_RELEASE_WAKELOCK: - sDriverStopWakeLock.release(); - break; - case MESSAGE_START_ACCESS_POINT: setWifiApEnabledBlocking(true, msg.arg1, diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 2e28afb..b82ec01 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -155,7 +155,6 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean DEBUG_STARTING_WINDOW = false; static final boolean DEBUG_REORDER = false; static final boolean DEBUG_WALLPAPER = false; - static final boolean DEBUG_FREEZE = false; static final boolean SHOW_TRANSACTIONS = false; static final boolean HIDE_STACK_CRAWLS = true; static final boolean MEASURE_LATENCY = false; @@ -4421,8 +4420,7 @@ public class WindowManagerService extends IWindowManager.Stub final int N = mWindows.size(); for (int i=0; i<N; i++) { WindowState w = mWindows.get(i); - if (w.isVisibleLw() && !w.mObscured - && (w.mOrientationChanging || !w.isDrawnLw())) { + if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { return; } } @@ -6785,7 +6783,7 @@ public class WindowManagerService extends IWindowManager.Stub final AppWindowToken atoken = mAppToken; return mSurface != null && !mAttachedHidden && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested) - && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending)) + && !mDrawPending && !mCommitDrawPending && !mExiting && !mDestroying; } @@ -6889,14 +6887,12 @@ public class WindowManagerService extends IWindowManager.Stub /** * Returns true if the window has a surface that it has drawn a - * complete UI in to. Note that this returns true if the orientation - * is changing even if the window hasn't redrawn because we don't want - * to stop things from executing during that time. + * complete UI in to. */ public boolean isDrawnLw() { final AppWindowToken atoken = mAppToken; return mSurface != null && !mDestroying - && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending)); + && !mDrawPending && !mCommitDrawPending; } public boolean fillsScreenLw(int screenWidth, int screenHeight, @@ -8417,6 +8413,11 @@ public class WindowManagerService extends IWindowManager.Stub private final void performLayoutAndPlaceSurfacesLockedInner( boolean recoveringMemory) { + if (mDisplay == null) { + Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay"); + return; + } + final long currentTime = SystemClock.uptimeMillis(); final int dw = mDisplay.getWidth(); final int dh = mDisplay.getHeight(); @@ -9195,12 +9196,6 @@ public class WindowManagerService extends IWindowManager.Stub if (w.mAttachedHidden || !w.isReadyForDisplay()) { if (!w.mLastHidden) { //dump(); - if (DEBUG_CONFIGURATION) Slog.v(TAG, "Window hiding: waitingToShow=" - + w.mRootToken.waitingToShow + " polvis=" - + w.mPolicyVisibility + " atthid=" - + w.mAttachedHidden + " tokhid=" - + w.mRootToken.hidden + " vis=" - + w.mViewVisibility); w.mLastHidden = true; if (SHOW_TRANSACTIONS) logSurface(w, "HIDE (performLayout)", null); @@ -9597,30 +9592,26 @@ public class WindowManagerService extends IWindowManager.Stub } else if (animating) { requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis()); } - + mInputMonitor.updateInputWindowsLw(); - - if (DEBUG_FREEZE) Slog.v(TAG, "Layout: mDisplayFrozen=" + mDisplayFrozen - + " holdScreen=" + holdScreen); - if (!mDisplayFrozen) { - setHoldScreenLocked(holdScreen != null); - if (screenBrightness < 0 || screenBrightness > 1.0f) { - mPowerManager.setScreenBrightnessOverride(-1); - } else { - mPowerManager.setScreenBrightnessOverride((int) - (screenBrightness * Power.BRIGHTNESS_ON)); - } - if (buttonBrightness < 0 || buttonBrightness > 1.0f) { - mPowerManager.setButtonBrightnessOverride(-1); - } else { - mPowerManager.setButtonBrightnessOverride((int) - (buttonBrightness * Power.BRIGHTNESS_ON)); - } - if (holdScreen != mHoldingScreenOn) { - mHoldingScreenOn = holdScreen; - Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen); - mH.sendMessage(m); - } + + setHoldScreenLocked(holdScreen != null); + if (screenBrightness < 0 || screenBrightness > 1.0f) { + mPowerManager.setScreenBrightnessOverride(-1); + } else { + mPowerManager.setScreenBrightnessOverride((int) + (screenBrightness * Power.BRIGHTNESS_ON)); + } + if (buttonBrightness < 0 || buttonBrightness > 1.0f) { + mPowerManager.setButtonBrightnessOverride(-1); + } else { + mPowerManager.setButtonBrightnessOverride((int) + (buttonBrightness * Power.BRIGHTNESS_ON)); + } + if (holdScreen != mHoldingScreenOn) { + mHoldingScreenOn = holdScreen; + Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen); + mH.sendMessage(m); } if (mTurnOnScreen) { @@ -9909,8 +9900,6 @@ public class WindowManagerService extends IWindowManager.Stub mFreezeGcPending = now; } - if (DEBUG_FREEZE) Slog.v(TAG, "*** FREEZING DISPLAY", new RuntimeException()); - mDisplayFrozen = true; mInputMonitor.freezeInputDispatchingLw(); @@ -9937,8 +9926,6 @@ public class WindowManagerService extends IWindowManager.Stub return; } - if (DEBUG_FREEZE) Slog.v(TAG, "*** UNFREEZING DISPLAY", new RuntimeException()); - mDisplayFrozen = false; mH.removeMessages(H.APP_FREEZE_TIMEOUT); if (PROFILE_ORIENTATION) { diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 672149d..0c8769e 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -11663,7 +11663,69 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } } - + + public boolean dumpHeap(String process, boolean managed, + String path, ParcelFileDescriptor fd) throws RemoteException { + + try { + synchronized (this) { + // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to + // its own permission (same as profileControl). + if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires permission " + + android.Manifest.permission.SET_ACTIVITY_WATCHER); + } + + if (fd == null) { + throw new IllegalArgumentException("null fd"); + } + + ProcessRecord proc = null; + try { + int pid = Integer.parseInt(process); + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(pid); + } + } catch (NumberFormatException e) { + } + + if (proc == null) { + HashMap<String, SparseArray<ProcessRecord>> all + = mProcessNames.getMap(); + SparseArray<ProcessRecord> procs = all.get(process); + if (procs != null && procs.size() > 0) { + proc = procs.valueAt(0); + } + } + + if (proc == null || proc.thread == null) { + throw new IllegalArgumentException("Unknown process: " + process); + } + + boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0")); + if (isSecure) { + if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) { + throw new SecurityException("Process not debuggable: " + proc); + } + } + + proc.thread.dumpHeap(managed, path, fd); + fd = null; + return true; + } + } catch (RemoteException e) { + throw new IllegalStateException("Process disappeared"); + } finally { + if (fd != null) { + try { + fd.close(); + } catch (IOException e) { + } + } + } + } + /** In this method we try to acquire our lock to make sure that we have not deadlocked */ public void monitor() { synchronized (this) { } diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index b29f875..d27ccc0 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -65,7 +65,8 @@ import java.util.Set; public class Tethering extends INetworkManagementEventObserver.Stub { private Context mContext; - private final String TAG = "Tethering"; + private final static String TAG = "Tethering"; + private final static boolean DEBUG = false; private boolean mBooted = false; //used to remember if we got connected before boot finished @@ -174,7 +175,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public void interfaceLinkStatusChanged(String iface, boolean link) { - Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link); + if (DEBUG) Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link); boolean found = false; boolean usb = false; if (isWifi(iface)) { @@ -229,28 +230,30 @@ public class Tethering extends INetworkManagementEventObserver.Stub { usb = true; } if (found == false) { - Log.d(TAG, iface + " is not a tetherable iface, ignoring"); + if (DEBUG) Log.d(TAG, iface + " is not a tetherable iface, ignoring"); return; } synchronized (mIfaces) { TetherInterfaceSM sm = mIfaces.get(iface); if (sm != null) { - Log.e(TAG, "active iface (" + iface + ") reported as added, ignoring"); + if (DEBUG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring"); return; } sm = new TetherInterfaceSM(iface, mLooper, usb); mIfaces.put(iface, sm); sm.start(); } - Log.d(TAG, "interfaceAdded :" + iface); + if (DEBUG) Log.d(TAG, "interfaceAdded :" + iface); } public void interfaceRemoved(String iface) { synchronized (mIfaces) { TetherInterfaceSM sm = mIfaces.get(iface); if (sm == null) { - Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring"); + if (DEBUG) { + Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring"); + } return; } sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); @@ -350,8 +353,10 @@ public class Tethering extends INetworkManagementEventObserver.Stub { broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, erroredList); mContext.sendStickyBroadcast(broadcast); - Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " + - activeList.size() + ", " + erroredList.size()); + if (DEBUG) { + Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " + + activeList.size() + ", " + erroredList.size()); + } if (usbTethered) { if (wifiTethered) { @@ -436,7 +441,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { mUsbMassStorageOff = true; updateUsbStatus(); } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { - Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); + if (DEBUG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { mBooted = true; @@ -469,7 +474,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { // toggled when we enter/leave the fully teathered state private boolean enableUsbRndis(boolean enabled) { - Log.d(TAG, "enableUsbRndis(" + enabled + ")"); + if (DEBUG) Log.d(TAG, "enableUsbRndis(" + enabled + ")"); IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); @@ -494,7 +499,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { // configured when we start tethering and unconfig'd on error or conclusion private boolean configureUsbIface(boolean enabled) { - Log.d(TAG, "configureUsbIface(" + enabled + ")"); + if (DEBUG) Log.d(TAG, "configureUsbIface(" + enabled + ")"); IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); @@ -741,7 +746,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { @Override public boolean processMessage(Message message) { - Log.d(TAG, "InitialState.processMessage what=" + message.what); + if (DEBUG) Log.d(TAG, "InitialState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_REQUESTED: @@ -782,7 +787,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public boolean processMessage(Message message) { - Log.d(TAG, "StartingState.processMessage what=" + message.what); + if (DEBUG) Log.d(TAG, "StartingState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { // maybe a parent class? @@ -834,7 +839,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return; } if (mUsb) Tethering.this.enableUsbRndis(true); - Log.d(TAG, "Tethered " + mIfaceName); + if (DEBUG) Log.d(TAG, "Tethered " + mIfaceName); setAvailable(false); setTethered(true); sendTetherStateChangedBroadcast(); @@ -845,7 +850,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public boolean processMessage(Message message) { - Log.d(TAG, "TetheredState.processMessage what=" + message.what); + if (DEBUG) Log.d(TAG, "TetheredState.processMessage what=" + message.what); boolean retValue = true; boolean error = false; switch (message.what) { @@ -888,7 +893,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } else if (message.what == CMD_INTERFACE_DOWN) { transitionTo(mUnavailableState); } - Log.d(TAG, "Untethered " + mIfaceName); + if (DEBUG) Log.d(TAG, "Untethered " + mIfaceName); break; case CMD_TETHER_CONNECTION_CHANGED: String newUpstreamIfaceName = (String)(message.obj); @@ -961,7 +966,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { ConnectivityManager.TETHER_ERROR_MASTER_ERROR); break; } - Log.d(TAG, "Tether lost upstream connection " + mIfaceName); + if (DEBUG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName); sendTetherStateChangedBroadcast(); if (mUsb) { if (!Tethering.this.configureUsbIface(false)) { @@ -1199,8 +1204,10 @@ public class Tethering extends INetworkManagementEventObserver.Stub { IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); mConnectionRequested = false; - Log.d(TAG, "chooseUpstreamType(" + tryCell + "), dunRequired =" - + mDunRequired + ", iface=" + iface); + if (DEBUG) { + Log.d(TAG, "chooseUpstreamType(" + tryCell + "), dunRequired =" + + mDunRequired + ", iface=" + iface); + } if (iface != null) { try { if (mDunRequired) { @@ -1208,7 +1215,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { NetworkInfo info = cm.getNetworkInfo( ConnectivityManager.TYPE_MOBILE_DUN); if (info.isConnected()) { - Log.d(TAG, "setting dun ifacename =" + iface); + if (DEBUG) Log.d(TAG, "setting dun ifacename =" + iface); // even if we're already connected - it may be somebody else's // refcount, so add our own turnOnMobileConnection(); @@ -1220,11 +1227,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } } } else { - Log.d(TAG, "checking if hipri brought us this connection"); + if (DEBUG) Log.d(TAG, "checking if hipri brought us this connection"); NetworkInfo info = cm.getNetworkInfo( ConnectivityManager.TYPE_MOBILE_HIPRI); if (info.isConnected()) { - Log.d(TAG, "yes - hipri in use"); + if (DEBUG) Log.d(TAG, "yes - hipri in use"); // even if we're already connected - it may be sombody else's // refcount, so add our own turnOnMobileConnection(); @@ -1246,7 +1253,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { notifyTetheredOfNewUpstreamIface(iface); } protected void notifyTetheredOfNewUpstreamIface(String ifaceName) { - Log.d(TAG, "notifying tethered with iface =" + ifaceName); + if (DEBUG) Log.d(TAG, "notifying tethered with iface =" + ifaceName); mUpstreamIfaceName = ifaceName; for (Object o : mNotifyList) { TetherInterfaceSM sm = (TetherInterfaceSM)o; @@ -1263,19 +1270,19 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public boolean processMessage(Message message) { - Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); + if (DEBUG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_MODE_REQUESTED: mDunRequired = isDunRequired(); TetherInterfaceSM who = (TetherInterfaceSM)message.obj; - Log.d(TAG, "Tether Mode requested by " + who.toString()); + if (DEBUG) Log.d(TAG, "Tether Mode requested by " + who.toString()); mNotifyList.add(who); transitionTo(mTetherModeAliveState); break; case CMD_TETHER_MODE_UNREQUESTED: who = (TetherInterfaceSM)message.obj; - Log.d(TAG, "Tether Mode unrequested by " + who.toString()); + if (DEBUG) Log.d(TAG, "Tether Mode unrequested by " + who.toString()); int index = mNotifyList.indexOf(who); if (index != -1) { mNotifyList.remove(who); @@ -1305,7 +1312,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public boolean processMessage(Message message) { - Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); + if (DEBUG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_MODE_REQUESTED: @@ -1333,8 +1340,10 @@ public class Tethering extends INetworkManagementEventObserver.Stub { // make sure we're still using a requested connection - may have found // wifi or something since then. if (mConnectionRequested) { - Log.d(TAG, "renewing mobile connection - requeuing for another " + - CELL_CONNECTION_RENEW_MS + "ms"); + if (DEBUG) { + Log.d(TAG, "renewing mobile connection - requeuing for another " + + CELL_CONNECTION_RENEW_MS + "ms"); + } turnOnMobileConnection(); } break; |