Merge "SystemUI: Use new USB notifications to detect USB disconnect." into gingerbread
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
index 7ccf210..0fc092e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
@@ -711,21 +711,20 @@
ConnectivityManager.EXTRA_NETWORK_INFO));
int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
Slog.d(TAG, "got CONNECTIVITY_ACTION - info=" + info + ", status = " + connectionStatus);
- if (info.isConnected() == false) return;
+
+ int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
switch (info.getType()) {
case ConnectivityManager.TYPE_MOBILE:
- if (info.isConnected()) {
- updateDataNetType(info.getSubtype(), connectionStatus);
- updateDataIcon();
- updateSignalStrength(); // apply any change in connectionStatus
- }
+ mInetCondition = inetCondition;
+ updateDataNetType(info.getSubtype());
+ updateDataIcon();
+ updateSignalStrength(); // apply any change in connectionStatus
break;
case ConnectivityManager.TYPE_WIFI:
+ mInetCondition = inetCondition;
if (info.isConnected()) {
mIsWifiConnected = true;
- mInetCondition =
- (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
int iconId;
if (mLastWifiSignalLevel == -1) {
iconId = sWifiSignalImages[mInetCondition][0];
@@ -738,7 +737,6 @@
} else {
mLastWifiSignalLevel = -1;
mIsWifiConnected = false;
- mInetCondition = 0;
int iconId = sWifiSignalImages[0][0];
mService.setIcon("wifi", iconId, 0);
@@ -777,9 +775,8 @@
@Override
public void onDataConnectionStateChanged(int state, int networkType) {
mDataState = state;
- updateDataNetType(networkType, 0);
+ updateDataNetType(networkType);
updateDataIcon();
- updateSignalStrength(); // apply the change in connection status
}
@Override
@@ -940,8 +937,7 @@
return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
}
- private final void updateDataNetType(int net, int inetCondition) {
- mInetCondition = (inetCondition > INET_CONDITION_THRESHOLD ? 1 : 0);
+ private final void updateDataNetType(int net) {
switch (net) {
case TelephonyManager.NETWORK_TYPE_EDGE:
mDataIconList = sDataNetType_e[mInetCondition];
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index af736aa..b555277 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -82,7 +82,7 @@
public class StatusBarService extends Service implements CommandQueue.Callbacks {
static final String TAG = "StatusBarService";
- static final boolean SPEW = false;
+ static final boolean SPEW = true;
public static final String ACTION_STATUSBAR_START
= "com.android.internal.policy.statusbar.START";
@@ -1534,4 +1534,3 @@
}
};
}
-
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index c5505d1..f38748b 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -48,6 +48,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.GregorianCalendar;
import java.util.List;
/**
@@ -109,6 +110,10 @@
private boolean mSystemReady;
private Intent mInitialBroadcast;
+ // used in DBG mode to track inet condition reports
+ private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
+ private ArrayList mInetLog;
+
private static class NetworkAttributes {
/**
* Class for holding settings read from resources.
@@ -329,6 +334,9 @@
mTethering.getTetherableWifiRegexs().length != 0) &&
mTethering.getUpstreamIfaceRegexs().length != 0);
+ if (DBG) {
+ mInetLog = new ArrayList();
+ }
}
@@ -912,11 +920,19 @@
newNet = tryFailover(prevNetType);
if (newNet != null) {
NetworkInfo switchTo = newNet.getNetworkInfo();
+ if (!switchTo.isConnected()) {
+ // if the other net is connected they've already reset this and perhaps even gotten
+ // a positive report we don't want to overwrite, but if not we need to clear this now
+ // to turn our cellular sig strength white
+ mDefaultInetConditionPublished = 0;
+ }
intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
} else {
+ mDefaultInetConditionPublished = 0; // we're not connected anymore
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
}
}
+ intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
// do this before we broadcast the change
handleConnectivityChange(prevNetType);
@@ -1075,12 +1091,20 @@
newNet = tryFailover(info.getType());
if (newNet != null) {
NetworkInfo switchTo = newNet.getNetworkInfo();
+ if (!switchTo.isConnected()) {
+ // if the other net is connected they've already reset this and perhaps even gotten
+ // a positive report we don't want to overwrite, but if not we need to clear this now
+ // to turn our cellular sig strength white
+ mDefaultInetConditionPublished = 0;
+ }
intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
} else {
+ mDefaultInetConditionPublished = 0;
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
}
}
+ intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
sendStickyBroadcast(intent);
/*
* If the failover network is already connected, then immediately send
@@ -1365,6 +1389,14 @@
pw.println();
mTethering.dump(fd, pw, args);
+
+ if (mInetLog != null) {
+ pw.println();
+ pw.println("Inet condition reports:");
+ for(int i = 0; i < mInetLog.size(); i++) {
+ pw.println(mInetLog.get(i));
+ }
+ }
}
// must be stateless - things change under us.
@@ -1613,6 +1645,17 @@
android.Manifest.permission.STATUS_BAR,
"ConnectivityService");
+ if (DBG) {
+ int pid = getCallingPid();
+ int uid = getCallingUid();
+ String s = pid + "(" + uid + ") reports inet is " +
+ (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
+ "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
+ mInetLog.add(s);
+ while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
+ mInetLog.remove(0);
+ }
+ }
mHandler.sendMessage(mHandler.obtainMessage(
NetworkStateTracker.EVENT_INET_CONDITION_CHANGE, networkType, percentage));
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3172077..4f0d2d5 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -561,6 +561,11 @@
BroadcastRecord mPendingBroadcast = null;
/**
+ * The receiver index that is pending, to restart the broadcast if needed.
+ */
+ int mPendingBroadcastRecvIndex;
+
+ /**
* Keeps track of all IIntentReceivers that have been registered for
* broadcasts. Hash keys are the receiver IBinder, hash value is
* a ReceiverList.
@@ -747,6 +752,7 @@
ComponentName mTopComponent;
String mTopAction;
String mTopData;
+ boolean mProcessesReady = false;
boolean mSystemReady = false;
boolean mBooting = false;
boolean mWaitingUpdate = false;
@@ -964,7 +970,11 @@
return;
}
- broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
+ Intent intent = new Intent("android.intent.action.ANR");
+ if (!mProcessesReady) {
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ }
+ broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
false, false, MY_PID, Process.SYSTEM_UID);
@@ -1051,7 +1061,7 @@
// Only process broadcast timeouts if the system is ready. That way
// PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
// to do heavy lifting for system up
- if (mSystemReady) {
+ if (mProcessesReady) {
broadcastTimeout();
}
} break;
@@ -1717,10 +1727,12 @@
if (!knownToBeDead || app.thread == null) {
// We already have the app running, or are waiting for it to
// come up (we have a pid but not yet its thread), so keep it.
+ if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
return app;
} else {
// An application record is attached to a previous process,
// clean it up now.
+ if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
handleAppDiedLocked(app, true);
}
}
@@ -1732,6 +1744,8 @@
// If we are in the background, then check to see if this process
// is bad. If so, we will just silently fail.
if (mBadProcesses.get(info.processName, info.uid) != null) {
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
+ + "/" + info.processName);
return null;
}
} else {
@@ -1739,6 +1753,8 @@
// crash count so that we won't make it bad until they see at
// least one crash dialog again, and make the process good again
// if it had been bad.
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
+ + "/" + info.processName);
mProcessCrashTimes.remove(info.processName, info.uid);
if (mBadProcesses.get(info.processName, info.uid) != null) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
@@ -1760,12 +1776,13 @@
// If the system is not ready yet, then hold off on starting this
// process until it is.
- if (!mSystemReady
+ if (!mProcessesReady
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
+ if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
return app;
}
@@ -1787,6 +1804,8 @@
app.pid = 0;
}
+ if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+ "startProcessLocked removing on hold: " + app);
mProcessesOnHold.remove(app);
updateCpuStats();
@@ -3040,11 +3059,8 @@
Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, pkgUid);
- synchronized (this) {
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null,
- false, false, MY_PID, Process.SYSTEM_UID);
- }
+ broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
+ null, null, 0, null, null, null, false, false);
} catch (RemoteException e) {
}
} finally {
@@ -3148,6 +3164,7 @@
public void closeSystemDialogs(String reason) {
Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
if (reason != null) {
intent.putExtra("reason", reason);
}
@@ -3225,6 +3242,9 @@
forceStopPackageLocked(packageName, uid, false, false, true);
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
+ if (!mProcessesReady) {
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ }
intent.putExtra(Intent.EXTRA_UID, uid);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
@@ -3427,6 +3447,8 @@
}
if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
+ mPendingBroadcast.state = BroadcastRecord.IDLE;
+ mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
scheduleBroadcastsLocked();
}
@@ -3502,7 +3524,7 @@
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
- boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
+ boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
if (!normalMode) {
@@ -3561,6 +3583,8 @@
// Remove this record from the list of starting applications.
mPersistentStartingProcesses.remove(app);
+ if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+ "Attach application locked removing on hold: " + app);
mProcessesOnHold.remove(app);
boolean badApp = false;
@@ -3702,7 +3726,9 @@
ArrayList<ProcessRecord> procs =
new ArrayList<ProcessRecord>(mProcessesOnHold);
for (int ip=0; ip<NP; ip++) {
- this.startProcessLocked(procs.get(ip), "on-hold", null);
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
+ + procs.get(ip));
+ startProcessLocked(procs.get(ip), "on-hold", null);
}
}
@@ -5253,7 +5279,7 @@
throw new SecurityException(msg);
}
- if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
+ if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
&& !cpi.processName.equals("system")) {
// If this content provider does not run in the system
// process, and the system is not yet ready to run other
@@ -6040,6 +6066,11 @@
Slog.i(TAG, "Removing system update proc: " + proc);
removeProcessLocked(proc, true);
}
+
+ // Now that we have cleaned up any update processes, we
+ // are ready to start launching real processes and know that
+ // we won't trample on them any more.
+ mProcessesReady = true;
}
}
@@ -7283,8 +7314,9 @@
if (dumpAll) {
pw.println(" Total persistent processes: " + numPers);
pw.println(" mStartRunning=" + mStartRunning
- + " mSystemReady=" + mSystemReady
- + " mBooting=" + mBooting
+ + " mProcessesReady=" + mProcessesReady
+ + " mSystemReady=" + mSystemReady);
+ pw.println(" mBooting=" + mBooting
+ " mBooted=" + mBooted
+ " mFactoryTest=" + mFactoryTest);
pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
@@ -8098,6 +8130,8 @@
restart = true;
}
}
+ if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+ "Clean-up removing on hold: " + app);
mProcessesOnHold.remove(app);
if (app == mHomeProcess) {
@@ -10118,7 +10152,7 @@
}
boolean replaced = false;
if (replacePending) {
- for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
+ for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
if (DEBUG_BROADCAST) Slog.v(TAG,
"***** DROPPING ORDERED: " + intent);
@@ -10137,35 +10171,41 @@
return BROADCAST_SUCCESS;
}
- public final int broadcastIntent(IApplicationThread caller,
- Intent intent, String resolvedType, IIntentReceiver resultTo,
- int resultCode, String resultData, Bundle map,
- String requiredPermission, boolean serialized, boolean sticky) {
+ final Intent verifyBroadcastLocked(Intent intent) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+ int flags = intent.getFlags();
+
+ if (!mProcessesReady) {
+ // if the caller really truly claims to know what they're doing, go
+ // ahead and allow the broadcast without launching any receivers
+ if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
+ intent = new Intent(intent);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
+ Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
+ + " before boot completion");
+ throw new IllegalStateException("Cannot broadcast before boot completed");
+ }
+ }
+
+ if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
+ throw new IllegalArgumentException(
+ "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
+ }
+
+ return intent;
+ }
+
+ public final int broadcastIntent(IApplicationThread caller,
+ Intent intent, String resolvedType, IIntentReceiver resultTo,
+ int resultCode, String resultData, Bundle map,
+ String requiredPermission, boolean serialized, boolean sticky) {
synchronized(this) {
- int flags = intent.getFlags();
-
- if (!mSystemReady) {
- // if the caller really truly claims to know what they're doing, go
- // ahead and allow the broadcast without launching any receivers
- if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
- intent = new Intent(intent);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
- Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
- + " before boot completion");
- throw new IllegalStateException("Cannot broadcast before boot completed");
- }
- }
-
- if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
- throw new IllegalArgumentException(
- "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
- }
+ intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
@@ -10186,6 +10226,8 @@
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized, boolean sticky) {
synchronized(this) {
+ intent = verifyBroadcastLocked(intent);
+
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
resultTo, resultCode, resultData, map, requiredPermission,
@@ -10399,6 +10441,8 @@
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + " for app " + app);
if (app.thread == null) {
throw new RemoteException();
}
@@ -10418,9 +10462,13 @@
ensurePackageDexOpt(r.intent.getComponent().getPackageName());
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
r.resultCode, r.resultData, r.resultExtras, r.ordered);
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
} finally {
if (!started) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + ": NOT STARTED!");
r.receiver = null;
r.curApp = null;
app.curReceiver = null;
@@ -10585,6 +10633,8 @@
} else {
Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
+ " died before responding to broadcast");
+ mPendingBroadcast.state = BroadcastRecord.IDLE;
+ mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
@@ -10615,7 +10665,7 @@
// one time heavy lifting after system upgrades and can take
// significant amounts of time.
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
- if (mSystemReady && r.dispatchTime > 0) {
+ if (mProcessesReady && r.dispatchTime > 0) {
long now = SystemClock.uptimeMillis();
if ((numReceivers > 0) &&
(now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
@@ -10686,7 +10736,7 @@
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
+ r);
if (DEBUG_BROADCAST) Slog.v(TAG,
- "Submitting BROADCAST_TIMEOUT_MSG for "
+ "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at "
+ (r.receiverTime + BROADCAST_TIMEOUT));
Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
@@ -10754,10 +10804,15 @@
}
if (r.curApp != null && r.curApp.crashing) {
// If the target process is crashing, just skip it.
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Skipping deliver ordered " + r + " to " + r.curApp
+ + ": process crashing");
skip = true;
}
if (skip) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Skipping delivery of ordered " + r + " for whatever reason");
r.receiver = null;
r.curFilter = null;
r.state = BroadcastRecord.IDLE;
@@ -10789,6 +10844,8 @@
}
// Not running -- get it started, to be executed when the app comes up.
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Need to start app " + targetProcess + " for broadcast " + r);
if ((r.curApp=startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
@@ -10810,6 +10867,7 @@
}
mPendingBroadcast = r;
+ mPendingBroadcastRecvIndex = recIdx;
}
}
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 4fc8020..a4497d6 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1104,26 +1104,30 @@
// Okay we are now going to start a switch, to 'next'. We may first
// have to pause the current activity, but this is an important point
// where we have decided to go to 'next' so keep track of that.
- if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
- long now = SystemClock.uptimeMillis();
- final boolean inTime = mLastStartedActivity.startTime != 0
- && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
- final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
- final int nextUid = next.info.applicationInfo.uid;
- if (inTime && lastUid != nextUid
- && lastUid != next.launchedFromUid
- && mService.checkPermission(
- android.Manifest.permission.STOP_APP_SWITCHES,
- -1, next.launchedFromUid)
- != PackageManager.PERMISSION_GRANTED) {
- mService.showLaunchWarningLocked(mLastStartedActivity, next);
+ // XXX "App Redirected" dialog is getting too many false positives
+ // at this point, so turn off for now.
+ if (false) {
+ if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
+ long now = SystemClock.uptimeMillis();
+ final boolean inTime = mLastStartedActivity.startTime != 0
+ && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
+ final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
+ final int nextUid = next.info.applicationInfo.uid;
+ if (inTime && lastUid != nextUid
+ && lastUid != next.launchedFromUid
+ && mService.checkPermission(
+ android.Manifest.permission.STOP_APP_SWITCHES,
+ -1, next.launchedFromUid)
+ != PackageManager.PERMISSION_GRANTED) {
+ mService.showLaunchWarningLocked(mLastStartedActivity, next);
+ } else {
+ next.startTime = now;
+ mLastStartedActivity = next;
+ }
} else {
- next.startTime = now;
+ next.startTime = SystemClock.uptimeMillis();
mLastStartedActivity = next;
}
- } else {
- next.startTime = SystemClock.uptimeMillis();
- mLastStartedActivity = next;
}
// We need to start pausing the current activity so the top one
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 9f86378..23cb42a 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -238,9 +238,7 @@
Phone.State s = Phone.State.IDLE;
for (Phone phone : mPhones) {
- if (phone.getState() == Phone.State.ANSWERING) {
- return Phone.State.ANSWERING;
- } else if (phone.getState() == Phone.State.RINGING) {
+ if (phone.getState() == Phone.State.RINGING) {
s = Phone.State.RINGING;
} else if (phone.getState() == Phone.State.OFFHOOK) {
if (s == Phone.State.IDLE) s = Phone.State.OFFHOOK;
@@ -357,20 +355,6 @@
return getFirstActiveRingingCall().getPhone();
}
- /**
- * @return the first answering call
- */
- public Call getFirstAnsweringCall() {
- for (Phone phone : mPhones) {
- if (phone.getState() == Phone.State.ANSWERING) {
- return phone.getForegroundCall();
- }
- }
- return null;
- }
-
-
-
public void setAudioMode() {
Context context = getContext();
if (context == null) return;
@@ -1359,7 +1343,7 @@
*/
public Call getFirstActiveBgCall() {
for (Call call : mBackgroundCalls) {
- if (!call.isIdle()) {
+ if (call.getState() != Call.State.IDLE) {
return call;
}
}
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 7464cc7..9afade3 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -55,12 +55,10 @@
* <li>OFFHOOK = The phone is off hook. At least one call
* exists that is dialing, active or holding and no calls are
* ringing or waiting.</li>
- * <li>ANSWERING = The incoming call is picked up but the
- * call is not established yet.</li>
* </ul>
*/
enum State {
- IDLE, RINGING, OFFHOOK, ANSWERING;
+ IDLE, RINGING, OFFHOOK;
};
/**
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 0a87ddb..35aa3b3 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -143,23 +143,15 @@
// in case the active/holding call disappeared and this
// is no longer call waiting
- if (ringingCall.getState() == Call.State.INCOMING) {
+ if ((ringingCall.getState() == Call.State.INCOMING) ||
+ (ringingCall.getState() == Call.State.WAITING)) {
Log.v(LOG_TAG, "acceptCall");
// Always unmute when answering a new call
setMute(false);
- // make ringingCall foreground
- foregroundCall.switchWith(ringingCall);
- foregroundCall.acceptCall();
- } else if (ringingCall.getState() == Call.State.WAITING) {
- setMute(false);
- switchHoldingAndActive();
- // make ringingCall foreground
- foregroundCall.switchWith(ringingCall);
- foregroundCall.acceptCall();
+ ringingCall.acceptCall();
} else {
throw new CallStateException("phone not ringing");
}
- updatePhoneState();
}
}
@@ -482,8 +474,8 @@
}
void acceptCall() throws CallStateException {
- if (this != foregroundCall) {
- throw new CallStateException("acceptCall() in a non-fg call");
+ if (this != ringingCall) {
+ throw new CallStateException("acceptCall() in a non-ringing call");
}
if (connections.size() != 1) {
throw new CallStateException("acceptCall() in a conf call");
@@ -646,6 +638,18 @@
if (newState == Call.State.INCOMING) {
setState(mOwner.getState()); // INCOMING or WAITING
} else {
+ if (mOwner == ringingCall) {
+ if (ringingCall.getState() == Call.State.WAITING) {
+ try {
+ switchHoldingAndActive();
+ } catch (CallStateException e) {
+ // disconnect the call.
+ onCallEnded(DisconnectCause.LOCAL);
+ return;
+ }
+ }
+ foregroundCall.switchWith(ringingCall);
+ }
if (newState == Call.State.ACTIVE) call.startAudio();
setState(newState);
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
index 2efbd17..9098e6f 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -538,8 +538,6 @@
if (getRingingCall().isRinging()) {
state = State.RINGING;
- } else if (getForegroundCall().isRinging()) {
- state = State.ANSWERING;
} else if (getForegroundCall().isIdle()
&& getBackgroundCall().isIdle()) {
state = State.IDLE;