summaryrefslogtreecommitdiffstats
path: root/services/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java')
-rw-r--r--services/java/com/android/server/BackupManagerService.java21
-rw-r--r--services/java/com/android/server/BatteryService.java1
-rw-r--r--services/java/com/android/server/InputDevice.java6
-rw-r--r--services/java/com/android/server/IntentResolver.java3
-rw-r--r--services/java/com/android/server/KeyInputQueue.java46
-rw-r--r--services/java/com/android/server/LocationManagerService.java37
-rw-r--r--services/java/com/android/server/PackageManagerService.java58
-rw-r--r--services/java/com/android/server/TelephonyRegistry.java181
-rw-r--r--services/java/com/android/server/WifiService.java44
-rw-r--r--services/java/com/android/server/WindowManagerService.java70
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java390
-rw-r--r--services/java/com/android/server/am/AppErrorDialog.java21
-rw-r--r--services/java/com/android/server/am/AppNotRespondingDialog.java46
-rw-r--r--services/java/com/android/server/am/BatteryStatsService.java5
-rw-r--r--services/java/com/android/server/am/HistoryRecord.java3
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java13
-rw-r--r--services/java/com/android/server/status/StatusBarPolicy.java469
-rw-r--r--services/java/com/android/server/status/StatusBarService.java9
18 files changed, 1088 insertions, 335 deletions
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 983329b..e3fff81 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -158,11 +158,13 @@ class BackupManagerService extends IBackupManager.Stub {
case MSG_RUN_BACKUP:
// snapshot the pending-backup set and work on that
synchronized (mQueueLock) {
- mBackupQueue = new ArrayList();
- for (BackupRequest b: mPendingBackups.values()) {
- mBackupQueue.add(b);
+ if (mBackupQueue == null) {
+ mBackupQueue = new ArrayList();
+ for (BackupRequest b: mPendingBackups.values()) {
+ mBackupQueue.add(b);
+ }
+ mPendingBackups = new HashMap<ComponentName,BackupRequest>();
}
- mPendingBackups = new HashMap<ComponentName,BackupRequest>();
// !!! TODO: start a new backup-queue journal file too
// WARNING: If we crash after this line, anything in mPendingBackups will
// be lost. FIX THIS.
@@ -190,9 +192,13 @@ class BackupManagerService extends IBackupManager.Stub {
BackupRequest request;
synchronized (mQueueLock) {
int queueSize = mBackupQueue.size();
+ Log.d(TAG, "mBackupQueue.size=" + queueSize);
if (queueSize == 0) {
mBackupQueue = null;
- // TODO: Anything else to do here?
+ // if there are pending backups, start those after a short delay
+ if (mPendingBackups.size() > 0) {
+ mBackupHandler.sendEmptyMessageDelayed(MSG_RUN_BACKUP, COLLECTION_INTERVAL);
+ }
return;
}
request = mBackupQueue.get(0);
@@ -267,7 +273,7 @@ class BackupManagerService extends IBackupManager.Stub {
// !!! TODO: After successful transport, delete the now-stale data
// and juggle the files so that next time the new state is passed
- backupDataName.delete();
+ //backupDataName.delete();
newStateName.renameTo(savedStateName);
} catch (FileNotFoundException fnf) {
@@ -284,6 +290,9 @@ class BackupManagerService extends IBackupManager.Stub {
mBackupQueue.remove(0);
}
mContext.unbindService(mBackupHandler);
+
+ // start the next one
+ startOneService();
}
// Add the backup services in the given package to our set of known backup participants.
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index caad7d0..596053d 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -271,6 +271,7 @@ class BatteryService extends Binder {
* - is not plugged and battery level crosses the WARNING boundary (becomes < 15).
*/
final boolean sendBatteryLow = !plugged
+ && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& mBatteryLevel < BATTERY_LEVEL_WARNING
&& (oldPlugged || mLastBatteryLevel >= BATTERY_LEVEL_WARNING);
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 7b8a2a4..9c1f942 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -63,7 +63,7 @@ public class InputDevice {
yMoveScale = my != 0 ? (1.0f/my) : 1.0f;
}
- MotionEvent generateMotion(InputDevice device, long curTime,
+ MotionEvent generateMotion(InputDevice device, long curTime, long curTimeNano,
boolean isAbs, Display display, int orientation,
int metaState) {
if (!changed) {
@@ -167,7 +167,7 @@ public class InputDevice {
if (!isAbs) {
x = y = 0;
}
- return MotionEvent.obtain(downTime, curTime, action,
+ return MotionEvent.obtainNano(downTime, curTime, curTimeNano, action,
scaledX, scaledY, scaledPressure, scaledSize, metaState,
xPrecision, yPrecision, device.id, edgeFlags);
} else {
@@ -181,7 +181,7 @@ public class InputDevice {
}
return null;
}
- MotionEvent me = MotionEvent.obtain(downTime, curTime,
+ MotionEvent me = MotionEvent.obtainNano(downTime, curTime, curTimeNano,
MotionEvent.ACTION_MOVE, scaledX, scaledY,
scaledPressure, scaledSize, metaState,
xPrecision, yPrecision, device.id, edgeFlags);
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index 53e63c2..d8c8c90 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -180,8 +180,7 @@ public class IntentResolver<F extends IntentFilter, R extends Object> {
return resultList;
}
- public List<R> queryIntent(ContentResolver resolver, Intent intent,
- String resolvedType, boolean defaultOnly) {
+ public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
String scheme = intent.getScheme();
ArrayList<R> finalList = new ArrayList<R>();
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index 411cd6b..78cdf8b 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -18,8 +18,9 @@ package com.android.server;
import android.content.Context;
import android.content.res.Configuration;
-import android.os.SystemClock;
+import android.os.LatencyTimer;
import android.os.PowerManager;
+import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
@@ -73,14 +74,17 @@ public abstract class KeyInputQueue {
public static final int FILTER_REMOVE = 0;
public static final int FILTER_KEEP = 1;
public static final int FILTER_ABORT = -1;
-
+
+ private static final boolean MEASURE_LATENCY = false;
+ private LatencyTimer lt;
+
public interface FilterCallback {
int filterEvent(QueuedEvent ev);
}
static class QueuedEvent {
InputDevice inputDevice;
- long when;
+ long whenNano;
int flags; // From the raw event
int classType; // One of the class constants in InputEvent
Object event;
@@ -88,7 +92,7 @@ public abstract class KeyInputQueue {
void copyFrom(QueuedEvent that) {
this.inputDevice = that.inputDevice;
- this.when = that.when;
+ this.whenNano = that.whenNano;
this.flags = that.flags;
this.classType = that.classType;
this.event = that.event;
@@ -107,6 +111,10 @@ public abstract class KeyInputQueue {
}
KeyInputQueue(Context context) {
+ if (MEASURE_LATENCY) {
+ lt = new LatencyTimer(100, 1000);
+ }
+
PowerManager pm = (PowerManager)context.getSystemService(
Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
@@ -241,7 +249,7 @@ public abstract class KeyInputQueue {
if (configChanged) {
synchronized (mFirst) {
- addLocked(di, SystemClock.uptimeMillis(), 0,
+ addLocked(di, System.nanoTime(), 0,
RawInputEvent.CLASS_CONFIGURATION_CHANGED,
null);
}
@@ -256,6 +264,7 @@ public abstract class KeyInputQueue {
// timebase as SystemClock.uptimeMillis().
//curTime = gotOne ? ev.when : SystemClock.uptimeMillis();
final long curTime = SystemClock.uptimeMillis();
+ final long curTimeNano = System.nanoTime();
//Log.i(TAG, "curTime=" + curTime + ", systemClock=" + SystemClock.uptimeMillis());
final int classes = di.classes;
@@ -276,7 +285,7 @@ public abstract class KeyInputQueue {
down = false;
}
int keycode = rotateKeyCodeLocked(ev.keycode);
- addLocked(di, curTime, ev.flags,
+ addLocked(di, curTimeNano, ev.flags,
RawInputEvent.CLASS_KEYBOARD,
newKeyEvent(di, di.mDownTime, curTime, down,
keycode, 0, scancode,
@@ -330,7 +339,7 @@ public abstract class KeyInputQueue {
}
MotionEvent me;
- me = di.mAbs.generateMotion(di, curTime, true,
+ me = di.mAbs.generateMotion(di, curTime, curTimeNano, true,
mDisplay, mOrientation, mGlobalMetaState);
if (false) Log.v(TAG, "Absolute: x=" + di.mAbs.x
+ " y=" + di.mAbs.y + " ev=" + me);
@@ -338,15 +347,15 @@ public abstract class KeyInputQueue {
if (WindowManagerPolicy.WATCH_POINTER) {
Log.i(TAG, "Enqueueing: " + me);
}
- addLocked(di, curTime, ev.flags,
+ addLocked(di, curTimeNano, ev.flags,
RawInputEvent.CLASS_TOUCHSCREEN, me);
}
- me = di.mRel.generateMotion(di, curTime, false,
+ me = di.mRel.generateMotion(di, curTime, curTimeNano, false,
mDisplay, mOrientation, mGlobalMetaState);
if (false) Log.v(TAG, "Relative: x=" + di.mRel.x
+ " y=" + di.mRel.y + " ev=" + me);
if (me != null) {
- addLocked(di, curTime, ev.flags,
+ addLocked(di, curTimeNano, ev.flags,
RawInputEvent.CLASS_TRACKBALL, me);
}
}
@@ -530,7 +539,7 @@ public abstract class KeyInputQueue {
}
}
- private QueuedEvent obtainLocked(InputDevice device, long when,
+ private QueuedEvent obtainLocked(InputDevice device, long whenNano,
int flags, int classType, Object event) {
QueuedEvent ev;
if (mCacheCount == 0) {
@@ -542,7 +551,7 @@ public abstract class KeyInputQueue {
mCacheCount--;
}
ev.inputDevice = device;
- ev.when = when;
+ ev.whenNano = whenNano;
ev.flags = flags;
ev.classType = classType;
ev.event = event;
@@ -561,13 +570,13 @@ public abstract class KeyInputQueue {
}
}
- private void addLocked(InputDevice device, long when, int flags,
+ private void addLocked(InputDevice device, long whenNano, int flags,
int classType, Object event) {
boolean poke = mFirst.next == mLast;
- QueuedEvent ev = obtainLocked(device, when, flags, classType, event);
+ QueuedEvent ev = obtainLocked(device, whenNano, flags, classType, event);
QueuedEvent p = mLast.prev;
- while (p != mFirst && ev.when < p.when) {
+ while (p != mFirst && ev.whenNano < p.whenNano) {
p = p.prev;
}
@@ -578,8 +587,15 @@ public abstract class KeyInputQueue {
ev.inQueue = true;
if (poke) {
+ long time;
+ if (MEASURE_LATENCY) {
+ time = System.nanoTime();
+ }
mFirst.notify();
mWakeLock.acquire();
+ if (MEASURE_LATENCY) {
+ lt.sample("1 addLocked-queued event ", System.nanoTime() - time);
+ }
}
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 05888e0..147a085 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -46,7 +46,6 @@ import android.location.Address;
import android.location.IGeocodeProvider;
import android.location.IGpsStatusListener;
import android.location.IGpsStatusProvider;
-import android.location.ILocationCollector;
import android.location.ILocationListener;
import android.location.ILocationManager;
import android.location.ILocationProvider;
@@ -107,8 +106,6 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
private static final String INSTALL_LOCATION_PROVIDER =
android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
- private static final String INSTALL_LOCATION_COLLECTOR =
- android.Manifest.permission.INSTALL_LOCATION_COLLECTOR;
// Set of providers that are explicitly enabled
private final Set<String> mEnabledProviders = new HashSet<String>();
@@ -171,9 +168,6 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
private HashMap<String,Location> mLastKnownLocation =
new HashMap<String,Location>();
- // Location collector
- private ILocationCollector mCollector;
-
private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
// for Settings change notification
@@ -630,16 +624,6 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
}
- public void installLocationCollector(ILocationCollector collector) {
- if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_COLLECTOR)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires INSTALL_LOCATION_COLLECTOR permission");
- }
-
- // FIXME - only support one collector
- mCollector = collector;
- }
-
public void installGeocodeProvider(IGeocodeProvider provider) {
if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
!= PackageManager.PERMISSION_GRANTED) {
@@ -1619,23 +1603,19 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
synchronized (mLock) {
Location location = (Location) msg.obj;
+ String provider = location.getProvider();
- if (mCollector != null &&
- LocationManager.GPS_PROVIDER.equals(location.getProvider())) {
- try {
- mCollector.updateLocation(location);
- } catch (RemoteException e) {
- Log.w(TAG, "mCollector.updateLocation failed");
- mCollector = null;
+ // notify other providers of the new location
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ LocationProviderProxy proxy = mProviders.get(i);
+ if (!provider.equals(proxy.getName())) {
+ proxy.updateLocation(location);
}
}
- String provider = location.getProvider();
- if (!isAllowedBySettingsLocked(provider)) {
- return;
+ if (isAllowedBySettingsLocked(provider)) {
+ handleLocationChangedLocked(location);
}
-
- handleLocationChangedLocked(location);
}
}
} catch (Exception e) {
@@ -1935,7 +1915,6 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
synchronized (mLock) {
pw.println("Current Location Manager state:");
pw.println(" sProvidersLoaded=" + sProvidersLoaded);
- pw.println(" mCollector=" + mCollector);
pw.println(" Listeners:");
int N = mReceivers.size();
for (int i=0; i<N; i++) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 5194aea..1cfe002 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -1270,8 +1270,7 @@ class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
List<PreferredActivity> prefs =
- mSettings.mPreferredActivities.queryIntent(null,
- intent, resolvedType,
+ mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
(flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
if (prefs != null && prefs.size() > 0) {
// First figure out how good the original match set is.
@@ -1348,7 +1347,7 @@ class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
return (List<ResolveInfo>)mActivities.
- queryIntent(null, intent, resolvedType, flags);
+ queryIntent(intent, resolvedType, flags);
}
}
@@ -1517,7 +1516,7 @@ class PackageManagerService extends IPackageManager.Stub {
String resolvedType, int flags) {
synchronized (mPackages) {
return (List<ResolveInfo>)mReceivers.
- queryIntent(null, intent, resolvedType, flags);
+ queryIntent(intent, resolvedType, flags);
}
}
@@ -1550,8 +1549,7 @@ class PackageManagerService extends IPackageManager.Stub {
}
synchronized (mPackages) {
- return (List<ResolveInfo>)mServices.
- queryIntent(null, intent, resolvedType, flags);
+ return (List<ResolveInfo>)mServices.queryIntent(intent, resolvedType, flags);
}
}
@@ -2831,6 +2829,21 @@ class PackageManagerService extends IPackageManager.Stub {
// we can't add any new permissions to it.
if (!gp.loadedPermissions.contains(perm)) {
allowed = false;
+ // Except... if this is a permission that was added
+ // to the platform (note: need to only do this when
+ // updating the platform).
+ final int NP = PackageParser.NEW_PERMISSIONS.length;
+ for (int ip=0; ip<NP; ip++) {
+ final PackageParser.NewPermissionInfo npi
+ = PackageParser.NEW_PERMISSIONS[ip];
+ if (npi.name.equals(perm)
+ && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
+ allowed = true;
+ Log.i(TAG, "Auto-granting WRITE_SDCARD to old pkg "
+ + pkg.packageName);
+ break;
+ }
+ }
}
}
if (allowed) {
@@ -2869,17 +2882,14 @@ class PackageManagerService extends IPackageManager.Stub {
private final class ActivityIntentResolver
extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
- public List queryIntent(ContentResolver resolver, Intent intent,
- String resolvedType, boolean defaultOnly) {
+ public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
+ return super.queryIntent(intent, resolvedType, defaultOnly);
}
- public List queryIntent(ContentResolver resolver, Intent intent,
- String resolvedType, int flags) {
+ public List queryIntent(Intent intent, String resolvedType, int flags) {
mFlags = flags;
- return super.queryIntent(
- resolver, intent, resolvedType,
+ return super.queryIntent(intent, resolvedType,
(flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
}
@@ -2893,8 +2903,13 @@ class PackageManagerService extends IPackageManager.Stub {
int N = packageActivities.size();
ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
+
+ ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
for (int i = 0; i < N; ++i) {
- listCut.add(packageActivities.get(i).intents);
+ intentFilters = packageActivities.get(i).intents;
+ if (intentFilters != null && intentFilters.size() > 0) {
+ listCut.add(intentFilters);
+ }
}
return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
}
@@ -3013,17 +3028,14 @@ class PackageManagerService extends IPackageManager.Stub {
private final class ServiceIntentResolver
extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
- public List queryIntent(ContentResolver resolver, Intent intent,
- String resolvedType, boolean defaultOnly) {
+ public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
+ return super.queryIntent(intent, resolvedType, defaultOnly);
}
- public List queryIntent(ContentResolver resolver, Intent intent,
- String resolvedType, int flags) {
+ public List queryIntent(Intent intent, String resolvedType, int flags) {
mFlags = flags;
- return super.queryIntent(
- resolver, intent, resolvedType,
+ return super.queryIntent(intent, resolvedType,
(flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
}
@@ -3589,7 +3601,9 @@ class PackageManagerService extends IPackageManager.Stub {
} else {
// Re installation failed. Restore old information
// Remove new pkg information
- removePackageLI(newPackage, true);
+ if (newPackage != null) {
+ removePackageLI(newPackage, true);
+ }
// Add back the old system package
scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
oldPkgSetting.resourcePath,
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index fa54421..88f47fd 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -26,6 +26,7 @@ import android.os.RemoteException;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -39,48 +40,64 @@ import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.DefaultPhoneNotifier;
import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneStateIntentReceiver;
import com.android.internal.telephony.TelephonyIntents;
import com.android.server.am.BatteryStatsService;
-
/**
- * Since phone process can be restarted, this class provides a centralized
- * place that applications can register and be called back from.
+ * Since phone process can be restarted, this class provides a centralized place
+ * that applications can register and be called back from.
*/
class TelephonyRegistry extends ITelephonyRegistry.Stub {
private static final String TAG = "TelephonyRegistry";
private static class Record {
String pkgForDebug;
+
IBinder binder;
+
IPhoneStateListener callback;
+
int events;
}
private final Context mContext;
+
private final ArrayList<Record> mRecords = new ArrayList();
+
private final IBatteryStats mBatteryStats;
private int mCallState = TelephonyManager.CALL_STATE_IDLE;
+
private String mCallIncomingNumber = "";
+
private ServiceState mServiceState = new ServiceState();
- private int mSignalStrength = -1;
+
+ private SignalStrength mSignalStrength = new SignalStrength();
+
private boolean mMessageWaiting = false;
+
private boolean mCallForwarding = false;
+
private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
+
private int mDataConnectionState = TelephonyManager.DATA_CONNECTED;
+
private boolean mDataConnectionPossible = false;
+
private String mDataConnectionReason = "";
+
private String mDataConnectionApn = "";
+
private String mDataConnectionInterfaceName = "";
+
private Bundle mCellLocation = new Bundle();
- // we keep a copy of all of the sate so we can send it out when folks register for it
+ // we keep a copy of all of the state so we can send it out when folks
+ // register for it
//
- // In these calls we call with the lock held. This is safe becasuse remote
- // calls go through a oneway interface and local calls going through a handler before
- // they get to app code.
+ // In these calls we call with the lock held. This is safe becasuse remote
+ // calls go through a oneway interface and local calls going through a
+ // handler before they get to app code.
TelephonyRegistry(Context context) {
CellLocation.getEmpty().fillInNotifierBundle(mCellLocation);
@@ -90,13 +107,18 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
boolean notifyNow) {
- //Log.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events));
+ // Log.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
+ // Integer.toHexString(events));
if (events != 0) {
// check permissions
if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
-
+ // ACCESS_FINE_LOCATION implies ACCESS_COARSE_LOCATION
+ if (mContext.checkCallingPermission(
+ android.Manifest.permission.ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
+ }
}
synchronized (mRecords) {
@@ -105,7 +127,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
find_and_add: {
IBinder b = callback.asBinder();
final int N = mRecords.size();
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < N; i++) {
r = mRecords.get(i);
if (b == r.binder) {
break find_and_add;
@@ -125,7 +147,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
- r.callback.onSignalStrengthChanged(mSignalStrength);
+ int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
+ r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+ : gsmSignalStrength));
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -168,6 +192,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
remove(r.binder);
}
}
+ if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
+ try {
+ r.callback.onSignalStrengthsChanged(mSignalStrength);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
}
}
} else {
@@ -177,8 +208,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
private void remove(IBinder binder) {
synchronized (mRecords) {
- final int N = mRecords.size();
- for (int i=0; i<N; i++) {
+ final int recordCount = mRecords.size();
+ for (int i = 0; i < recordCount; i++) {
if (mRecords.get(i).binder == binder) {
mRecords.remove(i);
return;
@@ -194,8 +225,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) {
mCallState = state;
mCallIncomingNumber = incomingNumber;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
try {
@@ -212,11 +242,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
public void notifyServiceState(ServiceState state) {
if (!checkPhoneStatePermission("notifyServiceState()")) {
return;
- }
+ }
synchronized (mRecords) {
mServiceState = state;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
sendServiceState(r, state);
@@ -226,35 +255,38 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
broadcastServiceStateChanged(state);
}
- public void notifySignalStrength(int signalStrengthASU) {
+ public void notifySignalStrength(SignalStrength signalStrength) {
if (!checkPhoneStatePermission("notifySignalStrength()")) {
return;
- }
+ }
synchronized (mRecords) {
- mSignalStrength = signalStrengthASU;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ mSignalStrength = signalStrength;
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
+ if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
+ sendSignalStrength(r, signalStrength);
+ }
if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
- r.callback.onSignalStrengthChanged(signalStrengthASU);
+ int gsmSignalStrength = signalStrength.getGsmSignalStrength();
+ r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+ : gsmSignalStrength));
} catch (RemoteException ex) {
remove(r.binder);
}
}
}
}
- broadcastSignalStrengthChanged(signalStrengthASU);
+ broadcastSignalStrengthChanged(signalStrength);
}
public void notifyMessageWaitingChanged(boolean mwi) {
if (!checkPhoneStatePermission("notifyMessageWaitingChanged()")) {
return;
- }
+ }
synchronized (mRecords) {
mMessageWaiting = mwi;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
try {
@@ -270,11 +302,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
public void notifyCallForwardingChanged(boolean cfi) {
if (!checkPhoneStatePermission("notifyCallForwardingChanged()")) {
return;
- }
+ }
synchronized (mRecords) {
mCallForwarding = cfi;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
try {
@@ -290,11 +321,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
public void notifyDataActivity(int state) {
if (!checkPhoneStatePermission("notifyDataActivity()")) {
return;
- }
+ }
synchronized (mRecords) {
mDataActivity = state;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
try {
@@ -307,19 +337,18 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- public void notifyDataConnection(int state, boolean isDataConnectivityPissible,
- String reason, String apn, String interfaceName) {
+ public void notifyDataConnection(int state, boolean isDataConnectivityPossible, String reason,
+ String apn, String interfaceName) {
if (!checkPhoneStatePermission("notifyDataConnection()")) {
return;
- }
+ }
synchronized (mRecords) {
mDataConnectionState = state;
- mDataConnectionPossible = isDataConnectivityPissible;
+ mDataConnectionPossible = isDataConnectivityPossible;
mDataConnectionReason = reason;
mDataConnectionApn = apn;
mDataConnectionInterfaceName = interfaceName;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
try {
@@ -330,17 +359,17 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
}
- broadcastDataConnectionStateChanged(state, isDataConnectivityPissible,
- reason, apn, interfaceName);
+ broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
+ interfaceName);
}
public void notifyDataConnectionFailed(String reason) {
if (!checkPhoneStatePermission("notifyDataConnectionFailed()")) {
return;
- }
+ }
/*
* This is commented out because there is on onDataConnectionFailed callback
- * on PhoneStateListener. There should be.
+ * on PhoneStateListener. There should be
synchronized (mRecords) {
mDataConnectionFailedReason = reason;
final int N = mRecords.size();
@@ -358,11 +387,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
public void notifyCellLocation(Bundle cellLocation) {
if (!checkPhoneStatePermission("notifyCellLocation()")) {
return;
- }
+ }
synchronized (mRecords) {
mCellLocation = cellLocation;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
sendCellLocation(r, cellLocation);
@@ -371,12 +399,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- //
- // the new callback broadcasting
- //
- // copy the service state object so they can't mess it up in the local calls
- //
- public void sendServiceState(Record r, ServiceState state) {
+ /**
+ * Copy the service state object so they can't mess it up in the local calls
+ */
+ private void sendServiceState(Record r, ServiceState state) {
try {
r.callback.onServiceStateChanged(new ServiceState(state));
} catch (RemoteException ex) {
@@ -384,7 +410,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- public void sendCellLocation(Record r, Bundle cellLocation) {
+ private void sendCellLocation(Record r, Bundle cellLocation) {
try {
r.callback.onCellLocationChanged(new Bundle(cellLocation));
} catch (RemoteException ex) {
@@ -392,18 +418,24 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
+ private void sendSignalStrength(Record r, SignalStrength signalStrength) {
+ try {
+ r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump telephony.registry from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
return;
}
synchronized (mRecords) {
- final int N = mRecords.size();
+ final int recordCount = mRecords.size();
pw.println("last known state:");
pw.println(" mCallState=" + mCallState);
pw.println(" mCallIncomingNumber=" + mCallIncomingNumber);
@@ -418,15 +450,14 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println(" mDataConnectionApn=" + mDataConnectionApn);
pw.println(" mDataConnectionInterfaceName=" + mDataConnectionInterfaceName);
pw.println(" mCellLocation=" + mCellLocation);
- pw.println("registrations: count=" + N);
- for (int i=0; i<N; i++) {
+ pw.println("registrations: count=" + recordCount);
+ for (int i = 0; i < recordCount; i++) {
Record r = mRecords.get(i);
pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
}
}
}
-
//
// the legacy intent broadcasting
//
@@ -439,17 +470,20 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mContext.sendStickyBroadcast(intent);
}
- private void broadcastSignalStrengthChanged(int asu) {
+ private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
long ident = Binder.clearCallingIdentity();
try {
- mBatteryStats.notePhoneSignalStrength(asu);
+ mBatteryStats.notePhoneSignalStrength(signalStrength);
} catch (RemoteException e) {
+ /* The remote entity disappeared, we can safely ignore the exception. */
} finally {
Binder.restoreCallingIdentity(ident);
}
-
+
Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
- intent.putExtra(PhoneStateIntentReceiver.INTENT_KEY_ASU, asu);
+ Bundle data = new Bundle();
+ signalStrength.fillInNotifierBundle(data);
+ intent.putExtras(data);
mContext.sendStickyBroadcast(intent);
}
@@ -462,13 +496,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mBatteryStats.notePhoneOn();
}
} catch (RemoteException e) {
+ /* The remote entity disappeared, we can safely ignore the exception. */
} finally {
Binder.restoreCallingIdentity(ident);
}
-
+
Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
- intent.putExtra(Phone.STATE_KEY,
- DefaultPhoneNotifier.convertCallState(state).toString());
+ intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
if (!TextUtils.isEmpty(incomingNumber)) {
intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
}
@@ -498,15 +532,14 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
mContext.sendStickyBroadcast(intent);
}
-
+
private boolean checkPhoneStatePermission(String method) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
== PackageManager.PERMISSION_GRANTED) {
return true;
}
String msg = "Modify Phone State Permission Denial: " + method + " from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid();
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
Log.w(TAG, msg);
return false;
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 348f0a1..5fa8701 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -96,8 +96,8 @@ public class WifiService extends IWifiManager.Stub {
private int mScanLocksAcquired;
private int mScanLocksReleased;
- private final List<WifiMulticaster> mMulticasters =
- new ArrayList<WifiMulticaster>();
+ private final List<Multicaster> mMulticasters =
+ new ArrayList<Multicaster>();
private int mMulticastEnabled;
private int mMulticastDisabled;
@@ -1449,10 +1449,12 @@ public class WifiService extends IWifiManager.Stub {
Settings.System.getInt(mContext.getContentResolver(),
Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0);
if (action.equals(Intent.ACTION_SCREEN_ON)) {
+ Log.d(TAG, "ACTION_SCREEN_ON");
mAlarmManager.cancel(mIdleIntent);
mDeviceIdle = false;
mScreenOff = false;
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+ Log.d(TAG, "ACTION_SCREEN_OFF");
mScreenOff = true;
/*
* Set a timer to put Wi-Fi to sleep, but only if the screen is off
@@ -1461,12 +1463,20 @@ public class WifiService extends IWifiManager.Stub {
* or plugged in to AC).
*/
if (!shouldWifiStayAwake(stayAwakeConditions, mPluggedType)) {
- long triggerTime = System.currentTimeMillis() + idleMillis;
- mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
+ if (!mWifiStateTracker.hasIpAddress()) {
+ // do not keep Wifi awake when screen is off if Wifi is not fully active
+ mDeviceIdle = true;
+ updateWifiState();
+ } else {
+ long triggerTime = System.currentTimeMillis() + idleMillis;
+ Log.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis + "ms");
+ mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
+ }
}
/* we can return now -- there's nothing to do until we get the idle intent back */
return;
} else if (action.equals(ACTION_DEVICE_IDLE)) {
+ Log.d(TAG, "got ACTION_DEVICE_IDLE");
mDeviceIdle = true;
} else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
/*
@@ -1477,9 +1487,11 @@ public class WifiService extends IWifiManager.Stub {
* the already-set timer.
*/
int pluggedType = intent.getIntExtra("plugged", 0);
+ Log.d(TAG, "ACTION_BATTERY_CHANGED pluggedType: " + pluggedType);
if (mScreenOff && shouldWifiStayAwake(stayAwakeConditions, mPluggedType) &&
!shouldWifiStayAwake(stayAwakeConditions, pluggedType)) {
long triggerTime = System.currentTimeMillis() + idleMillis;
+ Log.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis + "ms");
mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
mPluggedType = pluggedType;
return;
@@ -1732,7 +1744,7 @@ public class WifiService extends IWifiManager.Stub {
}
}
- private class WifiLock extends WifiDeathRecipient {
+ private class WifiLock extends DeathRecipient {
WifiLock(int lockMode, String tag, IBinder binder) {
super(lockMode, tag, binder);
}
@@ -1875,13 +1887,13 @@ public class WifiService extends IWifiManager.Stub {
return hadLock;
}
- private abstract class WifiDeathRecipient
+ private abstract class DeathRecipient
implements IBinder.DeathRecipient {
String mTag;
int mMode;
IBinder mBinder;
- WifiDeathRecipient(int mode, String tag, IBinder binder) {
+ DeathRecipient(int mode, String tag, IBinder binder) {
super();
mTag = tag;
mMode = mode;
@@ -1894,13 +1906,13 @@ public class WifiService extends IWifiManager.Stub {
}
}
- private class WifiMulticaster extends WifiDeathRecipient {
- WifiMulticaster(String tag, IBinder binder) {
+ private class Multicaster extends DeathRecipient {
+ Multicaster(String tag, IBinder binder) {
super(Binder.getCallingUid(), tag, binder);
}
public void binderDied() {
- Log.e(TAG, "WifiMulticaster binderDied");
+ Log.e(TAG, "Multicaster binderDied");
synchronized (mMulticasters) {
int i = mMulticasters.indexOf(this);
if (i != -1) {
@@ -1910,7 +1922,7 @@ public class WifiService extends IWifiManager.Stub {
}
public String toString() {
- return "WifiMulticaster{" + mTag + " binder=" + mBinder + "}";
+ return "Multicaster{" + mTag + " binder=" + mBinder + "}";
}
public int getUid() {
@@ -1918,12 +1930,12 @@ public class WifiService extends IWifiManager.Stub {
}
}
- public void enableWifiMulticast(IBinder binder, String tag) {
+ public void enableMulticast(IBinder binder, String tag) {
enforceChangePermission();
synchronized (mMulticasters) {
mMulticastEnabled++;
- mMulticasters.add(new WifiMulticaster(tag, binder));
+ mMulticasters.add(new Multicaster(tag, binder));
// Note that we could call stopPacketFiltering only when
// our new size == 1 (first call), but this function won't
// be called often and by making the stopPacket call each
@@ -1941,7 +1953,7 @@ public class WifiService extends IWifiManager.Stub {
}
}
- public void disableWifiMulticast() {
+ public void disableMulticast() {
enforceChangePermission();
int uid = Binder.getCallingUid();
@@ -1949,7 +1961,7 @@ public class WifiService extends IWifiManager.Stub {
mMulticastDisabled++;
int size = mMulticasters.size();
for (int i = size - 1; i >= 0; i--) {
- WifiMulticaster m = mMulticasters.get(i);
+ Multicaster m = mMulticasters.get(i);
if ((m != null) && (m.getUid() == uid)) {
removeMulticasterLocked(i, uid);
}
@@ -1973,7 +1985,7 @@ public class WifiService extends IWifiManager.Stub {
}
}
- public boolean isWifiMulticastEnabled() {
+ public boolean isMulticastEnabled() {
enforceAccessPermission();
synchronized (mMulticasters) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 3fa5baf..4561e1a 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -63,6 +63,7 @@ import android.os.Binder;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
+import android.os.LatencyTimer;
import android.os.LocalPowerManager;
import android.os.Looper;
import android.os.Message;
@@ -133,7 +134,9 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
static final boolean DEBUG_STARTING_WINDOW = false;
static final boolean DEBUG_REORDER = false;
static final boolean SHOW_TRANSACTIONS = false;
-
+ static final boolean MEASURE_LATENCY = false;
+ static private LatencyTimer lt;
+
static final boolean PROFILE_ORIENTATION = false;
static final boolean BLUR = true;
static final boolean localLOGV = DEBUG;
@@ -495,6 +498,10 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
private WindowManagerService(Context context, PowerManagerService pm,
boolean haveInputMethods) {
+ if (MEASURE_LATENCY) {
+ lt = new LatencyTimer(100, 1000);
+ }
+
mContext = context;
mHaveInputMethods = haveInputMethods;
mLimitedAlphaCompositing = context.getResources().getBoolean(
@@ -1300,7 +1307,6 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
}
}
-
if (localLOGV) Log.v(
TAG, "New client " + client.asBinder()
+ ": window=" + win);
@@ -3715,7 +3721,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
long curTime = SystemClock.uptimeMillis();
- if (eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
+ if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
if (mLastTouchEventType == eventType &&
(curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
return;
@@ -3775,9 +3781,17 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Log.v(TAG,
"dispatchPointer " + ev);
+ if (MEASURE_LATENCY) {
+ lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
+ }
+
Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
ev, true, false);
+ if (MEASURE_LATENCY) {
+ lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
+ }
+
int action = ev.getAction();
if (action == MotionEvent.ACTION_UP) {
@@ -3814,6 +3828,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
WindowState target = (WindowState)targetObj;
final long eventTime = ev.getEventTime();
+ final long eventTimeNano = ev.getEventTimeNano();
//Log.i(TAG, "Sending " + ev + " to " + target);
@@ -3832,6 +3847,10 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
}
}
+ if (MEASURE_LATENCY) {
+ lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano);
+ }
+
if ((target.mAttrs.flags &
WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
//target wants to ignore fat touch events
@@ -3914,6 +3933,10 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
}
}
+ if (MEASURE_LATENCY) {
+ lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano);
+ }
+
synchronized(mWindowMap) {
if (qev != null && action == MotionEvent.ACTION_MOVE) {
mKeyWaiter.bindTargetWindowLocked(target,
@@ -3951,7 +3974,16 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
Log.v(TAG, "Delivering pointer " + qev + " to " + target);
}
+
+ if (MEASURE_LATENCY) {
+ lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
+ }
+
target.mClient.dispatchPointer(ev, eventTime);
+
+ if (MEASURE_LATENCY) {
+ lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
+ }
return true;
} catch (android.os.RemoteException e) {
Log.i(TAG, "WINDOW DIED during motion dispatch: " + target);
@@ -5072,7 +5104,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
}
}
}
- };
+ }
public boolean detectSafeMode() {
mSafeMode = mPolicy.detectSafeMode();
@@ -5137,9 +5169,13 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
if (DEBUG_INPUT && ev != null) Log.v(
TAG, "Event: type=" + ev.classType + " data=" + ev.event);
+ if (MEASURE_LATENCY) {
+ lt.sample("2 got event ", System.nanoTime() - ev.whenNano);
+ }
+
try {
if (ev != null) {
- curTime = ev.when;
+ curTime = SystemClock.uptimeMillis();
int eventType;
if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
eventType = eventType((MotionEvent)ev.event);
@@ -5150,17 +5186,29 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
eventType = LocalPowerManager.OTHER_EVENT;
}
try {
- long now = SystemClock.uptimeMillis();
-
- if ((now - mLastBatteryStatsCallTime)
+ if ((curTime - mLastBatteryStatsCallTime)
>= MIN_TIME_BETWEEN_USERACTIVITIES) {
- mLastBatteryStatsCallTime = now;
+ mLastBatteryStatsCallTime = curTime;
mBatteryStats.noteInputEvent();
}
} catch (RemoteException e) {
// Ignore
}
- mPowerManager.userActivity(curTime, false, eventType, false);
+
+ if (eventType != TOUCH_EVENT
+ && eventType != LONG_TOUCH_EVENT
+ && eventType != CHEEK_EVENT) {
+ mPowerManager.userActivity(curTime, false,
+ eventType, false);
+ } else if (mLastTouchEventType != eventType
+ || (curTime - mLastUserActivityCallTime)
+ >= MIN_TIME_BETWEEN_USERACTIVITIES) {
+ mLastUserActivityCallTime = curTime;
+ mLastTouchEventType = eventType;
+ mPowerManager.userActivity(curTime, false,
+ eventType, false);
+ }
+
switch (ev.classType) {
case RawInputEvent.CLASS_KEYBOARD:
KeyEvent ke = (KeyEvent)ev.event;
@@ -7732,7 +7780,6 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
int i;
// FIRST LOOP: Perform a layout, if needed.
-
performLayoutLockedInner();
if (mFxSession == null) {
@@ -7752,7 +7799,6 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
}
// SECOND LOOP: Execute animations and update visibility of windows.
-
boolean orientationChangeComplete = true;
Session holdScreen = null;
float screenBrightness = -1;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 9471eff..f2959e3 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -30,6 +30,7 @@ import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.ActivityThread;
import android.app.AlertDialog;
+import android.app.ApplicationErrorReport;
import android.app.Dialog;
import android.app.IActivityWatcher;
import android.app.IApplicationThread;
@@ -41,6 +42,7 @@ import android.app.IThumbnailReceiver;
import android.app.Instrumentation;
import android.app.PendingIntent;
import android.app.ResultInfo;
+import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -78,10 +80,14 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Checkin;
import android.provider.Settings;
+import android.server.data.CrashData;
+import android.server.data.StackTraceElementData;
+import android.server.data.ThrowableData;
import android.text.TextUtils;
import android.util.Config;
import android.util.EventLog;
import android.util.Log;
+import android.util.LogPrinter;
import android.util.PrintWriterPrinter;
import android.util.SparseArray;
import android.view.Gravity;
@@ -92,10 +98,13 @@ import android.view.WindowManagerPolicy;
import dalvik.system.Zygote;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.PrintWriter;
import java.lang.IllegalStateException;
import java.lang.ref.WeakReference;
@@ -191,6 +200,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// Maximum number of recent tasks that we can remember.
static final int MAX_RECENT_TASKS = 20;
+ // Amount of time after a call to stopAppSwitches() during which we will
+ // prevent further untrusted switches from happening.
+ static final long APP_SWITCH_DELAY_TIME = 5*1000;
+
// How long until we reset a task when the user returns to it. Currently
// 30 minutes.
static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
@@ -328,6 +341,21 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
final ArrayList mHistory = new ArrayList();
/**
+ * Description of a request to start a new activity, which has been held
+ * due to app switches being disabled.
+ */
+ class PendingActivityLaunch {
+ HistoryRecord r;
+ HistoryRecord sourceRecord;
+ Uri[] grantedUriPermissions;
+ int grantedMode;
+ boolean onlyIfNeeded;
+ }
+
+ final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
+ = new ArrayList<PendingActivityLaunch>();
+
+ /**
* List of all active broadcasts that are to be executed immediately
* (without waiting for another broadcast to finish). Currently this only
* contains broadcasts to registered receivers, to avoid spinning up
@@ -705,6 +733,18 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
int mFactoryTest;
/**
+ * The time at which we will allow normal application switches again,
+ * after a call to {@link #stopAppSwitches()}.
+ */
+ long mAppSwitchesAllowedTime;
+
+ /**
+ * This is set to true after the first switch after mAppSwitchesAllowedTime
+ * is set; any switches after that will clear the time.
+ */
+ boolean mDidAppSwitch;
+
+ /**
* Set while we are wanting to sleep, to prevent any
* activities from being started/resumed.
*/
@@ -852,6 +892,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
static final int SERVICE_ERROR_MSG = 18;
static final int RESUME_TOP_ACTIVITY_MSG = 19;
static final int PROC_START_TIMEOUT_MSG = 20;
+ static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
AlertDialog mUidAlert;
@@ -910,6 +951,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
d.show();
proc.anrDialog = d;
}
+
+ ensureScreenEnabled();
} break;
case SHOW_FACTORY_ERROR_MSG: {
Dialog d = new FactoryErrorDialog(
@@ -1041,6 +1084,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
processStartTimedOutLocked(app);
}
}
+ case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
+ synchronized (ActivityManagerService.this) {
+ doPendingActivityLaunchesLocked(true);
+ }
+ }
}
}
};
@@ -1495,6 +1543,18 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
return null;
}
+ private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
+ int i = mHistory.size()-1;
+ while (i >= 0) {
+ HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ if (!r.finishing && !r.delayedResume && r != notTop) {
+ return r;
+ }
+ i--;
+ }
+ return null;
+ }
+
/**
* This is a simplified version of topRunningActivityLocked that provides a number of
* optional skip-over modes. It is intended for use with the ActivityWatcher hook only.
@@ -2245,6 +2305,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
return true;
}
+ next.delayedResume = false;
+
// If the top activity is the resumed one, nothing to do.
if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
// Make sure we have executed any pending transitions, since there
@@ -2471,7 +2533,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
return true;
}
- private final void startActivityLocked(HistoryRecord r, boolean newTask) {
+ private final void startActivityLocked(HistoryRecord r, boolean newTask,
+ boolean doResume) {
final int NH = mHistory.size();
int addPos = -1;
@@ -2558,7 +2621,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if ((r.intent.getFlags()
&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
resetTaskIfNeededLocked(r, r);
- doShow = topRunningActivityLocked(null) == r;
+ doShow = topRunningNonDelayedActivityLocked(null) == r;
}
}
if (SHOW_APP_STARTING_ICON && doShow) {
@@ -2588,13 +2651,15 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
mWindowManager.validateAppTokens(mHistory);
}
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
}
/**
* Perform clear operation as requested by
- * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: assuming the top task on the
- * stack is the one that the new activity is being launched in, look for
+ * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
+ * stack to the given task, then look for
* an instance of that activity in the stack and, if found, finish all
* activities on top of it and return the instance.
*
@@ -2602,9 +2667,21 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
* @return Returns the old activity that should be continue to be used,
* or null if none was found.
*/
- private final HistoryRecord performClearTopTaskLocked(int taskId,
+ private final HistoryRecord performClearTaskLocked(int taskId,
HistoryRecord newR, boolean doClear) {
int i = mHistory.size();
+
+ // First find the requested task.
+ while (i > 0) {
+ i--;
+ HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ if (r.task.taskId == taskId) {
+ i++;
+ break;
+ }
+ }
+
+ // Now clear it.
while (i > 0) {
i--;
HistoryRecord r = (HistoryRecord)mHistory.get(i);
@@ -2840,15 +2917,75 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
intent, resolvedType, aInfo, mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
- HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
- != 0 ? r : null;
-
+ if (mResumedActivity == null
+ || mResumedActivity.info.applicationInfo.uid != callingUid) {
+ if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
+ PendingActivityLaunch pal = new PendingActivityLaunch();
+ pal.r = r;
+ pal.sourceRecord = sourceRecord;
+ pal.grantedUriPermissions = grantedUriPermissions;
+ pal.grantedMode = grantedMode;
+ pal.onlyIfNeeded = onlyIfNeeded;
+ mPendingActivityLaunches.add(pal);
+ return START_SWITCHES_CANCELED;
+ }
+ }
+
+ if (mDidAppSwitch) {
+ // This is the second allowed switch since we stopped switches,
+ // so now just generally allow switches. Use case: user presses
+ // home (switches disabled, switch to home, mDidAppSwitch now true);
+ // user taps a home icon (coming from home so allowed, we hit here
+ // and now allow anyone to switch again).
+ mAppSwitchesAllowedTime = 0;
+ } else {
+ mDidAppSwitch = true;
+ }
+
+ doPendingActivityLaunchesLocked(false);
+
+ return startActivityUncheckedLocked(r, sourceRecord,
+ grantedUriPermissions, grantedMode, onlyIfNeeded, true);
+ }
+
+ private final void doPendingActivityLaunchesLocked(boolean doResume) {
+ final int N = mPendingActivityLaunches.size();
+ if (N <= 0) {
+ return;
+ }
+ for (int i=0; i<N; i++) {
+ PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
+ startActivityUncheckedLocked(pal.r, pal.sourceRecord,
+ pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
+ doResume && i == (N-1));
+ }
+ mPendingActivityLaunches.clear();
+ }
+
+ private final int startActivityUncheckedLocked(HistoryRecord r,
+ HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
+ int grantedMode, boolean onlyIfNeeded, boolean doResume) {
+ final Intent intent = r.intent;
+ final int callingUid = r.launchedFromUid;
+
+ int launchFlags = intent.getFlags();
+
// We'll invoke onUserLeaving before onPause only if the launching
// activity did not explicitly state that this is an automated launch.
mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
if (DEBUG_USER_LEAVING) Log.v(TAG,
"startActivity() => mUserLeaving=" + mUserLeaving);
+ // If the caller has asked not to resume at this point, we make note
+ // of this in the record so that we can skip it when trying to find
+ // the top running activity.
+ if (!doResume) {
+ r.delayedResume = true;
+ }
+
+ HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
+ != 0 ? r : null;
+
// If the onlyIfNeeded flag is set, then we can do this if the activity
// being launched is the same as the one making the call... or, as
// a special case, if we do not know the caller then we count the
@@ -2856,7 +2993,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (onlyIfNeeded) {
HistoryRecord checkedCaller = sourceRecord;
if (checkedCaller == null) {
- checkedCaller = topRunningActivityLocked(notTop);
+ checkedCaller = topRunningNonDelayedActivityLocked(notTop);
}
if (!checkedCaller.realActivity.equals(r.realActivity)) {
// Caller is not the same as launcher, so always needed.
@@ -2894,7 +3031,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
- if (resultRecord != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+ if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
// For whatever reason this activity is being launched into a new
// task... yet the caller has requested a result back. Well, that
// is pretty messed up, so instead immediately send back a cancel
@@ -2902,10 +3039,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// dependency on its originator.
Log.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
sendActivityResultLocked(-1,
- resultRecord, resultWho, requestCode,
+ r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
r.resultTo = null;
- resultRecord = null;
}
boolean addingToTask = false;
@@ -2916,7 +3052,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// If bring to front is requested, and no result is requested, and
// we can find a task that was started with this same
// component, then instead of launching bring that one to the front.
- if (resultRecord == null) {
+ if (r.resultTo == null) {
// See if there is a task to bring to the front. If this is
// a SINGLE_INSTANCE activity, there can be one and only one
// instance of it in the history, and it is always in its own
@@ -2938,7 +3074,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// to have the same behavior as if a new instance was
// being started, which means not bringing it to the front
// if the caller is not itself in the front.
- HistoryRecord curTop = topRunningActivityLocked(notTop);
+ HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
if (curTop.task != taskTop.task) {
r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
boolean callerAtFront = sourceRecord == null
@@ -2959,7 +3095,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// the client said not to do anything if that
// is the case, so this is it! And for paranoia, make
// sure we have correctly resumed the top activity.
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
return START_RETURN_INTENT_TO_CALLER;
}
if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
@@ -2969,7 +3107,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// from the task up to the one being started. In most
// cases this means we are resetting the task to its
// initial state.
- HistoryRecord top = performClearTopTaskLocked(
+ HistoryRecord top = performClearTaskLocked(
taskTop.task.taskId, r, true);
if (top != null) {
if (top.frontOfTask) {
@@ -3035,7 +3173,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// We didn't do anything... but it was needed (a.k.a., client
// don't use that intent!) And for paranoia, make
// sure we have correctly resumed the top activity.
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
return START_TASK_TO_FRONT;
}
}
@@ -3052,8 +3192,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// If the activity being launched is the same as the one currently
// at the top, then we need to check if it should only be launched
// once.
- HistoryRecord top = topRunningActivityLocked(notTop);
- if (top != null && resultRecord == null) {
+ HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
+ if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity)) {
if (top.app != null && top.app.thread != null) {
if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
@@ -3062,7 +3202,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
logStartActivity(LOG_AM_NEW_INTENT, top, top.task);
// For paranoia, make sure we have correctly
// resumed the top activity.
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
if (onlyIfNeeded) {
// We don't need to start a new activity, and
// the client said not to do anything if that
@@ -3077,9 +3219,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
} else {
- if (resultRecord != null) {
+ if (r.resultTo != null) {
sendActivityResultLocked(-1,
- resultRecord, resultWho, requestCode,
+ r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
}
return START_CLASS_NOT_FOUND;
@@ -3088,7 +3230,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
boolean newTask = false;
// Should this be considered a new task?
- if (resultRecord == null && !addingToTask
+ if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
// todo: should do better management of integers.
mCurTask++;
@@ -3108,14 +3250,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// In this case, we are adding the activity to an existing
// task, but the caller has asked to clear that task if the
// activity is already running.
- HistoryRecord top = performClearTopTaskLocked(
+ HistoryRecord top = performClearTaskLocked(
sourceRecord.task.taskId, r, true);
if (top != null) {
logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
deliverNewIntentLocked(top, r.intent);
// For paranoia, make sure we have correctly
// resumed the top activity.
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
return START_DELIVERED_TO_TOP;
}
} else if (!addingToTask &&
@@ -3128,7 +3272,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
HistoryRecord top = moveActivityToFrontLocked(where);
logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
deliverNewIntentLocked(top, r.intent);
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
return START_DELIVERED_TO_TOP;
}
}
@@ -3157,7 +3303,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
EventLog.writeEvent(LOG_AM_CREATE_TASK, r.task.taskId);
}
logStartActivity(LOG_AM_CREATE_ACTIVITY, r, r.task);
- startActivityLocked(r, newTask);
+ startActivityLocked(r, newTask, doResume);
return START_SUCCESS;
}
@@ -4911,6 +5057,20 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
+ final void ensureScreenEnabled() {
+ boolean enableScreen;
+ synchronized (this) {
+ enableScreen = !mBooted;
+ mBooted = true;
+ }
+
+ if (enableScreen) {
+ EventLog.writeEvent(LOG_BOOT_PROGRESS_ENABLE_SCREEN,
+ SystemClock.uptimeMillis());
+ enableScreenAfterBoot();
+ }
+ }
+
public final void activityPaused(IBinder token, Bundle icicle) {
// Refuse possible leaked file descriptors
if (icicle != null && icicle.hasFileDescriptors()) {
@@ -6251,6 +6411,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
"moveTaskToFront()");
synchronized(this) {
+ if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
+ Binder.getCallingUid(), "Task to front")) {
+ return;
+ }
final long origId = Binder.clearCallingIdentity();
try {
int N = mRecentTasks.size();
@@ -6335,6 +6499,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
"moveTaskToBack()");
synchronized(this) {
+ if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
+ if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
+ Binder.getCallingUid(), "Task to back")) {
+ return;
+ }
+ }
final long origId = Binder.clearCallingIdentity();
moveTaskToBackLocked(task);
Binder.restoreCallingIdentity(origId);
@@ -6438,6 +6608,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
"moveTaskBackwards()");
synchronized(this) {
+ if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
+ Binder.getCallingUid(), "Task backwards")) {
+ return;
+ }
final long origId = Binder.clearCallingIdentity();
moveTaskBackwardsLocked(task);
Binder.restoreCallingIdentity(origId);
@@ -7179,6 +7353,55 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
+ public void stopAppSwitches() {
+ if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission "
+ + android.Manifest.permission.STOP_APP_SWITCHES);
+ }
+
+ synchronized(this) {
+ mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
+ + APP_SWITCH_DELAY_TIME;
+ mDidAppSwitch = false;
+ mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
+ Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
+ mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
+ }
+ }
+
+ public void resumeAppSwitches() {
+ if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission "
+ + android.Manifest.permission.STOP_APP_SWITCHES);
+ }
+
+ synchronized(this) {
+ // Note that we don't execute any pending app switches... we will
+ // let those wait until either the timeout, or the next start
+ // activity request.
+ mAppSwitchesAllowedTime = 0;
+ }
+ }
+
+ boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
+ String name) {
+ if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
+ return true;
+ }
+
+ final int perm = checkComponentPermission(
+ android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
+ callingUid, -1);
+ if (perm == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+
+ Log.w(TAG, name + " request from " + callingUid + " stopped");
+ return false;
+ }
+
public void setDebugApp(String packageName, boolean waitForDebugger,
boolean persistent) {
enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
@@ -7595,6 +7818,30 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
return handleAppCrashLocked(app);
}
+ private ComponentName getErrorReportReceiver(ProcessRecord app) {
+ IPackageManager pm = ActivityThread.getPackageManager();
+ try {
+ // was an installer package name specified when this app was
+ // installed?
+ String installerPackageName = pm.getInstallerPackageName(app.info.packageName);
+ if (installerPackageName == null) {
+ return null;
+ }
+
+ // is there an Activity in this package that handles ACTION_APP_ERROR?
+ Intent intent = new Intent(Intent.ACTION_APP_ERROR);
+ ResolveInfo info = pm.resolveIntentForPackage(intent, null, 0, installerPackageName);
+ if (info == null || info.activityInfo == null) {
+ return null;
+ }
+
+ return new ComponentName(installerPackageName, info.activityInfo.name);
+ } catch (RemoteException e) {
+ // will return null and no error report will be delivered
+ }
+ return null;
+ }
+
void makeAppNotRespondingLocked(ProcessRecord app,
String tag, String shortMsg, String longMsg, byte[] crashData) {
app.notResponding = true;
@@ -7713,6 +7960,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
void startAppProblemLocked(ProcessRecord app) {
+ app.errorReportReceiver = getErrorReportReceiver(app);
skipCurrentReceiverLocked(app);
}
@@ -7745,7 +7993,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
public int handleApplicationError(IBinder app, int flags,
String tag, String shortMsg, String longMsg, byte[] crashData) {
AppErrorResult result = new AppErrorResult();
-
ProcessRecord r = null;
synchronized (this) {
if (app != null) {
@@ -7834,16 +8081,96 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
int res = result.get();
+ Intent appErrorIntent = null;
synchronized (this) {
if (r != null) {
mProcessCrashTimes.put(r.info.processName, r.info.uid,
SystemClock.uptimeMillis());
}
+ if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
+ appErrorIntent = createAppErrorIntentLocked(r);
+ res = AppErrorDialog.FORCE_QUIT;
+ }
+ }
+
+ if (appErrorIntent != null) {
+ try {
+ mContext.startActivity(appErrorIntent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "bug report receiver dissappeared", e);
+ }
}
return res;
}
+ Intent createAppErrorIntentLocked(ProcessRecord r) {
+ ApplicationErrorReport report = createAppErrorReportLocked(r);
+ if (report == null) {
+ return null;
+ }
+ Intent result = new Intent(Intent.ACTION_APP_ERROR);
+ result.setComponent(r.errorReportReceiver);
+ result.putExtra(Intent.EXTRA_BUG_REPORT, report);
+ result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return result;
+ }
+
+ ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r) {
+ if (r.errorReportReceiver == null) {
+ return null;
+ }
+
+ if (!r.crashing && !r.notResponding) {
+ return null;
+ }
+
+ try {
+ ApplicationErrorReport report = new ApplicationErrorReport();
+ report.packageName = r.info.packageName;
+ report.installerPackageName = r.errorReportReceiver.getPackageName();
+ report.processName = r.processName;
+
+ if (r.crashing) {
+ report.type = ApplicationErrorReport.TYPE_CRASH;
+ report.crashInfo = new ApplicationErrorReport.CrashInfo();
+
+ ByteArrayInputStream byteStream = new ByteArrayInputStream(
+ r.crashingReport.crashData);
+ DataInputStream dataStream = new DataInputStream(byteStream);
+ CrashData crashData = new CrashData(dataStream);
+ ThrowableData throwData = crashData.getThrowableData();
+
+ report.time = crashData.getTime();
+ report.crashInfo.stackTrace = throwData.toString();
+
+ // extract the source of the exception, useful for report
+ // clustering
+ while (throwData.getCause() != null) {
+ throwData = throwData.getCause();
+ }
+ StackTraceElementData trace = throwData.getStackTrace()[0];
+ report.crashInfo.exceptionClassName = throwData.getType();
+ report.crashInfo.throwFileName = trace.getFileName();
+ report.crashInfo.throwClassName = trace.getClassName();
+ report.crashInfo.throwMethodName = trace.getMethodName();
+ } else if (r.notResponding) {
+ report.type = ApplicationErrorReport.TYPE_ANR;
+ report.anrInfo = new ApplicationErrorReport.AnrInfo();
+
+ report.anrInfo.activity = r.notRespondingReport.tag;
+ report.anrInfo.cause = r.notRespondingReport.shortMsg;
+ report.anrInfo.info = r.notRespondingReport.longMsg;
+ }
+
+ return report;
+ } catch (IOException e) {
+ // we don't send it
+ }
+
+ return null;
+ }
+
public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
// assume our apps are happy - lazy create the list
List<ActivityManager.ProcessErrorStateInfo> errList = null;
@@ -10176,8 +10503,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
- final ContentResolver resolver = mContext.getContentResolver();
-
// Figure out who all will receive this broadcast.
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
@@ -10200,8 +10525,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
ActivityThread.getPackageManager().queryIntentReceivers(
intent, resolvedType, STOCK_PM_FLAGS);
}
- registeredReceivers = mReceiverResolver.queryIntent(resolver,
- intent, resolvedType, false);
+ registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java
index 3fcfad0..33894d6 100644
--- a/services/java/com/android/server/am/AppErrorDialog.java
+++ b/services/java/com/android/server/am/AppErrorDialog.java
@@ -19,17 +19,22 @@ package com.android.server.am;
import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
+import android.util.Log;
class AppErrorDialog extends BaseErrorDialog {
+ private final static String TAG = "AppErrorDialog";
+
private final AppErrorResult mResult;
private final ProcessRecord mProc;
// Event 'what' codes
static final int FORCE_QUIT = 0;
static final int DEBUG = 1;
+ static final int FORCE_QUIT_AND_REPORT = 2;
// 5-minute timeout, then we automatically dismiss the crash dialog
static final long DISMISS_TIMEOUT = 1000 * 60 * 5;
@@ -58,12 +63,22 @@ class AppErrorDialog extends BaseErrorDialog {
setCancelable(false);
- setButton(res.getText(com.android.internal.R.string.force_close),
- mHandler.obtainMessage(FORCE_QUIT));
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ res.getText(com.android.internal.R.string.force_close),
+ mHandler.obtainMessage(FORCE_QUIT));
+
if ((flags&1) != 0) {
- setButton(res.getText(com.android.internal.R.string.debug),
+ setButton(DialogInterface.BUTTON_NEUTRAL,
+ res.getText(com.android.internal.R.string.debug),
mHandler.obtainMessage(DEBUG));
}
+
+ if (app.errorReportReceiver != null) {
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ res.getText(com.android.internal.R.string.report),
+ mHandler.obtainMessage(FORCE_QUIT_AND_REPORT));
+ }
+
setTitle(res.getText(com.android.internal.R.string.aerr_title));
getWindow().addFlags(FLAG_SYSTEM_ERROR);
getWindow().setTitle("Application Error: " + app.info.processName);
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
index 7390ed0..03c2a04 100644
--- a/services/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -18,7 +18,10 @@ package com.android.server.am;
import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+import android.content.ActivityNotFoundException;
import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
@@ -26,6 +29,13 @@ import android.os.Process;
import android.util.Log;
class AppNotRespondingDialog extends BaseErrorDialog {
+ private static final String TAG = "AppNotRespondingDialog";
+
+ // Event 'what' codes
+ static final int FORCE_CLOSE = 1;
+ static final int WAIT = 2;
+ static final int WAIT_AND_REPORT = 3;
+
private final ActivityManagerService mService;
private final ProcessRecord mProc;
@@ -67,10 +77,19 @@ class AppNotRespondingDialog extends BaseErrorDialog {
? res.getString(resid, name1.toString(), name2.toString())
: res.getString(resid, name1.toString()));
- setButton(res.getText(com.android.internal.R.string.force_close),
- mHandler.obtainMessage(1));
- setButton2(res.getText(com.android.internal.R.string.wait),
- mHandler.obtainMessage(2));
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ res.getText(com.android.internal.R.string.force_close),
+ mHandler.obtainMessage(FORCE_CLOSE));
+ setButton(DialogInterface.BUTTON_NEUTRAL,
+ res.getText(com.android.internal.R.string.wait),
+ mHandler.obtainMessage(WAIT));
+
+ if (app.errorReportReceiver != null) {
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ res.getText(com.android.internal.R.string.report),
+ mHandler.obtainMessage(WAIT_AND_REPORT));
+ }
+
setTitle(res.getText(com.android.internal.R.string.anr_title));
getWindow().addFlags(FLAG_SYSTEM_ERROR);
getWindow().setTitle("Application Not Responding: " + app.info.processName);
@@ -81,16 +100,23 @@ class AppNotRespondingDialog extends BaseErrorDialog {
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
+ Intent appErrorIntent = null;
switch (msg.what) {
- case 1:
+ case FORCE_CLOSE:
// Kill the application.
mService.killAppAtUsersRequest(mProc,
AppNotRespondingDialog.this, true);
break;
- case 2:
+ case WAIT_AND_REPORT:
+ case WAIT:
// Continue waiting for the application.
synchronized (mService) {
ProcessRecord app = mProc;
+
+ if (msg.what == WAIT_AND_REPORT) {
+ appErrorIntent = mService.createAppErrorIntentLocked(app);
+ }
+
app.notResponding = false;
app.notRespondingReport = null;
if (app.anrDialog == AppNotRespondingDialog.this) {
@@ -99,6 +125,14 @@ class AppNotRespondingDialog extends BaseErrorDialog {
}
break;
}
+
+ if (appErrorIntent != null) {
+ try {
+ getContext().startActivity(appErrorIntent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "bug report receiver dissappeared", e);
+ }
+ }
}
};
}
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 0387be5..a695eba 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -25,6 +25,7 @@ import android.os.IBinder;
import android.os.Parcel;
import android.os.Process;
import android.os.ServiceManager;
+import android.telephony.SignalStrength;
import android.util.Log;
import java.io.FileDescriptor;
@@ -177,10 +178,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub {
}
}
- public void notePhoneSignalStrength(int asu) {
+ public void notePhoneSignalStrength(SignalStrength signalStrength) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.notePhoneSignalStrengthLocked(asu);
+ mStats.notePhoneSignalStrengthLocked(signalStrength);
}
}
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index 1488791..1789687 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -85,6 +85,7 @@ class HistoryRecord extends IApplicationToken.Stub {
boolean launchFailed; // set if a launched failed, to abort on 2nd try
boolean haveState; // have we gotten the last activity state?
boolean stopped; // is activity pause finished?
+ boolean delayedResume; // not yet resumed because of stopped app switches?
boolean finishing; // activity in pending finish list?
boolean configDestroy; // need to destroy due to config change?
int configChangeFlags; // which config values have changed
@@ -146,6 +147,7 @@ class HistoryRecord extends IApplicationToken.Stub {
pw.print(" icicle="); pw.println(icicle);
pw.print(prefix); pw.print("state="); pw.print(state);
pw.print(" stopped="); pw.print(stopped);
+ pw.print(" delayedResume="); pw.print(delayedResume);
pw.print(" finishing="); pw.println(finishing);
pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
pw.print(" inHistory="); pw.print(inHistory);
@@ -191,6 +193,7 @@ class HistoryRecord extends IApplicationToken.Stub {
launchFailed = false;
haveState = false;
stopped = false;
+ delayedResume = false;
finishing = false;
configDestroy = false;
keysPaused = false;
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 68aebc3..419dadf 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -107,6 +107,10 @@ class ProcessRecord implements Watchdog.PssRequestor {
ActivityManager.ProcessErrorStateInfo crashingReport;
ActivityManager.ProcessErrorStateInfo notRespondingReport;
+ // Who will be notified of the error. This is usually an activity in the
+ // app that installed the package.
+ ComponentName errorReportReceiver;
+
void dump(PrintWriter pw, String prefix) {
if (info.className != null) {
pw.print(prefix); pw.print("class="); pw.println(info.className);
@@ -157,7 +161,14 @@ class ProcessRecord implements Watchdog.PssRequestor {
pw.print(" "); pw.print(crashDialog);
pw.print(" notResponding="); pw.print(notResponding);
pw.print(" " ); pw.print(anrDialog);
- pw.print(" bad="); pw.println(bad);
+ pw.print(" bad="); pw.print(bad);
+
+ // crashing or notResponding is always set before errorReportReceiver
+ if (errorReportReceiver != null) {
+ pw.print(" errorReportReceiver=");
+ pw.print(errorReportReceiver.flattenToShortString());
+ }
+ pw.println();
}
if (activities.size() > 0) {
pw.print(prefix); pw.print("activities="); pw.println(activities);
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index b17ba82..76c05d9 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -41,6 +41,7 @@ import android.os.RemoteException;
import android.provider.Settings;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.format.DateFormat;
import android.util.Log;
@@ -57,6 +58,7 @@ import com.android.internal.app.IBatteryStats;
import com.android.internal.location.GpsLocationProvider;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.cdma.EriInfo;
import com.android.internal.telephony.cdma.TtyIntent;
import com.android.server.am.BatteryStatsService;
@@ -106,45 +108,140 @@ public class StatusBarPolicy {
// phone
private TelephonyManager mPhone;
private IBinder mPhoneIcon;
+ private IBinder mPhoneEvdoIcon;
//***** Signal strength icons
private IconData mPhoneData;
+ private IconData mPhoneEvdoData;
//GSM/UMTS
private static final int[] sSignalImages = new int[] {
- com.android.internal.R.drawable.stat_sys_signal_0,
- com.android.internal.R.drawable.stat_sys_signal_1,
- com.android.internal.R.drawable.stat_sys_signal_2,
- com.android.internal.R.drawable.stat_sys_signal_3,
- com.android.internal.R.drawable.stat_sys_signal_4
- };
+ com.android.internal.R.drawable.stat_sys_signal_0,
+ com.android.internal.R.drawable.stat_sys_signal_1,
+ com.android.internal.R.drawable.stat_sys_signal_2,
+ com.android.internal.R.drawable.stat_sys_signal_3,
+ com.android.internal.R.drawable.stat_sys_signal_4
+ };
private static final int[] sSignalImages_r = new int[] {
- com.android.internal.R.drawable.stat_sys_r_signal_0,
- com.android.internal.R.drawable.stat_sys_r_signal_1,
- com.android.internal.R.drawable.stat_sys_r_signal_2,
- com.android.internal.R.drawable.stat_sys_r_signal_3,
- com.android.internal.R.drawable.stat_sys_r_signal_4
- };
+ com.android.internal.R.drawable.stat_sys_r_signal_0,
+ com.android.internal.R.drawable.stat_sys_r_signal_1,
+ com.android.internal.R.drawable.stat_sys_r_signal_2,
+ com.android.internal.R.drawable.stat_sys_r_signal_3,
+ com.android.internal.R.drawable.stat_sys_r_signal_4
+ };
//CDMA
private static final int[] sSignalImages_cdma = new int[] {
- com.android.internal.R.drawable.stat_sys_signal_0_cdma,
- com.android.internal.R.drawable.stat_sys_signal_1_cdma,
- com.android.internal.R.drawable.stat_sys_signal_2_cdma,
- com.android.internal.R.drawable.stat_sys_signal_3_cdma,
- com.android.internal.R.drawable.stat_sys_signal_4_cdma
+ com.android.internal.R.drawable.stat_sys_signal_cdma_0,
+ com.android.internal.R.drawable.stat_sys_signal_cdma_1,
+ com.android.internal.R.drawable.stat_sys_signal_cdma_2,
+ com.android.internal.R.drawable.stat_sys_signal_cdma_3,
+ com.android.internal.R.drawable.stat_sys_signal_cdma_4
};
- private static final int[] sSignalImages_r_cdma = new int[] {
- com.android.internal.R.drawable.stat_sys_r_signal_0_cdma,
- com.android.internal.R.drawable.stat_sys_r_signal_1_cdma,
- com.android.internal.R.drawable.stat_sys_r_signal_2_cdma,
- com.android.internal.R.drawable.stat_sys_r_signal_3_cdma,
- com.android.internal.R.drawable.stat_sys_r_signal_4_cdma
+ private static final int[] sRoamingIndicatorImages_cdma = new int[] {
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
+ // 1 is Standard Roaming Indicator OFF
+ // TODO T: image never used, remove and put 0 instead?
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+ // 2 is Standard Roaming Indicator FLASHING
+ // TODO T: image never used, remove and put 0 instead?
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+ // 3-12 Standard ERI
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //3
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+ // 13-63 Reserved for Standard ERI
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //13
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+ // 64-127 Reserved for Non Standard (Operator Specific) ERI
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //64
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0 //83
+
+ // 128-255 Reserved
};
- private static final int[] sSignalImages_ra_cdma = new int[] {
- com.android.internal.R.drawable.stat_sys_ra_signal_0_cdma,
- com.android.internal.R.drawable.stat_sys_ra_signal_1_cdma,
- com.android.internal.R.drawable.stat_sys_ra_signal_2_cdma,
- com.android.internal.R.drawable.stat_sys_ra_signal_3_cdma,
- com.android.internal.R.drawable.stat_sys_ra_signal_4_cdma
+ // EVDO
+ private static final int[] sSignalImages_evdo = new int[] {
+ com.android.internal.R.drawable.stat_sys_signal_evdo_0,
+ com.android.internal.R.drawable.stat_sys_signal_evdo_1,
+ com.android.internal.R.drawable.stat_sys_signal_evdo_2,
+ com.android.internal.R.drawable.stat_sys_signal_evdo_3,
+ com.android.internal.R.drawable.stat_sys_signal_evdo_4
};
//***** Data connection icons
@@ -174,12 +271,14 @@ public class StatusBarPolicy {
com.android.internal.R.drawable.stat_sys_data_in_evdo,
com.android.internal.R.drawable.stat_sys_data_out_evdo,
com.android.internal.R.drawable.stat_sys_data_inandout_evdo,
+ com.android.internal.R.drawable.stat_sys_data_dormant_evdo,
};
private static final int[] sDataNetType_1xrtt = new int[] {
com.android.internal.R.drawable.stat_sys_data_connected_1xrtt,
com.android.internal.R.drawable.stat_sys_data_in_1xrtt,
com.android.internal.R.drawable.stat_sys_data_out_1xrtt,
com.android.internal.R.drawable.stat_sys_data_inandout_1xrtt,
+ com.android.internal.R.drawable.stat_sys_data_dormant_1xrtt,
};
// Assume it's all good unless we hear otherwise. We don't always seem
@@ -189,7 +288,7 @@ public class StatusBarPolicy {
int mDataState = TelephonyManager.DATA_DISCONNECTED;
int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
ServiceState mServiceState;
- int mSignalAsu = -1;
+ SignalStrength mSignalStrength;
// data connection
private IBinder mDataIcon;
@@ -244,6 +343,10 @@ public class StatusBarPolicy {
private IBinder mTTYModeIcon;
private IconData mTTYModeEnableIconData;
+ // Cdma Roaming Indicator, ERI
+ private IBinder mCdmaRoamingIndicatorIcon;
+ private IconData mCdmaRoamingIndicatorIconData;
+
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -304,6 +407,7 @@ public class StatusBarPolicy {
private StatusBarPolicy(Context context, StatusBarService service) {
mContext = context;
mService = service;
+ mSignalStrength = new SignalStrength();
mBatteryStats = BatteryStatsService.getService();
// clock
@@ -319,14 +423,21 @@ public class StatusBarPolicy {
// phone_signal
mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
- mPhoneData = IconData.makeIcon("phone_signal",
+ mPhoneData = IconData.makeIcon("phone_signal",
null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);
mPhoneIcon = service.addIcon(mPhoneData, null);
+
+ // phone_evdo_signal
+ mPhoneEvdoData = IconData.makeIcon("phone_evdo_signal",
+ null, com.android.internal.R.drawable.stat_sys_signal_evdo_0, 0, 0);
+ mPhoneEvdoIcon = service.addIcon(mPhoneEvdoData, null);
+ service.setIconVisibility(mPhoneEvdoIcon, false);
+
// register for phone state notifications.
((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_SERVICE_STATE
- | PhoneStateListener.LISTEN_SIGNAL_STRENGTH
+ | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
| PhoneStateListener.LISTEN_CALL_STATE
| PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
| PhoneStateListener.LISTEN_DATA_ACTIVITY);
@@ -349,6 +460,12 @@ public class StatusBarPolicy {
mTTYModeIcon = service.addIcon(mTTYModeEnableIconData, null);
service.setIconVisibility(mTTYModeIcon, false);
+ // Cdma Roaming Indicator, ERI
+ mCdmaRoamingIndicatorIconData = IconData.makeIcon("cdma_eri",
+ null, com.android.internal.R.drawable.stat_sys_roaming_cdma_0, 0, 0);
+ mCdmaRoamingIndicatorIcon = service.addIcon(mCdmaRoamingIndicatorIconData, null);
+ service.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+
// bluetooth status
mBluetoothData = IconData.makeIcon("bluetooth",
null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
@@ -645,8 +762,8 @@ public class StatusBarPolicy {
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
- public void onSignalStrengthChanged(int asu) {
- mSignalAsu = asu;
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ mSignalStrength = signalStrength;
updateSignalStrength();
}
@@ -654,6 +771,7 @@ public class StatusBarPolicy {
public void onServiceStateChanged(ServiceState state) {
mServiceState = state;
updateSignalStrength();
+ updateCdmaRoamingIcon();
updateDataIcon();
}
@@ -675,7 +793,6 @@ public class StatusBarPolicy {
updateDataIcon();
}
};
-
private final void updateSimState(Intent intent) {
String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
@@ -702,25 +819,51 @@ public class StatusBarPolicy {
updateDataIcon();
}
- private final void updateSignalStrength() {
- int asu = mSignalAsu;
- ServiceState ss = mServiceState;
+ // TODO(Teleca): I've add isCdma() to reduce some code duplication and simplify.
+ // Please validate the correctness of these changes
+ private boolean isCdma() {
+ // Is this equivalent, if so it seems simpler?
+// return ((mPhone != null) && (mPhone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA));
+
+ if (mServiceState != null) {
+ switch(mServiceState.getRadioTechnology()) {
+ case ServiceState.RADIO_TECHNOLOGY_1xRTT:
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_0:
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_A:
+ case ServiceState.RADIO_TECHNOLOGY_IS95A:
+ case ServiceState.RADIO_TECHNOLOGY_IS95B:
+ return true;
+ default:
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
- boolean hasService = true;
-
- if (ss != null) {
- int state = ss.getState();
- switch (state) {
+ // TODO(Teleca): I've add hasService() to reduce some code duplication and simplify.
+ // Please validate the correctness of these changes.
+ private boolean hasService() {
+ if (mServiceState != null) {
+ switch (mServiceState.getState()) {
case ServiceState.STATE_OUT_OF_SERVICE:
case ServiceState.STATE_POWER_OFF:
- hasService = false;
- break;
+ return false;
+ default:
+ return true;
}
} else {
- hasService = false;
+ return false;
}
+ }
- if (!hasService) {
+ private final void updateSignalStrength() {
+ int iconLevel = -1;
+ int evdoIconLevel = -1;
+ int[] iconList;
+ int[] evdoIconList;
+
+ if (!hasService()) {
//Log.d(TAG, "updateSignalStrength: no service");
if (Settings.System.getInt(mContext.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
@@ -729,48 +872,92 @@ public class StatusBarPolicy {
mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_null;
}
mService.updateIcon(mPhoneIcon, mPhoneData, null);
+ mService.setIconVisibility(mPhoneEvdoIcon,false);
return;
}
- // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
- // asu = 0 (-113dB or less) is very weak
- // signal, its better to show 0 bars to the user in such cases.
- // asu = 99 is a special case, where the signal strength is unknown.
- if (asu <= 0 || asu == 99) asu = 0;
- else if (asu >= 16) asu = 4;
- else if (asu >= 8) asu = 3;
- else if (asu >= 4) asu = 2;
- else asu = 1;
-
- int[] iconList;
- if (mPhone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
- switch(ss.getExtendedCdmaRoaming()) {
- case ServiceState.REGISTRATION_STATE_ROAMING:
- iconList = this.sSignalImages_r_cdma;
- break;
- case ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE:
- iconList = this.sSignalImages_ra_cdma;
- break;
- default:
- iconList = this.sSignalImages_cdma;
- break;
+ if (!isCdma()) {
+ int asu = mSignalStrength.getGsmSignalStrength();
+
+ // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+ // asu = 0 (-113dB or less) is very weak
+ // signal, its better to show 0 bars to the user in such cases.
+ // asu = 99 is a special case, where the signal strength is unknown.
+ if (asu <= 0 || asu == 99) iconLevel = 0;
+ else if (asu >= 16) iconLevel = 4;
+ else if (asu >= 8) iconLevel = 3;
+ else if (asu >= 4) iconLevel = 2;
+ else iconLevel = 1;
+
+ if (mPhone.isNetworkRoaming()) {
+ iconList = sSignalImages_r;
+ } else {
+ iconList = sSignalImages;
}
- } else if (mPhone.isNetworkRoaming()) {
- iconList = sSignalImages_r;
} else {
- iconList = sSignalImages;
+ iconList = this.sSignalImages_cdma;
+
+ int cdmaDbm = mSignalStrength.getCdmaDbm();
+ int cdmaEcio = mSignalStrength.getCdmaEcio();
+ int levelDbm = 0;
+ int levelEcio = 0;
+
+ if (cdmaDbm >= -75) levelDbm = 4;
+ else if (cdmaDbm >= -85) levelDbm = 3;
+ else if (cdmaDbm >= -95) levelDbm = 2;
+ else if (cdmaDbm >= -100) levelDbm = 1;
+ else levelDbm = 0;
+
+ // Ec/Io are in dB*10
+ if (cdmaEcio >= -90) levelEcio = 4;
+ else if (cdmaEcio >= -110) levelEcio = 3;
+ else if (cdmaEcio >= -130) levelEcio = 2;
+ else if (cdmaEcio >= -150) levelEcio = 1;
+ else levelEcio = 0;
+
+ iconLevel = (levelDbm < levelEcio) ? levelDbm : levelEcio;
}
- mPhoneData.iconId = iconList[asu];
+ if ((mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
+ || (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_A)) {
+ // Use Evdo icon
+ evdoIconList = this.sSignalImages_evdo;
+
+ int evdoEcio = mSignalStrength.getEvdoEcio();
+ int evdoSnr = mSignalStrength.getEvdoSnr();
+ int levelEvdoEcio = 0;
+ int levelEvdoSnr = 0;
+
+ // Ec/Io are in dB*10
+ if (evdoEcio >= -650) levelEvdoEcio = 4;
+ else if (evdoEcio >= -750) levelEvdoEcio = 3;
+ else if (evdoEcio >= -900) levelEvdoEcio = 2;
+ else if (evdoEcio >= -1050) levelEvdoEcio = 1;
+ else levelEvdoEcio = 0;
+
+ if (evdoSnr > 7) levelEvdoSnr = 4;
+ else if (evdoSnr > 5) levelEvdoSnr = 3;
+ else if (evdoSnr > 3) levelEvdoSnr = 2;
+ else if (evdoSnr > 1) levelEvdoSnr = 1;
+ else levelEvdoSnr = 0;
+
+ evdoIconLevel = (levelEvdoEcio < levelEvdoSnr) ? levelEvdoEcio : levelEvdoSnr;
+
+ mPhoneEvdoData.iconId = evdoIconList[evdoIconLevel];
+ mService.updateIcon(mPhoneEvdoIcon, mPhoneEvdoData, null);
+ mService.setIconVisibility(mPhoneEvdoIcon,true);
+ } else {
+ mService.setIconVisibility(mPhoneEvdoIcon,false);
+ }
+
+ mPhoneData.iconId = iconList[iconLevel];
mService.updateIcon(mPhoneIcon, mPhoneData, null);
}
private final void updateDataNetType() {
int net = mPhone.getNetworkType();
- ServiceState ss = this.mServiceState;
switch (net) {
-
case TelephonyManager.NETWORK_TYPE_EDGE:
mDataIconList = sDataNetType_e;
break;
@@ -798,32 +985,51 @@ public class StatusBarPolicy {
int iconId;
boolean visible = true;
- if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
- int data = mDataState;
-
- int[] list = mDataIconList;
-
- ServiceState ss = mServiceState;
-
- boolean hasService = false;
-
- if (ss != null) {
- hasService = (ss.getState() == ServiceState.STATE_IN_SERVICE);
+ if (!isCdma()) {
+ // GSM case, we have to check also the sim state
+ if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
+ if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
+ switch (mDataActivity) {
+ case TelephonyManager.DATA_ACTIVITY_IN:
+ iconId = mDataIconList[1];
+ break;
+ case TelephonyManager.DATA_ACTIVITY_OUT:
+ iconId = mDataIconList[2];
+ break;
+ case TelephonyManager.DATA_ACTIVITY_INOUT:
+ iconId = mDataIconList[3];
+ break;
+ default:
+ iconId = mDataIconList[0];
+ break;
+ }
+ mDataData.iconId = iconId;
+ mService.updateIcon(mDataIcon, mDataData, null);
+ } else {
+ visible = false;
+ }
+ } else {
+ mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
+ mService.updateIcon(mDataIcon, mDataData, null);
}
-
- if (hasService && data == TelephonyManager.DATA_CONNECTED) {
+ } else {
+ // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
+ if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
switch (mDataActivity) {
case TelephonyManager.DATA_ACTIVITY_IN:
- iconId = list[1];
+ iconId = mDataIconList[1];
break;
case TelephonyManager.DATA_ACTIVITY_OUT:
- iconId = list[2];
+ iconId = mDataIconList[2];
break;
case TelephonyManager.DATA_ACTIVITY_INOUT:
- iconId = list[3];
+ iconId = mDataIconList[3];
+ break;
+ case TelephonyManager.DATA_ACTIVITY_DORMANT:
+ iconId = mDataIconList[4];
break;
default:
- iconId = list[0];
+ iconId = mDataIconList[0];
break;
}
mDataData.iconId = iconId;
@@ -831,10 +1037,8 @@ public class StatusBarPolicy {
} else {
visible = false;
}
- } else {
- mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
- mService.updateIcon(mDataIcon, mDataData, null);
}
+
long ident = Binder.clearCallingIdentity();
try {
mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
@@ -842,6 +1046,7 @@ public class StatusBarPolicy {
} finally {
Binder.restoreCallingIdentity(ident);
}
+
if (mDataIconVisible != visible) {
mService.setIconVisibility(mDataIcon, visible);
mDataIconVisible = visible;
@@ -852,7 +1057,7 @@ public class StatusBarPolicy {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
final int ringerMode = audioManager.getRingerMode();
final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
- ringerMode == AudioManager.RINGER_MODE_VIBRATE;
+ ringerMode == AudioManager.RINGER_MODE_VIBRATE;
final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
? com.android.internal.R.drawable.stat_sys_ringer_vibrate
: com.android.internal.R.drawable.stat_sys_ringer_silent;
@@ -884,7 +1089,7 @@ public class StatusBarPolicy {
} else {
return;
}
-
+
if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED ||
mBluetoothA2dpState == BluetoothA2dp.STATE_CONNECTED ||
mBluetoothA2dpState == BluetoothA2dp.STATE_PLAYING) {
@@ -899,15 +1104,15 @@ public class StatusBarPolicy {
private final void updateWifi(Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-
+
final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-
+
if (!enabled) {
// If disabled, hide the icon. (We show icon when connected.)
mService.setIconVisibility(mWifiIcon, false);
}
-
+
} else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
false);
@@ -916,9 +1121,9 @@ public class StatusBarPolicy {
}
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- final NetworkInfo networkInfo = (NetworkInfo)
+ final NetworkInfo networkInfo = (NetworkInfo)
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-
+
int iconId;
if (networkInfo != null && networkInfo.isConnected()) {
mIsWifiConnected = true;
@@ -965,18 +1170,18 @@ public class StatusBarPolicy {
if (action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION) && enabled) {
// GPS is getting fixes
mService.updateIcon(mGpsIcon, mGpsFixIconData, null);
- mService.setIconVisibility(mGpsIcon, true);
+ mService.setIconVisibility(mGpsIcon, true);
} else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
// GPS is off
- mService.setIconVisibility(mGpsIcon, false);
+ mService.setIconVisibility(mGpsIcon, false);
} else {
// GPS is on, but not receiving fixes
mService.updateIcon(mGpsIcon, mGpsEnabledIconData, null);
- mService.setIconVisibility(mGpsIcon, true);
+ mService.setIconVisibility(mGpsIcon, true);
}
}
- private final void updateTTY(Intent intent) {
+ private final void updateTTY(Intent intent) {
final String action = intent.getAction();
final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
@@ -986,14 +1191,59 @@ public class StatusBarPolicy {
// TTY is on
Log.i(TAG, "updateTTY: set TTY on");
mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
- mService.setIconVisibility(mTTYModeIcon, true);
+ mService.setIconVisibility(mTTYModeIcon, true);
} else {
// TTY is off
Log.i(TAG, "updateTTY: set TTY off");
- mService.setIconVisibility(mTTYModeIcon, false);
+ mService.setIconVisibility(mTTYModeIcon, false);
+ }
+ }
+
+ private final void updateCdmaRoamingIcon() {
+ if (!hasService()) {
+ mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+ }
+
+ if (!isCdma()) {
+ mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+ }
+
+ int[] iconList = sRoamingIndicatorImages_cdma;
+ int iconIndex = mPhone.getCdmaEriIconIndex();
+ int iconMode = mPhone.getCdmaEriIconMode();
+
+ if (iconIndex == -1) {
+ Log.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
+ return;
+ }
+
+ if (iconMode == -1) {
+ Log.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
+ return;
+ }
+
+ if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
+ Log.d(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
+ mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+ return;
+ }
+
+ switch (iconMode) {
+ case EriInfo.ROAMING_ICON_MODE_NORMAL:
+ mCdmaRoamingIndicatorIconData.iconId = iconList[iconIndex];
+ mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
+ mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
+ break;
+ case EriInfo.ROAMING_ICON_MODE_FLASH:
+ mCdmaRoamingIndicatorIconData.iconId = com.android.internal.R.drawable.stat_sys_roaming_cdma_flash;
+ mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
+ break;
+
}
+ mService.updateIcon(mPhoneIcon, mPhoneData, null);
}
+
private class StatusBarHandler extends Handler {
@Override
public void handleMessage(Message msg) {
@@ -1007,6 +1257,3 @@ public class StatusBarPolicy {
}
}
}
-
-
-
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 5336e27..48cbace 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -19,6 +19,7 @@ package com.android.server.status;
import com.android.internal.R;
import com.android.internal.util.CharSequences;
+import android.app.ActivityManagerNative;
import android.app.Dialog;
import android.app.IStatusBar;
import android.app.PendingIntent;
@@ -1254,6 +1255,14 @@ public class StatusBarService extends IStatusBar.Stub
public void onClick(View v) {
try {
+ // The intent we are sending is for the application, which
+ // won't have permission to immediately start an activity after
+ // the user switches to home. We know it is safe to do at this
+ // point, so make sure new activity switches are now allowed.
+ ActivityManagerNative.getDefault().resumeAppSwitches();
+ } catch (RemoteException e) {
+ }
+ try {
mIntent.send();
mNotificationCallbacks.onNotificationClick(mPkg, mId);
} catch (PendingIntent.CanceledException e) {