summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/8.xml22
-rw-r--r--api/current.xml33
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java64
-rw-r--r--core/java/android/app/ActivityManagerNative.java47
-rw-r--r--core/java/android/app/IActivityManager.java48
-rw-r--r--core/java/android/content/pm/PackageManager.java13
-rw-r--r--core/java/android/net/MobileDataStateTracker.java9
-rw-r--r--core/java/android/pim/EventRecurrence.java63
-rw-r--r--core/java/android/speech/RecognizerIntent.java9
-rw-r--r--core/res/res/values/strings.xml11
-rw-r--r--services/java/com/android/server/PackageManagerService.java32
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java106
-rw-r--r--services/java/com/android/server/am/HistoryRecord.java2
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java35
14 files changed, 302 insertions, 192 deletions
diff --git a/api/8.xml b/api/8.xml
index a07537cef744..c5e899dfcffc 100644
--- a/api/8.xml
+++ b/api/8.xml
@@ -42346,28 +42346,6 @@
visibility="public"
>
</field>
-<field name="PKG_INSTALL_COMPLETE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PKG_INSTALL_INCOMPLETE"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="SIGNATURE_FIRST_NOT_SIGNED"
type="int"
transient="false"
diff --git a/api/current.xml b/api/current.xml
index 815b9ff2a224..ad1df1abca1b 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -45440,28 +45440,6 @@
visibility="public"
>
</field>
-<field name="PKG_INSTALL_COMPLETE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PKG_INSTALL_INCOMPLETE"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="SIGNATURE_FIRST_NOT_SIGNED"
type="int"
transient="false"
@@ -138443,6 +138421,17 @@
visibility="public"
>
</field>
+<field name="EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extra.ONLY_RETURN_LANGUAGE_PREFERENCE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EXTRA_PARTIAL_RESULTS"
type="java.lang.String"
transient="false"
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index b6c9de41101f..5d6970ac3fc2 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -35,6 +35,7 @@ import android.view.IWindowManager;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.PrintStream;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.Set;
@@ -47,6 +48,7 @@ public class Am {
private String mCurArgData;
private boolean mDebugOption = false;
+ private boolean mWaitOption = false;
// These are magic strings understood by the Eclipse plugin.
private static final String FATAL_ERROR_CODE = "Error type 1";
@@ -106,6 +108,7 @@ public class Am {
boolean hasIntentInfo = false;
mDebugOption = false;
+ mWaitOption = false;
Uri data = null;
String type = null;
@@ -153,6 +156,8 @@ public class Am {
intent.setFlags(Integer.decode(str).intValue());
} else if (opt.equals("-D")) {
mDebugOption = true;
+ } else if (opt.equals("-W")) {
+ mWaitOption = true;
} else {
System.err.println("Error: Unknown option: " + opt);
showUsage();
@@ -199,58 +204,90 @@ public class Am {
System.out.println("Starting: " + intent);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// XXX should do something to determine the MIME type.
- int res = mAm.startActivity(null, intent, intent.getType(),
- null, 0, null, null, 0, false, mDebugOption);
+ IActivityManager.WaitResult result = null;
+ int res;
+ if (mWaitOption) {
+ result = mAm.startActivityAndWait(null, intent, intent.getType(),
+ null, 0, null, null, 0, false, mDebugOption);
+ res = result.result;
+ } else {
+ res = mAm.startActivity(null, intent, intent.getType(),
+ null, 0, null, null, 0, false, mDebugOption);
+ }
+ PrintStream out = mWaitOption ? System.out : System.err;
+ boolean launched = false;
switch (res) {
case IActivityManager.START_SUCCESS:
+ launched = true;
break;
case IActivityManager.START_SWITCHES_CANCELED:
- System.err.println(
+ launched = true;
+ out.println(
"Warning: Activity not started because the "
+ " current activity is being kept for the user.");
break;
case IActivityManager.START_DELIVERED_TO_TOP:
- System.err.println(
+ launched = true;
+ out.println(
"Warning: Activity not started, intent has "
+ "been delivered to currently running "
+ "top-most instance.");
break;
case IActivityManager.START_RETURN_INTENT_TO_CALLER:
- System.err.println(
+ launched = true;
+ out.println(
"Warning: Activity not started because intent "
+ "should be handled by the caller");
break;
case IActivityManager.START_TASK_TO_FRONT:
- System.err.println(
+ launched = true;
+ out.println(
"Warning: Activity not started, its current "
+ "task has been brought to the front");
break;
case IActivityManager.START_INTENT_NOT_RESOLVED:
- System.err.println(
+ out.println(
"Error: Activity not started, unable to "
+ "resolve " + intent.toString());
break;
case IActivityManager.START_CLASS_NOT_FOUND:
- System.err.println(NO_CLASS_ERROR_CODE);
- System.err.println("Error: Activity class " +
+ out.println(NO_CLASS_ERROR_CODE);
+ out.println("Error: Activity class " +
intent.getComponent().toShortString()
+ " does not exist.");
break;
case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
- System.err.println(
+ out.println(
"Error: Activity not started, you requested to "
+ "both forward and receive its result");
break;
case IActivityManager.START_PERMISSION_DENIED:
- System.err.println(
+ out.println(
"Error: Activity not started, you do not "
+ "have permission to access it.");
break;
default:
- System.err.println(
+ out.println(
"Error: Activity not started, unknown error code " + res);
break;
}
+ if (mWaitOption && launched) {
+ if (result == null) {
+ result = new IActivityManager.WaitResult();
+ result.who = intent.getComponent();
+ }
+ System.out.println("Status: " + (result.timeout ? "timeout" : "ok"));
+ if (result.who != null) {
+ System.out.println("Activity: " + result.who.flattenToShortString());
+ }
+ if (result.thisTime >= 0) {
+ System.out.println("ThisTime: " + result.thisTime);
+ }
+ if (result.totalTime >= 0) {
+ System.out.println("TotalTime: " + result.totalTime);
+ }
+ System.out.println("Complete");
+ }
}
private void sendBroadcast() throws Exception {
@@ -504,8 +541,9 @@ public class Am {
System.err.println(
"usage: am [subcommand] [options]\n" +
"\n" +
- " start an Activity: am start [-D] <INTENT>\n" +
+ " start an Activity: am start [-D] [-W] <INTENT>\n" +
" -D: enable debugging\n" +
+ " -W: wait for launch to complete\n" +
"\n" +
" start a Service: am startservice <INTENT>\n" +
"\n" +
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 2e39c10db744..6849fd766035 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -146,6 +146,28 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case START_ACTIVITY_AND_WAIT_TRANSACTION:
+ {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder b = data.readStrongBinder();
+ IApplicationThread app = ApplicationThreadNative.asInterface(b);
+ Intent intent = Intent.CREATOR.createFromParcel(data);
+ String resolvedType = data.readString();
+ Uri[] grantedUriPermissions = data.createTypedArray(Uri.CREATOR);
+ int grantedMode = data.readInt();
+ IBinder resultTo = data.readStrongBinder();
+ String resultWho = data.readString();
+ int requestCode = data.readInt();
+ boolean onlyIfNeeded = data.readInt() != 0;
+ boolean debug = data.readInt() != 0;
+ WaitResult result = startActivityAndWait(app, intent, resolvedType,
+ grantedUriPermissions, grantedMode, resultTo, resultWho,
+ requestCode, onlyIfNeeded, debug);
+ reply.writeNoException();
+ result.writeToParcel(reply, 0);
+ return true;
+ }
+
case START_ACTIVITY_INTENT_SENDER_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
@@ -1238,6 +1260,31 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
return result;
}
+ public WaitResult startActivityAndWait(IApplicationThread caller, Intent intent,
+ String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
+ IBinder resultTo, String resultWho,
+ int requestCode, boolean onlyIfNeeded,
+ boolean debug) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(caller != null ? caller.asBinder() : null);
+ intent.writeToParcel(data, 0);
+ data.writeString(resolvedType);
+ data.writeTypedArray(grantedUriPermissions, 0);
+ data.writeInt(grantedMode);
+ data.writeStrongBinder(resultTo);
+ data.writeString(resultWho);
+ data.writeInt(requestCode);
+ data.writeInt(onlyIfNeeded ? 1 : 0);
+ data.writeInt(debug ? 1 : 0);
+ mRemote.transact(START_ACTIVITY_AND_WAIT_TRANSACTION, data, reply, 0);
+ reply.readException();
+ WaitResult result = WaitResult.CREATOR.createFromParcel(reply);
+ reply.recycle();
+ data.recycle();
+ return result;
+ }
public int startActivityIntentSender(IApplicationThread caller,
IntentSender intent, Intent fillInIntent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode,
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 86f28bfa6cb3..3913ed5da0a2 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -84,6 +84,10 @@ public interface IActivityManager extends IInterface {
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo, String resultWho, int requestCode,
boolean onlyIfNeeded, boolean debug) throws RemoteException;
+ public WaitResult startActivityAndWait(IApplicationThread caller,
+ Intent intent, String resolvedType, Uri[] grantedUriPermissions,
+ int grantedMode, IBinder resultTo, String resultWho, int requestCode,
+ boolean onlyIfNeeded, boolean debug) throws RemoteException;
public int startActivityIntentSender(IApplicationThread caller,
IntentSender intent, Intent fillInIntent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode,
@@ -348,6 +352,49 @@ public interface IActivityManager extends IInterface {
}
};
+ /** Information returned after waiting for an activity start. */
+ public static class WaitResult implements Parcelable {
+ public int result;
+ public boolean timeout;
+ public ComponentName who;
+ public long thisTime;
+ public long totalTime;
+
+ public WaitResult() {
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(result);
+ dest.writeInt(timeout ? 1 : 0);
+ ComponentName.writeToParcel(who, dest);
+ dest.writeLong(thisTime);
+ dest.writeLong(totalTime);
+ }
+
+ public static final Parcelable.Creator<WaitResult> CREATOR
+ = new Parcelable.Creator<WaitResult>() {
+ public WaitResult createFromParcel(Parcel source) {
+ return new WaitResult(source);
+ }
+
+ public WaitResult[] newArray(int size) {
+ return new WaitResult[size];
+ }
+ };
+
+ private WaitResult(Parcel source) {
+ result = source.readInt();
+ timeout = source.readInt() != 0;
+ who = ComponentName.readFromParcel(source);
+ thisTime = source.readLong();
+ totalTime = source.readLong();
+ }
+ };
+
String descriptor = "android.app.IActivityManager";
// Please keep these transaction codes the same -- they are also
@@ -453,4 +500,5 @@ public interface IActivityManager extends IInterface {
int HANDLE_APPLICATION_WTF_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+101;
int KILL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+102;
int IS_USER_A_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+103;
+ int START_ACTIVITY_AND_WAIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+104;
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2edb430fa2f7..dc8f3864b736 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -530,19 +530,6 @@ public abstract class PackageManager {
public static final int INSTALL_FAILED_INTERNAL_ERROR = -110;
/**
- * Indicates the state of installation. Used by PackageManager to
- * figure out incomplete installations. Say a package is being installed
- * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till
- * the package installation is successful or unsuccesful lin which case
- * the PackageManager will no longer maintain state information associated
- * with the package. If some exception(like device freeze or battery being
- * pulled out) occurs during installation of a package, the PackageManager
- * needs this information to clean up the previously failed installation.
- */
- public static final int PKG_INSTALL_INCOMPLETE = 0;
- public static final int PKG_INSTALL_COMPLETE = 1;
-
- /**
* Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
* package's data directory.
*
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index b2549615b70d..b59e2791e757 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -48,6 +48,7 @@ public class MobileDataStateTracker extends NetworkStateTracker {
private ITelephony mPhoneService;
private String mApnType;
+ private String mApnTypeToWatchFor;
private String mApnName;
private boolean mEnabled;
private BroadcastReceiver mStateReceiver;
@@ -65,6 +66,12 @@ public class MobileDataStateTracker extends NetworkStateTracker {
TelephonyManager.getDefault().getNetworkType(), tag,
TelephonyManager.getDefault().getNetworkTypeName());
mApnType = networkTypeToApnType(netType);
+ if (TextUtils.equals(mApnType, Phone.APN_TYPE_HIPRI)) {
+ mApnTypeToWatchFor = Phone.APN_TYPE_DEFAULT;
+ } else {
+ mApnTypeToWatchFor = mApnType;
+ }
+
mPhoneService = null;
if(netType == ConnectivityManager.TYPE_MOBILE) {
mEnabled = true;
@@ -122,7 +129,7 @@ public class MobileDataStateTracker extends NetworkStateTracker {
String[] list = typeList.split(",");
for(int i=0; i< list.length; i++) {
- if (TextUtils.equals(list[i], mApnType) ||
+ if (TextUtils.equals(list[i], mApnTypeToWatchFor) ||
TextUtils.equals(list[i], Phone.APN_TYPE_ALL)) {
return true;
}
diff --git a/core/java/android/pim/EventRecurrence.java b/core/java/android/pim/EventRecurrence.java
index 3ea9b4a89bbc..56c4f7ad8a28 100644
--- a/core/java/android/pim/EventRecurrence.java
+++ b/core/java/android/pim/EventRecurrence.java
@@ -16,7 +16,6 @@
package android.pim;
-import android.content.res.Resources;
import android.text.TextUtils;
import android.text.format.Time;
@@ -325,55 +324,6 @@ public class EventRecurrence
return s.toString();
}
- public String getRepeatString() {
- Resources r = Resources.getSystem();
-
- // TODO Implement "Until" portion of string, as well as custom settings
- switch (this.freq) {
- case DAILY:
- return r.getString(com.android.internal.R.string.daily);
- case WEEKLY: {
- if (repeatsOnEveryWeekDay()) {
- return r.getString(com.android.internal.R.string.every_weekday);
- } else {
- String format = r.getString(com.android.internal.R.string.weekly);
- StringBuilder days = new StringBuilder();
-
- // Do one less iteration in the loop so the last element is added out of the
- // loop. This is done so the comma is not placed after the last item.
- int count = this.bydayCount - 1;
- if (count >= 0) {
- for (int i = 0 ; i < count ; i++) {
- days.append(dayToString(r, this.byday[i]));
- days.append(",");
- }
- days.append(dayToString(r, this.byday[count]));
-
- return String.format(format, days.toString());
- }
-
- // There is no "BYDAY" specifier, so use the day of the
- // first event. For this to work, the setStartDate()
- // method must have been used by the caller to set the
- // date of the first event in the recurrence.
- if (startDate == null) {
- return null;
- }
-
- int day = timeDay2Day(startDate.weekDay);
- return String.format(format, dayToString(r, day));
- }
- }
- case MONTHLY: {
- return r.getString(com.android.internal.R.string.monthly);
- }
- case YEARLY:
- return r.getString(com.android.internal.R.string.yearly);
- }
-
- return null;
- }
-
public boolean repeatsOnEveryWeekDay() {
if (this.freq != WEEKLY) {
return false;
@@ -405,17 +355,4 @@ public class EventRecurrence
return true;
}
-
- private String dayToString(Resources r, int day) {
- switch (day) {
- case SU: return r.getString(com.android.internal.R.string.day_of_week_long_sunday);
- case MO: return r.getString(com.android.internal.R.string.day_of_week_long_monday);
- case TU: return r.getString(com.android.internal.R.string.day_of_week_long_tuesday);
- case WE: return r.getString(com.android.internal.R.string.day_of_week_long_wednesday);
- case TH: return r.getString(com.android.internal.R.string.day_of_week_long_thursday);
- case FR: return r.getString(com.android.internal.R.string.day_of_week_long_friday);
- case SA: return r.getString(com.android.internal.R.string.day_of_week_long_saturday);
- default: throw new IllegalArgumentException("bad day argument: " + day);
- }
- }
}
diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java
index bf411e1bce01..d55a9431d1d2 100644
--- a/core/java/android/speech/RecognizerIntent.java
+++ b/core/java/android/speech/RecognizerIntent.java
@@ -298,6 +298,15 @@ public class RecognizerIntent {
"android.speech.action.GET_LANGUAGE_DETAILS";
/**
+ * Specify this boolean extra in a broadcast of {@link #ACTION_GET_LANGUAGE_DETAILS} to
+ * indicate that only the current language preference is needed in the response. This
+ * avoids any additional computation if all you need is {@link #EXTRA_LANGUAGE_PREFERENCE}
+ * in the response.
+ */
+ public static final String EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE =
+ "android.speech.extra.ONLY_RETURN_LANGUAGE_PREFERENCE";
+
+ /**
* The key to the extra in the {@link Bundle} returned by {@link #ACTION_GET_LANGUAGE_DETAILS}
* which is a {@link String} that represents the current language preference this user has
* specified - a locale string like "en-US".
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 1c15f12bdb3c..394ce0a31985 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1822,17 +1822,6 @@
<!-- Appened to express the value is this unit of time. -->
<string name="years">years</string>
- <!-- Calendar spinner item, to select that an event recurs every weekday. -->
- <string name="every_weekday">"Every weekday (Mon\u2013Fri)"</string>
- <!-- Calendar spinner item, to select that an event recurs every day. -->
- <string name="daily">Daily</string>
- <!-- Calendar spinner item, to select that an event recurs every week on a particular day of the week. -->
- <string name="weekly">"Weekly on <xliff:g id="day">%s</xliff:g>"</string>
- <!-- Calendar spinner item, to select that an event recurs every month. -->
- <string name="monthly">Monthly</string>
- <!-- Calendar spinner item, to select that an event recurs every year. -->
- <string name="yearly">Yearly</string>
-
<!-- Title for error alert when a video cannot be played. it can be used by any app. -->
<string name="VideoView_error_title">Cannot play video</string>
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 63fdaef3d4a7..7ce9a4ce69a1 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -56,8 +56,6 @@ import android.content.pm.PackageStats;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
-import static android.content.pm.PackageManager.PKG_INSTALL_COMPLETE;
-import static android.content.pm.PackageManager.PKG_INSTALL_INCOMPLETE;
import android.content.pm.PackageParser;
import android.content.pm.PermissionInfo;
import android.content.pm.PermissionGroupInfo;
@@ -151,6 +149,19 @@ class PackageManagerService extends IPackageManager.Stub {
// package apks to install directory.
private static final String INSTALL_PACKAGE_SUFFIX = "-";
+ /**
+ * Indicates the state of installation. Used by PackageManager to
+ * figure out incomplete installations. Say a package is being installed
+ * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till
+ * the package installation is successful or unsuccesful lin which case
+ * the PackageManager will no longer maintain state information associated
+ * with the package. If some exception(like device freeze or battery being
+ * pulled out) occurs during installation of a package, the PackageManager
+ * needs this information to clean up the previously failed installation.
+ */
+ private static final int PKG_INSTALL_INCOMPLETE = 0;
+ private static final int PKG_INSTALL_COMPLETE = 1;
+
static final int SCAN_MONITOR = 1<<0;
static final int SCAN_NO_DEX = 1<<1;
static final int SCAN_FORCE_DEX = 1<<2;
@@ -4426,8 +4437,11 @@ class PackageManagerService extends IPackageManager.Stub {
}
public void handleStartCopy(IMediaContainerService imcs) {
- int ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- if (imcs != null) {
+ int ret = PackageManager.INSTALL_SUCCEEDED;
+ // Dont need to invoke getInstallLocation for forward locked apps.
+ if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
+ flags &= ~PackageManager.INSTALL_EXTERNAL;
+ } else if (imcs != null) {
// Remote call to find out default install location
int loc = getInstallLocation(imcs);
// Use install location to create InstallArgs and temporary
@@ -4447,16 +4461,6 @@ class PackageManagerService extends IPackageManager.Stub {
flags &= ~PackageManager.INSTALL_EXTERNAL;
}
}
- // Disable forward locked apps on sdcard.
- if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 &&
- (flags & PackageManager.INSTALL_EXTERNAL) != 0) {
- // Make sure forward locked apps can only be installed
- // on internal storage
- Log.w(TAG, "Cannot install protected apps on sdcard");
- ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
- } else {
- ret = PackageManager.INSTALL_SUCCEEDED;
- }
}
}
// Create the file args now.
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 7b6470432044..a404ec5c7f54 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -35,6 +35,7 @@ import android.app.AlertDialog;
import android.app.ApplicationErrorReport;
import android.app.Dialog;
import android.app.IActivityController;
+import android.app.IActivityManager;
import android.app.IActivityWatcher;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
@@ -388,6 +389,18 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
= new ArrayList<PendingActivityLaunch>();
/**
+ * List of people waiting to find out about the next launched activity.
+ */
+ final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
+ = new ArrayList<IActivityManager.WaitResult>();
+
+ /**
+ * List of people waiting to find out about the next visible activity.
+ */
+ final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
+ = new ArrayList<IActivityManager.WaitResult>();
+
+ /**
* 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
@@ -3559,11 +3572,38 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
return START_SUCCESS;
}
- public final int startActivity(IApplicationThread caller,
+ void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
+ long thisTime, long totalTime) {
+ for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
+ WaitResult w = mWaitingActivityLaunched.get(i);
+ w.timeout = timeout;
+ if (r != null) {
+ w.who = new ComponentName(r.info.packageName, r.info.name);
+ }
+ w.thisTime = thisTime;
+ w.totalTime = totalTime;
+ }
+ notify();
+ }
+
+ void reportActivityVisibleLocked(HistoryRecord r) {
+ for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
+ WaitResult w = mWaitingActivityVisible.get(i);
+ w.timeout = false;
+ if (r != null) {
+ w.who = new ComponentName(r.info.packageName, r.info.name);
+ }
+ w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
+ w.thisTime = w.totalTime;
+ }
+ notify();
+ }
+
+ private final int startActivityMayWait(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded,
- boolean debug) {
+ boolean debug, WaitResult outResult) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -3603,7 +3643,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
- synchronized(this) {
+ synchronized (this) {
int callingPid;
int callingUid;
if (caller == null) {
@@ -3618,11 +3658,62 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
resultTo, resultWho, requestCode, callingPid, callingUid,
onlyIfNeeded, componentSpecified);
Binder.restoreCallingIdentity(origId);
+
+ if (outResult != null) {
+ outResult.result = res;
+ if (res == IActivityManager.START_SUCCESS) {
+ mWaitingActivityLaunched.add(outResult);
+ do {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ } while (!outResult.timeout && outResult.who == null);
+ } else if (res == IActivityManager.START_TASK_TO_FRONT) {
+ HistoryRecord r = this.topRunningActivityLocked(null);
+ if (r.nowVisible) {
+ outResult.timeout = false;
+ outResult.who = new ComponentName(r.info.packageName, r.info.name);
+ outResult.totalTime = 0;
+ outResult.thisTime = 0;
+ } else {
+ outResult.thisTime = SystemClock.uptimeMillis();
+ mWaitingActivityVisible.add(outResult);
+ do {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ } while (!outResult.timeout && outResult.who == null);
+ }
+ }
+ }
+
return res;
}
}
- public int startActivityIntentSender(IApplicationThread caller,
+ public final int startActivity(IApplicationThread caller,
+ Intent intent, String resolvedType, Uri[] grantedUriPermissions,
+ int grantedMode, IBinder resultTo,
+ String resultWho, int requestCode, boolean onlyIfNeeded,
+ boolean debug) {
+ return startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
+ grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, null);
+ }
+
+ public final WaitResult startActivityAndWait(IApplicationThread caller,
+ Intent intent, String resolvedType, Uri[] grantedUriPermissions,
+ int grantedMode, IBinder resultTo,
+ String resultWho, int requestCode, boolean onlyIfNeeded,
+ boolean debug) {
+ WaitResult res = new WaitResult();
+ startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
+ grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, res);
+ return res;
+ }
+
+ public int startActivityIntentSender(IApplicationThread caller,
IntentSender intent, Intent fillInIntent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode,
int flagsMask, int flagsValues) {
@@ -5505,6 +5596,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (index >= 0) {
HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ if (fromTimeout) {
+ reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
+ }
+
// This is a hack to semi-deal with a race condition
// in the client where it can be constructed with a
// newer configuration from when we asked it to launch.
@@ -5539,6 +5634,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
mBooted = true;
enableScreen = true;
}
+
+ } else if (fromTimeout) {
+ reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
}
// Atomically retrieve all of the other things to do.
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index 0b34f7c99f66..7d7247c64268 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -387,12 +387,14 @@ class HistoryRecord extends IApplicationToken.Stub {
sb.append(" ms)");
Log.i(ActivityManagerService.TAG, sb.toString());
}
+ service.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
if (totalTime > 0) {
service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
}
startTime = 0;
service.mInitialStartTime = 0;
}
+ service.reportActivityVisibleLocked(this);
if (ActivityManagerService.DEBUG_SWITCH) Log.v(
ActivityManagerService.TAG, "windowsVisible(): " + this);
if (!nowVisible) {
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 16638bc02bfe..1c47bb4bed1b 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -31,6 +31,7 @@ import android.net.InterfaceConfiguration;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.NetworkInfo;
+import android.os.BatteryManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -88,11 +89,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
private String mUpstreamIfaceName;
- // turning on/off RNDIS resets the interface generating and extra discon/conn cycle
- // count how many to ignore.. Self correcting if you plug/unplug a bunch of times.
- // TODO - brittle - maybe don't need?
- private int mUsbResetExpected = 0;
-
HierarchicalStateMachine mTetherMasterSM;
public Tethering(Context context) {
@@ -116,8 +112,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
// TODO - remove this hack after real USB connections are detected.
IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_UMS_DISCONNECTED);
- filter.addAction(Intent.ACTION_UMS_CONNECTED);
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mStateReceiver = new StateReceiver();
mContext.registerReceiver(mStateReceiver, filter);
@@ -428,26 +423,10 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
private class StateReceiver extends BroadcastReceiver {
public void onReceive(Context content, Intent intent) {
String action = intent.getAction();
- if (action.equals(Intent.ACTION_UMS_CONNECTED)) {
- Log.w(TAG, "got UMS connected");
- synchronized (Tethering.this) {
- if(mUsbResetExpected != 0) {
- Log.w(TAG, "mUsbResetExpected == " + mUsbResetExpected + ", ignored");
- mUsbResetExpected--;
- return;
- }
- }
- Tethering.this.enableUsbIfaces(true); // add them
- } else if (action.equals(Intent.ACTION_UMS_DISCONNECTED)) {
- Log.w(TAG, "got UMS disconneded broadcast");
- synchronized (Tethering.this) {
- if(mUsbResetExpected != 0) {
- Log.w(TAG, "mUsbResetExpected == " + mUsbResetExpected + ", ignored");
- mUsbResetExpected--;
- return;
- }
- }
- Tethering.this.enableUsbIfaces(false); // remove them
+ if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+ boolean usbConnected = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)
+ == BatteryManager.BATTERY_PLUGGED_USB);
+ Tethering.this.enableUsbIfaces(usbConnected); // add or remove them
} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
@@ -497,10 +476,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
try {
if (enabled) {
- // turning this on will reset USB and generate two bogus events - ignore them
synchronized (this) {
if (!service.isUsbRNDISStarted()) {
- mUsbResetExpected += 2;
service.startUsbRNDIS();
}
}